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