28ad8a9871177a3f99ad85078d0b3d59d536cbdc
[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 "FTLForOSREntryJITCode.h"
36 #include "FTLFormattedValue.h"
37 #include "FTLInlineCacheSize.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 "VirtualRegister.h"
46
47 #include <wtf/ProcessID.h>
48
49 namespace JSC { namespace FTL {
50
51 using namespace DFG;
52
53 static int compileCounter;
54
55 // Using this instead of typeCheck() helps to reduce the load on LLVM, by creating
56 // significantly less dead code.
57 #define FTL_TYPE_CHECK(lowValue, highValue, typesPassedThrough, failCondition) do { \
58         FormattedValue _ftc_lowValue = (lowValue);                      \
59         Edge _ftc_highValue = (highValue);                              \
60         SpeculatedType _ftc_typesPassedThrough = (typesPassedThrough);  \
61         if (!m_interpreter.needsTypeCheck(_ftc_highValue, _ftc_typesPassedThrough)) \
62             break;                                                      \
63         typeCheck(_ftc_lowValue, _ftc_highValue, _ftc_typesPassedThrough, (failCondition)); \
64     } while (false)
65
66 class LowerDFGToLLVM {
67 public:
68     LowerDFGToLLVM(State& state)
69         : m_graph(state.graph)
70         , m_ftlState(state)
71         , m_heaps(state.context)
72         , m_out(state.context)
73         , m_valueSources(OperandsLike, state.graph.block(0)->variablesAtHead)
74         , m_lastSetOperand(VirtualRegister())
75         , m_state(state.graph)
76         , m_interpreter(state.graph, m_state)
77         , m_stackmapIDs(0)
78     {
79     }
80     
81     void lower()
82     {
83         CString name;
84         if (verboseCompilationEnabled()) {
85             name = toCString(
86                 "jsBody_", atomicIncrement(&compileCounter), "_", codeBlock()->inferredName(),
87                 "_", codeBlock()->hash());
88         } else
89             name = "jsBody";
90         
91         m_graph.m_dominators.computeIfNecessary(m_graph);
92         
93         m_ftlState.module =
94             llvm->ModuleCreateWithNameInContext(name.data(), m_ftlState.context);
95         
96         m_ftlState.function = addFunction(
97             m_ftlState.module, name.data(), functionType(m_out.int64, m_out.intPtr));
98         setFunctionCallingConv(m_ftlState.function, LLVMCCallConv);
99         
100         m_out.initialize(m_ftlState.module, m_ftlState.function, m_heaps);
101         
102         m_prologue = appendBasicBlock(m_ftlState.context, m_ftlState.function);
103         m_out.appendTo(m_prologue);
104         createPhiVariables();
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         m_out.appendTo(m_prologue);
118         m_out.jump(lowBlock(m_graph.block(0)));
119         
120         Vector<BasicBlock*> depthFirst;
121         m_graph.getBlocksInDepthFirstOrder(depthFirst);
122         for (unsigned i = 0; i < depthFirst.size(); ++i)
123             compileBlock(depthFirst[i]);
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 NodeResultInt52:
155                     type = m_out.int64;
156                     break;
157                 case NodeResultBoolean:
158                     type = m_out.boolean;
159                     break;
160                 case NodeResultJS:
161                     type = m_out.int64;
162                     break;
163                 default:
164                     RELEASE_ASSERT_NOT_REACHED();
165                     break;
166                 }
167                 m_phis.add(node, buildAlloca(m_out.m_builder, type));
168             }
169         }
170     }
171     
172     void compileBlock(BasicBlock* block)
173     {
174         if (!block)
175             return;
176         
177         if (verboseCompilationEnabled())
178             dataLog("Compiling block ", *block, "\n");
179         
180         m_highBlock = block;
181         
182         LBasicBlock lowBlock = m_blocks.get(m_highBlock);
183         
184         m_nextHighBlock = 0;
185         for (BlockIndex nextBlockIndex = m_highBlock->index + 1; nextBlockIndex < m_graph.numBlocks(); ++nextBlockIndex) {
186             m_nextHighBlock = m_graph.block(nextBlockIndex);
187             if (m_nextHighBlock)
188                 break;
189         }
190         m_nextLowBlock = m_nextHighBlock ? m_blocks.get(m_nextHighBlock) : 0;
191         
192         // All of this effort to find the next block gives us the ability to keep the
193         // generated IR in roughly program order. This ought not affect the performance
194         // of the generated code (since we expect LLVM to reorder things) but it will
195         // make IR dumps easier to read.
196         m_out.appendTo(lowBlock, m_nextLowBlock);
197         
198         if (Options::ftlCrashes())
199             m_out.crashNonTerminal();
200         
201         if (!m_highBlock->cfaHasVisited) {
202             m_out.crash();
203             return;
204         }
205         
206         initializeOSRExitStateForBlock();
207         
208         m_live = block->ssa->liveAtHead;
209         
210         m_state.reset();
211         m_state.beginBasicBlock(m_highBlock);
212         
213         for (m_nodeIndex = 0; m_nodeIndex < m_highBlock->size(); ++m_nodeIndex) {
214             if (!compileNode(m_nodeIndex))
215                 break;
216         }
217     }
218     
219     bool compileNode(unsigned nodeIndex)
220     {
221         if (!m_state.isValid()) {
222             m_out.unreachable();
223             return false;
224         }
225         
226         m_node = m_highBlock->at(nodeIndex);
227         m_codeOriginForExitProfile = m_node->codeOrigin;
228         m_codeOriginForExitTarget = m_node->codeOriginForExitTarget;
229         
230         if (verboseCompilationEnabled())
231             dataLog("Lowering ", m_node, "\n");
232         
233         bool shouldExecuteEffects = m_interpreter.startExecuting(m_node);
234         
235         m_direction = (m_node->flags() & NodeExitsForward) ? ForwardSpeculation : BackwardSpeculation;
236         
237         switch (m_node->op()) {
238         case Upsilon:
239             compileUpsilon();
240             break;
241         case Phi:
242             compilePhi();
243             break;
244         case JSConstant:
245             break;
246         case WeakJSConstant:
247             compileWeakJSConstant();
248             break;
249         case GetArgument:
250             compileGetArgument();
251             break;
252         case ExtractOSREntryLocal:
253             compileExtractOSREntryLocal();
254             break;
255         case GetLocal:
256             compileGetLocal();
257             break;
258         case SetLocal:
259             compileSetLocal();
260             break;
261         case MovHint:
262             compileMovHint();
263             break;
264         case ZombieHint:
265             compileZombieHint();
266             break;
267         case MovHintAndCheck:
268             compileMovHintAndCheck();
269             break;
270         case Phantom:
271             compilePhantom();
272             break;
273         case Flush:
274         case PhantomLocal:
275         case SetArgument:
276         case LoopHint:
277             break;
278         case ArithAdd:
279         case ValueAdd:
280             compileAddSub();
281             break;
282         case ArithSub:
283             compileAddSub();
284             break;
285         case ArithMul:
286             compileArithMul();
287             break;
288         case ArithDiv:
289             compileArithDivMod();
290             break;
291         case ArithMod:
292             compileArithDivMod();
293             break;
294         case ArithMin:
295         case ArithMax:
296             compileArithMinOrMax();
297             break;
298         case ArithAbs:
299             compileArithAbs();
300             break;
301         case ArithNegate:
302             compileArithNegate();
303             break;
304         case BitAnd:
305             compileBitAnd();
306             break;
307         case BitOr:
308             compileBitOr();
309             break;
310         case BitXor:
311             compileBitXor();
312             break;
313         case BitRShift:
314             compileBitRShift();
315             break;
316         case BitLShift:
317             compileBitLShift();
318             break;
319         case BitURShift:
320             compileBitURShift();
321             break;
322         case UInt32ToNumber:
323             compileUInt32ToNumber();
324             break;
325         case Int32ToDouble:
326             compileInt32ToDouble();
327             break;
328         case CheckStructure:
329             compileCheckStructure();
330             break;
331         case StructureTransitionWatchpoint:
332             compileStructureTransitionWatchpoint();
333             break;
334         case ArrayifyToStructure:
335             compileArrayifyToStructure();
336             break;
337         case PutStructure:
338             compilePutStructure();
339             break;
340         case PhantomPutStructure:
341             compilePhantomPutStructure();
342             break;
343         case GetById:
344             compileGetById();
345             break;
346         case PutById:
347             compilePutById();
348             break;
349         case GetButterfly:
350             compileGetButterfly();
351             break;
352         case GetIndexedPropertyStorage:
353             compileGetIndexedPropertyStorage();
354             break;
355         case CheckArray:
356             compileCheckArray();
357             break;
358         case GetArrayLength:
359             compileGetArrayLength();
360             break;
361         case GetByVal:
362             compileGetByVal();
363             break;
364         case PutByVal:
365         case PutByValAlias:
366             compilePutByVal();
367             break;
368         case GetByOffset:
369             compileGetByOffset();
370             break;
371         case PutByOffset:
372             compilePutByOffset();
373             break;
374         case GetGlobalVar:
375             compileGetGlobalVar();
376             break;
377         case PutGlobalVar:
378             compilePutGlobalVar();
379             break;
380         case GlobalVarWatchpoint:
381             compileGlobalVarWatchpoint();
382             break;
383         case GetMyScope:
384             compileGetMyScope();
385             break;
386         case SkipScope:
387             compileSkipScope();
388             break;
389         case GetClosureRegisters:
390             compileGetClosureRegisters();
391             break;
392         case GetClosureVar:
393             compileGetClosureVar();
394             break;
395         case PutClosureVar:
396             compilePutClosureVar();
397             break;
398         case CompareEq:
399             compileCompareEq();
400             break;
401         case CompareEqConstant:
402             compileCompareEqConstant();
403             break;
404         case CompareStrictEq:
405             compileCompareStrictEq();
406             break;
407         case CompareStrictEqConstant:
408             compileCompareStrictEqConstant();
409             break;
410         case CompareLess:
411             compileCompareLess();
412             break;
413         case CompareLessEq:
414             compileCompareLessEq();
415             break;
416         case CompareGreater:
417             compileCompareGreater();
418             break;
419         case CompareGreaterEq:
420             compileCompareGreaterEq();
421             break;
422         case LogicalNot:
423             compileLogicalNot();
424             break;
425         case Call:
426         case Construct:
427             compileCallOrConstruct();
428             break;
429         case Jump:
430             compileJump();
431             break;
432         case Branch:
433             compileBranch();
434             break;
435         case Switch:
436             compileSwitch();
437             break;
438         case Return:
439             compileReturn();
440             break;
441         case ForceOSRExit:
442             compileForceOSRExit();
443             break;
444         case InvalidationPoint:
445             compileInvalidationPoint();
446             break;
447         case ValueToInt32:
448             compileValueToInt32();
449             break;
450         case Int52ToValue:
451             compileInt52ToValue();
452             break;
453         default:
454             RELEASE_ASSERT_NOT_REACHED();
455             break;
456         }
457         
458         if (m_node->shouldGenerate())
459             DFG_NODE_DO_TO_CHILDREN(m_graph, m_node, use);
460         
461         if (m_node->adjustedRefCount())
462             m_live.add(m_node);
463         
464         if (shouldExecuteEffects)
465             m_interpreter.executeEffects(nodeIndex);
466         
467         return true;
468     }
469
470     void compileValueToInt32()
471     {
472         ASSERT(m_node->child1().useKind() == BooleanUse);
473         setInt32(m_out.zeroExt(lowBoolean(m_node->child1()), m_out.int32));
474     }
475
476     void compileInt52ToValue()
477     {
478         setJSValue(lowJSValue(m_node->child1()));
479     }
480
481     void compileUpsilon()
482     {
483         LValue destination = m_phis.get(m_node->phi());
484         
485         switch (m_node->child1().useKind()) {
486         case NumberUse:
487             m_out.set(lowDouble(m_node->child1()), destination);
488             break;
489         case Int32Use:
490             m_out.set(lowInt32(m_node->child1()), destination);
491             break;
492         case MachineIntUse:
493             m_out.set(lowInt52(m_node->child1()), destination);
494             break;
495         case BooleanUse:
496             m_out.set(lowBoolean(m_node->child1()), destination);
497             break;
498         case CellUse:
499             m_out.set(lowCell(m_node->child1()), destination);
500             break;
501         case UntypedUse:
502             m_out.set(lowJSValue(m_node->child1()), destination);
503             break;
504         default:
505             RELEASE_ASSERT_NOT_REACHED();
506             break;
507         }
508     }
509     
510     void compilePhi()
511     {
512         LValue source = m_phis.get(m_node);
513         
514         switch (m_node->flags() & NodeResultMask) {
515         case NodeResultNumber:
516             setDouble(m_out.get(source));
517             break;
518         case NodeResultInt32:
519             setInt32(m_out.get(source));
520             break;
521         case NodeResultInt52:
522             setInt52(m_out.get(source));
523             break;
524         case NodeResultBoolean:
525             setBoolean(m_out.get(source));
526             break;
527         case NodeResultJS:
528             setJSValue(m_out.get(source));
529             break;
530         default:
531             RELEASE_ASSERT_NOT_REACHED();
532             break;
533         }
534     }
535     
536     void compileJSConstant()
537     {
538         JSValue value = m_graph.valueOfJSConstant(m_node);
539         if (value.isDouble())
540             setDouble(m_out.constDouble(value.asDouble()));
541         else
542             setJSValue(m_out.constInt64(JSValue::encode(value)));
543     }
544     
545     void compileWeakJSConstant()
546     {
547         setJSValue(weakPointer(m_node->weakConstant()));
548     }
549     
550     void compileGetArgument()
551     {
552         VariableAccessData* variable = m_node->variableAccessData();
553         VirtualRegister operand = variable->machineLocal();
554         RELEASE_ASSERT(operand.isArgument());
555
556         LValue jsValue = m_out.load64(addressFor(operand));
557
558         switch (useKindFor(variable->flushFormat())) {
559         case Int32Use:
560             speculateBackward(BadType, jsValueValue(jsValue), m_node, isNotInt32(jsValue));
561             setInt32(unboxInt32(jsValue));
562             break;
563         case CellUse:
564             speculateBackward(BadType, jsValueValue(jsValue), m_node, isNotCell(jsValue));
565             setJSValue(jsValue);
566             break;
567         case BooleanUse:
568             speculateBackward(BadType, jsValueValue(jsValue), m_node, isNotBoolean(jsValue));
569             setBoolean(unboxBoolean(jsValue));
570             break;
571         case UntypedUse:
572             setJSValue(jsValue);
573             break;
574         default:
575             RELEASE_ASSERT_NOT_REACHED();
576             break;
577         }
578     }
579     
580     void compileExtractOSREntryLocal()
581     {
582         EncodedJSValue* buffer = static_cast<EncodedJSValue*>(
583             m_ftlState.jitCode->ftlForOSREntry()->entryBuffer()->dataBuffer());
584         setJSValue(m_out.load64(m_out.absolute(buffer + m_node->unlinkedLocal().toLocal())));
585     }
586     
587     void compileGetLocal()
588     {
589         // GetLocals arise only for captured variables.
590         
591         VariableAccessData* variable = m_node->variableAccessData();
592         AbstractValue& value = m_state.variables().operand(variable->local());
593         
594         RELEASE_ASSERT(variable->isCaptured());
595         
596         if (isInt32Speculation(value.m_type))
597             setInt32(m_out.load32(payloadFor(variable->machineLocal())));
598         else
599             setJSValue(m_out.load64(addressFor(variable->machineLocal())));
600     }
601     
602     void compileSetLocal()
603     {
604         observeMovHint(m_node);
605         
606         VariableAccessData* variable = m_node->variableAccessData();
607         switch (variable->flushFormat()) {
608         case FlushedJSValue: {
609             LValue value = lowJSValue(m_node->child1());
610             m_out.store64(value, addressFor(variable->machineLocal()));
611             m_valueSources.operand(variable->local()) = ValueSource(ValueInJSStack, variable->machineLocal());
612             return;
613         }
614             
615         case FlushedDouble: {
616             LValue value = lowDouble(m_node->child1());
617             m_out.storeDouble(value, addressFor(variable->machineLocal()));
618             m_valueSources.operand(variable->local()) = ValueSource(DoubleInJSStack, variable->machineLocal());
619             return;
620         }
621             
622         case FlushedInt32: {
623             LValue value = lowInt32(m_node->child1());
624             m_out.store32(value, payloadFor(variable->machineLocal()));
625             m_valueSources.operand(variable->local()) = ValueSource(Int32InJSStack, variable->machineLocal());
626             return;
627         }
628             
629         case FlushedInt52: {
630             LValue value = lowInt52(m_node->child1());
631             m_out.store64(value, addressFor(variable->machineLocal()));
632             m_valueSources.operand(variable->local()) = ValueSource(Int52InJSStack, variable->machineLocal());
633             return;
634         }
635             
636         case FlushedCell: {
637             LValue value = lowCell(m_node->child1());
638             m_out.store64(value, addressFor(variable->machineLocal()));
639             m_valueSources.operand(variable->local()) = ValueSource(ValueInJSStack, variable->machineLocal());
640             return;
641         }
642             
643         case FlushedBoolean: {
644             speculateBoolean(m_node->child1());
645             m_out.store64(
646                 lowJSValue(m_node->child1(), ManualOperandSpeculation),
647                 addressFor(variable->machineLocal()));
648             m_valueSources.operand(variable->local()) = ValueSource(ValueInJSStack, variable->machineLocal());
649             return;
650         }
651             
652         case DeadFlush:
653             RELEASE_ASSERT_NOT_REACHED();
654         }
655         
656         RELEASE_ASSERT_NOT_REACHED();
657     }
658     
659     void compileMovHint()
660     {
661         observeMovHint(m_node);
662     }
663     
664     void compileZombieHint()
665     {
666         VariableAccessData* data = m_node->variableAccessData();
667         m_lastSetOperand = data->local();
668         m_valueSources.operand(data->local()) = ValueSource(SourceIsDead);
669     }
670     
671     void compileMovHintAndCheck()
672     {
673         observeMovHint(m_node);
674         speculate(m_node->child1());
675     }
676     
677     void compilePhantom()
678     {
679         DFG_NODE_DO_TO_CHILDREN(m_graph, m_node, speculate);
680     }
681     
682     void compileAddSub()
683     {
684         bool isSub =  m_node->op() == ArithSub;
685         switch (m_node->binaryUseKind()) {
686         case Int32Use: {
687             LValue left = lowInt32(m_node->child1());
688             LValue right = lowInt32(m_node->child2());
689             LValue result = isSub ? m_out.sub(left, right) : m_out.add(left, right);
690
691             if (bytecodeCanTruncateInteger(m_node->arithNodeFlags())) {
692                 setInt32(result);
693                 break;
694             }
695
696             LValue overflow = isSub ? m_out.subWithOverflow32(left, right) : m_out.addWithOverflow32(left, right);
697
698             speculate(Overflow, noValue(), 0, m_out.extractValue(overflow, 1));
699             setInt32(result);
700             break;
701         }
702             
703         case MachineIntUse: {
704             if (!m_state.forNode(m_node->child1()).couldBeType(SpecInt52)
705                 && !m_state.forNode(m_node->child2()).couldBeType(SpecInt52)) {
706                 Int52Kind kind;
707                 LValue left = lowWhicheverInt52(m_node->child1(), kind);
708                 LValue right = lowInt52(m_node->child2(), kind);
709                 setInt52(isSub ? m_out.sub(left, right) : m_out.add(left, right), kind);
710                 break;
711             }
712             
713             LValue left = lowInt52(m_node->child1());
714             LValue right = lowInt52(m_node->child2());
715             LValue result = isSub ? m_out.sub(left, right) : m_out.add(left, right);
716
717             LValue overflow = isSub ? m_out.subWithOverflow64(left, right) : m_out.addWithOverflow64(left, right);
718             speculate(Int52Overflow, noValue(), 0, m_out.extractValue(overflow, 1));
719             setInt52(result);
720             break;
721         }
722             
723         case NumberUse: {
724             LValue C1 = lowDouble(m_node->child1());
725             LValue C2 = lowDouble(m_node->child2());
726
727             setDouble(isSub ? m_out.doubleSub(C1, C2) : m_out.doubleAdd(C1, C2));
728             break;
729         }
730             
731         default:
732             RELEASE_ASSERT_NOT_REACHED();
733             break;
734         }
735     }
736     
737     void compileArithMul()
738     {
739         switch (m_node->binaryUseKind()) {
740         case Int32Use: {
741             LValue left = lowInt32(m_node->child1());
742             LValue right = lowInt32(m_node->child2());
743             LValue result = m_out.mul(left, right);
744
745             if (!bytecodeCanTruncateInteger(m_node->arithNodeFlags())) {
746                 LValue overflowResult = m_out.mulWithOverflow32(left, right);
747                 speculate(Overflow, noValue(), 0, m_out.extractValue(overflowResult, 1));
748             }
749             
750             if (!bytecodeCanIgnoreNegativeZero(m_node->arithNodeFlags())) {
751                 LBasicBlock slowCase = FTL_NEW_BLOCK(m_out, ("ArithMul slow case"));
752                 LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("ArithMul continuation"));
753                 
754                 m_out.branch(m_out.notZero32(result), continuation, slowCase);
755                 
756                 LBasicBlock lastNext = m_out.appendTo(slowCase, continuation);
757                 LValue cond = m_out.bitOr(m_out.lessThan(left, m_out.int32Zero), m_out.lessThan(right, m_out.int32Zero));
758                 speculate(NegativeZero, noValue(), 0, cond);
759                 m_out.jump(continuation);
760                 m_out.appendTo(continuation, lastNext);
761             }
762             
763             setInt32(result);
764             break;
765         }
766             
767         case MachineIntUse: {
768             Int52Kind kind;
769             LValue left = lowWhicheverInt52(m_node->child1(), kind);
770             LValue right = lowInt52(m_node->child2(), opposite(kind));
771             LValue result = m_out.mul(left, right);
772
773
774             LValue overflowResult = m_out.mulWithOverflow64(left, right);
775             speculate(Int52Overflow, noValue(), 0, m_out.extractValue(overflowResult, 1));
776
777             if (!bytecodeCanIgnoreNegativeZero(m_node->arithNodeFlags())) {
778                 LBasicBlock slowCase = FTL_NEW_BLOCK(m_out, ("ArithMul slow case"));
779                 LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("ArithMul continuation"));
780                 
781                 m_out.branch(m_out.notZero64(result), continuation, slowCase);
782                 
783                 LBasicBlock lastNext = m_out.appendTo(slowCase, continuation);
784                 LValue cond = m_out.bitOr(m_out.lessThan(left, m_out.int64Zero), m_out.lessThan(right, m_out.int64Zero));
785                 speculate(NegativeZero, noValue(), 0, cond);
786                 m_out.jump(continuation);
787                 m_out.appendTo(continuation, lastNext);
788             }
789             
790             setInt52(result);
791             break;
792         }
793             
794         case NumberUse: {
795             setDouble(
796                 m_out.doubleMul(lowDouble(m_node->child1()), lowDouble(m_node->child2())));
797             break;
798         }
799             
800         default:
801             RELEASE_ASSERT_NOT_REACHED();
802             break;
803         }
804     }
805
806     void compileArithDivMod()
807     {
808         switch (m_node->binaryUseKind()) {
809         case Int32Use: {
810             LValue numerator = lowInt32(m_node->child1());
811             LValue denominator = lowInt32(m_node->child2());
812             
813             LBasicBlock unsafeDenominator = FTL_NEW_BLOCK(m_out, ("ArithDivMod unsafe denominator"));
814             LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("ArithDivMod continuation"));
815             LBasicBlock done = FTL_NEW_BLOCK(m_out, ("ArithDivMod done"));
816             
817             Vector<ValueFromBlock, 3> results;
818             
819             LValue adjustedDenominator = m_out.add(denominator, m_out.int32One);
820             
821             m_out.branch(m_out.above(adjustedDenominator, m_out.int32One), continuation, unsafeDenominator);
822             
823             LBasicBlock lastNext = m_out.appendTo(unsafeDenominator, continuation);
824             
825             LValue neg2ToThe31 = m_out.constInt32(-2147483647-1);
826             
827             if (bytecodeUsesAsNumber(m_node->arithNodeFlags())) {
828                 LValue cond = m_out.bitOr(m_out.isZero32(denominator), m_out.equal(numerator, neg2ToThe31));
829                 speculate(Overflow, noValue(), 0, cond);
830                 m_out.jump(continuation);
831             } else {
832                 // This is the case where we convert the result to an int after we're done. So,
833                 // if the denominator is zero, then the result should be zero.
834                 // If the denominator is not zero (i.e. it's -1 because we're guarded by the
835                 // check above) and the numerator is -2^31 then the result should be -2^31.
836                 
837                 LBasicBlock divByZero = FTL_NEW_BLOCK(m_out, ("ArithDiv divide by zero"));
838                 LBasicBlock notDivByZero = FTL_NEW_BLOCK(m_out, ("ArithDiv not divide by zero"));
839                 LBasicBlock neg2ToThe31ByNeg1 = FTL_NEW_BLOCK(m_out, ("ArithDiv -2^31/-1"));
840                 
841                 m_out.branch(m_out.isZero32(denominator), divByZero, notDivByZero);
842                 
843                 m_out.appendTo(divByZero, notDivByZero);
844                 results.append(m_out.anchor(m_out.int32Zero));
845                 m_out.jump(done);
846                 
847                 m_out.appendTo(notDivByZero, neg2ToThe31ByNeg1);
848                 m_out.branch(m_out.equal(numerator, neg2ToThe31), neg2ToThe31ByNeg1, continuation);
849                 
850                 m_out.appendTo(neg2ToThe31ByNeg1, continuation);
851                 results.append(m_out.anchor(neg2ToThe31));
852                 m_out.jump(done);
853             }
854             
855             m_out.appendTo(continuation, done);
856             
857             if (!bytecodeCanIgnoreNegativeZero(m_node->arithNodeFlags())) {
858                 LBasicBlock zeroNumerator = FTL_NEW_BLOCK(m_out, ("ArithDivMod zero numerator"));
859                 LBasicBlock numeratorContinuation = FTL_NEW_BLOCK(m_out, ("ArithDivMod numerator continuation"));
860                 
861                 m_out.branch(m_out.isZero32(numerator), zeroNumerator, numeratorContinuation);
862                 
863                 LBasicBlock innerLastNext = m_out.appendTo(zeroNumerator, numeratorContinuation);
864                 
865                 speculate(
866                     NegativeZero, noValue(), 0, m_out.lessThan(denominator, m_out.int32Zero));
867                 
868                 m_out.jump(numeratorContinuation);
869                 
870                 m_out.appendTo(numeratorContinuation, innerLastNext);
871             }
872             
873             LValue divModResult = m_node->op() == ArithDiv
874                 ? m_out.div(numerator, denominator)
875                 : m_out.rem(numerator, denominator);
876             
877             if (bytecodeUsesAsNumber(m_node->arithNodeFlags())) {
878                 speculate(
879                     Overflow, noValue(), 0,
880                     m_out.notEqual(m_out.mul(divModResult, denominator), numerator));
881             }
882             
883             results.append(m_out.anchor(divModResult));
884             m_out.jump(done);
885             
886             m_out.appendTo(done, lastNext);
887             
888             setInt32(m_out.phi(m_out.int32, results));
889             break;
890         }
891             
892         case NumberUse: {
893             LValue C1 = lowDouble(m_node->child1());
894             LValue C2 = lowDouble(m_node->child2());
895             setDouble(m_node->op() == ArithDiv ? m_out.doubleDiv(C1, C2) : m_out.doubleRem(C1, C2));
896             break;
897         }
898             
899         default:
900             RELEASE_ASSERT_NOT_REACHED();
901             break;
902         }
903     }
904     
905     void compileArithMinOrMax()
906     {
907         switch (m_node->binaryUseKind()) {
908         case Int32Use: {
909             LValue left = lowInt32(m_node->child1());
910             LValue right = lowInt32(m_node->child2());
911             
912             setInt32(
913                 m_out.select(
914                     m_node->op() == ArithMin
915                         ? m_out.lessThan(left, right)
916                         : m_out.lessThan(right, left),
917                     left, right));
918             break;
919         }
920             
921         case NumberUse: {
922             LValue left = lowDouble(m_node->child1());
923             LValue right = lowDouble(m_node->child2());
924             
925             LBasicBlock notLessThan = FTL_NEW_BLOCK(m_out, ("ArithMin/ArithMax not less than"));
926             LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("ArithMin/ArithMax continuation"));
927             
928             Vector<ValueFromBlock, 2> results;
929             
930             results.append(m_out.anchor(left));
931             m_out.branch(
932                 m_node->op() == ArithMin
933                     ? m_out.doubleLessThan(left, right)
934                     : m_out.doubleGreaterThan(left, right),
935                 continuation, notLessThan);
936             
937             LBasicBlock lastNext = m_out.appendTo(notLessThan, continuation);
938             results.append(m_out.anchor(m_out.select(
939                 m_node->op() == ArithMin
940                     ? m_out.doubleGreaterThanOrEqual(left, right)
941                     : m_out.doubleLessThanOrEqual(left, right),
942                 right, m_out.constDouble(0.0 / 0.0))));
943             m_out.jump(continuation);
944             
945             m_out.appendTo(continuation, lastNext);
946             setDouble(m_out.phi(m_out.doubleType, results));
947             break;
948         }
949             
950         default:
951             RELEASE_ASSERT_NOT_REACHED();
952             break;
953         }
954     }
955     
956     void compileArithAbs()
957     {
958         switch (m_node->child1().useKind()) {
959         case Int32Use: {
960             LValue value = lowInt32(m_node->child1());
961             
962             LValue mask = m_out.aShr(value, m_out.constInt32(31));
963             LValue result = m_out.bitXor(mask, m_out.add(mask, value));
964             
965             speculate(Overflow, noValue(), 0, m_out.equal(result, m_out.constInt32(1 << 31)));
966             
967             setInt32(result);
968             break;
969         }
970             
971         case NumberUse: {
972             setDouble(m_out.doubleAbs(lowDouble(m_node->child1())));
973             break;
974         }
975             
976         default:
977             RELEASE_ASSERT_NOT_REACHED();
978             break;
979         }
980     }
981     
982     void compileArithNegate()
983     {
984         switch (m_node->child1().useKind()) {
985         case Int32Use: {
986             LValue value = lowInt32(m_node->child1());
987             
988             LValue result = m_out.neg(value);
989             if (!bytecodeCanTruncateInteger(m_node->arithNodeFlags())) {
990                 if (bytecodeCanIgnoreNegativeZero(m_node->arithNodeFlags())) {
991                     // We don't have a negate-with-overflow intrinsic. Hopefully this
992                     // does the trick, though.
993                     LValue overflowResult = m_out.subWithOverflow32(m_out.int32Zero, value);
994                     speculate(Overflow, noValue(), 0, m_out.extractValue(overflowResult, 1));
995                 } else
996                     speculate(Overflow, noValue(), 0, m_out.testIsZero32(value, m_out.constInt32(0x7fffffff)));
997
998             }
999
1000             setInt32(result);
1001             break;
1002         }
1003             
1004         case MachineIntUse: {
1005             if (!m_state.forNode(m_node->child1()).couldBeType(SpecInt52)) {
1006                 Int52Kind kind;
1007                 LValue value = lowWhicheverInt52(m_node->child1(), kind);
1008                 LValue result = m_out.neg(value);
1009                 if (!bytecodeCanIgnoreNegativeZero(m_node->arithNodeFlags()))
1010                     speculate(NegativeZero, noValue(), 0, m_out.isZero64(result));
1011                 setInt52(result, kind);
1012                 break;
1013             }
1014             
1015             LValue value = lowInt52(m_node->child1());
1016             LValue overflowResult = m_out.subWithOverflow64(m_out.int64Zero, value);
1017             speculate(Int52Overflow, noValue(), 0, m_out.extractValue(overflowResult, 1));
1018             LValue result = m_out.neg(value);
1019             speculate(NegativeZero, noValue(), 0, m_out.isZero64(result));
1020             setInt52(result);
1021             break;
1022         }
1023             
1024         case NumberUse: {
1025             setDouble(m_out.doubleNeg(lowDouble(m_node->child1())));
1026             break;
1027         }
1028             
1029         default:
1030             RELEASE_ASSERT_NOT_REACHED();
1031             break;
1032         }
1033     }
1034     
1035     void compileBitAnd()
1036     {
1037         setInt32(m_out.bitAnd(lowInt32(m_node->child1()), lowInt32(m_node->child2())));
1038     }
1039     
1040     void compileBitOr()
1041     {
1042         setInt32(m_out.bitOr(lowInt32(m_node->child1()), lowInt32(m_node->child2())));
1043     }
1044     
1045     void compileBitXor()
1046     {
1047         setInt32(m_out.bitXor(lowInt32(m_node->child1()), lowInt32(m_node->child2())));
1048     }
1049     
1050     void compileBitRShift()
1051     {
1052         setInt32(m_out.aShr(
1053             lowInt32(m_node->child1()),
1054             m_out.bitAnd(lowInt32(m_node->child2()), m_out.constInt32(31))));
1055     }
1056     
1057     void compileBitLShift()
1058     {
1059         setInt32(m_out.shl(
1060             lowInt32(m_node->child1()),
1061             m_out.bitAnd(lowInt32(m_node->child2()), m_out.constInt32(31))));
1062     }
1063     
1064     void compileBitURShift()
1065     {
1066         setInt32(m_out.lShr(
1067             lowInt32(m_node->child1()),
1068             m_out.bitAnd(lowInt32(m_node->child2()), m_out.constInt32(31))));
1069     }
1070     
1071     void compileUInt32ToNumber()
1072     {
1073         LValue value = lowInt32(m_node->child1());
1074
1075         if (!nodeCanSpeculateInt32(m_node->arithNodeFlags())) {
1076             setDouble(m_out.unsignedToDouble(value));
1077             return;
1078         }
1079         
1080         speculateForward(
1081             Overflow, noValue(), 0, m_out.lessThan(value, m_out.int32Zero),
1082             FormattedValue(ValueFormatUInt32, value));
1083         setInt32(value);
1084     }
1085     
1086     void compileInt32ToDouble()
1087     {
1088         if (!m_interpreter.needsTypeCheck(m_node->child1(), SpecFullNumber)
1089             || m_node->speculationDirection() == BackwardSpeculation) {
1090             setDouble(lowDouble(m_node->child1()));
1091             return;
1092         }
1093         
1094         LValue boxedValue = lowJSValue(m_node->child1(), ManualOperandSpeculation);
1095         
1096         LBasicBlock intCase = FTL_NEW_BLOCK(m_out, ("Double unboxing int case"));
1097         LBasicBlock doubleCase = FTL_NEW_BLOCK(m_out, ("Double unboxing double case"));
1098         LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("Double unboxing continuation"));
1099         
1100         m_out.branch(isNotInt32(boxedValue), doubleCase, intCase);
1101         
1102         LBasicBlock lastNext = m_out.appendTo(intCase, doubleCase);
1103         
1104         ValueFromBlock intToDouble = m_out.anchor(
1105             m_out.intToDouble(unboxInt32(boxedValue)));
1106         m_out.jump(continuation);
1107         
1108         m_out.appendTo(doubleCase, continuation);
1109
1110         forwardTypeCheck(
1111             jsValueValue(boxedValue), m_node->child1(), SpecFullNumber,
1112             isCellOrMisc(boxedValue), jsValueValue(boxedValue));
1113         
1114         ValueFromBlock unboxedDouble = m_out.anchor(unboxDouble(boxedValue));
1115         m_out.jump(continuation);
1116         
1117         m_out.appendTo(continuation, lastNext);
1118         
1119         LValue result = m_out.phi(m_out.doubleType, intToDouble, unboxedDouble);
1120         
1121         setDouble(result);
1122     }
1123     
1124     void compileCheckStructure()
1125     {
1126         LValue cell = lowCell(m_node->child1());
1127         
1128         ExitKind exitKind;
1129         if (m_node->child1()->op() == WeakJSConstant)
1130             exitKind = BadWeakConstantCache;
1131         else
1132             exitKind = BadCache;
1133         
1134         LValue structure = m_out.loadPtr(cell, m_heaps.JSCell_structure);
1135         
1136         if (m_node->structureSet().size() == 1) {
1137             speculate(
1138                 exitKind, jsValueValue(cell), 0,
1139                 m_out.notEqual(structure, weakPointer(m_node->structureSet()[0])));
1140             return;
1141         }
1142         
1143         LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("CheckStructure continuation"));
1144         
1145         LBasicBlock lastNext = m_out.insertNewBlocksBefore(continuation);
1146         for (unsigned i = 0; i < m_node->structureSet().size() - 1; ++i) {
1147             LBasicBlock nextStructure = FTL_NEW_BLOCK(m_out, ("CheckStructure nextStructure"));
1148             m_out.branch(
1149                 m_out.equal(structure, weakPointer(m_node->structureSet()[i])),
1150                 continuation, nextStructure);
1151             m_out.appendTo(nextStructure);
1152         }
1153         
1154         speculate(
1155             exitKind, jsValueValue(cell), 0,
1156             m_out.notEqual(structure, weakPointer(m_node->structureSet().last())));
1157         
1158         m_out.jump(continuation);
1159         m_out.appendTo(continuation, lastNext);
1160     }
1161     
1162     void compileStructureTransitionWatchpoint()
1163     {
1164         addWeakReference(m_node->structure());
1165         speculateCell(m_node->child1());
1166     }
1167     
1168     void compileArrayifyToStructure()
1169     {
1170         LValue cell = lowCell(m_node->child1());
1171         LValue property = !!m_node->child2() ? lowInt32(m_node->child2()) : 0;
1172         
1173         LBasicBlock unexpectedStructure = FTL_NEW_BLOCK(m_out, ("ArrayifyToStructure unexpected structure"));
1174         LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("ArrayifyToStructure continuation"));
1175         
1176         LValue structure = m_out.loadPtr(cell, m_heaps.JSCell_structure);
1177         
1178         m_out.branch(
1179             m_out.notEqual(structure, weakPointer(m_node->structure())),
1180             unexpectedStructure, continuation);
1181         
1182         LBasicBlock lastNext = m_out.appendTo(unexpectedStructure, continuation);
1183         
1184         if (property) {
1185             switch (m_node->arrayMode().type()) {
1186             case Array::Int32:
1187             case Array::Double:
1188             case Array::Contiguous:
1189                 speculate(
1190                     Uncountable, noValue(), 0,
1191                     m_out.aboveOrEqual(property, m_out.constInt32(MIN_SPARSE_ARRAY_INDEX)));
1192                 break;
1193             default:
1194                 break;
1195             }
1196         }
1197         
1198         switch (m_node->arrayMode().type()) {
1199         case Array::Int32:
1200             vmCall(m_out.operation(operationEnsureInt32), m_callFrame, cell);
1201             break;
1202         case Array::Double:
1203             vmCall(m_out.operation(operationEnsureDouble), m_callFrame, cell);
1204             break;
1205         case Array::Contiguous:
1206             if (m_node->arrayMode().conversion() == Array::RageConvert)
1207                 vmCall(m_out.operation(operationRageEnsureContiguous), m_callFrame, cell);
1208             else
1209                 vmCall(m_out.operation(operationEnsureContiguous), m_callFrame, cell);
1210             break;
1211         case Array::ArrayStorage:
1212         case Array::SlowPutArrayStorage:
1213             vmCall(m_out.operation(operationEnsureArrayStorage), m_callFrame, cell);
1214             break;
1215         default:
1216             RELEASE_ASSERT_NOT_REACHED();
1217             break;
1218         }
1219         
1220         structure = m_out.loadPtr(cell, m_heaps.JSCell_structure);
1221         speculate(
1222             BadIndexingType, jsValueValue(cell), 0,
1223             m_out.notEqual(structure, weakPointer(m_node->structure())));
1224         m_out.jump(continuation);
1225         
1226         m_out.appendTo(continuation, lastNext);
1227     }
1228     
1229     void compilePutStructure()
1230     {
1231         m_ftlState.jitCode->common.notifyCompilingStructureTransition(m_graph.m_plan, codeBlock(), m_node);
1232         
1233         m_out.store64(
1234             m_out.constIntPtr(m_node->structureTransitionData().newStructure),
1235             lowCell(m_node->child1()), m_heaps.JSCell_structure);
1236     }
1237     
1238     void compilePhantomPutStructure()
1239     {
1240         m_ftlState.jitCode->common.notifyCompilingStructureTransition(m_graph.m_plan, codeBlock(), m_node);
1241     }
1242     
1243     void compileGetById()
1244     {
1245         // UntypedUse is a bit harder to reason about and I'm not sure how best to do it, yet.
1246         // Basically we need to emit a cell branch that takes you to the slow path, but the slow
1247         // path is generated by the IC generator so we can't jump to it from here. And the IC
1248         // generator currently doesn't know how to emit such a branch. So, for now, we just
1249         // restrict this to CellUse.
1250         ASSERT(m_node->child1().useKind() == CellUse);
1251
1252         LValue base = lowCell(m_node->child1());
1253         StringImpl* uid = m_graph.identifiers()[m_node->identifierNumber()];
1254
1255         // Arguments: id, bytes, target, numArgs, args...
1256         unsigned stackmapID = m_stackmapIDs++;
1257         setJSValue(m_out.call(
1258             m_out.patchpointInt64Intrinsic(),
1259             m_out.constInt32(stackmapID), m_out.constInt32(sizeOfGetById()),
1260             constNull(m_out.ref8), m_out.constInt32(2), m_callFrame, base));
1261         
1262         m_ftlState.getByIds.append(GetByIdDescriptor(stackmapID, m_node->codeOrigin, uid));
1263     }
1264     
1265     void compilePutById()
1266     {
1267         // See above; CellUse is easier so we do only that for now.
1268         ASSERT(m_node->child1().useKind() == CellUse);
1269
1270         LValue base = lowCell(m_node->child1());
1271         LValue value = lowJSValue(m_node->child2());
1272         StringImpl* uid = m_graph.identifiers()[m_node->identifierNumber()];
1273
1274         // Arguments: id, bytes, target, numArgs, args...
1275         unsigned stackmapID = m_stackmapIDs++;
1276         m_out.call(
1277             m_out.patchpointVoidIntrinsic(),
1278             m_out.constInt32(stackmapID), m_out.constInt32(sizeOfPutById()),
1279             constNull(m_out.ref8), m_out.constInt32(3), m_callFrame, base, value);
1280         
1281         m_ftlState.putByIds.append(PutByIdDescriptor(
1282             stackmapID, m_node->codeOrigin, uid,
1283             m_graph.executableFor(m_node->codeOrigin)->ecmaMode(),
1284             m_node->op() == PutByIdDirect ? Direct : NotDirect));
1285     }
1286     
1287     void compileGetButterfly()
1288     {
1289         setStorage(m_out.loadPtr(lowCell(m_node->child1()), m_heaps.JSObject_butterfly));
1290     }
1291     
1292     void compileGetIndexedPropertyStorage()
1293     {
1294         setStorage(m_out.loadPtr(lowCell(m_node->child1()), m_heaps.JSArrayBufferView_vector));
1295     }
1296     
1297     void compileCheckArray()
1298     {
1299         Edge edge = m_node->child1();
1300         LValue cell = lowCell(edge);
1301         
1302         if (m_node->arrayMode().alreadyChecked(m_graph, m_node, m_state.forNode(edge)))
1303             return;
1304         
1305         speculate(
1306             BadIndexingType, jsValueValue(cell), 0,
1307             m_out.bitNot(isArrayType(cell, m_node->arrayMode())));
1308     }
1309     
1310     void compileGetArrayLength()
1311     {
1312         switch (m_node->arrayMode().type()) {
1313         case Array::Int32:
1314         case Array::Double:
1315         case Array::Contiguous: {
1316             setInt32(m_out.load32(lowStorage(m_node->child2()), m_heaps.Butterfly_publicLength));
1317             return;
1318         }
1319             
1320         default:
1321             if (isTypedView(m_node->arrayMode().typedArrayType())) {
1322                 setInt32(
1323                     m_out.load32(lowCell(m_node->child1()), m_heaps.JSArrayBufferView_length));
1324                 return;
1325             }
1326             
1327             RELEASE_ASSERT_NOT_REACHED();
1328             return;
1329         }
1330     }
1331     
1332     void compileGetByVal()
1333     {
1334         LValue index = lowInt32(m_node->child2());
1335         LValue storage = lowStorage(m_node->child3());
1336         
1337         switch (m_node->arrayMode().type()) {
1338         case Array::Int32:
1339         case Array::Contiguous: {
1340             if (m_node->arrayMode().isInBounds()) {
1341                 speculate(
1342                     OutOfBounds, noValue(), 0,
1343                     m_out.aboveOrEqual(
1344                         index, m_out.load32(storage, m_heaps.Butterfly_publicLength)));
1345                 
1346                 LValue result = m_out.load64(m_out.baseIndex(
1347                     m_node->arrayMode().type() == Array::Int32 ?
1348                         m_heaps.indexedInt32Properties : m_heaps.indexedContiguousProperties,
1349                     storage, m_out.zeroExt(index, m_out.intPtr),
1350                     m_state.forNode(m_node->child2()).m_value));
1351                 speculate(LoadFromHole, noValue(), 0, m_out.isZero64(result));
1352                 setJSValue(result);
1353                 return;
1354             }
1355             
1356             // FIXME: Implement hole/OOB loads in the FTL.
1357             // https://bugs.webkit.org/show_bug.cgi?id=118077
1358             RELEASE_ASSERT_NOT_REACHED();
1359             return;
1360         }
1361             
1362         case Array::Double: {
1363             if (m_node->arrayMode().isInBounds()) {
1364                 speculate(
1365                     OutOfBounds, noValue(), 0,
1366                     m_out.aboveOrEqual(
1367                         index, m_out.load32(storage, m_heaps.Butterfly_publicLength)));
1368                 
1369                 LValue result = m_out.loadDouble(m_out.baseIndex(
1370                     m_heaps.indexedDoubleProperties,
1371                     storage, m_out.zeroExt(index, m_out.intPtr),
1372                     m_state.forNode(m_node->child2()).m_value));
1373                 
1374                 if (!m_node->arrayMode().isSaneChain()) {
1375                     speculate(
1376                         LoadFromHole, noValue(), 0,
1377                         m_out.doubleNotEqualOrUnordered(result, result));
1378                 }
1379                 setDouble(result);
1380                 break;
1381             }
1382             
1383             // FIXME: Implement hole/OOB loads in the FTL.
1384             // https://bugs.webkit.org/show_bug.cgi?id=118077
1385             RELEASE_ASSERT_NOT_REACHED();
1386             return;
1387         }
1388             
1389         default: {
1390             TypedArrayType type = m_node->arrayMode().typedArrayType();
1391             
1392             if (isTypedView(type)) {
1393                 LValue array = lowCell(m_node->child1());
1394                 
1395                 speculate(
1396                     OutOfBounds, noValue(), 0,
1397                     m_out.aboveOrEqual(
1398                         index, m_out.load32(array, m_heaps.JSArrayBufferView_length)));
1399                 
1400                 TypedPointer pointer = TypedPointer(
1401                     m_heaps.typedArrayProperties,
1402                     m_out.add(
1403                         storage,
1404                         m_out.shl(
1405                             m_out.zeroExt(index, m_out.intPtr),
1406                             m_out.constIntPtr(logElementSize(type)))));
1407                 
1408                 if (isInt(type)) {
1409                     LValue result;
1410                     switch (elementSize(type)) {
1411                     case 1:
1412                         result = m_out.load8(pointer);
1413                         break;
1414                     case 2:
1415                         result = m_out.load16(pointer);
1416                         break;
1417                     case 4:
1418                         result = m_out.load32(pointer);
1419                         break;
1420                     default:
1421                         RELEASE_ASSERT_NOT_REACHED();
1422                     }
1423                     
1424                     if (elementSize(type) < 4) {
1425                         if (isSigned(type))
1426                             result = m_out.signExt(result, m_out.int32);
1427                         else
1428                             result = m_out.zeroExt(result, m_out.int32);
1429                         setInt32(result);
1430                         return;
1431                     }
1432                     
1433                     if (isSigned(type)) {
1434                         setInt32(result);
1435                         return;
1436                     }
1437                     
1438                     if (m_node->shouldSpeculateInt32()) {
1439                         speculateForward(
1440                             Overflow, noValue(), 0, m_out.lessThan(result, m_out.int32Zero),
1441                             uInt32Value(result));
1442                         setInt32(result);
1443                         return;
1444                     }
1445                     
1446                     setDouble(m_out.unsignedToFP(result, m_out.doubleType));
1447                     return;
1448                 }
1449             
1450                 ASSERT(isFloat(type));
1451                 
1452                 LValue result;
1453                 switch (type) {
1454                 case TypeFloat32:
1455                     result = m_out.fpCast(m_out.loadFloat(pointer), m_out.doubleType);
1456                     break;
1457                 case TypeFloat64:
1458                     result = m_out.loadDouble(pointer);
1459                     break;
1460                 default:
1461                     RELEASE_ASSERT_NOT_REACHED();
1462                 }
1463                 
1464                 result = m_out.select(
1465                     m_out.doubleEqual(result, result), result, m_out.constDouble(QNaN));
1466                 setDouble(result);
1467                 return;
1468             }
1469             
1470             RELEASE_ASSERT_NOT_REACHED();
1471             return;
1472         } }
1473     }
1474     
1475     void compilePutByVal()
1476     {
1477         Edge child1 = m_graph.varArgChild(m_node, 0);
1478         Edge child2 = m_graph.varArgChild(m_node, 1);
1479         Edge child3 = m_graph.varArgChild(m_node, 2);
1480         Edge child4 = m_graph.varArgChild(m_node, 3);
1481
1482         LValue base = lowCell(child1);
1483         LValue index = lowInt32(child2);
1484         LValue storage = lowStorage(child4);
1485         
1486         switch (m_node->arrayMode().type()) {
1487         case Array::Int32:
1488         case Array::Double:
1489         case Array::Contiguous: {
1490             LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("PutByVal continuation"));
1491             LBasicBlock outerLastNext = m_out.appendTo(m_out.m_block, continuation);
1492             
1493             switch (m_node->arrayMode().type()) {
1494             case Array::Int32:
1495             case Array::Contiguous: {
1496                 LValue value = lowJSValue(child3, ManualOperandSpeculation);
1497                 
1498                 if (m_node->arrayMode().type() == Array::Int32)
1499                     FTL_TYPE_CHECK(jsValueValue(value), child3, SpecInt32, isNotInt32(value));
1500                 
1501                 TypedPointer elementPointer = m_out.baseIndex(
1502                     m_node->arrayMode().type() == Array::Int32 ?
1503                     m_heaps.indexedInt32Properties : m_heaps.indexedContiguousProperties,
1504                     storage, m_out.zeroExt(index, m_out.intPtr),
1505                     m_state.forNode(child2).m_value);
1506                 
1507                 if (m_node->op() == PutByValAlias) {
1508                     m_out.store64(value, elementPointer);
1509                     break;
1510                 }
1511                 
1512                 contiguousPutByValOutOfBounds(
1513                     codeBlock()->isStrictMode()
1514                     ? operationPutByValBeyondArrayBoundsStrict
1515                     : operationPutByValBeyondArrayBoundsNonStrict,
1516                     base, storage, index, value, continuation);
1517                 
1518                 m_out.store64(value, elementPointer);
1519                 break;
1520             }
1521                 
1522             case Array::Double: {
1523                 LValue value = lowDouble(child3);
1524                 
1525                 FTL_TYPE_CHECK(
1526                     doubleValue(value), child3, SpecFullRealNumber,
1527                     m_out.doubleNotEqualOrUnordered(value, value));
1528                 
1529                 TypedPointer elementPointer = m_out.baseIndex(
1530                     m_heaps.indexedDoubleProperties,
1531                     storage, m_out.zeroExt(index, m_out.intPtr),
1532                     m_state.forNode(child2).m_value);
1533                 
1534                 if (m_node->op() == PutByValAlias) {
1535                     m_out.storeDouble(value, elementPointer);
1536                     break;
1537                 }
1538                 
1539                 contiguousPutByValOutOfBounds(
1540                     codeBlock()->isStrictMode()
1541                     ? operationPutDoubleByValBeyondArrayBoundsStrict
1542                     : operationPutDoubleByValBeyondArrayBoundsNonStrict,
1543                     base, storage, index, value, continuation);
1544                 
1545                 m_out.storeDouble(value, elementPointer);
1546                 break;
1547             }
1548                 
1549             default:
1550                 RELEASE_ASSERT_NOT_REACHED();
1551             }
1552
1553             m_out.jump(continuation);
1554             m_out.appendTo(continuation, outerLastNext);
1555             return;
1556         }
1557             
1558         default:
1559             TypedArrayType type = m_node->arrayMode().typedArrayType();
1560             
1561             if (isTypedView(type)) {
1562                 if (m_node->op() == PutByVal) {
1563                     speculate(
1564                         OutOfBounds, noValue(), 0,
1565                         m_out.aboveOrEqual(
1566                             index, m_out.load32(base, m_heaps.JSArrayBufferView_length)));
1567                 }
1568                 
1569                 TypedPointer pointer = TypedPointer(
1570                     m_heaps.typedArrayProperties,
1571                     m_out.add(
1572                         storage,
1573                         m_out.shl(
1574                             m_out.zeroExt(index, m_out.intPtr),
1575                             m_out.constIntPtr(logElementSize(type)))));
1576                 
1577                 if (isInt(type)) {
1578                     LValue intValue;
1579                     switch (child3.useKind()) {
1580                     case MachineIntUse:
1581                     case Int32Use: {
1582                         if (child3.useKind() == Int32Use)
1583                             intValue = lowInt32(child3);
1584                         else
1585                             intValue = m_out.castToInt32(lowInt52(child3));
1586
1587                         if (isClamped(type)) {
1588                             ASSERT(elementSize(type) == 1);
1589                             
1590                             LBasicBlock atLeastZero = FTL_NEW_BLOCK(m_out, ("PutByVal int clamp atLeastZero"));
1591                             LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("PutByVal int clamp continuation"));
1592                             
1593                             Vector<ValueFromBlock, 2> intValues;
1594                             intValues.append(m_out.anchor(m_out.int32Zero));
1595                             m_out.branch(
1596                                 m_out.lessThan(intValue, m_out.int32Zero),
1597                                 continuation, atLeastZero);
1598                             
1599                             LBasicBlock lastNext = m_out.appendTo(atLeastZero, continuation);
1600                             
1601                             intValues.append(m_out.anchor(m_out.select(
1602                                 m_out.greaterThan(intValue, m_out.constInt32(255)),
1603                                 m_out.constInt32(255),
1604                                 intValue)));
1605                             m_out.jump(continuation);
1606                             
1607                             m_out.appendTo(continuation, lastNext);
1608                             intValue = m_out.phi(m_out.int32, intValues);
1609                         }
1610                         break;
1611                     }
1612                         
1613                     case NumberUse: {
1614                         LValue doubleValue = lowDouble(child3);
1615                         
1616                         if (isClamped(type)) {
1617                             ASSERT(elementSize(type) == 1);
1618                             
1619                             LBasicBlock atLeastZero = FTL_NEW_BLOCK(m_out, ("PutByVal double clamp atLeastZero"));
1620                             LBasicBlock withinRange = FTL_NEW_BLOCK(m_out, ("PutByVal double clamp withinRange"));
1621                             LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("PutByVal double clamp continuation"));
1622                             
1623                             Vector<ValueFromBlock, 3> intValues;
1624                             intValues.append(m_out.anchor(m_out.int32Zero));
1625                             m_out.branch(
1626                                 m_out.doubleLessThanOrUnordered(doubleValue, m_out.doubleZero),
1627                                 continuation, atLeastZero);
1628                             
1629                             LBasicBlock lastNext = m_out.appendTo(atLeastZero, withinRange);
1630                             intValues.append(m_out.anchor(m_out.constInt32(255)));
1631                             m_out.branch(
1632                                 m_out.doubleGreaterThan(doubleValue, m_out.constDouble(255)),
1633                                 continuation, withinRange);
1634                             
1635                             m_out.appendTo(withinRange, continuation);
1636                             intValues.append(m_out.anchor(m_out.fpToInt32(doubleValue)));
1637                             m_out.jump(continuation);
1638                             
1639                             m_out.appendTo(continuation, lastNext);
1640                             intValue = m_out.phi(m_out.int32, intValues);
1641                         } else if (isSigned(type))
1642                             intValue = doubleToInt32(doubleValue);
1643                         else
1644                             intValue = doubleToUInt32(doubleValue);
1645                         break;
1646                     }
1647                         
1648                     default:
1649                         RELEASE_ASSERT_NOT_REACHED();
1650                     }
1651                     
1652                     switch (elementSize(type)) {
1653                     case 1:
1654                         m_out.store8(m_out.intCast(intValue, m_out.int8), pointer);
1655                         break;
1656                     case 2:
1657                         m_out.store16(m_out.intCast(intValue, m_out.int16), pointer);
1658                         break;
1659                     case 4:
1660                         m_out.store32(intValue, pointer);
1661                         break;
1662                     default:
1663                         RELEASE_ASSERT_NOT_REACHED();
1664                     }
1665                     
1666                     return;
1667                 }
1668                 
1669                 ASSERT(isFloat(type));
1670                 
1671                 LValue value = lowDouble(child3);
1672                 switch (type) {
1673                 case TypeFloat32:
1674                     m_out.storeFloat(m_out.fpCast(value, m_out.floatType), pointer);
1675                     break;
1676                 case TypeFloat64:
1677                     m_out.storeDouble(value, pointer);
1678                     break;
1679                 default:
1680                     RELEASE_ASSERT_NOT_REACHED();
1681                 }
1682                 return;
1683             }
1684             
1685             RELEASE_ASSERT_NOT_REACHED();
1686             break;
1687         }
1688     }
1689     
1690     void compileGetByOffset()
1691     {
1692         StorageAccessData& data =
1693             m_graph.m_storageAccessData[m_node->storageAccessDataIndex()];
1694         
1695         setJSValue(
1696             m_out.load64(
1697                 m_out.address(
1698                     m_heaps.properties[data.identifierNumber],
1699                     lowStorage(m_node->child1()),
1700                     offsetRelativeToBase(data.offset))));
1701     }
1702     
1703     void compilePutByOffset()
1704     {
1705         StorageAccessData& data =
1706             m_graph.m_storageAccessData[m_node->storageAccessDataIndex()];
1707         
1708         m_out.store64(
1709             lowJSValue(m_node->child3()),
1710             m_out.address(
1711                 m_heaps.properties[data.identifierNumber],
1712                 lowStorage(m_node->child1()),
1713                 offsetRelativeToBase(data.offset)));
1714     }
1715     
1716     void compileGetGlobalVar()
1717     {
1718         setJSValue(m_out.load64(m_out.absolute(m_node->registerPointer())));
1719     }
1720     
1721     void compilePutGlobalVar()
1722     {
1723         m_out.store64(
1724             lowJSValue(m_node->child1()), m_out.absolute(m_node->registerPointer()));
1725     }
1726     
1727     void compileGlobalVarWatchpoint()
1728     {
1729         // FIXME: In debug mode we could emit some assertion code here.
1730         // https://bugs.webkit.org/show_bug.cgi?id=123471
1731     }
1732     
1733     void compileGetMyScope()
1734     {
1735         setJSValue(m_out.loadPtr(addressFor(
1736             m_node->codeOrigin.stackOffset() + JSStack::ScopeChain)));
1737     }
1738     
1739     void compileSkipScope()
1740     {
1741         setJSValue(m_out.loadPtr(lowCell(m_node->child1()), m_heaps.JSScope_next));
1742     }
1743     
1744     void compileGetClosureRegisters()
1745     {
1746         setStorage(m_out.loadPtr(
1747             lowCell(m_node->child1()), m_heaps.JSVariableObject_registers));
1748     }
1749     
1750     void compileGetClosureVar()
1751     {
1752         setJSValue(m_out.load64(
1753             addressFor(lowStorage(m_node->child1()), m_node->varNumber())));
1754     }
1755     
1756     void compilePutClosureVar()
1757     {
1758         m_out.store64(
1759             lowJSValue(m_node->child3()),
1760             addressFor(lowStorage(m_node->child2()), m_node->varNumber()));
1761     }
1762     
1763     void compileCompareEq()
1764     {
1765         if (m_node->isBinaryUseKind(Int32Use)
1766             || m_node->isBinaryUseKind(MachineIntUse)
1767             || m_node->isBinaryUseKind(NumberUse)
1768             || m_node->isBinaryUseKind(ObjectUse)) {
1769             compileCompareStrictEq();
1770             return;
1771         }
1772         
1773         RELEASE_ASSERT_NOT_REACHED();
1774     }
1775     
1776     void compileCompareEqConstant()
1777     {
1778         ASSERT(m_graph.valueOfJSConstant(m_node->child2().node()).isNull());
1779         setBoolean(
1780             equalNullOrUndefined(
1781                 m_node->child1(), AllCellsAreFalse, EqualNullOrUndefined));
1782     }
1783     
1784     void compileCompareStrictEq()
1785     {
1786         if (m_node->isBinaryUseKind(Int32Use)) {
1787             setBoolean(
1788                 m_out.equal(lowInt32(m_node->child1()), lowInt32(m_node->child2())));
1789             return;
1790         }
1791         
1792         if (m_node->isBinaryUseKind(MachineIntUse)) {
1793             Int52Kind kind;
1794             LValue left = lowWhicheverInt52(m_node->child1(), kind);
1795             LValue right = lowInt52(m_node->child2(), kind);
1796             setBoolean(m_out.equal(left, right));
1797             return;
1798         }
1799         
1800         if (m_node->isBinaryUseKind(NumberUse)) {
1801             setBoolean(
1802                 m_out.doubleEqual(lowDouble(m_node->child1()), lowDouble(m_node->child2())));
1803             return;
1804         }
1805         
1806         if (m_node->isBinaryUseKind(ObjectUse)) {
1807             setBoolean(
1808                 m_out.equal(
1809                     lowNonNullObject(m_node->child1()),
1810                     lowNonNullObject(m_node->child2())));
1811             return;
1812         }
1813         
1814         RELEASE_ASSERT_NOT_REACHED();
1815     }
1816     
1817     void compileCompareStrictEqConstant()
1818     {
1819         JSValue constant = m_graph.valueOfJSConstant(m_node->child2().node());
1820
1821         if (constant.isUndefinedOrNull()
1822             && !masqueradesAsUndefinedWatchpointIsStillValid()) {
1823             if (constant.isNull()) {
1824                 setBoolean(equalNullOrUndefined(m_node->child1(), AllCellsAreFalse, EqualNull));
1825                 return;
1826             }
1827         
1828             ASSERT(constant.isUndefined());
1829             setBoolean(equalNullOrUndefined(m_node->child1(), AllCellsAreFalse, EqualUndefined));
1830             return;
1831         }
1832         
1833         setBoolean(
1834             m_out.equal(
1835                 lowJSValue(m_node->child1()),
1836                 m_out.constInt64(JSValue::encode(constant))));
1837     }
1838     
1839     void compileCompareLess()
1840     {
1841         if (m_node->isBinaryUseKind(Int32Use)) {
1842             setBoolean(
1843                 m_out.lessThan(lowInt32(m_node->child1()), lowInt32(m_node->child2())));
1844             return;
1845         }
1846         
1847         if (m_node->isBinaryUseKind(MachineIntUse)) {
1848             Int52Kind kind;
1849             LValue left = lowWhicheverInt52(m_node->child1(), kind);
1850             LValue right = lowInt52(m_node->child2(), kind);
1851             setBoolean(m_out.lessThan(left, right));
1852             return;
1853         }
1854         
1855         if (m_node->isBinaryUseKind(NumberUse)) {
1856             setBoolean(
1857                 m_out.doubleLessThan(lowDouble(m_node->child1()), lowDouble(m_node->child2())));
1858             return;
1859         }
1860         
1861         RELEASE_ASSERT_NOT_REACHED();
1862     }
1863     
1864     void compileCompareLessEq()
1865     {
1866         if (m_node->isBinaryUseKind(Int32Use)) {
1867             setBoolean(
1868                 m_out.lessThanOrEqual(lowInt32(m_node->child1()), lowInt32(m_node->child2())));
1869             return;
1870         }
1871         
1872         if (m_node->isBinaryUseKind(MachineIntUse)) {
1873             Int52Kind kind;
1874             LValue left = lowWhicheverInt52(m_node->child1(), kind);
1875             LValue right = lowInt52(m_node->child2(), kind);
1876             setBoolean(m_out.lessThanOrEqual(left, right));
1877             return;
1878         }
1879         
1880         if (m_node->isBinaryUseKind(NumberUse)) {
1881             setBoolean(
1882                 m_out.doubleLessThanOrEqual(
1883                     lowDouble(m_node->child1()), lowDouble(m_node->child2())));
1884             return;
1885         }
1886         
1887         RELEASE_ASSERT_NOT_REACHED();
1888     }
1889     
1890     void compileCompareGreater()
1891     {
1892         if (m_node->isBinaryUseKind(Int32Use)) {
1893             setBoolean(
1894                 m_out.greaterThan(lowInt32(m_node->child1()), lowInt32(m_node->child2())));
1895             return;
1896         }
1897         
1898         if (m_node->isBinaryUseKind(MachineIntUse)) {
1899             Int52Kind kind;
1900             LValue left = lowWhicheverInt52(m_node->child1(), kind);
1901             LValue right = lowInt52(m_node->child2(), kind);
1902             setBoolean(m_out.greaterThan(left, right));
1903             return;
1904         }
1905         
1906         if (m_node->isBinaryUseKind(NumberUse)) {
1907             setBoolean(
1908                 m_out.doubleGreaterThan(
1909                     lowDouble(m_node->child1()), lowDouble(m_node->child2())));
1910             return;
1911         }
1912         
1913         RELEASE_ASSERT_NOT_REACHED();
1914     }
1915     
1916     void compileCompareGreaterEq()
1917     {
1918         if (m_node->isBinaryUseKind(Int32Use)) {
1919             setBoolean(
1920                 m_out.greaterThanOrEqual(
1921                     lowInt32(m_node->child1()), lowInt32(m_node->child2())));
1922             return;
1923         }
1924         
1925         if (m_node->isBinaryUseKind(MachineIntUse)) {
1926             Int52Kind kind;
1927             LValue left = lowWhicheverInt52(m_node->child1(), kind);
1928             LValue right = lowInt52(m_node->child2(), kind);
1929             setBoolean(m_out.greaterThanOrEqual(left, right));
1930             return;
1931         }
1932         
1933         if (m_node->isBinaryUseKind(NumberUse)) {
1934             setBoolean(
1935                 m_out.doubleGreaterThanOrEqual(
1936                     lowDouble(m_node->child1()), lowDouble(m_node->child2())));
1937             return;
1938         }
1939         
1940         RELEASE_ASSERT_NOT_REACHED();
1941     }
1942     
1943     void compileLogicalNot()
1944     {
1945         setBoolean(m_out.bitNot(boolify(m_node->child1())));
1946     }
1947     
1948     void compileCallOrConstruct()
1949     {
1950         // FIXME: This is unacceptably slow.
1951         // https://bugs.webkit.org/show_bug.cgi?id=113621
1952         
1953         J_JITOperation_E function =
1954             m_node->op() == Call ? operationFTLCall : operationFTLConstruct;
1955         
1956         int dummyThisArgument = m_node->op() == Call ? 0 : 1;
1957         
1958         int numPassedArgs = m_node->numChildren() - 1;
1959         
1960         LValue calleeFrame = m_out.add(
1961             m_callFrame,
1962             m_out.constIntPtr(sizeof(Register) * virtualRegisterForLocal(codeBlock()->m_numCalleeRegisters).offset()));
1963         
1964         m_out.store32(
1965             m_out.constInt32(numPassedArgs + dummyThisArgument),
1966             payloadFor(calleeFrame, JSStack::ArgumentCount));
1967         m_out.store64(m_callFrame, calleeFrame, m_heaps.CallFrame_callerFrame);
1968         m_out.store64(
1969             lowJSValue(m_graph.varArgChild(m_node, 0)),
1970             addressFor(calleeFrame, JSStack::Callee));
1971         
1972         for (int i = 0; i < numPassedArgs; ++i) {
1973             m_out.store64(
1974                 lowJSValue(m_graph.varArgChild(m_node, 1 + i)),
1975                 addressFor(calleeFrame, virtualRegisterForArgument(i + dummyThisArgument).offset()));
1976         }
1977         
1978         setJSValue(vmCall(m_out.operation(function), calleeFrame));
1979     }
1980     
1981     void compileJump()
1982     {
1983         m_out.jump(lowBlock(m_node->takenBlock()));
1984     }
1985     
1986     void compileBranch()
1987     {
1988         m_out.branch(
1989             boolify(m_node->child1()),
1990             lowBlock(m_node->takenBlock()),
1991             lowBlock(m_node->notTakenBlock()));
1992     }
1993     
1994     void compileSwitch()
1995     {
1996         SwitchData* data = m_node->switchData();
1997         switch (data->kind) {
1998         case SwitchImm: {
1999             Vector<ValueFromBlock, 2> intValues;
2000             LBasicBlock switchOnInts = FTL_NEW_BLOCK(m_out, ("Switch/SwitchImm int case"));
2001             
2002             LBasicBlock lastNext = m_out.appendTo(m_out.m_block, switchOnInts);
2003             
2004             switch (m_node->child1().useKind()) {
2005             case Int32Use: {
2006                 intValues.append(m_out.anchor(lowInt32(m_node->child1())));
2007                 m_out.jump(switchOnInts);
2008                 break;
2009             }
2010                 
2011             case UntypedUse: {
2012                 LBasicBlock isInt = FTL_NEW_BLOCK(m_out, ("Switch/SwitchImm is int"));
2013                 LBasicBlock isNotInt = FTL_NEW_BLOCK(m_out, ("Switch/SwitchImm is not int"));
2014                 LBasicBlock isDouble = FTL_NEW_BLOCK(m_out, ("Switch/SwitchImm is double"));
2015                 
2016                 LValue boxedValue = lowJSValue(m_node->child1());
2017                 m_out.branch(isNotInt32(boxedValue), isNotInt, isInt);
2018                 
2019                 LBasicBlock innerLastNext = m_out.appendTo(isInt, isNotInt);
2020                 
2021                 intValues.append(m_out.anchor(unboxInt32(boxedValue)));
2022                 m_out.jump(switchOnInts);
2023                 
2024                 m_out.appendTo(isNotInt, isDouble);
2025                 m_out.branch(
2026                     isCellOrMisc(boxedValue), lowBlock(data->fallThrough), isDouble);
2027                 
2028                 m_out.appendTo(isDouble, innerLastNext);
2029                 LValue doubleValue = unboxDouble(boxedValue);
2030                 LValue intInDouble = m_out.fpToInt32(doubleValue);
2031                 intValues.append(m_out.anchor(intInDouble));
2032                 m_out.branch(
2033                     m_out.doubleEqual(m_out.intToDouble(intInDouble), doubleValue),
2034                     switchOnInts, lowBlock(data->fallThrough));
2035                 break;
2036             }
2037                 
2038             default:
2039                 RELEASE_ASSERT_NOT_REACHED();
2040                 break;
2041             }
2042             
2043             m_out.appendTo(switchOnInts, lastNext);
2044             buildSwitch(data, m_out.int32, m_out.phi(m_out.int32, intValues));
2045             return;
2046         }
2047         
2048         case SwitchChar: {
2049             LValue stringValue;
2050             
2051             switch (m_node->child1().useKind()) {
2052             case StringUse: {
2053                 stringValue = lowString(m_node->child1());
2054                 break;
2055             }
2056                 
2057             case UntypedUse: {
2058                 LValue unboxedValue = lowJSValue(m_node->child1());
2059                 
2060                 LBasicBlock isCellCase = FTL_NEW_BLOCK(m_out, ("Switch/SwitchChar is cell"));
2061                 LBasicBlock isStringCase = FTL_NEW_BLOCK(m_out, ("Switch/SwitchChar is string"));
2062                 
2063                 m_out.branch(
2064                     isNotCell(unboxedValue), lowBlock(data->fallThrough), isCellCase);
2065                 
2066                 LBasicBlock lastNext = m_out.appendTo(isCellCase, isStringCase);
2067                 LValue cellValue = unboxedValue;
2068                 m_out.branch(isNotString(cellValue), lowBlock(data->fallThrough), isStringCase);
2069                 
2070                 m_out.appendTo(isStringCase, lastNext);
2071                 stringValue = cellValue;
2072                 break;
2073             }
2074                 
2075             default:
2076                 RELEASE_ASSERT_NOT_REACHED();
2077                 break;
2078             }
2079             
2080             LBasicBlock lengthIs1 = FTL_NEW_BLOCK(m_out, ("Switch/SwitchChar length is 1"));
2081             LBasicBlock needResolution = FTL_NEW_BLOCK(m_out, ("Switch/SwitchChar resolution"));
2082             LBasicBlock resolved = FTL_NEW_BLOCK(m_out, ("Switch/SwitchChar resolved"));
2083             LBasicBlock is8Bit = FTL_NEW_BLOCK(m_out, ("Switch/SwitchChar 8bit"));
2084             LBasicBlock is16Bit = FTL_NEW_BLOCK(m_out, ("Switch/SwitchChar 16bit"));
2085             LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("Switch/SwitchChar continuation"));
2086             
2087             m_out.branch(
2088                 m_out.notEqual(
2089                     m_out.load32(stringValue, m_heaps.JSString_length),
2090                     m_out.int32One),
2091                 lowBlock(data->fallThrough), lengthIs1);
2092             
2093             LBasicBlock lastNext = m_out.appendTo(lengthIs1, needResolution);
2094             Vector<ValueFromBlock, 2> values;
2095             LValue fastValue = m_out.loadPtr(stringValue, m_heaps.JSString_value);
2096             values.append(m_out.anchor(fastValue));
2097             m_out.branch(m_out.isNull(fastValue), needResolution, resolved);
2098             
2099             m_out.appendTo(needResolution, resolved);
2100             values.append(m_out.anchor(
2101                 vmCall(m_out.operation(operationResolveRope), m_callFrame, stringValue)));
2102             m_out.jump(resolved);
2103             
2104             m_out.appendTo(resolved, is8Bit);
2105             LValue value = m_out.phi(m_out.intPtr, values);
2106             LValue characterData = m_out.loadPtr(value, m_heaps.StringImpl_data);
2107             m_out.branch(
2108                 m_out.testNonZero32(
2109                     m_out.load32(value, m_heaps.StringImpl_hashAndFlags),
2110                     m_out.constInt32(StringImpl::flagIs8Bit())),
2111                 is8Bit, is16Bit);
2112             
2113             Vector<ValueFromBlock, 2> characters;
2114             m_out.appendTo(is8Bit, is16Bit);
2115             characters.append(m_out.anchor(
2116                 m_out.zeroExt(m_out.load8(characterData, m_heaps.characters8[0]), m_out.int16)));
2117             m_out.jump(continuation);
2118             
2119             m_out.appendTo(is16Bit, continuation);
2120             characters.append(m_out.anchor(m_out.load16(characterData, m_heaps.characters16[0])));
2121             m_out.jump(continuation);
2122             
2123             m_out.appendTo(continuation, lastNext);
2124             buildSwitch(data, m_out.int16, m_out.phi(m_out.int16, characters));
2125             return;
2126         }
2127         
2128         case SwitchString:
2129             RELEASE_ASSERT_NOT_REACHED();
2130             break;
2131         }
2132         
2133         RELEASE_ASSERT_NOT_REACHED();
2134     }
2135     
2136     void compileReturn()
2137     {
2138         // FIXME: have a real epilogue when we switch to using our calling convention.
2139         // https://bugs.webkit.org/show_bug.cgi?id=113621
2140         m_out.ret(lowJSValue(m_node->child1()));
2141     }
2142     
2143     void compileForceOSRExit()
2144     {
2145         terminate(InadequateCoverage);
2146     }
2147     
2148     void compileInvalidationPoint()
2149     {
2150         if (verboseCompilationEnabled())
2151             dataLog("    Invalidation point with value sources: ", m_valueSources, "\n");
2152         
2153         m_ftlState.jitCode->osrExit.append(OSRExit(
2154             UncountableInvalidation, InvalidValueFormat, MethodOfGettingAValueProfile(),
2155             m_codeOriginForExitTarget, m_codeOriginForExitProfile, m_lastSetOperand.offset(),
2156             m_valueSources.numberOfArguments(), m_valueSources.numberOfLocals()));
2157         m_ftlState.finalizer->osrExit.append(OSRExitCompilationInfo());
2158         
2159         OSRExit& exit = m_ftlState.jitCode->osrExit.last();
2160         OSRExitCompilationInfo& info = m_ftlState.finalizer->osrExit.last();
2161         
2162         ExitArgumentList arguments;
2163         
2164         buildExitArguments(exit, arguments, FormattedValue());
2165         callStackmap(exit, arguments);
2166         
2167         info.m_isInvalidationPoint = true;
2168     }
2169     
2170     LValue boolify(Edge edge)
2171     {
2172         switch (edge.useKind()) {
2173         case BooleanUse:
2174             return lowBoolean(m_node->child1());
2175         case Int32Use:
2176             return m_out.notZero32(lowInt32(m_node->child1()));
2177         case NumberUse:
2178             return m_out.doubleNotEqual(lowDouble(edge), m_out.doubleZero);
2179         case ObjectOrOtherUse:
2180             return m_out.bitNot(
2181                 equalNullOrUndefined(
2182                     edge, CellCaseSpeculatesObject, SpeculateNullOrUndefined,
2183                     ManualOperandSpeculation));
2184         case StringUse: {
2185             LValue stringValue = lowString(m_node->child1());
2186             LValue length = m_out.load32(stringValue, m_heaps.JSString_length);
2187             return m_out.notEqual(length, m_out.int32Zero);
2188         }
2189         default:
2190             RELEASE_ASSERT_NOT_REACHED();
2191             return 0;
2192         }
2193     }
2194     
2195     enum StringOrObjectMode {
2196         AllCellsAreFalse,
2197         CellCaseSpeculatesObject
2198     };
2199     enum EqualNullOrUndefinedMode {
2200         EqualNull,
2201         EqualUndefined,
2202         EqualNullOrUndefined,
2203         SpeculateNullOrUndefined
2204     };
2205     LValue equalNullOrUndefined(
2206         Edge edge, StringOrObjectMode cellMode, EqualNullOrUndefinedMode primitiveMode,
2207         OperandSpeculationMode operandMode = AutomaticOperandSpeculation)
2208     {
2209         bool validWatchpoint = masqueradesAsUndefinedWatchpointIsStillValid();
2210         
2211         LValue value = lowJSValue(edge, operandMode);
2212         
2213         LBasicBlock cellCase = FTL_NEW_BLOCK(m_out, ("EqualNullOrUndefined cell case"));
2214         LBasicBlock primitiveCase = FTL_NEW_BLOCK(m_out, ("EqualNullOrUndefined primitive case"));
2215         LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("EqualNullOrUndefined continuation"));
2216         
2217         m_out.branch(isNotCell(value), primitiveCase, cellCase);
2218         
2219         LBasicBlock lastNext = m_out.appendTo(cellCase, primitiveCase);
2220         
2221         Vector<ValueFromBlock, 3> results;
2222         
2223         switch (cellMode) {
2224         case AllCellsAreFalse:
2225             break;
2226         case CellCaseSpeculatesObject:
2227             FTL_TYPE_CHECK(
2228                 jsValueValue(value), edge, (~SpecCell) | SpecObject,
2229                 m_out.equal(
2230                     m_out.loadPtr(value, m_heaps.JSCell_structure),
2231                     m_out.constIntPtr(vm().stringStructure.get())));
2232             break;
2233         }
2234         
2235         if (validWatchpoint) {
2236             results.append(m_out.anchor(m_out.booleanFalse));
2237             m_out.jump(continuation);
2238         } else {
2239             LBasicBlock masqueradesCase =
2240                 FTL_NEW_BLOCK(m_out, ("EqualNullOrUndefined masquerades case"));
2241                 
2242             LValue structure = m_out.loadPtr(value, m_heaps.JSCell_structure);
2243             
2244             results.append(m_out.anchor(m_out.booleanFalse));
2245             
2246             m_out.branch(
2247                 m_out.testNonZero8(
2248                     m_out.load8(structure, m_heaps.Structure_typeInfoFlags),
2249                     m_out.constInt8(MasqueradesAsUndefined)),
2250                 masqueradesCase, continuation);
2251             
2252             m_out.appendTo(masqueradesCase, primitiveCase);
2253             
2254             results.append(m_out.anchor(
2255                 m_out.equal(
2256                     m_out.constIntPtr(m_graph.globalObjectFor(m_node->codeOrigin)),
2257                     m_out.loadPtr(structure, m_heaps.Structure_globalObject))));
2258             m_out.jump(continuation);
2259         }
2260         
2261         m_out.appendTo(primitiveCase, continuation);
2262         
2263         LValue primitiveResult;
2264         switch (primitiveMode) {
2265         case EqualNull:
2266             primitiveResult = m_out.equal(value, m_out.constInt64(ValueNull));
2267             break;
2268         case EqualUndefined:
2269             primitiveResult = m_out.equal(value, m_out.constInt64(ValueUndefined));
2270             break;
2271         case EqualNullOrUndefined:
2272             primitiveResult = m_out.equal(
2273                 m_out.bitAnd(value, m_out.constInt64(~TagBitUndefined)),
2274                 m_out.constInt64(ValueNull));
2275             break;
2276         case SpeculateNullOrUndefined:
2277             FTL_TYPE_CHECK(
2278                 jsValueValue(value), edge, SpecCell | SpecOther,
2279                 m_out.notEqual(
2280                     m_out.bitAnd(value, m_out.constInt64(~TagBitUndefined)),
2281                     m_out.constInt64(ValueNull)));
2282             primitiveResult = m_out.booleanTrue;
2283             break;
2284         }
2285         results.append(m_out.anchor(primitiveResult));
2286         m_out.jump(continuation);
2287         
2288         m_out.appendTo(continuation, lastNext);
2289         
2290         return m_out.phi(m_out.boolean, results);
2291     }
2292     
2293     template<typename FunctionType>
2294     void contiguousPutByValOutOfBounds(
2295         FunctionType slowPathFunction,
2296         LValue base, LValue storage, LValue index, LValue value,
2297         LBasicBlock continuation)
2298     {
2299         LValue isNotInBounds = m_out.aboveOrEqual(
2300             index, m_out.load32(storage, m_heaps.Butterfly_publicLength));
2301         if (m_node->arrayMode().isInBounds())
2302             speculate(StoreToHoleOrOutOfBounds, noValue(), 0, isNotInBounds);
2303         else {
2304             LBasicBlock notInBoundsCase =
2305                 FTL_NEW_BLOCK(m_out, ("PutByVal not in bounds"));
2306             LBasicBlock performStore =
2307                 FTL_NEW_BLOCK(m_out, ("PutByVal perform store"));
2308                 
2309             m_out.branch(isNotInBounds, notInBoundsCase, performStore);
2310                 
2311             LBasicBlock lastNext = m_out.appendTo(notInBoundsCase, performStore);
2312                 
2313             LValue isOutOfBounds = m_out.aboveOrEqual(
2314                 index, m_out.load32(storage, m_heaps.Butterfly_vectorLength));
2315                 
2316             if (!m_node->arrayMode().isOutOfBounds())
2317                 speculate(OutOfBounds, noValue(), 0, isOutOfBounds);
2318             else {
2319                 LBasicBlock outOfBoundsCase =
2320                     FTL_NEW_BLOCK(m_out, ("PutByVal out of bounds"));
2321                 LBasicBlock holeCase =
2322                     FTL_NEW_BLOCK(m_out, ("PutByVal hole case"));
2323                     
2324                 m_out.branch(isOutOfBounds, outOfBoundsCase, holeCase);
2325                     
2326                 LBasicBlock innerLastNext = m_out.appendTo(outOfBoundsCase, holeCase);
2327                     
2328                 vmCall(
2329                     m_out.operation(slowPathFunction),
2330                     m_callFrame, base, index, value);
2331                     
2332                 m_out.jump(continuation);
2333                     
2334                 m_out.appendTo(holeCase, innerLastNext);
2335             }
2336             
2337             m_out.store32(
2338                 m_out.add(index, m_out.int32One),
2339                 storage, m_heaps.Butterfly_publicLength);
2340                 
2341             m_out.jump(performStore);
2342             m_out.appendTo(performStore, lastNext);
2343         }
2344     }
2345     
2346     void buildSwitch(SwitchData* data, LType type, LValue switchValue)
2347     {
2348         Vector<SwitchCase> cases;
2349         for (unsigned i = 0; i < data->cases.size(); ++i) {
2350             cases.append(SwitchCase(
2351                 constInt(type, data->cases[i].value.switchLookupValue()),
2352                 lowBlock(data->cases[i].target)));
2353         }
2354         
2355         m_out.switchInstruction(switchValue, cases, lowBlock(data->fallThrough));
2356     }
2357     
2358     LValue doubleToInt32(LValue doubleValue, double low, double high, bool isSigned = true)
2359     {
2360         // FIXME: Optimize double-to-int conversions.
2361         // <rdar://problem/14938465>
2362         
2363         LBasicBlock greatEnough = FTL_NEW_BLOCK(m_out, ("doubleToInt32 greatEnough"));
2364         LBasicBlock withinRange = FTL_NEW_BLOCK(m_out, ("doubleToInt32 withinRange"));
2365         LBasicBlock slowPath = FTL_NEW_BLOCK(m_out, ("doubleToInt32 slowPath"));
2366         LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("doubleToInt32 continuation"));
2367         
2368         Vector<ValueFromBlock, 2> results;
2369         
2370         m_out.branch(
2371             m_out.doubleGreaterThanOrEqual(doubleValue, m_out.constDouble(low)),
2372             greatEnough, slowPath);
2373         
2374         LBasicBlock lastNext = m_out.appendTo(greatEnough, withinRange);
2375         m_out.branch(
2376             m_out.doubleLessThanOrEqual(doubleValue, m_out.constDouble(high)),
2377             withinRange, slowPath);
2378         
2379         m_out.appendTo(withinRange, slowPath);
2380         LValue fastResult;
2381         if (isSigned)
2382             fastResult = m_out.fpToInt32(doubleValue);
2383         else
2384             fastResult = m_out.fpToUInt32(doubleValue);
2385         results.append(m_out.anchor(fastResult));
2386         m_out.jump(continuation);
2387         
2388         m_out.appendTo(slowPath, continuation);
2389         results.append(m_out.anchor(m_out.call(m_out.operation(toInt32), doubleValue)));
2390         m_out.jump(continuation);
2391         
2392         m_out.appendTo(continuation, lastNext);
2393         return m_out.phi(m_out.int32, results);
2394     }
2395     
2396     LValue doubleToInt32(LValue doubleValue)
2397     {
2398         double limit = pow(2, 31) - 1;
2399         return doubleToInt32(doubleValue, -limit, limit);
2400     }
2401     
2402     LValue doubleToUInt32(LValue doubleValue)
2403     {
2404         return doubleToInt32(doubleValue, 0, pow(2, 32) - 1, false);
2405     }
2406     
2407     void speculateBackward(
2408         ExitKind kind, FormattedValue lowValue, Node* highValue, LValue failCondition)
2409     {
2410         appendOSRExit(
2411             kind, lowValue, highValue, failCondition, BackwardSpeculation, FormattedValue());
2412     }
2413     
2414     void speculateForward(
2415         ExitKind kind, FormattedValue lowValue, Node* highValue, LValue failCondition,
2416         const FormattedValue& recovery)
2417     {
2418         appendOSRExit(
2419             kind, lowValue, highValue, failCondition, ForwardSpeculation, recovery);
2420     }
2421     
2422     void speculate(
2423         ExitKind kind, FormattedValue lowValue, Node* highValue, LValue failCondition)
2424     {
2425         appendOSRExit(
2426             kind, lowValue, highValue, failCondition, m_direction, FormattedValue());
2427     }
2428     
2429     void terminate(ExitKind kind)
2430     {
2431         speculate(kind, noValue(), 0, m_out.booleanTrue);
2432     }
2433     
2434     void backwardTypeCheck(
2435         FormattedValue lowValue, Edge highValue, SpeculatedType typesPassedThrough,
2436         LValue failCondition)
2437     {
2438         appendTypeCheck(
2439             lowValue, highValue, typesPassedThrough, failCondition, BackwardSpeculation,
2440             FormattedValue());
2441     }
2442     
2443     void forwardTypeCheck(
2444         FormattedValue lowValue, Edge highValue, SpeculatedType typesPassedThrough,
2445         LValue failCondition, const FormattedValue& recovery)
2446     {
2447         appendTypeCheck(
2448             lowValue, highValue, typesPassedThrough, failCondition, ForwardSpeculation,
2449             recovery);
2450     }
2451     
2452     void typeCheck(
2453         FormattedValue lowValue, Edge highValue, SpeculatedType typesPassedThrough,
2454         LValue failCondition)
2455     {
2456         appendTypeCheck(
2457             lowValue, highValue, typesPassedThrough, failCondition, m_direction,
2458             FormattedValue());
2459     }
2460     
2461     void appendTypeCheck(
2462         FormattedValue lowValue, Edge highValue, SpeculatedType typesPassedThrough,
2463         LValue failCondition, SpeculationDirection direction, FormattedValue recovery)
2464     {
2465         if (!m_interpreter.needsTypeCheck(highValue, typesPassedThrough))
2466             return;
2467         ASSERT(mayHaveTypeCheck(highValue.useKind()));
2468         appendOSRExit(BadType, lowValue, highValue.node(), failCondition, direction, recovery);
2469         m_interpreter.filter(highValue, typesPassedThrough);
2470     }
2471     
2472     LValue lowInt32(Edge edge, OperandSpeculationMode mode = AutomaticOperandSpeculation)
2473     {
2474         ASSERT_UNUSED(mode, mode == ManualOperandSpeculation || (edge.useKind() == Int32Use || edge.useKind() == KnownInt32Use));
2475         
2476         if (edge->hasConstant()) {
2477             JSValue value = m_graph.valueOfJSConstant(edge.node());
2478             if (!value.isInt32()) {
2479                 terminate(Uncountable);
2480                 return m_out.int32Zero;
2481             }
2482             return m_out.constInt32(value.asInt32());
2483         }
2484         
2485         LoweredNodeValue value = m_int32Values.get(edge.node());
2486         if (isValid(value))
2487             return value.value();
2488         
2489         value = m_strictInt52Values.get(edge.node());
2490         if (isValid(value))
2491             return strictInt52ToInt32(edge, value.value());
2492         
2493         value = m_int52Values.get(edge.node());
2494         if (isValid(value))
2495             return strictInt52ToInt32(edge, int52ToStrictInt52(value.value()));
2496         
2497         value = m_jsValueValues.get(edge.node());
2498         if (isValid(value)) {
2499             LValue boxedResult = value.value();
2500             FTL_TYPE_CHECK(
2501                 jsValueValue(boxedResult), edge, SpecInt32, isNotInt32(boxedResult));
2502             LValue result = unboxInt32(boxedResult);
2503             setInt32(edge.node(), result);
2504             return result;
2505         }
2506
2507         RELEASE_ASSERT(!(m_state.forNode(edge).m_type & SpecInt32));
2508         terminate(Uncountable);
2509         return m_out.int32Zero;
2510     }
2511     
2512     enum Int52Kind { StrictInt52, Int52 };
2513     LValue lowInt52(Edge edge, Int52Kind kind, OperandSpeculationMode mode = AutomaticOperandSpeculation)
2514     {
2515         ASSERT_UNUSED(mode, mode == ManualOperandSpeculation || edge.useKind() == MachineIntUse);
2516         
2517         if (edge->hasConstant()) {
2518             JSValue value = m_graph.valueOfJSConstant(edge.node());
2519             if (!value.isMachineInt()) {
2520                 terminate(Uncountable);
2521                 return m_out.int64Zero;
2522             }
2523             int64_t result = value.asMachineInt();
2524             if (kind == Int52)
2525                 result <<= JSValue::int52ShiftAmount;
2526             return m_out.constInt64(result);
2527         }
2528         
2529         LoweredNodeValue value;
2530         
2531         switch (kind) {
2532         case Int52:
2533             value = m_int52Values.get(edge.node());
2534             if (isValid(value))
2535                 return value.value();
2536             
2537             value = m_strictInt52Values.get(edge.node());
2538             if (isValid(value))
2539                 return strictInt52ToInt52(value.value());
2540             break;
2541             
2542         case StrictInt52:
2543             value = m_strictInt52Values.get(edge.node());
2544             if (isValid(value))
2545                 return value.value();
2546             
2547             value = m_int52Values.get(edge.node());
2548             if (isValid(value))
2549                 return int52ToStrictInt52(value.value());
2550             break;
2551         }
2552         
2553         value = m_int32Values.get(edge.node());
2554         if (isValid(value)) {
2555             return setInt52WithStrictValue(
2556                 edge.node(), m_out.signExt(value.value(), m_out.int64), kind);
2557         }
2558         
2559         RELEASE_ASSERT(!(m_state.forNode(edge).m_type & SpecInt52));
2560         
2561         value = m_jsValueValues.get(edge.node());
2562         if (isValid(value)) {
2563             LValue boxedResult = value.value();
2564             FTL_TYPE_CHECK(
2565                 jsValueValue(boxedResult), edge, SpecMachineInt, isNotInt32(boxedResult));
2566             return setInt52WithStrictValue(
2567                 edge.node(), m_out.signExt(unboxInt32(boxedResult), m_out.int64), kind);
2568         }
2569         
2570         RELEASE_ASSERT(!(m_state.forNode(edge).m_type & SpecMachineInt));
2571         terminate(Uncountable);
2572         return m_out.int64Zero;
2573     }
2574     
2575     LValue lowInt52(Edge edge, OperandSpeculationMode mode = AutomaticOperandSpeculation)
2576     {
2577         return lowInt52(edge, Int52, mode);
2578     }
2579     
2580     LValue lowStrictInt52(Edge edge, OperandSpeculationMode mode = AutomaticOperandSpeculation)
2581     {
2582         return lowInt52(edge, StrictInt52, mode);
2583     }
2584     
2585     bool betterUseStrictInt52(Node* node)
2586     {
2587         return !isValid(m_int52Values.get(node));
2588     }
2589     bool betterUseStrictInt52(Edge edge)
2590     {
2591         return betterUseStrictInt52(edge.node());
2592     }
2593     template<typename T>
2594     Int52Kind bestInt52Kind(T node)
2595     {
2596         return betterUseStrictInt52(node) ? StrictInt52 : Int52;
2597     }
2598     Int52Kind opposite(Int52Kind kind)
2599     {
2600         switch (kind) {
2601         case Int52:
2602             return StrictInt52;
2603         case StrictInt52:
2604             return Int52;
2605         }
2606         RELEASE_ASSERT_NOT_REACHED();
2607     }
2608     
2609     LValue lowWhicheverInt52(Edge edge, Int52Kind& kind, OperandSpeculationMode mode = AutomaticOperandSpeculation)
2610     {
2611         kind = bestInt52Kind(edge);
2612         return lowInt52(edge, kind, mode);
2613     }
2614     
2615     LValue lowCell(Edge edge, OperandSpeculationMode mode = AutomaticOperandSpeculation)
2616     {
2617         ASSERT_UNUSED(mode, mode == ManualOperandSpeculation || isCell(edge.useKind()));
2618         
2619         if (edge->op() == JSConstant) {
2620             JSValue value = m_graph.valueOfJSConstant(edge.node());
2621             if (!value.isCell()) {
2622                 terminate(Uncountable);
2623                 return m_out.intPtrZero;
2624             }
2625             return m_out.constIntPtr(value.asCell());
2626         }
2627         
2628         LoweredNodeValue value = m_jsValueValues.get(edge.node());
2629         if (isValid(value)) {
2630             LValue uncheckedValue = value.value();
2631             FTL_TYPE_CHECK(
2632                 jsValueValue(uncheckedValue), edge, SpecCell, isNotCell(uncheckedValue));
2633             return uncheckedValue;
2634         }
2635         
2636         RELEASE_ASSERT(!(m_state.forNode(edge).m_type & SpecCell));
2637         terminate(Uncountable);
2638         return m_out.intPtrZero;
2639     }
2640     
2641     LValue lowObject(Edge edge, OperandSpeculationMode mode = AutomaticOperandSpeculation)
2642     {
2643         ASSERT_UNUSED(mode, mode == ManualOperandSpeculation || edge.useKind() == ObjectUse);
2644         
2645         LValue result = lowCell(edge, mode);
2646         speculateObject(edge, result);
2647         return result;
2648     }
2649     
2650     LValue lowString(Edge edge, OperandSpeculationMode mode = AutomaticOperandSpeculation)
2651     {
2652         ASSERT_UNUSED(mode, mode == ManualOperandSpeculation || edge.useKind() == StringUse || edge.useKind() == KnownStringUse);
2653         
2654         LValue result = lowCell(edge, mode);
2655         speculateString(edge, result);
2656         return result;
2657     }
2658     
2659     LValue lowNonNullObject(Edge edge, OperandSpeculationMode mode = AutomaticOperandSpeculation)
2660     {
2661         ASSERT_UNUSED(mode, mode == ManualOperandSpeculation || edge.useKind() == ObjectUse);
2662         
2663         LValue result = lowCell(edge, mode);
2664         speculateNonNullObject(edge, result);
2665         return result;
2666     }
2667     
2668     LValue lowBoolean(Edge edge, OperandSpeculationMode mode = AutomaticOperandSpeculation)
2669     {
2670         ASSERT_UNUSED(mode, mode == ManualOperandSpeculation || edge.useKind() == BooleanUse);
2671         
2672         if (edge->hasConstant()) {
2673             JSValue value = m_graph.valueOfJSConstant(edge.node());
2674             if (!value.isBoolean()) {
2675                 terminate(Uncountable);
2676                 return m_out.booleanFalse;
2677             }
2678             return m_out.constBool(value.asBoolean());
2679         }
2680         
2681         LoweredNodeValue value = m_booleanValues.get(edge.node());
2682         if (isValid(value))
2683             return value.value();
2684         
2685         value = m_jsValueValues.get(edge.node());
2686         if (isValid(value)) {
2687             LValue unboxedResult = value.value();
2688             FTL_TYPE_CHECK(
2689                 jsValueValue(unboxedResult), edge, SpecBoolean, isNotBoolean(unboxedResult));
2690             LValue result = unboxBoolean(unboxedResult);
2691             setBoolean(edge.node(), result);
2692             return result;
2693         }
2694         
2695         RELEASE_ASSERT(!(m_state.forNode(edge).m_type & SpecBoolean));
2696         terminate(Uncountable);
2697         return m_out.booleanFalse;
2698     }
2699     
2700     LValue lowDouble(Edge edge, OperandSpeculationMode mode = AutomaticOperandSpeculation)
2701     {
2702         ASSERT_UNUSED(mode, mode == ManualOperandSpeculation || isDouble(edge.useKind()));
2703         
2704         if (edge->hasConstant()) {
2705             JSValue value = m_graph.valueOfJSConstant(edge.node());
2706             if (!value.isNumber()) {
2707                 terminate(Uncountable);
2708                 return m_out.doubleZero;
2709             }
2710             return m_out.constDouble(value.asNumber());
2711         }
2712         
2713         LoweredNodeValue value = m_doubleValues.get(edge.node());
2714         if (isValid(value))
2715             return value.value();
2716         
2717         value = m_int32Values.get(edge.node());
2718         if (isValid(value)) {
2719             LValue result = m_out.intToDouble(value.value());
2720             setDouble(edge.node(), result);
2721             return result;
2722         }
2723         
2724         value = m_strictInt52Values.get(edge.node());
2725         if (isValid(value))
2726             return strictInt52ToDouble(edge, value.value());
2727         
2728         value = m_int52Values.get(edge.node());
2729         if (isValid(value))
2730             return strictInt52ToDouble(edge, int52ToStrictInt52(value.value()));
2731         
2732         value = m_jsValueValues.get(edge.node());
2733         if (isValid(value)) {
2734             LValue boxedResult = value.value();
2735             
2736             LBasicBlock intCase = FTL_NEW_BLOCK(m_out, ("Double unboxing int case"));
2737             LBasicBlock doubleCase = FTL_NEW_BLOCK(m_out, ("Double unboxing double case"));
2738             LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("Double unboxing continuation"));
2739             
2740             m_out.branch(isNotInt32(boxedResult), doubleCase, intCase);
2741             
2742             LBasicBlock lastNext = m_out.appendTo(intCase, doubleCase);
2743             
2744             ValueFromBlock intToDouble = m_out.anchor(
2745                 m_out.intToDouble(unboxInt32(boxedResult)));
2746             m_out.jump(continuation);
2747             
2748             m_out.appendTo(doubleCase, continuation);
2749             
2750             FTL_TYPE_CHECK(
2751                 jsValueValue(boxedResult), edge, SpecFullNumber, isCellOrMisc(boxedResult));
2752             
2753             ValueFromBlock unboxedDouble = m_out.anchor(unboxDouble(boxedResult));
2754             m_out.jump(continuation);
2755             
2756             m_out.appendTo(continuation, lastNext);
2757             
2758             LValue result = m_out.phi(m_out.doubleType, intToDouble, unboxedDouble);
2759             
2760             setDouble(edge.node(), result);
2761             return result;
2762         }
2763         
2764         RELEASE_ASSERT(!(m_state.forNode(edge).m_type & SpecFullNumber));
2765         terminate(Uncountable);
2766         return m_out.doubleZero;
2767     }
2768     
2769     LValue lowJSValue(Edge edge, OperandSpeculationMode mode = AutomaticOperandSpeculation)
2770     {
2771         ASSERT_UNUSED(mode, mode == ManualOperandSpeculation || edge.useKind() == UntypedUse);
2772         
2773         if (edge->hasConstant())
2774             return m_out.constInt64(JSValue::encode(m_graph.valueOfJSConstant(edge.node())));
2775         
2776         LoweredNodeValue value = m_jsValueValues.get(edge.node());
2777         if (isValid(value))
2778             return value.value();
2779         
2780         value = m_int32Values.get(edge.node());
2781         if (isValid(value)) {
2782             LValue result = boxInt32(value.value());
2783             setJSValue(edge.node(), result);
2784             return result;
2785         }
2786         
2787         value = m_strictInt52Values.get(edge.node());
2788         if (isValid(value))
2789             return strictInt52ToJSValue(value.value());
2790         
2791         value = m_int52Values.get(edge.node());
2792         if (isValid(value))
2793             return strictInt52ToJSValue(int52ToStrictInt52(value.value()));
2794         
2795         value = m_booleanValues.get(edge.node());
2796         if (isValid(value)) {
2797             LValue result = boxBoolean(value.value());
2798             setJSValue(edge.node(), result);
2799             return result;
2800         }
2801         
2802         value = m_doubleValues.get(edge.node());
2803         if (isValid(value)) {
2804             LValue result = boxDouble(value.value());
2805             setJSValue(edge.node(), result);
2806             return result;
2807         }
2808         
2809         RELEASE_ASSERT_NOT_REACHED();
2810         return 0;
2811     }
2812     
2813     LValue lowStorage(Edge edge)
2814     {
2815         LoweredNodeValue value = m_storageValues.get(edge.node());
2816         if (isValid(value))
2817             return value.value();
2818         
2819         LValue result = lowCell(edge);
2820         setStorage(edge.node(), result);
2821         return result;
2822     }
2823     
2824     LValue strictInt52ToInt32(Edge edge, LValue value)
2825     {
2826         LValue result = m_out.castToInt32(value);
2827         FTL_TYPE_CHECK(
2828             noValue(), edge, SpecInt32,
2829             m_out.notEqual(m_out.signExt(result, m_out.int64), value));
2830         setInt32(edge.node(), result);
2831         return result;
2832     }
2833     
2834     LValue strictInt52ToDouble(Edge edge, LValue value)
2835     {
2836         LValue result = m_out.intToDouble(value);
2837         setDouble(edge.node(), result);
2838         return result;
2839     }
2840     
2841     LValue strictInt52ToJSValue(LValue value)
2842     {
2843         LBasicBlock isInt32 = FTL_NEW_BLOCK(m_out, ("strictInt52ToJSValue isInt32 case"));
2844         LBasicBlock isDouble = FTL_NEW_BLOCK(m_out, ("strictInt52ToJSValue isDouble case"));
2845         LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("strictInt52ToJSValue continuation"));
2846         
2847         Vector<ValueFromBlock, 2> results;
2848             
2849         LValue int32Value = m_out.castToInt32(value);
2850         m_out.branch(
2851             m_out.equal(m_out.signExt(int32Value, m_out.int64), value),
2852             isInt32, isDouble);
2853         
2854         LBasicBlock lastNext = m_out.appendTo(isInt32, isDouble);
2855         
2856         results.append(m_out.anchor(boxInt32(int32Value)));
2857         m_out.jump(continuation);
2858         
2859         m_out.appendTo(isDouble, continuation);
2860         
2861         results.append(m_out.anchor(boxDouble(m_out.intToDouble(value))));
2862         m_out.jump(continuation);
2863         
2864         m_out.appendTo(continuation, lastNext);
2865         return m_out.phi(m_out.int64, results);
2866     }
2867     
2868     LValue setInt52WithStrictValue(Node* node, LValue value, Int52Kind kind)
2869     {
2870         switch (kind) {
2871         case StrictInt52:
2872             setStrictInt52(node, value);
2873             return value;
2874             
2875         case Int52:
2876             value = strictInt52ToInt52(value);
2877             setInt52(node, value);
2878             return value;
2879         }
2880         
2881         RELEASE_ASSERT_NOT_REACHED();
2882         return 0;
2883     }
2884
2885     LValue strictInt52ToInt52(LValue value)
2886     {
2887         return m_out.shl(value, m_out.constInt64(JSValue::int52ShiftAmount));
2888     }
2889     
2890     LValue int52ToStrictInt52(LValue value)
2891     {
2892         return m_out.aShr(value, m_out.constInt64(JSValue::int52ShiftAmount));
2893     }
2894     
2895     LValue isNotInt32(LValue jsValue)
2896     {
2897         return m_out.below(jsValue, m_tagTypeNumber);
2898     }
2899     LValue unboxInt32(LValue jsValue)
2900     {
2901         return m_out.castToInt32(jsValue);
2902     }
2903     LValue boxInt32(LValue value)
2904     {
2905         return m_out.add(m_out.zeroExt(value, m_out.int64), m_tagTypeNumber);
2906     }
2907     
2908     LValue isCellOrMisc(LValue jsValue)
2909     {
2910         return m_out.testIsZero64(jsValue, m_tagTypeNumber);
2911     }
2912     LValue unboxDouble(LValue jsValue)
2913     {
2914         return m_out.bitCast(m_out.add(jsValue, m_tagTypeNumber), m_out.doubleType);
2915     }
2916     LValue boxDouble(LValue doubleValue)
2917     {
2918         return m_out.sub(m_out.bitCast(doubleValue, m_out.int64), m_tagTypeNumber);
2919     }
2920     
2921     LValue isNotCell(LValue jsValue)
2922     {
2923         return m_out.testNonZero64(jsValue, m_tagMask);
2924     }
2925     
2926     LValue isNotBoolean(LValue jsValue)
2927     {
2928         return m_out.testNonZero64(
2929             m_out.bitXor(jsValue, m_out.constInt64(ValueFalse)),
2930             m_out.constInt64(~1));
2931     }
2932     LValue unboxBoolean(LValue jsValue)
2933     {
2934         // We want to use a cast that guarantees that LLVM knows that even the integer
2935         // value is just 0 or 1. But for now we do it the dumb way.
2936         return m_out.notZero64(m_out.bitAnd(jsValue, m_out.constInt64(1)));
2937     }
2938     LValue boxBoolean(LValue value)
2939     {
2940         return m_out.select(
2941             value, m_out.constInt64(ValueTrue), m_out.constInt64(ValueFalse));
2942     }
2943
2944     void speculate(Edge edge)
2945     {
2946         switch (edge.useKind()) {
2947         case UntypedUse:
2948             break;
2949         case KnownInt32Use:
2950         case KnownNumberUse:
2951             ASSERT(!m_interpreter.needsTypeCheck(edge));
2952             break;
2953         case Int32Use:
2954             speculateInt32(edge);
2955             break;
2956         case CellUse:
2957             speculateCell(edge);
2958             break;
2959         case KnownCellUse:
2960             ASSERT(!m_interpreter.needsTypeCheck(edge));
2961             break;
2962         case ObjectUse:
2963             speculateObject(edge);
2964             break;
2965         case ObjectOrOtherUse:
2966             speculateObjectOrOther(edge);
2967             break;
2968         case StringUse:
2969             speculateString(edge);
2970             break;
2971         case RealNumberUse:
2972             speculateRealNumber(edge);
2973             break;
2974         case NumberUse:
2975             speculateNumber(edge);
2976             break;
2977         case MachineIntUse:
2978             speculateMachineInt(edge);
2979             break;
2980         case BooleanUse:
2981             speculateBoolean(edge);
2982             break;
2983         default:
2984             dataLog("Unsupported speculation use kind: ", edge.useKind(), "\n");
2985             RELEASE_ASSERT_NOT_REACHED();
2986         }
2987     }
2988     
2989     void speculate(Node*, Edge edge)
2990     {
2991         speculate(edge);
2992     }
2993     
2994     void speculateInt32(Edge edge)
2995     {
2996         lowInt32(edge);
2997     }
2998     
2999     void speculateCell(Edge edge)
3000     {
3001         lowCell(edge);
3002     }
3003     
3004     LValue isObject(LValue cell)
3005     {
3006         return m_out.notEqual(
3007             m_out.loadPtr(cell, m_heaps.JSCell_structure),
3008             m_out.constIntPtr(vm().stringStructure.get()));
3009     }
3010     
3011     LValue isNotString(LValue cell)
3012     {
3013         return isObject(cell);
3014     }
3015     
3016     LValue isString(LValue cell)
3017     {
3018         return m_out.equal(
3019             m_out.loadPtr(cell, m_heaps.JSCell_structure),
3020             m_out.constIntPtr(vm().stringStructure.get()));
3021     }
3022     
3023     LValue isNotObject(LValue cell)
3024     {
3025         return isString(cell);
3026     }
3027     
3028     LValue isArrayType(LValue cell, ArrayMode arrayMode)
3029     {
3030         switch (arrayMode.type()) {
3031         case Array::Int32:
3032         case Array::Double:
3033         case Array::Contiguous: {
3034             LValue indexingType = m_out.load8(
3035                 m_out.loadPtr(cell, m_heaps.JSCell_structure),
3036                 m_heaps.Structure_indexingType);
3037             
3038             switch (arrayMode.arrayClass()) {
3039             case Array::OriginalArray:
3040                 RELEASE_ASSERT_NOT_REACHED();
3041                 return 0;
3042                 
3043             case Array::Array:
3044                 return m_out.equal(
3045                     m_out.bitAnd(indexingType, m_out.constInt8(IsArray | IndexingShapeMask)),
3046                     m_out.constInt8(IsArray | arrayMode.shapeMask()));
3047                 
3048             default:
3049                 return m_out.equal(
3050                     m_out.bitAnd(indexingType, m_out.constInt8(IndexingShapeMask)),
3051                     m_out.constInt8(arrayMode.shapeMask()));
3052             }
3053         }
3054             
3055         default:
3056             return hasClassInfo(cell, classInfoForType(arrayMode.typedArrayType()));
3057         }
3058     }
3059     
3060     LValue hasClassInfo(LValue cell, const ClassInfo* classInfo)
3061     {
3062         return m_out.equal(
3063             m_out.loadPtr(
3064                 m_out.loadPtr(cell, m_heaps.JSCell_structure),
3065                 m_heaps.Structure_classInfo),
3066             m_out.constIntPtr(classInfo));
3067     }
3068     
3069     void speculateObject(Edge edge, LValue cell)
3070     {
3071         FTL_TYPE_CHECK(jsValueValue(cell), edge, SpecObject, isNotObject(cell));
3072     }
3073     
3074     void speculateObject(Edge edge)
3075     {
3076         speculateObject(edge, lowCell(edge));
3077     }
3078     
3079     void speculateObjectOrOther(Edge edge)
3080     {
3081         if (!m_interpreter.needsTypeCheck(edge))
3082             return;
3083         
3084         LValue value = lowJSValue(edge);
3085         
3086         LBasicBlock cellCase = FTL_NEW_BLOCK(m_out, ("speculateObjectOrOther cell case"));
3087         LBasicBlock primitiveCase = FTL_NEW_BLOCK(m_out, ("speculateObjectOrOther primitive case"));
3088         LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("speculateObjectOrOther continuation"));
3089         
3090         m_out.branch(isNotCell(value), primitiveCase, cellCase);
3091         
3092         LBasicBlock lastNext = m_out.appendTo(cellCase, primitiveCase);
3093         
3094         FTL_TYPE_CHECK(
3095             jsValueValue(value), edge, (~SpecCell) | SpecObject,
3096             m_out.equal(
3097                 m_out.loadPtr(value, m_heaps.JSCell_structure),
3098                 m_out.constIntPtr(vm().stringStructure.get())));
3099         
3100         m_out.jump(continuation);
3101         
3102         m_out.appendTo(primitiveCase, continuation);
3103         
3104         FTL_TYPE_CHECK(
3105             jsValueValue(value), edge, SpecCell | SpecOther,
3106             m_out.notEqual(
3107                 m_out.bitAnd(value, m_out.constInt64(~TagBitUndefined)),
3108                 m_out.constInt64(ValueNull)));
3109         
3110         m_out.jump(continuation);
3111         
3112         m_out.appendTo(continuation, lastNext);
3113     }
3114     
3115     void speculateString(Edge edge, LValue cell)
3116     {
3117         FTL_TYPE_CHECK(jsValueValue(cell), edge, SpecString, isNotString(cell));
3118     }
3119     
3120     void speculateString(Edge edge)
3121     {
3122         speculateString(edge, lowCell(edge));
3123     }
3124     
3125     void speculateNonNullObject(Edge edge, LValue cell)
3126     {
3127         LValue structure = m_out.loadPtr(cell, m_heaps.JSCell_structure);
3128         FTL_TYPE_CHECK(
3129             jsValueValue(cell), edge, SpecObject, 
3130             m_out.equal(structure, m_out.constIntPtr(vm().stringStructure.get())));
3131         if (masqueradesAsUndefinedWatchpointIsStillValid())
3132             return;
3133         
3134         speculate(
3135             BadType, jsValueValue(cell), edge.node(),
3136             m_out.testNonZero8(
3137                 m_out.load8(structure, m_heaps.Structure_typeInfoFlags),
3138                 m_out.constInt8(MasqueradesAsUndefined)));
3139     }
3140     
3141     void speculateNumber(Edge edge)
3142     {
3143         // Do an early return here because lowDouble() can create a lot of control flow.
3144         if (!m_interpreter.needsTypeCheck(edge))
3145             return;
3146         
3147         lowDouble(edge);
3148     }
3149     
3150     void speculateRealNumber(Edge edge)
3151     {
3152         // Do an early return here because lowDouble() can create a lot of control flow.
3153         if (!m_interpreter.needsTypeCheck(edge))
3154             return;
3155         
3156         LValue value = lowDouble(edge);
3157         FTL_TYPE_CHECK(
3158             doubleValue(value), edge, SpecFullRealNumber,
3159             m_out.doubleNotEqualOrUnordered(value, value));
3160     }
3161     
3162     void speculateMachineInt(Edge edge)
3163     {
3164         if (!m_interpreter.needsTypeCheck(edge))
3165             return;
3166         
3167         Int52Kind kind;
3168         lowWhicheverInt52(edge, kind);
3169     }
3170     
3171     void speculateBoolean(Edge edge)
3172     {
3173         lowBoolean(edge);
3174     }
3175     
3176     bool masqueradesAsUndefinedWatchpointIsStillValid()
3177     {
3178         return m_graph.masqueradesAsUndefinedWatchpointIsStillValid(m_node->codeOrigin);
3179     }
3180     
3181     enum ExceptionCheckMode { NoExceptions, CheckExceptions };
3182     
3183     LValue vmCall(LValue function, ExceptionCheckMode mode = CheckExceptions)
3184     {
3185         callPreflight();
3186         LValue result = m_out.call(function);
3187         callCheck(mode);
3188         return result;
3189     }
3190     LValue vmCall(LValue function, LValue arg1, ExceptionCheckMode mode = CheckExceptions)
3191     {
3192         callPreflight();
3193         LValue result = m_out.call(function, arg1);
3194         callCheck(mode);
3195         return result;
3196     }
3197     LValue vmCall(LValue function, LValue arg1, LValue arg2, ExceptionCheckMode mode = CheckExceptions)
3198     {
3199         callPreflight();
3200         LValue result = m_out.call(function, arg1, arg2);
3201         callCheck(mode);
3202         return result;
3203     }
3204     LValue vmCall(LValue function, LValue arg1, LValue arg2, LValue arg3, ExceptionCheckMode mode = CheckExceptions)
3205     {
3206         callPreflight();
3207         LValue result = m_out.call(function, arg1, arg2, arg3);
3208         callCheck(mode);
3209         return result;
3210     }
3211     LValue vmCall(LValue function, LValue arg1, LValue arg2, LValue arg3, LValue arg4, ExceptionCheckMode mode = CheckExceptions)
3212     {
3213         callPreflight();
3214         LValue result = m_out.call(function, arg1, arg2, arg3, arg4);
3215         callCheck(mode);
3216         return result;
3217     }
3218     
3219     void callPreflight(CodeOrigin codeOrigin)
3220     {
3221         m_out.store32(
3222             m_out.constInt32(
3223                 CallFrame::Location::encodeAsCodeOriginIndex(
3224                     m_ftlState.jitCode->common.addCodeOrigin(codeOrigin))),
3225             tagFor(JSStack::ArgumentCount));
3226     }
3227     void callPreflight()
3228     {
3229         callPreflight(m_node->codeOrigin);
3230     }
3231     
3232     void callCheck(ExceptionCheckMode mode = CheckExceptions)
3233     {
3234         if (mode == NoExceptions)
3235             return;
3236         
3237         LBasicBlock didHaveException = FTL_NEW_BLOCK(m_out, ("Did have exception"));
3238         LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("Exception check continuation"));
3239         
3240         m_out.branch(
3241             m_out.notZero64(m_out.load64(m_out.absolute(vm().addressOfException()))),
3242             didHaveException, continuation);
3243         
3244         LBasicBlock lastNext = m_out.appendTo(didHaveException, continuation);
3245         // FIXME: Handle exceptions. https://bugs.webkit.org/show_bug.cgi?id=113622
3246         m_out.crash();
3247         
3248         m_out.appendTo(continuation, lastNext);
3249     }
3250     
3251     bool isLive(Node* node)
3252     {
3253         return m_live.contains(node);
3254     }
3255     
3256     void use(Edge edge)
3257     {
3258         ASSERT(edge->hasResult());
3259         if (!edge.doesKill())
3260             return;
3261         m_live.remove(edge.node());
3262     }
3263     
3264     // Wrapper used only for DFG_NODE_DO_TO_CHILDREN
3265     void use(Node*, Edge edge)
3266     {
3267         use(edge);
3268     }
3269     
3270     LBasicBlock lowBlock(BasicBlock* block)
3271     {
3272         return m_blocks.get(block);
3273     }
3274     
3275     void initializeOSRExitStateForBlock()
3276     {
3277         for (unsigned i = m_valueSources.size(); i--;) {
3278             FlushedAt flush = m_highBlock->ssa->flushAtHead[i];
3279             switch (flush.format()) {
3280             case DeadFlush: {
3281                 // Must consider available nodes instead.
3282                 Node* node = m_highBlock->ssa->availabilityAtHead[i];
3283                 if (!node) {
3284                     m_valueSources[i] = ValueSource(SourceIsDead);
3285                     break;
3286                 }
3287                 
3288                 m_valueSources[i] = ValueSource(node);
3289                 break;
3290             }
3291                 
3292             case FlushedInt32:
3293                 m_valueSources[i] = ValueSource(Int32InJSStack, flush.virtualRegister());
3294                 break;
3295                 
3296             case FlushedInt52:
3297                 m_valueSources[i] = ValueSource(Int52InJSStack, flush.virtualRegister());
3298                 break;
3299                 
3300             case FlushedDouble:
3301                 m_valueSources[i] = ValueSource(DoubleInJSStack, flush.virtualRegister());
3302                 break;
3303                 
3304             case FlushedCell:
3305             case FlushedBoolean:
3306             case FlushedJSValue:
3307                 m_valueSources[i] = ValueSource(ValueInJSStack, flush.virtualRegister());
3308                 break;
3309             }
3310         }
3311     }
3312     
3313     void appendOSRExit(
3314         ExitKind kind, FormattedValue lowValue, Node* highValue, LValue failCondition,
3315         SpeculationDirection direction, FormattedValue recovery)
3316     {
3317         if (verboseCompilationEnabled())
3318             dataLog("    OSR exit with value sources: ", m_valueSources, "\n");
3319         
3320         ASSERT(m_ftlState.jitCode->osrExit.size() == m_ftlState.finalizer->osrExit.size());
3321         
3322         m_ftlState.jitCode->osrExit.append(OSRExit(
3323             kind, lowValue.format(), m_graph.methodOfGettingAValueProfileFor(highValue),
3324             m_codeOriginForExitTarget, m_codeOriginForExitProfile, m_lastSetOperand.offset(),
3325             m_valueSources.numberOfArguments(), m_valueSources.numberOfLocals()));
3326         m_ftlState.finalizer->osrExit.append(OSRExitCompilationInfo());
3327         
3328         OSRExit& exit = m_ftlState.jitCode->osrExit.last();
3329
3330         LBasicBlock lastNext = 0;
3331         LBasicBlock continuation = 0;
3332         
3333         LBasicBlock failCase = FTL_NEW_BLOCK(m_out, ("OSR exit failCase for ", m_node));
3334         continuation = FTL_NEW_BLOCK(m_out, ("OSR exit continuation for ", m_node));
3335         
3336         m_out.branch(failCondition, failCase, continuation);
3337         
3338         lastNext = m_out.appendTo(failCase, continuation);
3339         
3340         emitOSRExitCall(exit, lowValue, direction, recovery);
3341         
3342         m_out.unreachable();
3343         
3344         m_out.appendTo(continuation, lastNext);
3345     }
3346     
3347     void emitOSRExitCall(
3348         OSRExit& exit, FormattedValue lowValue, SpeculationDirection direction,
3349         FormattedValue recovery)
3350     {
3351         ExitArgumentList arguments;
3352         
3353         buildExitArguments(exit, arguments, lowValue);
3354         
3355         if (direction == ForwardSpeculation) {
3356             ASSERT(m_node);
3357             exit.convertToForward(m_highBlock, m_node, m_nodeIndex, recovery, arguments);
3358         }
3359         
3360         callStackmap(exit, arguments);
3361     }
3362     
3363     void buildExitArguments(
3364         OSRExit& exit, ExitArgumentList& arguments, FormattedValue lowValue)
3365     {
3366         arguments.append(m_callFrame);
3367         if (!!lowValue)
3368             arguments.append(lowValue.value());
3369         
3370         for (unsigned i = 0; i < exit.m_values.size(); ++i) {
3371             ValueSource source = m_valueSources[i];
3372             
3373             switch (source.kind()) {
3374             case ValueInJSStack:
3375                 exit.m_values[i] = ExitValue::inJSStack(source.virtualRegister());
3376                 break;
3377             case Int32InJSStack:
3378                 exit.m_values[i] = ExitValue::inJSStackAsInt32(source.virtualRegister());
3379                 break;
3380             case Int52InJSStack:
3381                 exit.m_values[i] = ExitValue::inJSStackAsInt52(source.virtualRegister());
3382                 break;
3383             case DoubleInJSStack:
3384                 exit.m_values[i] = ExitValue::inJSStackAsDouble(source.virtualRegister());
3385                 break;
3386             case SourceIsDead:
3387                 exit.m_values[i] = ExitValue::dead();
3388                 break;
3389             case HaveNode:
3390                 addExitArgumentForNode(exit, arguments, i, source.node());
3391                 break;
3392             default:
3393                 RELEASE_ASSERT_NOT_REACHED();
3394                 break;
3395             }
3396         }
3397         
3398         if (verboseCompilationEnabled())
3399             dataLog("        Exit values: ", exit.m_values, "\n");
3400     }
3401     
3402     void callStackmap(OSRExit& exit, ExitArgumentList& arguments)
3403     {
3404         exit.m_stackmapID = m_stackmapIDs++;
3405         arguments.insert(0, m_out.constInt32(MacroAssembler::maxJumpReplacementSize()));
3406         arguments.insert(0, m_out.constInt32(exit.m_stackmapID));
3407         
3408         m_out.call(m_out.stackmapIntrinsic(), arguments);
3409     }
3410     
3411     void addExitArgumentForNode(
3412         OSRExit& exit, ExitArgumentList& arguments, unsigned index, Node* node)
3413     {
3414         ASSERT(node->shouldGenerate());
3415         ASSERT(node->hasResult());
3416
3417         if (tryToSetConstantExitArgument(exit, index, node))
3418             return;
3419         
3420         if (!isLive(node)) {
3421             bool found = false;
3422             
3423             if (permitsOSRBackwardRewiring(node->op())) {
3424                 node = node->child1().node();
3425                 if (tryToSetConstantExitArgument(exit, index, node))
3426                     return;
3427                 if (isLive(node))
3428                     found = true;
3429             }
3430             
3431             if (!found) {
3432                 Node* bestNode = 0;
3433                 unsigned bestScore = 0;
3434                 
3435                 HashSet<Node*>::iterator iter = m_live.begin();
3436                 HashSet<Node*>::iterator end = m_live.end();
3437                 for (; iter != end; ++iter) {
3438                     Node* candidate = *iter;
3439                     if (candidate->flags() & NodeHasVarArgs)
3440                         continue;
3441                     if (!candidate->child1())
3442                         continue;
3443                     if (candidate->child1() != node)
3444                         continue;
3445                     unsigned myScore = forwardRewiringSelectionScore(candidate->op());
3446                     if (myScore <= bestScore)
3447                         continue;
3448                     bestNode = candidate;
3449                     bestScore = myScore;
3450                 }
3451                 
3452                 if (bestNode) {
3453                     ASSERT(isLive(bestNode));
3454                     node = bestNode;
3455                     found = true;
3456                 }
3457             }
3458             
3459             if (!found) {
3460                 exit.m_values[index] = ExitValue::dead();
3461                 return;
3462             }
3463         }
3464         
3465         ASSERT(isLive(node));
3466
3467         LoweredNodeValue value = m_int32Values.get(node);
3468         if (isValid(value)) {
3469             addExitArgument(exit, arguments, index, ValueFormatInt32, value.value());
3470             return;
3471         }
3472         
3473         value = m_int52Values.get(node);
3474         if (isValid(value)) {
3475             addExitArgument(exit, arguments, index, ValueFormatInt52, value.value());
3476             return;
3477         }
3478         
3479         value = m_strictInt52Values.get(node);
3480         if (isValid(value)) {
3481             addExitArgument(exit, arguments, index, ValueFormatStrictInt52, value.value());
3482             return;
3483         }
3484         
3485         value = m_booleanValues.get(node);
3486         if (isValid(value)) {
3487             LValue valueToPass = m_out.zeroExt(value.value(), m_out.int32);
3488             addExitArgument(exit, arguments, index, ValueFormatBoolean, valueToPass);
3489             return;
3490         }
3491         
3492         value = m_jsValueValues.get(node);
3493         if (isValid(value)) {
3494             addExitArgument(exit, arguments, index, ValueFormatJSValue, value.value());
3495             return;
3496         }
3497         
3498         value = m_doubleValues.get(node);
3499         if (isValid(value)) {
3500             addExitArgument(exit, arguments, index, ValueFormatDouble, value.value());
3501             return;
3502         }
3503
3504         dataLog("Cannot find value for node: ", node, "\n");
3505         RELEASE_ASSERT_NOT_REACHED();
3506     }
3507     
3508     bool tryToSetConstantExitArgument(OSRExit& exit, unsigned index, Node* node)
3509     {
3510         if (!node)
3511             return false;
3512         
3513         switch (node->op()) {
3514         case JSConstant:
3515         case WeakJSConstant:
3516             exit.m_values[index] = ExitValue::constant(m_graph.valueOfJSConstant(node));
3517             return true;
3518         case PhantomArguments:
3519             // FIXME: implement PhantomArguments.
3520             // https://bugs.webkit.org/show_bug.cgi?id=113986
3521             RELEASE_ASSERT_NOT_REACHED();
3522             return true;
3523         default:
3524             return false;
3525         }
3526     }
3527     
3528     void addExitArgument(
3529         OSRExit& exit, ExitArgumentList& arguments, unsigned index, ValueFormat format,
3530         LValue value)
3531     {
3532         exit.m_values[index] = ExitValue::exitArgument(ExitArgument(format, arguments.size()));
3533         arguments.append(value);
3534     }
3535     
3536     void observeMovHint(Node* node)
3537     {
3538         ASSERT(node->containsMovHint());
3539         ASSERT(node->op() != ZombieHint);
3540         
3541         VirtualRegister operand = node->local();
3542         
3543         m_lastSetOperand = operand;
3544         m_valueSources.operand(operand) = ValueSource(node->child1().node());
3545     }
3546     
3547     void setInt32(Node* node, LValue value)
3548     {
3549         m_int32Values.set(node, LoweredNodeValue(value, m_highBlock));
3550     }
3551     void setInt52(Node* node, LValue value)
3552     {
3553         m_int52Values.set(node, LoweredNodeValue(value, m_highBlock));
3554     }
3555     void setStrictInt52(Node* node, LValue value)
3556     {
3557         m_strictInt52Values.set(node, LoweredNodeValue(value, m_highBlock));
3558     }
3559     void setInt52(Node* node, LValue value, Int52Kind kind)
3560     {
3561         switch (kind) {
3562         case Int52:
3563             setInt52(node, value);
3564             return;
3565             
3566         case StrictInt52:
3567             setStrictInt52(node, value);
3568             return;
3569         }
3570         
3571         RELEASE_ASSERT_NOT_REACHED();
3572     }
3573     void setJSValue(Node* node, LValue value)
3574     {
3575         m_jsValueValues.set(node, LoweredNodeValue(value, m_highBlock));
3576     }
3577     void setBoolean(Node* node, LValue value)
3578     {
3579         m_booleanValues.set(node, LoweredNodeValue(value, m_highBlock));
3580     }
3581     void setStorage(Node* node, LValue value)
3582     {
3583         m_storageValues.set(node, LoweredNodeValue(value, m_highBlock));
3584     }
3585     void setDouble(Node* node, LValue value)
3586     {
3587         m_doubleValues.set(node, LoweredNodeValue(value, m_highBlock));
3588     }
3589
3590     void setInt32(LValue value)
3591     {
3592         setInt32(m_node, value);
3593     }
3594     void setInt52(LValue value)
3595     {
3596         setInt52(m_node, value);
3597     }
3598     void setStrictInt52(LValue value)
3599     {
3600         setStrictInt52(m_node, value);
3601     }
3602     void setInt52(LValue value, Int52Kind kind)
3603     {
3604         setInt52(m_node, value, kind);
3605     }
3606     void setJSValue(LValue value)
3607     {
3608         setJSValue(m_node, value);
3609     }
3610     void setBoolean(LValue value)
3611     {
3612         setBoolean(m_node, value);
3613     }
3614     void setStorage(LValue value)
3615     {
3616         setStorage(m_node, value);
3617     }
3618     void setDouble(LValue value)
3619     {
3620         setDouble(m_node, value);
3621     }
3622     
3623     bool isValid(const LoweredNodeValue& value)
3624     {
3625         if (!value)
3626             return false;
3627         if (!m_graph.m_dominators.dominates(value.block(), m_highBlock))
3628             return false;
3629         return true;
3630     }
3631     
3632     void addWeakReference(JSCell* target)
3633     {
3634         m_graph.m_plan.weakReferences.addLazily(target);
3635     }
3636     
3637     LValue weakPointer(JSCell* pointer)
3638     {
3639         addWeakReference(pointer);
3640         return m_out.constIntPtr(pointer);
3641     }