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