DFG should have adaptive structure watchpoints
[WebKit-https.git] / Source / JavaScriptCore / ftl / FTLLowerDFGToLLVM.cpp
1 /*
2  * Copyright (C) 2013-2015 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 "DFGOSRAvailabilityAnalysisPhase.h"
35 #include "DFGOSRExitFuzz.h"
36 #include "DirectArguments.h"
37 #include "FTLAbstractHeapRepository.h"
38 #include "FTLAvailableRecovery.h"
39 #include "FTLForOSREntryJITCode.h"
40 #include "FTLFormattedValue.h"
41 #include "FTLInlineCacheSize.h"
42 #include "FTLLoweredNodeValue.h"
43 #include "FTLOperations.h"
44 #include "FTLOutput.h"
45 #include "FTLThunks.h"
46 #include "FTLWeightedTarget.h"
47 #include "JSCInlines.h"
48 #include "JSLexicalEnvironment.h"
49 #include "OperandsInlines.h"
50 #include "ScopedArguments.h"
51 #include "ScopedArgumentsTable.h"
52 #include "VirtualRegister.h"
53 #include <atomic>
54 #include <dlfcn.h>
55 #include <llvm/InitializeLLVM.h>
56 #include <unordered_set>
57 #include <wtf/ProcessID.h>
58
59 namespace JSC { namespace FTL {
60
61 using namespace DFG;
62
63 namespace {
64
65 std::atomic<int> compileCounter;
66
67 #if ASSERT_DISABLED
68 NO_RETURN_DUE_TO_CRASH static void ftlUnreachable()
69 {
70     CRASH();
71 }
72 #else
73 NO_RETURN_DUE_TO_CRASH static void ftlUnreachable(
74     CodeBlock* codeBlock, BlockIndex blockIndex, unsigned nodeIndex)
75 {
76     dataLog("Crashing in thought-to-be-unreachable FTL-generated code for ", pointerDump(codeBlock), " at basic block #", blockIndex);
77     if (nodeIndex != UINT_MAX)
78         dataLog(", node @", nodeIndex);
79     dataLog(".\n");
80     CRASH();
81 }
82 #endif
83
84 // Using this instead of typeCheck() helps to reduce the load on LLVM, by creating
85 // significantly less dead code.
86 #define FTL_TYPE_CHECK(lowValue, highValue, typesPassedThrough, failCondition) do { \
87         FormattedValue _ftc_lowValue = (lowValue);                      \
88         Edge _ftc_highValue = (highValue);                              \
89         SpeculatedType _ftc_typesPassedThrough = (typesPassedThrough);  \
90         if (!m_interpreter.needsTypeCheck(_ftc_highValue, _ftc_typesPassedThrough)) \
91             break;                                                      \
92         typeCheck(_ftc_lowValue, _ftc_highValue, _ftc_typesPassedThrough, (failCondition)); \
93     } while (false)
94
95 class LowerDFGToLLVM {
96 public:
97     LowerDFGToLLVM(State& state)
98         : m_graph(state.graph)
99         , m_ftlState(state)
100         , m_heaps(state.context)
101         , m_out(state.context)
102         , m_state(state.graph)
103         , m_interpreter(state.graph, m_state)
104         , m_stackmapIDs(0)
105         , m_tbaaKind(mdKindID(state.context, "tbaa"))
106         , m_tbaaStructKind(mdKindID(state.context, "tbaa.struct"))
107     {
108     }
109     
110     void lower()
111     {
112         CString name;
113         if (verboseCompilationEnabled()) {
114             name = toCString(
115                 "jsBody_", ++compileCounter, "_", codeBlock()->inferredName(),
116                 "_", codeBlock()->hash());
117         } else
118             name = "jsBody";
119         
120         m_graph.m_dominators.computeIfNecessary(m_graph);
121         
122         m_ftlState.module =
123             moduleCreateWithNameInContext(name.data(), m_ftlState.context);
124         
125         m_ftlState.function = addFunction(
126             m_ftlState.module, name.data(), functionType(m_out.int64));
127         setFunctionCallingConv(m_ftlState.function, LLVMCCallConv);
128         if (isX86() && Options::llvmDisallowAVX()) {
129             // AVX makes V8/raytrace 80% slower. It makes Kraken/audio-oscillator 4.5x
130             // slower. It should be disabled.
131             addTargetDependentFunctionAttr(m_ftlState.function, "target-features", "-avx");
132         }
133         
134         if (verboseCompilationEnabled())
135             dataLog("Function ready, beginning lowering.\n");
136         
137         m_out.initialize(m_ftlState.module, m_ftlState.function, m_heaps);
138         
139         m_prologue = FTL_NEW_BLOCK(m_out, ("Prologue"));
140         LBasicBlock stackOverflow = FTL_NEW_BLOCK(m_out, ("Stack overflow"));
141         m_handleExceptions = FTL_NEW_BLOCK(m_out, ("Handle Exceptions"));
142         
143         LBasicBlock checkArguments = FTL_NEW_BLOCK(m_out, ("Check arguments"));
144
145         for (BlockIndex blockIndex = 0; blockIndex < m_graph.numBlocks(); ++blockIndex) {
146             m_highBlock = m_graph.block(blockIndex);
147             if (!m_highBlock)
148                 continue;
149             m_blocks.add(m_highBlock, FTL_NEW_BLOCK(m_out, ("Block ", *m_highBlock)));
150         }
151         
152         m_out.appendTo(m_prologue, stackOverflow);
153         createPhiVariables();
154
155         auto preOrder = m_graph.blocksInPreOrder();
156
157         LValue capturedAlloca = m_out.alloca(arrayType(m_out.int64, m_graph.m_nextMachineLocal));
158         
159         m_captured = m_out.add(
160             m_out.ptrToInt(capturedAlloca, m_out.intPtr),
161             m_out.constIntPtr(m_graph.m_nextMachineLocal * sizeof(Register)));
162         
163         m_ftlState.capturedStackmapID = m_stackmapIDs++;
164         m_out.call(
165             m_out.stackmapIntrinsic(), m_out.constInt64(m_ftlState.capturedStackmapID),
166             m_out.int32Zero, capturedAlloca);
167         
168         // If we have any CallVarargs then we nee to have a spill slot for it.
169         bool hasVarargs = false;
170         for (BasicBlock* block : preOrder) {
171             for (Node* node : *block) {
172                 switch (node->op()) {
173                 case CallVarargs:
174                 case CallForwardVarargs:
175                 case ConstructVarargs:
176                 case ConstructForwardVarargs:
177                     hasVarargs = true;
178                     break;
179                 default:
180                     break;
181                 }
182             }
183         }
184         if (hasVarargs) {
185             LValue varargsSpillSlots = m_out.alloca(
186                 arrayType(m_out.int64, JSCallVarargs::numSpillSlotsNeeded()));
187             m_ftlState.varargsSpillSlotsStackmapID = m_stackmapIDs++;
188             m_out.call(
189                 m_out.stackmapIntrinsic(), m_out.constInt64(m_ftlState.varargsSpillSlotsStackmapID),
190                 m_out.int32Zero, varargsSpillSlots);
191         }
192         
193         // We should not create any alloca's after this point, since they will cease to
194         // be mem2reg candidates.
195         
196         m_callFrame = m_out.ptrToInt(
197             m_out.call(m_out.frameAddressIntrinsic(), m_out.int32Zero), m_out.intPtr);
198         m_tagTypeNumber = m_out.constInt64(TagTypeNumber);
199         m_tagMask = m_out.constInt64(TagMask);
200         
201         m_out.storePtr(m_out.constIntPtr(codeBlock()), addressFor(JSStack::CodeBlock));
202         
203         m_out.branch(
204             didOverflowStack(), rarely(stackOverflow), usually(checkArguments));
205         
206         m_out.appendTo(stackOverflow, m_handleExceptions);
207         m_out.call(m_out.operation(operationThrowStackOverflowError), m_callFrame, m_out.constIntPtr(codeBlock()));
208         m_ftlState.handleStackOverflowExceptionStackmapID = m_stackmapIDs++;
209         m_out.call(
210             m_out.stackmapIntrinsic(), m_out.constInt64(m_ftlState.handleStackOverflowExceptionStackmapID),
211             m_out.constInt32(MacroAssembler::maxJumpReplacementSize()));
212         m_out.unreachable();
213         
214         m_out.appendTo(m_handleExceptions, checkArguments);
215         m_ftlState.handleExceptionStackmapID = m_stackmapIDs++;
216         m_out.call(
217             m_out.stackmapIntrinsic(), m_out.constInt64(m_ftlState.handleExceptionStackmapID),
218             m_out.constInt32(MacroAssembler::maxJumpReplacementSize()));
219         m_out.unreachable();
220         
221         m_out.appendTo(checkArguments, lowBlock(m_graph.block(0)));
222         availabilityMap().clear();
223         availabilityMap().m_locals = Operands<Availability>(codeBlock()->numParameters(), 0);
224         for (unsigned i = codeBlock()->numParameters(); i--;) {
225             availabilityMap().m_locals.argument(i) =
226                 Availability(FlushedAt(FlushedJSValue, virtualRegisterForArgument(i)));
227         }
228         m_codeOriginForExitTarget = CodeOrigin(0);
229         m_codeOriginForExitProfile = CodeOrigin(0);
230         m_node = nullptr;
231         for (unsigned i = codeBlock()->numParameters(); i--;) {
232             Node* node = m_graph.m_arguments[i];
233             VirtualRegister operand = virtualRegisterForArgument(i);
234             
235             LValue jsValue = m_out.load64(addressFor(operand));
236             
237             if (node) {
238                 DFG_ASSERT(m_graph, node, operand == node->stackAccessData()->machineLocal);
239                 
240                 // This is a hack, but it's an effective one. It allows us to do CSE on the
241                 // primordial load of arguments. This assumes that the GetLocal that got put in
242                 // place of the original SetArgument doesn't have any effects before it. This
243                 // should hold true.
244                 m_loadedArgumentValues.add(node, jsValue);
245             }
246             
247             switch (m_graph.m_argumentFormats[i]) {
248             case FlushedInt32:
249                 speculate(BadType, jsValueValue(jsValue), node, isNotInt32(jsValue));
250                 break;
251             case FlushedBoolean:
252                 speculate(BadType, jsValueValue(jsValue), node, isNotBoolean(jsValue));
253                 break;
254             case FlushedCell:
255                 speculate(BadType, jsValueValue(jsValue), node, isNotCell(jsValue));
256                 break;
257             case FlushedJSValue:
258                 break;
259             default:
260                 DFG_CRASH(m_graph, node, "Bad flush format for argument");
261                 break;
262             }
263         }
264         m_out.jump(lowBlock(m_graph.block(0)));
265         
266         for (BasicBlock* block : preOrder)
267             compileBlock(block);
268         
269         if (Options::dumpLLVMIR())
270             dumpModule(m_ftlState.module);
271         
272         if (verboseCompilationEnabled())
273             m_ftlState.dumpState("after lowering");
274         if (validationEnabled())
275             verifyModule(m_ftlState.module);
276     }
277
278 private:
279     
280     void createPhiVariables()
281     {
282         for (BlockIndex blockIndex = m_graph.numBlocks(); blockIndex--;) {
283             BasicBlock* block = m_graph.block(blockIndex);
284             if (!block)
285                 continue;
286             for (unsigned nodeIndex = block->size(); nodeIndex--;) {
287                 Node* node = block->at(nodeIndex);
288                 if (node->op() != Phi)
289                     continue;
290                 LType type;
291                 switch (node->flags() & NodeResultMask) {
292                 case NodeResultDouble:
293                     type = m_out.doubleType;
294                     break;
295                 case NodeResultInt32:
296                     type = m_out.int32;
297                     break;
298                 case NodeResultInt52:
299                     type = m_out.int64;
300                     break;
301                 case NodeResultBoolean:
302                     type = m_out.boolean;
303                     break;
304                 case NodeResultJS:
305                     type = m_out.int64;
306                     break;
307                 default:
308                     DFG_CRASH(m_graph, node, "Bad Phi node result type");
309                     break;
310                 }
311                 m_phis.add(node, buildAlloca(m_out.m_builder, type));
312             }
313         }
314     }
315     
316     void compileBlock(BasicBlock* block)
317     {
318         if (!block)
319             return;
320         
321         if (verboseCompilationEnabled())
322             dataLog("Compiling block ", *block, "\n");
323         
324         m_highBlock = block;
325         
326         LBasicBlock lowBlock = m_blocks.get(m_highBlock);
327         
328         m_nextHighBlock = 0;
329         for (BlockIndex nextBlockIndex = m_highBlock->index + 1; nextBlockIndex < m_graph.numBlocks(); ++nextBlockIndex) {
330             m_nextHighBlock = m_graph.block(nextBlockIndex);
331             if (m_nextHighBlock)
332                 break;
333         }
334         m_nextLowBlock = m_nextHighBlock ? m_blocks.get(m_nextHighBlock) : 0;
335         
336         // All of this effort to find the next block gives us the ability to keep the
337         // generated IR in roughly program order. This ought not affect the performance
338         // of the generated code (since we expect LLVM to reorder things) but it will
339         // make IR dumps easier to read.
340         m_out.appendTo(lowBlock, m_nextLowBlock);
341         
342         if (Options::ftlCrashes())
343             m_out.trap();
344         
345         if (!m_highBlock->cfaHasVisited) {
346             if (verboseCompilationEnabled())
347                 dataLog("Bailing because CFA didn't reach.\n");
348             crash(m_highBlock->index, UINT_MAX);
349             return;
350         }
351         
352         m_availabilityCalculator.beginBlock(m_highBlock);
353         
354         m_state.reset();
355         m_state.beginBasicBlock(m_highBlock);
356         
357         for (m_nodeIndex = 0; m_nodeIndex < m_highBlock->size(); ++m_nodeIndex) {
358             if (!compileNode(m_nodeIndex))
359                 break;
360         }
361     }
362
363     void safelyInvalidateAfterTermination()
364     {
365         if (verboseCompilationEnabled())
366             dataLog("Bailing.\n");
367         crash();
368
369         // Invalidate dominated blocks. Under normal circumstances we would expect
370         // them to be invalidated already. But you can have the CFA become more
371         // precise over time because the structures of objects change on the main
372         // thread. Failing to do this would result in weird crashes due to a value
373         // being used but not defined. Race conditions FTW!
374         for (BlockIndex blockIndex = m_graph.numBlocks(); blockIndex--;) {
375             BasicBlock* target = m_graph.block(blockIndex);
376             if (!target)
377                 continue;
378             if (m_graph.m_dominators.dominates(m_highBlock, target)) {
379                 if (verboseCompilationEnabled())
380                     dataLog("Block ", *target, " will bail also.\n");
381                 target->cfaHasVisited = false;
382             }
383         }
384     }
385
386     bool compileNode(unsigned nodeIndex)
387     {
388         if (!m_state.isValid()) {
389             safelyInvalidateAfterTermination();
390             return false;
391         }
392         
393         m_node = m_highBlock->at(nodeIndex);
394         m_codeOriginForExitProfile = m_node->origin.semantic;
395         m_codeOriginForExitTarget = m_node->origin.forExit;
396         
397         if (verboseCompilationEnabled())
398             dataLog("Lowering ", m_node, "\n");
399         
400         m_availableRecoveries.resize(0);
401         
402         m_interpreter.startExecuting();
403         
404         switch (m_node->op()) {
405         case Upsilon:
406             compileUpsilon();
407             break;
408         case Phi:
409             compilePhi();
410             break;
411         case JSConstant:
412             break;
413         case DoubleConstant:
414             compileDoubleConstant();
415             break;
416         case Int52Constant:
417             compileInt52Constant();
418             break;
419         case DoubleRep:
420             compileDoubleRep();
421             break;
422         case DoubleAsInt32:
423             compileDoubleAsInt32();
424             break;
425         case ValueRep:
426             compileValueRep();
427             break;
428         case Int52Rep:
429             compileInt52Rep();
430             break;
431         case ValueToInt32:
432             compileValueToInt32();
433             break;
434         case BooleanToNumber:
435             compileBooleanToNumber();
436             break;
437         case ExtractOSREntryLocal:
438             compileExtractOSREntryLocal();
439             break;
440         case GetStack:
441             compileGetStack();
442             break;
443         case PutStack:
444             compilePutStack();
445             break;
446         case Check:
447             compileNoOp();
448             break;
449         case ToThis:
450             compileToThis();
451             break;
452         case ValueAdd:
453             compileValueAdd();
454             break;
455         case ArithAdd:
456         case ArithSub:
457             compileArithAddOrSub();
458             break;
459         case ArithClz32:
460             compileArithClz32();
461             break;
462         case ArithMul:
463             compileArithMul();
464             break;
465         case ArithDiv:
466             compileArithDiv();
467             break;
468         case ArithMod:
469             compileArithMod();
470             break;
471         case ArithMin:
472         case ArithMax:
473             compileArithMinOrMax();
474             break;
475         case ArithAbs:
476             compileArithAbs();
477             break;
478         case ArithSin:
479             compileArithSin();
480             break;
481         case ArithCos:
482             compileArithCos();
483             break;
484         case ArithPow:
485             compileArithPow();
486             break;
487         case ArithRound:
488             compileArithRound();
489             break;
490         case ArithSqrt:
491             compileArithSqrt();
492             break;
493         case ArithLog:
494             compileArithLog();
495             break;
496         case ArithFRound:
497             compileArithFRound();
498             break;
499         case ArithNegate:
500             compileArithNegate();
501             break;
502         case BitAnd:
503             compileBitAnd();
504             break;
505         case BitOr:
506             compileBitOr();
507             break;
508         case BitXor:
509             compileBitXor();
510             break;
511         case BitRShift:
512             compileBitRShift();
513             break;
514         case BitLShift:
515             compileBitLShift();
516             break;
517         case BitURShift:
518             compileBitURShift();
519             break;
520         case UInt32ToNumber:
521             compileUInt32ToNumber();
522             break;
523         case CheckStructure:
524             compileCheckStructure();
525             break;
526         case CheckCell:
527             compileCheckCell();
528             break;
529         case CheckNotEmpty:
530             compileCheckNotEmpty();
531             break;
532         case CheckBadCell:
533             compileCheckBadCell();
534             break;
535         case GetExecutable:
536             compileGetExecutable();
537             break;
538         case ArrayifyToStructure:
539             compileArrayifyToStructure();
540             break;
541         case PutStructure:
542             compilePutStructure();
543             break;
544         case GetById:
545             compileGetById();
546             break;
547         case In:
548             compileIn();
549             break;
550         case PutById:
551         case PutByIdDirect:
552             compilePutById();
553             break;
554         case GetButterfly:
555             compileGetButterfly();
556             break;
557         case ConstantStoragePointer:
558             compileConstantStoragePointer();
559             break;
560         case GetIndexedPropertyStorage:
561             compileGetIndexedPropertyStorage();
562             break;
563         case CheckArray:
564             compileCheckArray();
565             break;
566         case GetArrayLength:
567             compileGetArrayLength();
568             break;
569         case CheckInBounds:
570             compileCheckInBounds();
571             break;
572         case GetByVal:
573             compileGetByVal();
574             break;
575         case GetMyArgumentByVal:
576             compileGetMyArgumentByVal();
577             break;
578         case PutByVal:
579         case PutByValAlias:
580         case PutByValDirect:
581             compilePutByVal();
582             break;
583         case ArrayPush:
584             compileArrayPush();
585             break;
586         case ArrayPop:
587             compileArrayPop();
588             break;
589         case CreateActivation:
590             compileCreateActivation();
591             break;
592         case NewFunction:
593             compileNewFunction();
594             break;
595         case CreateDirectArguments:
596             compileCreateDirectArguments();
597             break;
598         case CreateScopedArguments:
599             compileCreateScopedArguments();
600             break;
601         case CreateClonedArguments:
602             compileCreateClonedArguments();
603             break;
604         case NewObject:
605             compileNewObject();
606             break;
607         case NewArray:
608             compileNewArray();
609             break;
610         case NewArrayBuffer:
611             compileNewArrayBuffer();
612             break;
613         case NewArrayWithSize:
614             compileNewArrayWithSize();
615             break;
616         case GetTypedArrayByteOffset:
617             compileGetTypedArrayByteOffset();
618             break;
619         case AllocatePropertyStorage:
620             compileAllocatePropertyStorage();
621             break;
622         case ReallocatePropertyStorage:
623             compileReallocatePropertyStorage();
624             break;
625         case ToString:
626         case CallStringConstructor:
627             compileToStringOrCallStringConstructor();
628             break;
629         case ToPrimitive:
630             compileToPrimitive();
631             break;
632         case MakeRope:
633             compileMakeRope();
634             break;
635         case StringCharAt:
636             compileStringCharAt();
637             break;
638         case StringCharCodeAt:
639             compileStringCharCodeAt();
640             break;
641         case GetByOffset:
642         case GetGetterSetterByOffset:
643             compileGetByOffset();
644             break;
645         case GetGetter:
646             compileGetGetter();
647             break;
648         case GetSetter:
649             compileGetSetter();
650             break;
651         case MultiGetByOffset:
652             compileMultiGetByOffset();
653             break;
654         case PutByOffset:
655             compilePutByOffset();
656             break;
657         case MultiPutByOffset:
658             compileMultiPutByOffset();
659             break;
660         case GetGlobalVar:
661             compileGetGlobalVar();
662             break;
663         case PutGlobalVar:
664             compilePutGlobalVar();
665             break;
666         case NotifyWrite:
667             compileNotifyWrite();
668             break;
669         case GetCallee:
670             compileGetCallee();
671             break;
672         case GetArgumentCount:
673             compileGetArgumentCount();
674             break;
675         case GetScope:
676             compileGetScope();
677             break;
678         case SkipScope:
679             compileSkipScope();
680             break;
681         case GetClosureVar:
682             compileGetClosureVar();
683             break;
684         case PutClosureVar:
685             compilePutClosureVar();
686             break;
687         case GetFromArguments:
688             compileGetFromArguments();
689             break;
690         case PutToArguments:
691             compilePutToArguments();
692             break;
693         case CompareEq:
694             compileCompareEq();
695             break;
696         case CompareEqConstant:
697             compileCompareEqConstant();
698             break;
699         case CompareStrictEq:
700             compileCompareStrictEq();
701             break;
702         case CompareLess:
703             compileCompareLess();
704             break;
705         case CompareLessEq:
706             compileCompareLessEq();
707             break;
708         case CompareGreater:
709             compileCompareGreater();
710             break;
711         case CompareGreaterEq:
712             compileCompareGreaterEq();
713             break;
714         case LogicalNot:
715             compileLogicalNot();
716             break;
717         case Call:
718         case Construct:
719             compileCallOrConstruct();
720             break;
721         case CallVarargs:
722         case CallForwardVarargs:
723         case ConstructVarargs:
724         case ConstructForwardVarargs:
725             compileCallOrConstructVarargs();
726             break;
727         case LoadVarargs:
728             compileLoadVarargs();
729             break;
730         case ForwardVarargs:
731             compileForwardVarargs();
732             break;
733         case Jump:
734             compileJump();
735             break;
736         case Branch:
737             compileBranch();
738             break;
739         case Switch:
740             compileSwitch();
741             break;
742         case Return:
743             compileReturn();
744             break;
745         case ForceOSRExit:
746             compileForceOSRExit();
747             break;
748         case Throw:
749         case ThrowReferenceError:
750             compileThrow();
751             break;
752         case InvalidationPoint:
753             compileInvalidationPoint();
754             break;
755         case IsUndefined:
756             compileIsUndefined();
757             break;
758         case IsBoolean:
759             compileIsBoolean();
760             break;
761         case IsNumber:
762             compileIsNumber();
763             break;
764         case IsString:
765             compileIsString();
766             break;
767         case IsObject:
768             compileIsObject();
769             break;
770         case IsObjectOrNull:
771             compileIsObjectOrNull();
772             break;
773         case IsFunction:
774             compileIsFunction();
775             break;
776         case TypeOf:
777             compileTypeOf();
778             break;
779         case CheckHasInstance:
780             compileCheckHasInstance();
781             break;
782         case InstanceOf:
783             compileInstanceOf();
784             break;
785         case CountExecution:
786             compileCountExecution();
787             break;
788         case StoreBarrier:
789             compileStoreBarrier();
790             break;
791         case HasIndexedProperty:
792             compileHasIndexedProperty();
793             break;
794         case HasGenericProperty:
795             compileHasGenericProperty();
796             break;
797         case HasStructureProperty:
798             compileHasStructureProperty();
799             break;
800         case GetDirectPname:
801             compileGetDirectPname();
802             break;
803         case GetEnumerableLength:
804             compileGetEnumerableLength();
805             break;
806         case GetPropertyEnumerator:
807             compileGetPropertyEnumerator();
808             break;
809         case GetEnumeratorStructurePname:
810             compileGetEnumeratorStructurePname();
811             break;
812         case GetEnumeratorGenericPname:
813             compileGetEnumeratorGenericPname();
814             break;
815         case ToIndexString:
816             compileToIndexString();
817             break;
818         case CheckStructureImmediate:
819             compileCheckStructureImmediate();
820             break;
821         case MaterializeNewObject:
822             compileMaterializeNewObject();
823             break;
824         case MaterializeCreateActivation:
825             compileMaterializeCreateActivation();
826             break;
827
828         case PhantomLocal:
829         case LoopHint:
830         case MovHint:
831         case ZombieHint:
832         case PhantomNewObject:
833         case PhantomNewFunction:
834         case PhantomCreateActivation:
835         case PhantomDirectArguments:
836         case PhantomClonedArguments:
837         case PutHint:
838         case BottomValue:
839         case KillStack:
840             break;
841         default:
842             DFG_CRASH(m_graph, m_node, "Unrecognized node in FTL backend");
843             break;
844         }
845         
846         if (m_node->isTerminal())
847             return false;
848         
849         if (!m_state.isValid()) {
850             safelyInvalidateAfterTermination();
851             return false;
852         }
853
854         m_availabilityCalculator.executeNode(m_node);
855         m_interpreter.executeEffects(nodeIndex);
856         
857         return true;
858     }
859
860     void compileUpsilon()
861     {
862         LValue destination = m_phis.get(m_node->phi());
863         
864         switch (m_node->child1().useKind()) {
865         case DoubleRepUse:
866             m_out.set(lowDouble(m_node->child1()), destination);
867             break;
868         case Int32Use:
869             m_out.set(lowInt32(m_node->child1()), destination);
870             break;
871         case Int52RepUse:
872             m_out.set(lowInt52(m_node->child1()), destination);
873             break;
874         case BooleanUse:
875             m_out.set(lowBoolean(m_node->child1()), destination);
876             break;
877         case CellUse:
878             m_out.set(lowCell(m_node->child1()), destination);
879             break;
880         case UntypedUse:
881             m_out.set(lowJSValue(m_node->child1()), destination);
882             break;
883         default:
884             DFG_CRASH(m_graph, m_node, "Bad use kind");
885             break;
886         }
887     }
888     
889     void compilePhi()
890     {
891         LValue source = m_phis.get(m_node);
892         
893         switch (m_node->flags() & NodeResultMask) {
894         case NodeResultDouble:
895             setDouble(m_out.get(source));
896             break;
897         case NodeResultInt32:
898             setInt32(m_out.get(source));
899             break;
900         case NodeResultInt52:
901             setInt52(m_out.get(source));
902             break;
903         case NodeResultBoolean:
904             setBoolean(m_out.get(source));
905             break;
906         case NodeResultJS:
907             setJSValue(m_out.get(source));
908             break;
909         default:
910             DFG_CRASH(m_graph, m_node, "Bad use kind");
911             break;
912         }
913     }
914     
915     void compileDoubleConstant()
916     {
917         setDouble(m_out.constDouble(m_node->asNumber()));
918     }
919     
920     void compileInt52Constant()
921     {
922         int64_t value = m_node->asMachineInt();
923         
924         setInt52(m_out.constInt64(value << JSValue::int52ShiftAmount));
925         setStrictInt52(m_out.constInt64(value));
926     }
927
928     void compileDoubleRep()
929     {
930         switch (m_node->child1().useKind()) {
931         case RealNumberUse: {
932             LValue value = lowJSValue(m_node->child1(), ManualOperandSpeculation);
933             
934             LValue doubleValue = unboxDouble(value);
935             
936             LBasicBlock intCase = FTL_NEW_BLOCK(m_out, ("DoubleRep RealNumberUse int case"));
937             LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("DoubleRep continuation"));
938             
939             ValueFromBlock fastResult = m_out.anchor(doubleValue);
940             m_out.branch(
941                 m_out.doubleEqual(doubleValue, doubleValue),
942                 usually(continuation), rarely(intCase));
943             
944             LBasicBlock lastNext = m_out.appendTo(intCase, continuation);
945             
946             FTL_TYPE_CHECK(
947                 jsValueValue(value), m_node->child1(), SpecBytecodeRealNumber,
948                 isNotInt32(value, provenType(m_node->child1()) & ~SpecFullDouble));
949             ValueFromBlock slowResult = m_out.anchor(m_out.intToDouble(unboxInt32(value)));
950             m_out.jump(continuation);
951             
952             m_out.appendTo(continuation, lastNext);
953             
954             setDouble(m_out.phi(m_out.doubleType, fastResult, slowResult));
955             return;
956         }
957             
958         case NotCellUse:
959         case NumberUse: {
960             bool shouldConvertNonNumber = m_node->child1().useKind() == NotCellUse;
961             
962             LValue value = lowJSValue(m_node->child1(), ManualOperandSpeculation);
963
964             LBasicBlock intCase = FTL_NEW_BLOCK(m_out, ("jsValueToDouble unboxing int case"));
965             LBasicBlock doubleTesting = FTL_NEW_BLOCK(m_out, ("jsValueToDouble testing double case"));
966             LBasicBlock doubleCase = FTL_NEW_BLOCK(m_out, ("jsValueToDouble unboxing double case"));
967             LBasicBlock nonDoubleCase = FTL_NEW_BLOCK(m_out, ("jsValueToDouble testing undefined case"));
968             LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("jsValueToDouble unboxing continuation"));
969             
970             m_out.branch(
971                 isNotInt32(value, provenType(m_node->child1())),
972                 unsure(doubleTesting), unsure(intCase));
973             
974             LBasicBlock lastNext = m_out.appendTo(intCase, doubleTesting);
975             
976             ValueFromBlock intToDouble = m_out.anchor(
977                 m_out.intToDouble(unboxInt32(value)));
978             m_out.jump(continuation);
979             
980             m_out.appendTo(doubleTesting, doubleCase);
981             LValue valueIsNumber = isNumber(value, provenType(m_node->child1()));
982             m_out.branch(valueIsNumber, usually(doubleCase), rarely(nonDoubleCase));
983
984             m_out.appendTo(doubleCase, nonDoubleCase);
985             ValueFromBlock unboxedDouble = m_out.anchor(unboxDouble(value));
986             m_out.jump(continuation);
987
988             if (shouldConvertNonNumber) {
989                 LBasicBlock undefinedCase = FTL_NEW_BLOCK(m_out, ("jsValueToDouble converting undefined case"));
990                 LBasicBlock testNullCase = FTL_NEW_BLOCK(m_out, ("jsValueToDouble testing null case"));
991                 LBasicBlock nullCase = FTL_NEW_BLOCK(m_out, ("jsValueToDouble converting null case"));
992                 LBasicBlock testBooleanTrueCase = FTL_NEW_BLOCK(m_out, ("jsValueToDouble testing boolean true case"));
993                 LBasicBlock convertBooleanTrueCase = FTL_NEW_BLOCK(m_out, ("jsValueToDouble convert boolean true case"));
994                 LBasicBlock convertBooleanFalseCase = FTL_NEW_BLOCK(m_out, ("jsValueToDouble convert boolean false case"));
995
996                 m_out.appendTo(nonDoubleCase, undefinedCase);
997                 LValue valueIsUndefined = m_out.equal(value, m_out.constInt64(ValueUndefined));
998                 m_out.branch(valueIsUndefined, unsure(undefinedCase), unsure(testNullCase));
999
1000                 m_out.appendTo(undefinedCase, testNullCase);
1001                 ValueFromBlock convertedUndefined = m_out.anchor(m_out.constDouble(PNaN));
1002                 m_out.jump(continuation);
1003
1004                 m_out.appendTo(testNullCase, nullCase);
1005                 LValue valueIsNull = m_out.equal(value, m_out.constInt64(ValueNull));
1006                 m_out.branch(valueIsNull, unsure(nullCase), unsure(testBooleanTrueCase));
1007
1008                 m_out.appendTo(nullCase, testBooleanTrueCase);
1009                 ValueFromBlock convertedNull = m_out.anchor(m_out.constDouble(0));
1010                 m_out.jump(continuation);
1011
1012                 m_out.appendTo(testBooleanTrueCase, convertBooleanTrueCase);
1013                 LValue valueIsBooleanTrue = m_out.equal(value, m_out.constInt64(ValueTrue));
1014                 m_out.branch(valueIsBooleanTrue, unsure(convertBooleanTrueCase), unsure(convertBooleanFalseCase));
1015
1016                 m_out.appendTo(convertBooleanTrueCase, convertBooleanFalseCase);
1017                 ValueFromBlock convertedTrue = m_out.anchor(m_out.constDouble(1));
1018                 m_out.jump(continuation);
1019
1020                 m_out.appendTo(convertBooleanFalseCase, continuation);
1021
1022                 LValue valueIsNotBooleanFalse = m_out.notEqual(value, m_out.constInt64(ValueFalse));
1023                 FTL_TYPE_CHECK(jsValueValue(value), m_node->child1(), ~SpecCell, valueIsNotBooleanFalse);
1024                 ValueFromBlock convertedFalse = m_out.anchor(m_out.constDouble(0));
1025                 m_out.jump(continuation);
1026
1027                 m_out.appendTo(continuation, lastNext);
1028                 setDouble(m_out.phi(m_out.doubleType, intToDouble, unboxedDouble, convertedUndefined, convertedNull, convertedTrue, convertedFalse));
1029                 return;
1030             }
1031             m_out.appendTo(nonDoubleCase, continuation);
1032             FTL_TYPE_CHECK(jsValueValue(value), m_node->child1(), SpecBytecodeNumber, m_out.booleanTrue);
1033             m_out.unreachable();
1034
1035             m_out.appendTo(continuation, lastNext);
1036
1037             setDouble(m_out.phi(m_out.doubleType, intToDouble, unboxedDouble));
1038             return;
1039         }
1040             
1041         case Int52RepUse: {
1042             setDouble(strictInt52ToDouble(lowStrictInt52(m_node->child1())));
1043             return;
1044         }
1045             
1046         default:
1047             DFG_CRASH(m_graph, m_node, "Bad use kind");
1048         }
1049     }
1050
1051     void compileDoubleAsInt32()
1052     {
1053         LValue integerValue = convertDoubleToInt32(lowDouble(m_node->child1()), shouldCheckNegativeZero(m_node->arithMode()));
1054         setInt32(integerValue);
1055     }
1056
1057     void compileValueRep()
1058     {
1059         switch (m_node->child1().useKind()) {
1060         case DoubleRepUse: {
1061             LValue value = lowDouble(m_node->child1());
1062             
1063             if (m_interpreter.needsTypeCheck(m_node->child1(), ~SpecDoubleImpureNaN)) {
1064                 value = m_out.select(
1065                     m_out.doubleEqual(value, value), value, m_out.constDouble(PNaN));
1066             }
1067             
1068             setJSValue(boxDouble(value));
1069             return;
1070         }
1071             
1072         case Int52RepUse: {
1073             setJSValue(strictInt52ToJSValue(lowStrictInt52(m_node->child1())));
1074             return;
1075         }
1076             
1077         default:
1078             DFG_CRASH(m_graph, m_node, "Bad use kind");
1079         }
1080     }
1081     
1082     void compileInt52Rep()
1083     {
1084         switch (m_node->child1().useKind()) {
1085         case Int32Use:
1086             setStrictInt52(m_out.signExt(lowInt32(m_node->child1()), m_out.int64));
1087             return;
1088             
1089         case MachineIntUse:
1090             setStrictInt52(
1091                 jsValueToStrictInt52(
1092                     m_node->child1(), lowJSValue(m_node->child1(), ManualOperandSpeculation)));
1093             return;
1094             
1095         case DoubleRepMachineIntUse:
1096             setStrictInt52(
1097                 doubleToStrictInt52(
1098                     m_node->child1(), lowDouble(m_node->child1())));
1099             return;
1100             
1101         default:
1102             RELEASE_ASSERT_NOT_REACHED();
1103         }
1104     }
1105     
1106     void compileValueToInt32()
1107     {
1108         switch (m_node->child1().useKind()) {
1109         case Int52RepUse:
1110             setInt32(m_out.castToInt32(lowStrictInt52(m_node->child1())));
1111             break;
1112             
1113         case DoubleRepUse:
1114             setInt32(doubleToInt32(lowDouble(m_node->child1())));
1115             break;
1116             
1117         case NumberUse:
1118         case NotCellUse: {
1119             LoweredNodeValue value = m_int32Values.get(m_node->child1().node());
1120             if (isValid(value)) {
1121                 setInt32(value.value());
1122                 break;
1123             }
1124             
1125             value = m_jsValueValues.get(m_node->child1().node());
1126             if (isValid(value)) {
1127                 setInt32(numberOrNotCellToInt32(m_node->child1(), value.value()));
1128                 break;
1129             }
1130             
1131             // We'll basically just get here for constants. But it's good to have this
1132             // catch-all since we often add new representations into the mix.
1133             setInt32(
1134                 numberOrNotCellToInt32(
1135                     m_node->child1(),
1136                     lowJSValue(m_node->child1(), ManualOperandSpeculation)));
1137             break;
1138         }
1139             
1140         default:
1141             DFG_CRASH(m_graph, m_node, "Bad use kind");
1142             break;
1143         }
1144     }
1145     
1146     void compileBooleanToNumber()
1147     {
1148         switch (m_node->child1().useKind()) {
1149         case BooleanUse: {
1150             setInt32(m_out.zeroExt(lowBoolean(m_node->child1()), m_out.int32));
1151             return;
1152         }
1153             
1154         case UntypedUse: {
1155             LValue value = lowJSValue(m_node->child1());
1156             
1157             if (!m_interpreter.needsTypeCheck(m_node->child1(), SpecBoolInt32 | SpecBoolean)) {
1158                 setInt32(m_out.bitAnd(m_out.castToInt32(value), m_out.int32One));
1159                 return;
1160             }
1161             
1162             LBasicBlock booleanCase = FTL_NEW_BLOCK(m_out, ("BooleanToNumber boolean case"));
1163             LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("BooleanToNumber continuation"));
1164             
1165             ValueFromBlock notBooleanResult = m_out.anchor(value);
1166             m_out.branch(
1167                 isBoolean(value, provenType(m_node->child1())),
1168                 unsure(booleanCase), unsure(continuation));
1169             
1170             LBasicBlock lastNext = m_out.appendTo(booleanCase, continuation);
1171             ValueFromBlock booleanResult = m_out.anchor(m_out.bitOr(
1172                 m_out.zeroExt(unboxBoolean(value), m_out.int64), m_tagTypeNumber));
1173             m_out.jump(continuation);
1174             
1175             m_out.appendTo(continuation, lastNext);
1176             setJSValue(m_out.phi(m_out.int64, booleanResult, notBooleanResult));
1177             return;
1178         }
1179             
1180         default:
1181             RELEASE_ASSERT_NOT_REACHED();
1182             return;
1183         }
1184     }
1185
1186     void compileExtractOSREntryLocal()
1187     {
1188         EncodedJSValue* buffer = static_cast<EncodedJSValue*>(
1189             m_ftlState.jitCode->ftlForOSREntry()->entryBuffer()->dataBuffer());
1190         setJSValue(m_out.load64(m_out.absolute(buffer + m_node->unlinkedLocal().toLocal())));
1191     }
1192     
1193     void compileGetStack()
1194     {
1195         // GetLocals arise only for captured variables and arguments. For arguments, we might have
1196         // already loaded it.
1197         if (LValue value = m_loadedArgumentValues.get(m_node)) {
1198             setJSValue(value);
1199             return;
1200         }
1201         
1202         StackAccessData* data = m_node->stackAccessData();
1203         AbstractValue& value = m_state.variables().operand(data->local);
1204         
1205         DFG_ASSERT(m_graph, m_node, isConcrete(data->format));
1206         DFG_ASSERT(m_graph, m_node, data->format != FlushedDouble); // This just happens to not arise for GetStacks, right now. It would be trivial to support.
1207         
1208         if (isInt32Speculation(value.m_type))
1209             setInt32(m_out.load32(payloadFor(data->machineLocal)));
1210         else
1211             setJSValue(m_out.load64(addressFor(data->machineLocal)));
1212     }
1213     
1214     void compilePutStack()
1215     {
1216         StackAccessData* data = m_node->stackAccessData();
1217         switch (data->format) {
1218         case FlushedJSValue: {
1219             LValue value = lowJSValue(m_node->child1());
1220             m_out.store64(value, addressFor(data->machineLocal));
1221             break;
1222         }
1223             
1224         case FlushedDouble: {
1225             LValue value = lowDouble(m_node->child1());
1226             m_out.storeDouble(value, addressFor(data->machineLocal));
1227             break;
1228         }
1229             
1230         case FlushedInt32: {
1231             LValue value = lowInt32(m_node->child1());
1232             m_out.store32(value, payloadFor(data->machineLocal));
1233             break;
1234         }
1235             
1236         case FlushedInt52: {
1237             LValue value = lowInt52(m_node->child1());
1238             m_out.store64(value, addressFor(data->machineLocal));
1239             break;
1240         }
1241             
1242         case FlushedCell: {
1243             LValue value = lowCell(m_node->child1());
1244             m_out.store64(value, addressFor(data->machineLocal));
1245             break;
1246         }
1247             
1248         case FlushedBoolean: {
1249             speculateBoolean(m_node->child1());
1250             m_out.store64(
1251                 lowJSValue(m_node->child1(), ManualOperandSpeculation),
1252                 addressFor(data->machineLocal));
1253             break;
1254         }
1255             
1256         default:
1257             DFG_CRASH(m_graph, m_node, "Bad flush format");
1258             break;
1259         }
1260     }
1261     
1262     void compileNoOp()
1263     {
1264         DFG_NODE_DO_TO_CHILDREN(m_graph, m_node, speculate);
1265     }
1266     
1267     void compileToThis()
1268     {
1269         LValue value = lowJSValue(m_node->child1());
1270         
1271         LBasicBlock isCellCase = FTL_NEW_BLOCK(m_out, ("ToThis is cell case"));
1272         LBasicBlock slowCase = FTL_NEW_BLOCK(m_out, ("ToThis slow case"));
1273         LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("ToThis continuation"));
1274         
1275         m_out.branch(
1276             isCell(value, provenType(m_node->child1())), usually(isCellCase), rarely(slowCase));
1277         
1278         LBasicBlock lastNext = m_out.appendTo(isCellCase, slowCase);
1279         ValueFromBlock fastResult = m_out.anchor(value);
1280         m_out.branch(isType(value, FinalObjectType), usually(continuation), rarely(slowCase));
1281         
1282         m_out.appendTo(slowCase, continuation);
1283         J_JITOperation_EJ function;
1284         if (m_graph.isStrictModeFor(m_node->origin.semantic))
1285             function = operationToThisStrict;
1286         else
1287             function = operationToThis;
1288         ValueFromBlock slowResult = m_out.anchor(
1289             vmCall(m_out.operation(function), m_callFrame, value));
1290         m_out.jump(continuation);
1291         
1292         m_out.appendTo(continuation, lastNext);
1293         setJSValue(m_out.phi(m_out.int64, fastResult, slowResult));
1294     }
1295     
1296     void compileValueAdd()
1297     {
1298         J_JITOperation_EJJ operation;
1299         if (!(provenType(m_node->child1()) & SpecFullNumber)
1300             && !(provenType(m_node->child2()) & SpecFullNumber))
1301             operation = operationValueAddNotNumber;
1302         else
1303             operation = operationValueAdd;
1304         setJSValue(vmCall(
1305             m_out.operation(operation), m_callFrame,
1306             lowJSValue(m_node->child1()), lowJSValue(m_node->child2())));
1307     }
1308     
1309     void compileArithAddOrSub()
1310     {
1311         bool isSub =  m_node->op() == ArithSub;
1312         switch (m_node->binaryUseKind()) {
1313         case Int32Use: {
1314             LValue left = lowInt32(m_node->child1());
1315             LValue right = lowInt32(m_node->child2());
1316
1317             if (!shouldCheckOverflow(m_node->arithMode())) {
1318                 setInt32(isSub ? m_out.sub(left, right) : m_out.add(left, right));
1319                 break;
1320             }
1321
1322             LValue result;
1323             if (!isSub) {
1324                 result = m_out.addWithOverflow32(left, right);
1325                 
1326                 if (doesKill(m_node->child2())) {
1327                     addAvailableRecovery(
1328                         m_node->child2(), SubRecovery,
1329                         m_out.extractValue(result, 0), left, ValueFormatInt32);
1330                 } else if (doesKill(m_node->child1())) {
1331                     addAvailableRecovery(
1332                         m_node->child1(), SubRecovery,
1333                         m_out.extractValue(result, 0), right, ValueFormatInt32);
1334                 }
1335             } else {
1336                 result = m_out.subWithOverflow32(left, right);
1337                 
1338                 if (doesKill(m_node->child2())) {
1339                     // result = left - right
1340                     // result - left = -right
1341                     // right = left - result
1342                     addAvailableRecovery(
1343                         m_node->child2(), SubRecovery,
1344                         left, m_out.extractValue(result, 0), ValueFormatInt32);
1345                 } else if (doesKill(m_node->child1())) {
1346                     // result = left - right
1347                     // result + right = left
1348                     addAvailableRecovery(
1349                         m_node->child1(), AddRecovery,
1350                         m_out.extractValue(result, 0), right, ValueFormatInt32);
1351                 }
1352             }
1353
1354             speculate(Overflow, noValue(), 0, m_out.extractValue(result, 1));
1355             setInt32(m_out.extractValue(result, 0));
1356             break;
1357         }
1358             
1359         case Int52RepUse: {
1360             if (!abstractValue(m_node->child1()).couldBeType(SpecInt52)
1361                 && !abstractValue(m_node->child2()).couldBeType(SpecInt52)) {
1362                 Int52Kind kind;
1363                 LValue left = lowWhicheverInt52(m_node->child1(), kind);
1364                 LValue right = lowInt52(m_node->child2(), kind);
1365                 setInt52(isSub ? m_out.sub(left, right) : m_out.add(left, right), kind);
1366                 break;
1367             }
1368             
1369             LValue left = lowInt52(m_node->child1());
1370             LValue right = lowInt52(m_node->child2());
1371
1372             LValue result;
1373             if (!isSub) {
1374                 result = m_out.addWithOverflow64(left, right);
1375                 
1376                 if (doesKill(m_node->child2())) {
1377                     addAvailableRecovery(
1378                         m_node->child2(), SubRecovery,
1379                         m_out.extractValue(result, 0), left, ValueFormatInt52);
1380                 } else if (doesKill(m_node->child1())) {
1381                     addAvailableRecovery(
1382                         m_node->child1(), SubRecovery,
1383                         m_out.extractValue(result, 0), right, ValueFormatInt52);
1384                 }
1385             } else {
1386                 result = m_out.subWithOverflow64(left, right);
1387                 
1388                 if (doesKill(m_node->child2())) {
1389                     // result = left - right
1390                     // result - left = -right
1391                     // right = left - result
1392                     addAvailableRecovery(
1393                         m_node->child2(), SubRecovery,
1394                         left, m_out.extractValue(result, 0), ValueFormatInt52);
1395                 } else if (doesKill(m_node->child1())) {
1396                     // result = left - right
1397                     // result + right = left
1398                     addAvailableRecovery(
1399                         m_node->child1(), AddRecovery,
1400                         m_out.extractValue(result, 0), right, ValueFormatInt52);
1401                 }
1402             }
1403
1404             speculate(Int52Overflow, noValue(), 0, m_out.extractValue(result, 1));
1405             setInt52(m_out.extractValue(result, 0));
1406             break;
1407         }
1408             
1409         case DoubleRepUse: {
1410             LValue C1 = lowDouble(m_node->child1());
1411             LValue C2 = lowDouble(m_node->child2());
1412
1413             setDouble(isSub ? m_out.doubleSub(C1, C2) : m_out.doubleAdd(C1, C2));
1414             break;
1415         }
1416             
1417         default:
1418             DFG_CRASH(m_graph, m_node, "Bad use kind");
1419             break;
1420         }
1421     }
1422
1423     void compileArithClz32()
1424     {
1425         LValue operand = lowInt32(m_node->child1());
1426         LValue isZeroUndef = m_out.booleanFalse;
1427         setInt32(m_out.ctlz32(operand, isZeroUndef));
1428     }
1429     
1430     void compileArithMul()
1431     {
1432         switch (m_node->binaryUseKind()) {
1433         case Int32Use: {
1434             LValue left = lowInt32(m_node->child1());
1435             LValue right = lowInt32(m_node->child2());
1436             
1437             LValue result;
1438
1439             if (!shouldCheckOverflow(m_node->arithMode()))
1440                 result = m_out.mul(left, right);
1441             else {
1442                 LValue overflowResult = m_out.mulWithOverflow32(left, right);
1443                 speculate(Overflow, noValue(), 0, m_out.extractValue(overflowResult, 1));
1444                 result = m_out.extractValue(overflowResult, 0);
1445             }
1446             
1447             if (shouldCheckNegativeZero(m_node->arithMode())) {
1448                 LBasicBlock slowCase = FTL_NEW_BLOCK(m_out, ("ArithMul slow case"));
1449                 LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("ArithMul continuation"));
1450                 
1451                 m_out.branch(
1452                     m_out.notZero32(result), usually(continuation), rarely(slowCase));
1453                 
1454                 LBasicBlock lastNext = m_out.appendTo(slowCase, continuation);
1455                 LValue cond = m_out.bitOr(m_out.lessThan(left, m_out.int32Zero), m_out.lessThan(right, m_out.int32Zero));
1456                 speculate(NegativeZero, noValue(), 0, cond);
1457                 m_out.jump(continuation);
1458                 m_out.appendTo(continuation, lastNext);
1459             }
1460             
1461             setInt32(result);
1462             break;
1463         }
1464             
1465         case Int52RepUse: {
1466             Int52Kind kind;
1467             LValue left = lowWhicheverInt52(m_node->child1(), kind);
1468             LValue right = lowInt52(m_node->child2(), opposite(kind));
1469
1470             LValue overflowResult = m_out.mulWithOverflow64(left, right);
1471             speculate(Int52Overflow, noValue(), 0, m_out.extractValue(overflowResult, 1));
1472             LValue result = m_out.extractValue(overflowResult, 0);
1473
1474             if (shouldCheckNegativeZero(m_node->arithMode())) {
1475                 LBasicBlock slowCase = FTL_NEW_BLOCK(m_out, ("ArithMul slow case"));
1476                 LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("ArithMul continuation"));
1477                 
1478                 m_out.branch(
1479                     m_out.notZero64(result), usually(continuation), rarely(slowCase));
1480                 
1481                 LBasicBlock lastNext = m_out.appendTo(slowCase, continuation);
1482                 LValue cond = m_out.bitOr(m_out.lessThan(left, m_out.int64Zero), m_out.lessThan(right, m_out.int64Zero));
1483                 speculate(NegativeZero, noValue(), 0, cond);
1484                 m_out.jump(continuation);
1485                 m_out.appendTo(continuation, lastNext);
1486             }
1487             
1488             setInt52(result);
1489             break;
1490         }
1491             
1492         case DoubleRepUse: {
1493             setDouble(
1494                 m_out.doubleMul(lowDouble(m_node->child1()), lowDouble(m_node->child2())));
1495             break;
1496         }
1497             
1498         default:
1499             DFG_CRASH(m_graph, m_node, "Bad use kind");
1500             break;
1501         }
1502     }
1503
1504     void compileArithDiv()
1505     {
1506         switch (m_node->binaryUseKind()) {
1507         case Int32Use: {
1508             LValue numerator = lowInt32(m_node->child1());
1509             LValue denominator = lowInt32(m_node->child2());
1510             
1511             LBasicBlock unsafeDenominator = FTL_NEW_BLOCK(m_out, ("ArithDiv unsafe denominator"));
1512             LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("ArithDiv continuation"));
1513             LBasicBlock done = FTL_NEW_BLOCK(m_out, ("ArithDiv done"));
1514             
1515             Vector<ValueFromBlock, 3> results;
1516             
1517             LValue adjustedDenominator = m_out.add(denominator, m_out.int32One);
1518             
1519             m_out.branch(
1520                 m_out.above(adjustedDenominator, m_out.int32One),
1521                 usually(continuation), rarely(unsafeDenominator));
1522             
1523             LBasicBlock lastNext = m_out.appendTo(unsafeDenominator, continuation);
1524             
1525             LValue neg2ToThe31 = m_out.constInt32(-2147483647-1);
1526             
1527             if (shouldCheckOverflow(m_node->arithMode())) {
1528                 LValue cond = m_out.bitOr(m_out.isZero32(denominator), m_out.equal(numerator, neg2ToThe31));
1529                 speculate(Overflow, noValue(), 0, cond);
1530                 m_out.jump(continuation);
1531             } else {
1532                 // This is the case where we convert the result to an int after we're done. So,
1533                 // if the denominator is zero, then the result should be zero.
1534                 // If the denominator is not zero (i.e. it's -1 because we're guarded by the
1535                 // check above) and the numerator is -2^31 then the result should be -2^31.
1536                 
1537                 LBasicBlock divByZero = FTL_NEW_BLOCK(m_out, ("ArithDiv divide by zero"));
1538                 LBasicBlock notDivByZero = FTL_NEW_BLOCK(m_out, ("ArithDiv not divide by zero"));
1539                 LBasicBlock neg2ToThe31ByNeg1 = FTL_NEW_BLOCK(m_out, ("ArithDiv -2^31/-1"));
1540                 
1541                 m_out.branch(
1542                     m_out.isZero32(denominator), rarely(divByZero), usually(notDivByZero));
1543                 
1544                 m_out.appendTo(divByZero, notDivByZero);
1545                 results.append(m_out.anchor(m_out.int32Zero));
1546                 m_out.jump(done);
1547                 
1548                 m_out.appendTo(notDivByZero, neg2ToThe31ByNeg1);
1549                 m_out.branch(
1550                     m_out.equal(numerator, neg2ToThe31),
1551                     rarely(neg2ToThe31ByNeg1), usually(continuation));
1552                 
1553                 m_out.appendTo(neg2ToThe31ByNeg1, continuation);
1554                 results.append(m_out.anchor(neg2ToThe31));
1555                 m_out.jump(done);
1556             }
1557             
1558             m_out.appendTo(continuation, done);
1559             
1560             if (shouldCheckNegativeZero(m_node->arithMode())) {
1561                 LBasicBlock zeroNumerator = FTL_NEW_BLOCK(m_out, ("ArithDiv zero numerator"));
1562                 LBasicBlock numeratorContinuation = FTL_NEW_BLOCK(m_out, ("ArithDiv numerator continuation"));
1563                 
1564                 m_out.branch(
1565                     m_out.isZero32(numerator),
1566                     rarely(zeroNumerator), usually(numeratorContinuation));
1567                 
1568                 LBasicBlock innerLastNext = m_out.appendTo(zeroNumerator, numeratorContinuation);
1569                 
1570                 speculate(
1571                     NegativeZero, noValue(), 0, m_out.lessThan(denominator, m_out.int32Zero));
1572                 
1573                 m_out.jump(numeratorContinuation);
1574                 
1575                 m_out.appendTo(numeratorContinuation, innerLastNext);
1576             }
1577             
1578             LValue result = m_out.div(numerator, denominator);
1579             
1580             if (shouldCheckOverflow(m_node->arithMode())) {
1581                 speculate(
1582                     Overflow, noValue(), 0,
1583                     m_out.notEqual(m_out.mul(result, denominator), numerator));
1584             }
1585             
1586             results.append(m_out.anchor(result));
1587             m_out.jump(done);
1588             
1589             m_out.appendTo(done, lastNext);
1590             
1591             setInt32(m_out.phi(m_out.int32, results));
1592             break;
1593         }
1594             
1595         case DoubleRepUse: {
1596             setDouble(m_out.doubleDiv(
1597                 lowDouble(m_node->child1()), lowDouble(m_node->child2())));
1598             break;
1599         }
1600             
1601         default:
1602             DFG_CRASH(m_graph, m_node, "Bad use kind");
1603             break;
1604         }
1605     }
1606     
1607     void compileArithMod()
1608     {
1609         switch (m_node->binaryUseKind()) {
1610         case Int32Use: {
1611             LValue numerator = lowInt32(m_node->child1());
1612             LValue denominator = lowInt32(m_node->child2());
1613             
1614             LBasicBlock unsafeDenominator = FTL_NEW_BLOCK(m_out, ("ArithMod unsafe denominator"));
1615             LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("ArithMod continuation"));
1616             LBasicBlock done = FTL_NEW_BLOCK(m_out, ("ArithMod done"));
1617             
1618             Vector<ValueFromBlock, 3> results;
1619             
1620             LValue adjustedDenominator = m_out.add(denominator, m_out.int32One);
1621             
1622             m_out.branch(
1623                 m_out.above(adjustedDenominator, m_out.int32One),
1624                 usually(continuation), rarely(unsafeDenominator));
1625             
1626             LBasicBlock lastNext = m_out.appendTo(unsafeDenominator, continuation);
1627             
1628             LValue neg2ToThe31 = m_out.constInt32(-2147483647-1);
1629             
1630             // FIXME: -2^31 / -1 will actually yield negative zero, so we could have a
1631             // separate case for that. But it probably doesn't matter so much.
1632             if (shouldCheckOverflow(m_node->arithMode())) {
1633                 LValue cond = m_out.bitOr(m_out.isZero32(denominator), m_out.equal(numerator, neg2ToThe31));
1634                 speculate(Overflow, noValue(), 0, cond);
1635                 m_out.jump(continuation);
1636             } else {
1637                 // This is the case where we convert the result to an int after we're done. So,
1638                 // if the denominator is zero, then the result should be result should be zero.
1639                 // If the denominator is not zero (i.e. it's -1 because we're guarded by the
1640                 // check above) and the numerator is -2^31 then the result should be -2^31.
1641                 
1642                 LBasicBlock modByZero = FTL_NEW_BLOCK(m_out, ("ArithMod modulo by zero"));
1643                 LBasicBlock notModByZero = FTL_NEW_BLOCK(m_out, ("ArithMod not modulo by zero"));
1644                 LBasicBlock neg2ToThe31ByNeg1 = FTL_NEW_BLOCK(m_out, ("ArithMod -2^31/-1"));
1645                 
1646                 m_out.branch(
1647                     m_out.isZero32(denominator), rarely(modByZero), usually(notModByZero));
1648                 
1649                 m_out.appendTo(modByZero, notModByZero);
1650                 results.append(m_out.anchor(m_out.int32Zero));
1651                 m_out.jump(done);
1652                 
1653                 m_out.appendTo(notModByZero, neg2ToThe31ByNeg1);
1654                 m_out.branch(
1655                     m_out.equal(numerator, neg2ToThe31),
1656                     rarely(neg2ToThe31ByNeg1), usually(continuation));
1657                 
1658                 m_out.appendTo(neg2ToThe31ByNeg1, continuation);
1659                 results.append(m_out.anchor(m_out.int32Zero));
1660                 m_out.jump(done);
1661             }
1662             
1663             m_out.appendTo(continuation, done);
1664             
1665             LValue remainder = m_out.rem(numerator, denominator);
1666             
1667             if (shouldCheckNegativeZero(m_node->arithMode())) {
1668                 LBasicBlock negativeNumerator = FTL_NEW_BLOCK(m_out, ("ArithMod negative numerator"));
1669                 LBasicBlock numeratorContinuation = FTL_NEW_BLOCK(m_out, ("ArithMod numerator continuation"));
1670                 
1671                 m_out.branch(
1672                     m_out.lessThan(numerator, m_out.int32Zero),
1673                     unsure(negativeNumerator), unsure(numeratorContinuation));
1674                 
1675                 LBasicBlock innerLastNext = m_out.appendTo(negativeNumerator, numeratorContinuation);
1676                 
1677                 speculate(NegativeZero, noValue(), 0, m_out.isZero32(remainder));
1678                 
1679                 m_out.jump(numeratorContinuation);
1680                 
1681                 m_out.appendTo(numeratorContinuation, innerLastNext);
1682             }
1683             
1684             results.append(m_out.anchor(remainder));
1685             m_out.jump(done);
1686             
1687             m_out.appendTo(done, lastNext);
1688             
1689             setInt32(m_out.phi(m_out.int32, results));
1690             break;
1691         }
1692             
1693         case DoubleRepUse: {
1694             setDouble(
1695                 m_out.doubleRem(lowDouble(m_node->child1()), lowDouble(m_node->child2())));
1696             break;
1697         }
1698             
1699         default:
1700             DFG_CRASH(m_graph, m_node, "Bad use kind");
1701             break;
1702         }
1703     }
1704
1705     void compileArithMinOrMax()
1706     {
1707         switch (m_node->binaryUseKind()) {
1708         case Int32Use: {
1709             LValue left = lowInt32(m_node->child1());
1710             LValue right = lowInt32(m_node->child2());
1711             
1712             setInt32(
1713                 m_out.select(
1714                     m_node->op() == ArithMin
1715                         ? m_out.lessThan(left, right)
1716                         : m_out.lessThan(right, left),
1717                     left, right));
1718             break;
1719         }
1720             
1721         case DoubleRepUse: {
1722             LValue left = lowDouble(m_node->child1());
1723             LValue right = lowDouble(m_node->child2());
1724             
1725             LBasicBlock notLessThan = FTL_NEW_BLOCK(m_out, ("ArithMin/ArithMax not less than"));
1726             LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("ArithMin/ArithMax continuation"));
1727             
1728             Vector<ValueFromBlock, 2> results;
1729             
1730             results.append(m_out.anchor(left));
1731             m_out.branch(
1732                 m_node->op() == ArithMin
1733                     ? m_out.doubleLessThan(left, right)
1734                     : m_out.doubleGreaterThan(left, right),
1735                 unsure(continuation), unsure(notLessThan));
1736             
1737             LBasicBlock lastNext = m_out.appendTo(notLessThan, continuation);
1738             results.append(m_out.anchor(m_out.select(
1739                 m_node->op() == ArithMin
1740                     ? m_out.doubleGreaterThanOrEqual(left, right)
1741                     : m_out.doubleLessThanOrEqual(left, right),
1742                 right, m_out.constDouble(PNaN))));
1743             m_out.jump(continuation);
1744             
1745             m_out.appendTo(continuation, lastNext);
1746             setDouble(m_out.phi(m_out.doubleType, results));
1747             break;
1748         }
1749             
1750         default:
1751             DFG_CRASH(m_graph, m_node, "Bad use kind");
1752             break;
1753         }
1754     }
1755     
1756     void compileArithAbs()
1757     {
1758         switch (m_node->child1().useKind()) {
1759         case Int32Use: {
1760             LValue value = lowInt32(m_node->child1());
1761             
1762             LValue mask = m_out.aShr(value, m_out.constInt32(31));
1763             LValue result = m_out.bitXor(mask, m_out.add(mask, value));
1764             
1765             speculate(Overflow, noValue(), 0, m_out.equal(result, m_out.constInt32(1 << 31)));
1766             
1767             setInt32(result);
1768             break;
1769         }
1770             
1771         case DoubleRepUse: {
1772             setDouble(m_out.doubleAbs(lowDouble(m_node->child1())));
1773             break;
1774         }
1775             
1776         default:
1777             DFG_CRASH(m_graph, m_node, "Bad use kind");
1778             break;
1779         }
1780     }
1781
1782     void compileArithSin() { setDouble(m_out.doubleSin(lowDouble(m_node->child1()))); }
1783
1784     void compileArithCos() { setDouble(m_out.doubleCos(lowDouble(m_node->child1()))); }
1785
1786     void compileArithPow()
1787     {
1788         // FIXME: investigate llvm.powi to better understand its performance characteristics.
1789         // It might be better to have the inline loop in DFG too.
1790         if (m_node->child2().useKind() == Int32Use)
1791             setDouble(m_out.doublePowi(lowDouble(m_node->child1()), lowInt32(m_node->child2())));
1792         else {
1793             LValue base = lowDouble(m_node->child1());
1794             LValue exponent = lowDouble(m_node->child2());
1795
1796             LBasicBlock integerExponentIsSmallBlock = FTL_NEW_BLOCK(m_out, ("ArithPow test integer exponent is small."));
1797             LBasicBlock integerExponentPowBlock = FTL_NEW_BLOCK(m_out, ("ArithPow pow(double, (int)double)."));
1798             LBasicBlock doubleExponentPowBlockEntry = FTL_NEW_BLOCK(m_out, ("ArithPow pow(double, double)."));
1799             LBasicBlock nanExceptionExponentIsInfinity = FTL_NEW_BLOCK(m_out, ("ArithPow NaN Exception, check exponent is infinity."));
1800             LBasicBlock nanExceptionBaseIsOne = FTL_NEW_BLOCK(m_out, ("ArithPow NaN Exception, check base is one."));
1801             LBasicBlock powBlock = FTL_NEW_BLOCK(m_out, ("ArithPow regular pow"));
1802             LBasicBlock nanExceptionResultIsNaN = FTL_NEW_BLOCK(m_out, ("ArithPow NaN Exception, result is NaN."));
1803             LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("ArithPow continuation"));
1804
1805             LValue integerExponent = m_out.fpToInt32(exponent);
1806             LValue integerExponentConvertedToDouble = m_out.intToDouble(integerExponent);
1807             LValue exponentIsInteger = m_out.doubleEqual(exponent, integerExponentConvertedToDouble);
1808             m_out.branch(exponentIsInteger, unsure(integerExponentIsSmallBlock), unsure(doubleExponentPowBlockEntry));
1809
1810             LBasicBlock lastNext = m_out.appendTo(integerExponentIsSmallBlock, integerExponentPowBlock);
1811             LValue integerExponentBelow1000 = m_out.below(integerExponent, m_out.constInt32(1000));
1812             m_out.branch(integerExponentBelow1000, usually(integerExponentPowBlock), rarely(doubleExponentPowBlockEntry));
1813
1814             m_out.appendTo(integerExponentPowBlock, doubleExponentPowBlockEntry);
1815             ValueFromBlock powDoubleIntResult = m_out.anchor(m_out.doublePowi(base, integerExponent));
1816             m_out.jump(continuation);
1817
1818             // If y is NaN, the result is NaN.
1819             m_out.appendTo(doubleExponentPowBlockEntry, nanExceptionExponentIsInfinity);
1820             LValue exponentIsNaN;
1821             if (provenType(m_node->child2()) & SpecDoubleNaN)
1822                 exponentIsNaN = m_out.doubleNotEqualOrUnordered(exponent, exponent);
1823             else
1824                 exponentIsNaN = m_out.booleanFalse;
1825             m_out.branch(exponentIsNaN, rarely(nanExceptionResultIsNaN), usually(nanExceptionExponentIsInfinity));
1826
1827             // If abs(x) is 1 and y is +infinity, the result is NaN.
1828             // If abs(x) is 1 and y is -infinity, the result is NaN.
1829             m_out.appendTo(nanExceptionExponentIsInfinity, nanExceptionBaseIsOne);
1830             LValue absoluteExponent = m_out.doubleAbs(exponent);
1831             LValue absoluteExponentIsInfinity = m_out.doubleEqual(absoluteExponent, m_out.constDouble(std::numeric_limits<double>::infinity()));
1832             m_out.branch(absoluteExponentIsInfinity, rarely(nanExceptionBaseIsOne), usually(powBlock));
1833
1834             m_out.appendTo(nanExceptionBaseIsOne, powBlock);
1835             LValue absoluteBase = m_out.doubleAbs(base);
1836             LValue absoluteBaseIsOne = m_out.doubleEqual(absoluteBase, m_out.constDouble(1));
1837             m_out.branch(absoluteBaseIsOne, unsure(nanExceptionResultIsNaN), unsure(powBlock));
1838
1839             m_out.appendTo(powBlock, nanExceptionResultIsNaN);
1840             ValueFromBlock powResult = m_out.anchor(m_out.doublePow(base, exponent));
1841             m_out.jump(continuation);
1842
1843             m_out.appendTo(nanExceptionResultIsNaN, continuation);
1844             ValueFromBlock pureNan = m_out.anchor(m_out.constDouble(PNaN));
1845             m_out.jump(continuation);
1846
1847             m_out.appendTo(continuation, lastNext);
1848             setDouble(m_out.phi(m_out.doubleType, powDoubleIntResult, powResult, pureNan));
1849         }
1850     }
1851
1852     void compileArithRound()
1853     {
1854         LBasicBlock realPartIsMoreThanHalf = FTL_NEW_BLOCK(m_out, ("ArithRound should round down"));
1855         LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("ArithRound continuation"));
1856
1857         LValue value = lowDouble(m_node->child1());
1858         LValue integerValue = m_out.ceil64(value);
1859         ValueFromBlock integerValueResult = m_out.anchor(integerValue);
1860
1861         LValue realPart = m_out.doubleSub(integerValue, value);
1862
1863         m_out.branch(m_out.doubleGreaterThanOrUnordered(realPart, m_out.constDouble(0.5)), unsure(realPartIsMoreThanHalf), unsure(continuation));
1864
1865         LBasicBlock lastNext = m_out.appendTo(realPartIsMoreThanHalf, continuation);
1866         LValue integerValueRoundedDown = m_out.doubleSub(integerValue, m_out.constDouble(1));
1867         ValueFromBlock integerValueRoundedDownResult = m_out.anchor(integerValueRoundedDown);
1868         m_out.jump(continuation);
1869         m_out.appendTo(continuation, lastNext);
1870
1871         LValue result = m_out.phi(m_out.doubleType, integerValueResult, integerValueRoundedDownResult);
1872
1873         if (producesInteger(m_node->arithRoundingMode())) {
1874             LValue integerValue = convertDoubleToInt32(result, shouldCheckNegativeZero(m_node->arithRoundingMode()));
1875             setInt32(integerValue);
1876         } else
1877             setDouble(result);
1878     }
1879
1880     void compileArithSqrt() { setDouble(m_out.doubleSqrt(lowDouble(m_node->child1()))); }
1881
1882     void compileArithLog() { setDouble(m_out.doubleLog(lowDouble(m_node->child1()))); }
1883     
1884     void compileArithFRound()
1885     {
1886         LValue floatValue = m_out.fpCast(lowDouble(m_node->child1()), m_out.floatType);
1887         setDouble(m_out.fpCast(floatValue, m_out.doubleType));
1888     }
1889     
1890     void compileArithNegate()
1891     {
1892         switch (m_node->child1().useKind()) {
1893         case Int32Use: {
1894             LValue value = lowInt32(m_node->child1());
1895             
1896             LValue result;
1897             if (!shouldCheckOverflow(m_node->arithMode()))
1898                 result = m_out.neg(value);
1899             else if (!shouldCheckNegativeZero(m_node->arithMode())) {
1900                 // We don't have a negate-with-overflow intrinsic. Hopefully this
1901                 // does the trick, though.
1902                 LValue overflowResult = m_out.subWithOverflow32(m_out.int32Zero, value);
1903                 speculate(Overflow, noValue(), 0, m_out.extractValue(overflowResult, 1));
1904                 result = m_out.extractValue(overflowResult, 0);
1905             } else {
1906                 speculate(Overflow, noValue(), 0, m_out.testIsZero32(value, m_out.constInt32(0x7fffffff)));
1907                 result = m_out.neg(value);
1908             }
1909
1910             setInt32(result);
1911             break;
1912         }
1913             
1914         case Int52RepUse: {
1915             if (!abstractValue(m_node->child1()).couldBeType(SpecInt52)) {
1916                 Int52Kind kind;
1917                 LValue value = lowWhicheverInt52(m_node->child1(), kind);
1918                 LValue result = m_out.neg(value);
1919                 if (shouldCheckNegativeZero(m_node->arithMode()))
1920                     speculate(NegativeZero, noValue(), 0, m_out.isZero64(result));
1921                 setInt52(result, kind);
1922                 break;
1923             }
1924             
1925             LValue value = lowInt52(m_node->child1());
1926             LValue overflowResult = m_out.subWithOverflow64(m_out.int64Zero, value);
1927             speculate(Int52Overflow, noValue(), 0, m_out.extractValue(overflowResult, 1));
1928             LValue result = m_out.extractValue(overflowResult, 0);
1929             speculate(NegativeZero, noValue(), 0, m_out.isZero64(result));
1930             setInt52(result);
1931             break;
1932         }
1933             
1934         case DoubleRepUse: {
1935             setDouble(m_out.doubleNeg(lowDouble(m_node->child1())));
1936             break;
1937         }
1938             
1939         default:
1940             DFG_CRASH(m_graph, m_node, "Bad use kind");
1941             break;
1942         }
1943     }
1944     
1945     void compileBitAnd()
1946     {
1947         setInt32(m_out.bitAnd(lowInt32(m_node->child1()), lowInt32(m_node->child2())));
1948     }
1949     
1950     void compileBitOr()
1951     {
1952         setInt32(m_out.bitOr(lowInt32(m_node->child1()), lowInt32(m_node->child2())));
1953     }
1954     
1955     void compileBitXor()
1956     {
1957         setInt32(m_out.bitXor(lowInt32(m_node->child1()), lowInt32(m_node->child2())));
1958     }
1959     
1960     void compileBitRShift()
1961     {
1962         setInt32(m_out.aShr(
1963             lowInt32(m_node->child1()),
1964             m_out.bitAnd(lowInt32(m_node->child2()), m_out.constInt32(31))));
1965     }
1966     
1967     void compileBitLShift()
1968     {
1969         setInt32(m_out.shl(
1970             lowInt32(m_node->child1()),
1971             m_out.bitAnd(lowInt32(m_node->child2()), m_out.constInt32(31))));
1972     }
1973     
1974     void compileBitURShift()
1975     {
1976         setInt32(m_out.lShr(
1977             lowInt32(m_node->child1()),
1978             m_out.bitAnd(lowInt32(m_node->child2()), m_out.constInt32(31))));
1979     }
1980     
1981     void compileUInt32ToNumber()
1982     {
1983         LValue value = lowInt32(m_node->child1());
1984
1985         if (doesOverflow(m_node->arithMode())) {
1986             setDouble(m_out.unsignedToDouble(value));
1987             return;
1988         }
1989         
1990         speculate(Overflow, noValue(), 0, m_out.lessThan(value, m_out.int32Zero));
1991         setInt32(value);
1992     }
1993     
1994     void compileCheckStructure()
1995     {
1996         LValue cell = lowCell(m_node->child1());
1997         
1998         ExitKind exitKind;
1999         if (m_node->child1()->hasConstant())
2000             exitKind = BadConstantCache;
2001         else
2002             exitKind = BadCache;
2003         
2004         LValue structureID = m_out.load32(cell, m_heaps.JSCell_structureID);
2005         
2006         checkStructure(
2007             structureID, jsValueValue(cell), exitKind, m_node->structureSet(),
2008             [this] (Structure* structure) {
2009                 return weakStructureID(structure);
2010             });
2011     }
2012     
2013     void compileCheckCell()
2014     {
2015         LValue cell = lowCell(m_node->child1());
2016         
2017         speculate(
2018             BadCell, jsValueValue(cell), m_node->child1().node(),
2019             m_out.notEqual(cell, weakPointer(m_node->cellOperand()->cell())));
2020     }
2021     
2022     void compileCheckBadCell()
2023     {
2024         terminate(BadCell);
2025     }
2026
2027     void compileCheckNotEmpty()
2028     {
2029         speculate(TDZFailure, noValue(), nullptr, m_out.isZero64(lowJSValue(m_node->child1())));
2030     }
2031
2032     void compileGetExecutable()
2033     {
2034         LValue cell = lowCell(m_node->child1());
2035         speculateFunction(m_node->child1(), cell);
2036         setJSValue(m_out.loadPtr(cell, m_heaps.JSFunction_executable));
2037     }
2038     
2039     void compileArrayifyToStructure()
2040     {
2041         LValue cell = lowCell(m_node->child1());
2042         LValue property = !!m_node->child2() ? lowInt32(m_node->child2()) : 0;
2043         
2044         LBasicBlock unexpectedStructure = FTL_NEW_BLOCK(m_out, ("ArrayifyToStructure unexpected structure"));
2045         LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("ArrayifyToStructure continuation"));
2046         
2047         LValue structureID = m_out.load32(cell, m_heaps.JSCell_structureID);
2048         
2049         m_out.branch(
2050             m_out.notEqual(structureID, weakStructureID(m_node->structure())),
2051             rarely(unexpectedStructure), usually(continuation));
2052         
2053         LBasicBlock lastNext = m_out.appendTo(unexpectedStructure, continuation);
2054         
2055         if (property) {
2056             switch (m_node->arrayMode().type()) {
2057             case Array::Int32:
2058             case Array::Double:
2059             case Array::Contiguous:
2060                 speculate(
2061                     Uncountable, noValue(), 0,
2062                     m_out.aboveOrEqual(property, m_out.constInt32(MIN_SPARSE_ARRAY_INDEX)));
2063                 break;
2064             default:
2065                 break;
2066             }
2067         }
2068         
2069         switch (m_node->arrayMode().type()) {
2070         case Array::Int32:
2071             vmCall(m_out.operation(operationEnsureInt32), m_callFrame, cell);
2072             break;
2073         case Array::Double:
2074             vmCall(m_out.operation(operationEnsureDouble), m_callFrame, cell);
2075             break;
2076         case Array::Contiguous:
2077             vmCall(m_out.operation(operationEnsureContiguous), m_callFrame, cell);
2078             break;
2079         case Array::ArrayStorage:
2080         case Array::SlowPutArrayStorage:
2081             vmCall(m_out.operation(operationEnsureArrayStorage), m_callFrame, cell);
2082             break;
2083         default:
2084             DFG_CRASH(m_graph, m_node, "Bad array type");
2085             break;
2086         }
2087         
2088         structureID = m_out.load32(cell, m_heaps.JSCell_structureID);
2089         speculate(
2090             BadIndexingType, jsValueValue(cell), 0,
2091             m_out.notEqual(structureID, weakStructureID(m_node->structure())));
2092         m_out.jump(continuation);
2093         
2094         m_out.appendTo(continuation, lastNext);
2095     }
2096     
2097     void compilePutStructure()
2098     {
2099         m_ftlState.jitCode->common.notifyCompilingStructureTransition(m_graph.m_plan, codeBlock(), m_node);
2100
2101         Structure* oldStructure = m_node->transition()->previous;
2102         Structure* newStructure = m_node->transition()->next;
2103         ASSERT_UNUSED(oldStructure, oldStructure->indexingType() == newStructure->indexingType());
2104         ASSERT(oldStructure->typeInfo().inlineTypeFlags() == newStructure->typeInfo().inlineTypeFlags());
2105         ASSERT(oldStructure->typeInfo().type() == newStructure->typeInfo().type());
2106
2107         LValue cell = lowCell(m_node->child1()); 
2108         m_out.store32(
2109             weakStructureID(newStructure),
2110             cell, m_heaps.JSCell_structureID);
2111     }
2112     
2113     void compileGetById()
2114     {
2115         // Pretty much the only reason why we don't also support GetByIdFlush is because:
2116         // https://bugs.webkit.org/show_bug.cgi?id=125711
2117         
2118         switch (m_node->child1().useKind()) {
2119         case CellUse: {
2120             setJSValue(getById(lowCell(m_node->child1())));
2121             return;
2122         }
2123             
2124         case UntypedUse: {
2125             // This is pretty weird, since we duplicate the slow path both here and in the
2126             // code generated by the IC. We should investigate making this less bad.
2127             // https://bugs.webkit.org/show_bug.cgi?id=127830
2128             LValue value = lowJSValue(m_node->child1());
2129             
2130             LBasicBlock cellCase = FTL_NEW_BLOCK(m_out, ("GetById untyped cell case"));
2131             LBasicBlock notCellCase = FTL_NEW_BLOCK(m_out, ("GetById untyped not cell case"));
2132             LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("GetById untyped continuation"));
2133             
2134             m_out.branch(
2135                 isCell(value, provenType(m_node->child1())), unsure(cellCase), unsure(notCellCase));
2136             
2137             LBasicBlock lastNext = m_out.appendTo(cellCase, notCellCase);
2138             ValueFromBlock cellResult = m_out.anchor(getById(value));
2139             m_out.jump(continuation);
2140             
2141             m_out.appendTo(notCellCase, continuation);
2142             ValueFromBlock notCellResult = m_out.anchor(vmCall(
2143                 m_out.operation(operationGetByIdGeneric),
2144                 m_callFrame, value,
2145                 m_out.constIntPtr(m_graph.identifiers()[m_node->identifierNumber()])));
2146             m_out.jump(continuation);
2147             
2148             m_out.appendTo(continuation, lastNext);
2149             setJSValue(m_out.phi(m_out.int64, cellResult, notCellResult));
2150             return;
2151         }
2152             
2153         default:
2154             DFG_CRASH(m_graph, m_node, "Bad use kind");
2155             return;
2156         }
2157     }
2158     
2159     void compilePutById()
2160     {
2161         // See above; CellUse is easier so we do only that for now.
2162         ASSERT(m_node->child1().useKind() == CellUse);
2163         
2164         LValue base = lowCell(m_node->child1());
2165         LValue value = lowJSValue(m_node->child2());
2166         auto uid = m_graph.identifiers()[m_node->identifierNumber()];
2167
2168         // Arguments: id, bytes, target, numArgs, args...
2169         unsigned stackmapID = m_stackmapIDs++;
2170
2171         if (verboseCompilationEnabled())
2172             dataLog("    Emitting PutById patchpoint with stackmap #", stackmapID, "\n");
2173         
2174         LValue call = m_out.call(
2175             m_out.patchpointVoidIntrinsic(),
2176             m_out.constInt64(stackmapID), m_out.constInt32(sizeOfPutById()),
2177             constNull(m_out.ref8), m_out.constInt32(2), base, value);
2178         setInstructionCallingConvention(call, LLVMAnyRegCallConv);
2179         
2180         m_ftlState.putByIds.append(PutByIdDescriptor(
2181             stackmapID, m_node->origin.semantic, uid,
2182             m_graph.executableFor(m_node->origin.semantic)->ecmaMode(),
2183             m_node->op() == PutByIdDirect ? Direct : NotDirect));
2184     }
2185     
2186     void compileGetButterfly()
2187     {
2188         setStorage(m_out.loadPtr(lowCell(m_node->child1()), m_heaps.JSObject_butterfly));
2189     }
2190     
2191     void compileConstantStoragePointer()
2192     {
2193         setStorage(m_out.constIntPtr(m_node->storagePointer()));
2194     }
2195     
2196     void compileGetIndexedPropertyStorage()
2197     {
2198         LValue cell = lowCell(m_node->child1());
2199         
2200         if (m_node->arrayMode().type() == Array::String) {
2201             LBasicBlock slowPath = FTL_NEW_BLOCK(m_out, ("GetIndexedPropertyStorage String slow case"));
2202             LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("GetIndexedPropertyStorage String continuation"));
2203             
2204             ValueFromBlock fastResult = m_out.anchor(
2205                 m_out.loadPtr(cell, m_heaps.JSString_value));
2206             
2207             m_out.branch(
2208                 m_out.notNull(fastResult.value()), usually(continuation), rarely(slowPath));
2209             
2210             LBasicBlock lastNext = m_out.appendTo(slowPath, continuation);
2211             
2212             ValueFromBlock slowResult = m_out.anchor(
2213                 vmCall(m_out.operation(operationResolveRope), m_callFrame, cell));
2214             
2215             m_out.jump(continuation);
2216             
2217             m_out.appendTo(continuation, lastNext);
2218             
2219             setStorage(m_out.loadPtr(m_out.phi(m_out.intPtr, fastResult, slowResult), m_heaps.StringImpl_data));
2220             return;
2221         }
2222         
2223         setStorage(m_out.loadPtr(cell, m_heaps.JSArrayBufferView_vector));
2224     }
2225     
2226     void compileCheckArray()
2227     {
2228         Edge edge = m_node->child1();
2229         LValue cell = lowCell(edge);
2230         
2231         if (m_node->arrayMode().alreadyChecked(m_graph, m_node, abstractValue(edge)))
2232             return;
2233         
2234         speculate(
2235             BadIndexingType, jsValueValue(cell), 0,
2236             m_out.bitNot(isArrayType(cell, m_node->arrayMode())));
2237     }
2238
2239     void compileGetTypedArrayByteOffset()
2240     {
2241         LValue basePtr = lowCell(m_node->child1());    
2242
2243         LBasicBlock simpleCase = FTL_NEW_BLOCK(m_out, ("wasteless typed array"));
2244         LBasicBlock wastefulCase = FTL_NEW_BLOCK(m_out, ("wasteful typed array"));
2245         LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("continuation branch"));
2246         
2247         LValue mode = m_out.load32(basePtr, m_heaps.JSArrayBufferView_mode);
2248         m_out.branch(
2249             m_out.notEqual(mode, m_out.constInt32(WastefulTypedArray)),
2250             unsure(simpleCase), unsure(wastefulCase));
2251
2252         // begin simple case        
2253         LBasicBlock lastNext = m_out.appendTo(simpleCase, wastefulCase);
2254
2255         ValueFromBlock simpleOut = m_out.anchor(m_out.constIntPtr(0));
2256
2257         m_out.jump(continuation);
2258
2259         // begin wasteful case
2260         m_out.appendTo(wastefulCase, continuation);
2261
2262         LValue vectorPtr = m_out.loadPtr(basePtr, m_heaps.JSArrayBufferView_vector);
2263         LValue butterflyPtr = m_out.loadPtr(basePtr, m_heaps.JSObject_butterfly);
2264         LValue arrayBufferPtr = m_out.loadPtr(butterflyPtr, m_heaps.Butterfly_arrayBuffer);
2265         LValue dataPtr = m_out.loadPtr(arrayBufferPtr, m_heaps.ArrayBuffer_data);
2266
2267         ValueFromBlock wastefulOut = m_out.anchor(m_out.sub(vectorPtr, dataPtr));
2268
2269         m_out.jump(continuation);
2270         m_out.appendTo(continuation, lastNext);
2271
2272         // output
2273         setInt32(m_out.castToInt32(m_out.phi(m_out.intPtr, simpleOut, wastefulOut)));
2274     }
2275     
2276     void compileGetArrayLength()
2277     {
2278         switch (m_node->arrayMode().type()) {
2279         case Array::Int32:
2280         case Array::Double:
2281         case Array::Contiguous: {
2282             setInt32(m_out.load32NonNegative(lowStorage(m_node->child2()), m_heaps.Butterfly_publicLength));
2283             return;
2284         }
2285             
2286         case Array::String: {
2287             LValue string = lowCell(m_node->child1());
2288             setInt32(m_out.load32NonNegative(string, m_heaps.JSString_length));
2289             return;
2290         }
2291             
2292         case Array::DirectArguments: {
2293             LValue arguments = lowCell(m_node->child1());
2294             speculate(
2295                 ExoticObjectMode, noValue(), nullptr,
2296                 m_out.notNull(m_out.loadPtr(arguments, m_heaps.DirectArguments_overrides)));
2297             setInt32(m_out.load32NonNegative(arguments, m_heaps.DirectArguments_length));
2298             return;
2299         }
2300             
2301         case Array::ScopedArguments: {
2302             LValue arguments = lowCell(m_node->child1());
2303             speculate(
2304                 ExoticObjectMode, noValue(), nullptr,
2305                 m_out.notZero8(m_out.load8(arguments, m_heaps.ScopedArguments_overrodeThings)));
2306             setInt32(m_out.load32NonNegative(arguments, m_heaps.ScopedArguments_totalLength));
2307             return;
2308         }
2309             
2310         default:
2311             if (isTypedView(m_node->arrayMode().typedArrayType())) {
2312                 setInt32(
2313                     m_out.load32NonNegative(lowCell(m_node->child1()), m_heaps.JSArrayBufferView_length));
2314                 return;
2315             }
2316             
2317             DFG_CRASH(m_graph, m_node, "Bad array type");
2318             return;
2319         }
2320     }
2321     
2322     void compileCheckInBounds()
2323     {
2324         speculate(
2325             OutOfBounds, noValue(), 0,
2326             m_out.aboveOrEqual(lowInt32(m_node->child1()), lowInt32(m_node->child2())));
2327     }
2328     
2329     void compileGetByVal()
2330     {
2331         switch (m_node->arrayMode().type()) {
2332         case Array::Int32:
2333         case Array::Contiguous: {
2334             LValue index = lowInt32(m_node->child2());
2335             LValue storage = lowStorage(m_node->child3());
2336             
2337             IndexedAbstractHeap& heap = m_node->arrayMode().type() == Array::Int32 ?
2338                 m_heaps.indexedInt32Properties : m_heaps.indexedContiguousProperties;
2339             
2340             if (m_node->arrayMode().isInBounds()) {
2341                 LValue result = m_out.load64(baseIndex(heap, storage, index, m_node->child2()));
2342                 LValue isHole = m_out.isZero64(result);
2343                 if (m_node->arrayMode().isSaneChain()) {
2344                     DFG_ASSERT(
2345                         m_graph, m_node, m_node->arrayMode().type() == Array::Contiguous);
2346                     result = m_out.select(
2347                         isHole, m_out.constInt64(JSValue::encode(jsUndefined())), result);
2348                 } else
2349                     speculate(LoadFromHole, noValue(), 0, isHole);
2350                 setJSValue(result);
2351                 return;
2352             }
2353             
2354             LValue base = lowCell(m_node->child1());
2355             
2356             LBasicBlock fastCase = FTL_NEW_BLOCK(m_out, ("GetByVal int/contiguous fast case"));
2357             LBasicBlock slowCase = FTL_NEW_BLOCK(m_out, ("GetByVal int/contiguous slow case"));
2358             LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("GetByVal int/contiguous continuation"));
2359             
2360             m_out.branch(
2361                 m_out.aboveOrEqual(
2362                     index, m_out.load32NonNegative(storage, m_heaps.Butterfly_publicLength)),
2363                 rarely(slowCase), usually(fastCase));
2364             
2365             LBasicBlock lastNext = m_out.appendTo(fastCase, slowCase);
2366             
2367             ValueFromBlock fastResult = m_out.anchor(
2368                 m_out.load64(baseIndex(heap, storage, index, m_node->child2())));
2369             m_out.branch(
2370                 m_out.isZero64(fastResult.value()), rarely(slowCase), usually(continuation));
2371             
2372             m_out.appendTo(slowCase, continuation);
2373             ValueFromBlock slowResult = m_out.anchor(
2374                 vmCall(m_out.operation(operationGetByValArrayInt), m_callFrame, base, index));
2375             m_out.jump(continuation);
2376             
2377             m_out.appendTo(continuation, lastNext);
2378             setJSValue(m_out.phi(m_out.int64, fastResult, slowResult));
2379             return;
2380         }
2381             
2382         case Array::Double: {
2383             LValue index = lowInt32(m_node->child2());
2384             LValue storage = lowStorage(m_node->child3());
2385             
2386             IndexedAbstractHeap& heap = m_heaps.indexedDoubleProperties;
2387             
2388             if (m_node->arrayMode().isInBounds()) {
2389                 LValue result = m_out.loadDouble(
2390                     baseIndex(heap, storage, index, m_node->child2()));
2391                 
2392                 if (!m_node->arrayMode().isSaneChain()) {
2393                     speculate(
2394                         LoadFromHole, noValue(), 0,
2395                         m_out.doubleNotEqualOrUnordered(result, result));
2396                 }
2397                 setDouble(result);
2398                 break;
2399             }
2400             
2401             LValue base = lowCell(m_node->child1());
2402             
2403             LBasicBlock inBounds = FTL_NEW_BLOCK(m_out, ("GetByVal double in bounds"));
2404             LBasicBlock boxPath = FTL_NEW_BLOCK(m_out, ("GetByVal double boxing"));
2405             LBasicBlock slowCase = FTL_NEW_BLOCK(m_out, ("GetByVal double slow case"));
2406             LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("GetByVal double continuation"));
2407             
2408             m_out.branch(
2409                 m_out.aboveOrEqual(
2410                     index, m_out.load32NonNegative(storage, m_heaps.Butterfly_publicLength)),
2411                 rarely(slowCase), usually(inBounds));
2412             
2413             LBasicBlock lastNext = m_out.appendTo(inBounds, boxPath);
2414             LValue doubleValue = m_out.loadDouble(
2415                 baseIndex(heap, storage, index, m_node->child2()));
2416             m_out.branch(
2417                 m_out.doubleNotEqualOrUnordered(doubleValue, doubleValue),
2418                 rarely(slowCase), usually(boxPath));
2419             
2420             m_out.appendTo(boxPath, slowCase);
2421             ValueFromBlock fastResult = m_out.anchor(boxDouble(doubleValue));
2422             m_out.jump(continuation);
2423             
2424             m_out.appendTo(slowCase, continuation);
2425             ValueFromBlock slowResult = m_out.anchor(
2426                 vmCall(m_out.operation(operationGetByValArrayInt), m_callFrame, base, index));
2427             m_out.jump(continuation);
2428             
2429             m_out.appendTo(continuation, lastNext);
2430             setJSValue(m_out.phi(m_out.int64, fastResult, slowResult));
2431             return;
2432         }
2433             
2434         case Array::DirectArguments: {
2435             LValue base = lowCell(m_node->child1());
2436             LValue index = lowInt32(m_node->child2());
2437             
2438             speculate(
2439                 ExoticObjectMode, noValue(), nullptr,
2440                 m_out.notNull(m_out.loadPtr(base, m_heaps.DirectArguments_overrides)));
2441             speculate(
2442                 ExoticObjectMode, noValue(), nullptr,
2443                 m_out.aboveOrEqual(
2444                     index,
2445                     m_out.load32NonNegative(base, m_heaps.DirectArguments_length)));
2446
2447             TypedPointer address = m_out.baseIndex(
2448                 m_heaps.DirectArguments_storage, base, m_out.zeroExtPtr(index));
2449             setJSValue(m_out.load64(address));
2450             return;
2451         }
2452             
2453         case Array::ScopedArguments: {
2454             LValue base = lowCell(m_node->child1());
2455             LValue index = lowInt32(m_node->child2());
2456             
2457             speculate(
2458                 ExoticObjectMode, noValue(), nullptr,
2459                 m_out.aboveOrEqual(
2460                     index,
2461                     m_out.load32NonNegative(base, m_heaps.ScopedArguments_totalLength)));
2462             
2463             LValue table = m_out.loadPtr(base, m_heaps.ScopedArguments_table);
2464             LValue namedLength = m_out.load32(table, m_heaps.ScopedArgumentsTable_length);
2465             
2466             LBasicBlock namedCase = FTL_NEW_BLOCK(m_out, ("GetByVal ScopedArguments named case"));
2467             LBasicBlock overflowCase = FTL_NEW_BLOCK(m_out, ("GetByVal ScopedArguments overflow case"));
2468             LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("GetByVal ScopedArguments continuation"));
2469             
2470             m_out.branch(
2471                 m_out.aboveOrEqual(index, namedLength), unsure(overflowCase), unsure(namedCase));
2472             
2473             LBasicBlock lastNext = m_out.appendTo(namedCase, overflowCase);
2474             
2475             LValue scope = m_out.loadPtr(base, m_heaps.ScopedArguments_scope);
2476             LValue arguments = m_out.loadPtr(table, m_heaps.ScopedArgumentsTable_arguments);
2477             
2478             TypedPointer address = m_out.baseIndex(
2479                 m_heaps.scopedArgumentsTableArguments, arguments, m_out.zeroExtPtr(index));
2480             LValue scopeOffset = m_out.load32(address);
2481             
2482             speculate(
2483                 ExoticObjectMode, noValue(), nullptr,
2484                 m_out.equal(scopeOffset, m_out.constInt32(ScopeOffset::invalidOffset)));
2485             
2486             address = m_out.baseIndex(
2487                 m_heaps.JSEnvironmentRecord_variables, scope, m_out.zeroExtPtr(scopeOffset));
2488             ValueFromBlock namedResult = m_out.anchor(m_out.load64(address));
2489             m_out.jump(continuation);
2490             
2491             m_out.appendTo(overflowCase, continuation);
2492             
2493             address = m_out.baseIndex(
2494                 m_heaps.ScopedArguments_overflowStorage, base,
2495                 m_out.zeroExtPtr(m_out.sub(index, namedLength)));
2496             LValue overflowValue = m_out.load64(address);
2497             speculate(ExoticObjectMode, noValue(), nullptr, m_out.isZero64(overflowValue));
2498             ValueFromBlock overflowResult = m_out.anchor(overflowValue);
2499             m_out.jump(continuation);
2500             
2501             m_out.appendTo(continuation, lastNext);
2502             setJSValue(m_out.phi(m_out.int64, namedResult, overflowResult));
2503             return;
2504         }
2505             
2506         case Array::Generic: {
2507             setJSValue(vmCall(
2508                 m_out.operation(operationGetByVal), m_callFrame,
2509                 lowJSValue(m_node->child1()), lowJSValue(m_node->child2())));
2510             return;
2511         }
2512             
2513         case Array::String: {
2514             compileStringCharAt();
2515             return;
2516         }
2517             
2518         default: {
2519             LValue index = lowInt32(m_node->child2());
2520             LValue storage = lowStorage(m_node->child3());
2521             
2522             TypedArrayType type = m_node->arrayMode().typedArrayType();
2523             
2524             if (isTypedView(type)) {
2525                 TypedPointer pointer = TypedPointer(
2526                     m_heaps.typedArrayProperties,
2527                     m_out.add(
2528                         storage,
2529                         m_out.shl(
2530                             m_out.zeroExtPtr(index),
2531                             m_out.constIntPtr(logElementSize(type)))));
2532                 
2533                 if (isInt(type)) {
2534                     LValue result;
2535                     switch (elementSize(type)) {
2536                     case 1:
2537                         result = m_out.load8(pointer);
2538                         break;
2539                     case 2:
2540                         result = m_out.load16(pointer);
2541                         break;
2542                     case 4:
2543                         result = m_out.load32(pointer);
2544                         break;
2545                     default:
2546                         DFG_CRASH(m_graph, m_node, "Bad element size");
2547                     }
2548                     
2549                     if (elementSize(type) < 4) {
2550                         if (isSigned(type))
2551                             result = m_out.signExt(result, m_out.int32);
2552                         else
2553                             result = m_out.zeroExt(result, m_out.int32);
2554                         setInt32(result);
2555                         return;
2556                     }
2557                     
2558                     if (isSigned(type)) {
2559                         setInt32(result);
2560                         return;
2561                     }
2562                     
2563                     if (m_node->shouldSpeculateInt32()) {
2564                         speculate(
2565                             Overflow, noValue(), 0, m_out.lessThan(result, m_out.int32Zero));
2566                         setInt32(result);
2567                         return;
2568                     }
2569                     
2570                     if (m_node->shouldSpeculateMachineInt()) {
2571                         setStrictInt52(m_out.zeroExt(result, m_out.int64));
2572                         return;
2573                     }
2574                     
2575                     setDouble(m_out.unsignedToFP(result, m_out.doubleType));
2576                     return;
2577                 }
2578             
2579                 ASSERT(isFloat(type));
2580                 
2581                 LValue result;
2582                 switch (type) {
2583                 case TypeFloat32:
2584                     result = m_out.fpCast(m_out.loadFloat(pointer), m_out.doubleType);
2585                     break;
2586                 case TypeFloat64:
2587                     result = m_out.loadDouble(pointer);
2588                     break;
2589                 default:
2590                     DFG_CRASH(m_graph, m_node, "Bad typed array type");
2591                 }
2592                 
2593                 setDouble(result);
2594                 return;
2595             }
2596             
2597             DFG_CRASH(m_graph, m_node, "Bad array type");
2598             return;
2599         } }
2600     }
2601     
2602     void compileGetMyArgumentByVal()
2603     {
2604         InlineCallFrame* inlineCallFrame = m_node->child1()->origin.semantic.inlineCallFrame;
2605         
2606         LValue index = lowInt32(m_node->child2());
2607         
2608         LValue limit;
2609         if (inlineCallFrame && !inlineCallFrame->isVarargs())
2610             limit = m_out.constInt32(inlineCallFrame->arguments.size() - 1);
2611         else {
2612             VirtualRegister argumentCountRegister;
2613             if (!inlineCallFrame)
2614                 argumentCountRegister = VirtualRegister(JSStack::ArgumentCount);
2615             else
2616                 argumentCountRegister = inlineCallFrame->argumentCountRegister;
2617             limit = m_out.sub(m_out.load32(payloadFor(argumentCountRegister)), m_out.int32One);
2618         }
2619         
2620         speculate(ExoticObjectMode, noValue(), 0, m_out.aboveOrEqual(index, limit));
2621         
2622         TypedPointer base;
2623         if (inlineCallFrame) {
2624             if (inlineCallFrame->arguments.size() <= 1) {
2625                 // We should have already exited due to the bounds check, above. Just tell the
2626                 // compiler that anything dominated by this instruction is not reachable, so
2627                 // that we don't waste time generating such code. This will also plant some
2628                 // kind of crashing instruction so that if by some fluke the bounds check didn't
2629                 // work, we'll crash in an easy-to-see way.
2630                 didAlreadyTerminate();
2631                 return;
2632             }
2633             base = addressFor(inlineCallFrame->arguments[1].virtualRegister());
2634         } else
2635             base = addressFor(virtualRegisterForArgument(1));
2636         
2637         LValue pointer = m_out.baseIndex(
2638             base.value(), m_out.zeroExt(index, m_out.intPtr), ScaleEight);
2639         setJSValue(m_out.load64(TypedPointer(m_heaps.variables.atAnyIndex(), pointer)));
2640     }
2641     
2642     void compilePutByVal()
2643     {
2644         Edge child1 = m_graph.varArgChild(m_node, 0);
2645         Edge child2 = m_graph.varArgChild(m_node, 1);
2646         Edge child3 = m_graph.varArgChild(m_node, 2);
2647         Edge child4 = m_graph.varArgChild(m_node, 3);
2648         Edge child5 = m_graph.varArgChild(m_node, 4);
2649         
2650         switch (m_node->arrayMode().type()) {
2651         case Array::Generic: {
2652             V_JITOperation_EJJJ operation;
2653             if (m_node->op() == PutByValDirect) {
2654                 if (m_graph.isStrictModeFor(m_node->origin.semantic))
2655                     operation = operationPutByValDirectStrict;
2656                 else
2657                     operation = operationPutByValDirectNonStrict;
2658             } else {
2659                 if (m_graph.isStrictModeFor(m_node->origin.semantic))
2660                     operation = operationPutByValStrict;
2661                 else
2662                     operation = operationPutByValNonStrict;
2663             }
2664                 
2665             vmCall(
2666                 m_out.operation(operation), m_callFrame,
2667                 lowJSValue(child1), lowJSValue(child2), lowJSValue(child3));
2668             return;
2669         }
2670             
2671         default:
2672             break;
2673         }
2674
2675         LValue base = lowCell(child1);
2676         LValue index = lowInt32(child2);
2677         LValue storage = lowStorage(child4);
2678         
2679         switch (m_node->arrayMode().type()) {
2680         case Array::Int32:
2681         case Array::Double:
2682         case Array::Contiguous: {
2683             LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("PutByVal continuation"));
2684             LBasicBlock outerLastNext = m_out.appendTo(m_out.m_block, continuation);
2685             
2686             switch (m_node->arrayMode().type()) {
2687             case Array::Int32:
2688             case Array::Contiguous: {
2689                 LValue value = lowJSValue(child3, ManualOperandSpeculation);
2690                 
2691                 if (m_node->arrayMode().type() == Array::Int32)
2692                     FTL_TYPE_CHECK(jsValueValue(value), child3, SpecInt32, isNotInt32(value));
2693                 
2694                 TypedPointer elementPointer = m_out.baseIndex(
2695                     m_node->arrayMode().type() == Array::Int32 ?
2696                     m_heaps.indexedInt32Properties : m_heaps.indexedContiguousProperties,
2697                     storage, m_out.zeroExtPtr(index), provenValue(child2));
2698                 
2699                 if (m_node->op() == PutByValAlias) {
2700                     m_out.store64(value, elementPointer);
2701                     break;
2702                 }
2703                 
2704                 contiguousPutByValOutOfBounds(
2705                     codeBlock()->isStrictMode()
2706                     ? operationPutByValBeyondArrayBoundsStrict
2707                     : operationPutByValBeyondArrayBoundsNonStrict,
2708                     base, storage, index, value, continuation);
2709                 
2710                 m_out.store64(value, elementPointer);
2711                 break;
2712             }
2713                 
2714             case Array::Double: {
2715                 LValue value = lowDouble(child3);
2716                 
2717                 FTL_TYPE_CHECK(
2718                     doubleValue(value), child3, SpecDoubleReal,
2719                     m_out.doubleNotEqualOrUnordered(value, value));
2720                 
2721                 TypedPointer elementPointer = m_out.baseIndex(
2722                     m_heaps.indexedDoubleProperties, storage, m_out.zeroExtPtr(index),
2723                     provenValue(child2));
2724                 
2725                 if (m_node->op() == PutByValAlias) {
2726                     m_out.storeDouble(value, elementPointer);
2727                     break;
2728                 }
2729                 
2730                 contiguousPutByValOutOfBounds(
2731                     codeBlock()->isStrictMode()
2732                     ? operationPutDoubleByValBeyondArrayBoundsStrict
2733                     : operationPutDoubleByValBeyondArrayBoundsNonStrict,
2734                     base, storage, index, value, continuation);
2735                 
2736                 m_out.storeDouble(value, elementPointer);
2737                 break;
2738             }
2739                 
2740             default:
2741                 DFG_CRASH(m_graph, m_node, "Bad array type");
2742             }
2743
2744             m_out.jump(continuation);
2745             m_out.appendTo(continuation, outerLastNext);
2746             return;
2747         }
2748             
2749         default:
2750             TypedArrayType type = m_node->arrayMode().typedArrayType();
2751             
2752             if (isTypedView(type)) {
2753                 TypedPointer pointer = TypedPointer(
2754                     m_heaps.typedArrayProperties,
2755                     m_out.add(
2756                         storage,
2757                         m_out.shl(
2758                             m_out.zeroExt(index, m_out.intPtr),
2759                             m_out.constIntPtr(logElementSize(type)))));
2760                 
2761                 LType refType;
2762                 LValue valueToStore;
2763                 
2764                 if (isInt(type)) {
2765                     LValue intValue;
2766                     switch (child3.useKind()) {
2767                     case Int52RepUse:
2768                     case Int32Use: {
2769                         if (child3.useKind() == Int32Use)
2770                             intValue = lowInt32(child3);
2771                         else
2772                             intValue = m_out.castToInt32(lowStrictInt52(child3));
2773
2774                         if (isClamped(type)) {
2775                             ASSERT(elementSize(type) == 1);
2776                             
2777                             LBasicBlock atLeastZero = FTL_NEW_BLOCK(m_out, ("PutByVal int clamp atLeastZero"));
2778                             LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("PutByVal int clamp continuation"));
2779                             
2780                             Vector<ValueFromBlock, 2> intValues;
2781                             intValues.append(m_out.anchor(m_out.int32Zero));
2782                             m_out.branch(
2783                                 m_out.lessThan(intValue, m_out.int32Zero),
2784                                 unsure(continuation), unsure(atLeastZero));
2785                             
2786                             LBasicBlock lastNext = m_out.appendTo(atLeastZero, continuation);
2787                             
2788                             intValues.append(m_out.anchor(m_out.select(
2789                                 m_out.greaterThan(intValue, m_out.constInt32(255)),
2790                                 m_out.constInt32(255),
2791                                 intValue)));
2792                             m_out.jump(continuation);
2793                             
2794                             m_out.appendTo(continuation, lastNext);
2795                             intValue = m_out.phi(m_out.int32, intValues);
2796                         }
2797                         break;
2798                     }
2799                         
2800                     case DoubleRepUse: {
2801                         LValue doubleValue = lowDouble(child3);
2802                         
2803                         if (isClamped(type)) {
2804                             ASSERT(elementSize(type) == 1);
2805                             
2806                             LBasicBlock atLeastZero = FTL_NEW_BLOCK(m_out, ("PutByVal double clamp atLeastZero"));
2807                             LBasicBlock withinRange = FTL_NEW_BLOCK(m_out, ("PutByVal double clamp withinRange"));
2808                             LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("PutByVal double clamp continuation"));
2809                             
2810                             Vector<ValueFromBlock, 3> intValues;
2811                             intValues.append(m_out.anchor(m_out.int32Zero));
2812                             m_out.branch(
2813                                 m_out.doubleLessThanOrUnordered(doubleValue, m_out.doubleZero),
2814                                 unsure(continuation), unsure(atLeastZero));
2815                             
2816                             LBasicBlock lastNext = m_out.appendTo(atLeastZero, withinRange);
2817                             intValues.append(m_out.anchor(m_out.constInt32(255)));
2818                             m_out.branch(
2819                                 m_out.doubleGreaterThan(doubleValue, m_out.constDouble(255)),
2820                                 unsure(continuation), unsure(withinRange));
2821                             
2822                             m_out.appendTo(withinRange, continuation);
2823                             intValues.append(m_out.anchor(m_out.fpToInt32(doubleValue)));
2824                             m_out.jump(continuation);
2825                             
2826                             m_out.appendTo(continuation, lastNext);
2827                             intValue = m_out.phi(m_out.int32, intValues);
2828                         } else
2829                             intValue = doubleToInt32(doubleValue);
2830                         break;
2831                     }
2832                         
2833                     default:
2834                         DFG_CRASH(m_graph, m_node, "Bad use kind");
2835                     }
2836                     
2837                     switch (elementSize(type)) {
2838                     case 1:
2839                         valueToStore = m_out.intCast(intValue, m_out.int8);
2840                         refType = m_out.ref8;
2841                         break;
2842                     case 2:
2843                         valueToStore = m_out.intCast(intValue, m_out.int16);
2844                         refType = m_out.ref16;
2845                         break;
2846                     case 4:
2847                         valueToStore = intValue;
2848                         refType = m_out.ref32;
2849                         break;
2850                     default:
2851                         DFG_CRASH(m_graph, m_node, "Bad element size");
2852                     }
2853                 } else /* !isInt(type) */ {
2854                     LValue value = lowDouble(child3);
2855                     switch (type) {
2856                     case TypeFloat32:
2857                         valueToStore = m_out.fpCast(value, m_out.floatType);
2858                         refType = m_out.refFloat;
2859                         break;
2860                     case TypeFloat64:
2861                         valueToStore = value;
2862                         refType = m_out.refDouble;
2863                         break;
2864                     default:
2865                         DFG_CRASH(m_graph, m_node, "Bad typed array type");
2866                     }
2867                 }
2868                 
2869                 if (m_node->arrayMode().isInBounds() || m_node->op() == PutByValAlias)
2870                     m_out.store(valueToStore, pointer, refType);
2871                 else {
2872                     LBasicBlock isInBounds = FTL_NEW_BLOCK(m_out, ("PutByVal typed array in bounds case"));
2873                     LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("PutByVal typed array continuation"));
2874                     
2875                     m_out.branch(
2876                         m_out.aboveOrEqual(index, lowInt32(child5)),
2877                         unsure(continuation), unsure(isInBounds));
2878                     
2879                     LBasicBlock lastNext = m_out.appendTo(isInBounds, continuation);
2880                     m_out.store(valueToStore, pointer, refType);
2881                     m_out.jump(continuation);
2882                     
2883                     m_out.appendTo(continuation, lastNext);
2884                 }
2885                 
2886                 return;
2887             }
2888             
2889             DFG_CRASH(m_graph, m_node, "Bad array type");
2890             break;
2891         }
2892     }
2893     
2894     void compileArrayPush()
2895     {
2896         LValue base = lowCell(m_node->child1());
2897         LValue storage = lowStorage(m_node->child3());
2898         
2899         switch (m_node->arrayMode().type()) {
2900         case Array::Int32:
2901         case Array::Contiguous:
2902         case Array::Double: {
2903             LValue value;
2904             LType refType;
2905             
2906             if (m_node->arrayMode().type() != Array::Double) {
2907                 value = lowJSValue(m_node->child2(), ManualOperandSpeculation);
2908                 if (m_node->arrayMode().type() == Array::Int32) {
2909                     FTL_TYPE_CHECK(
2910                         jsValueValue(value), m_node->child2(), SpecInt32, isNotInt32(value));
2911                 }
2912                 refType = m_out.ref64;
2913             } else {
2914                 value = lowDouble(m_node->child2());
2915                 FTL_TYPE_CHECK(
2916                     doubleValue(value), m_node->child2(), SpecDoubleReal,
2917                     m_out.doubleNotEqualOrUnordered(value, value));
2918                 refType = m_out.refDouble;
2919             }
2920             
2921             IndexedAbstractHeap& heap = m_heaps.forArrayType(m_node->arrayMode().type());
2922
2923             LValue prevLength = m_out.load32(storage, m_heaps.Butterfly_publicLength);
2924             
2925             LBasicBlock fastPath = FTL_NEW_BLOCK(m_out, ("ArrayPush fast path"));
2926             LBasicBlock slowPath = FTL_NEW_BLOCK(m_out, ("ArrayPush slow path"));
2927             LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("ArrayPush continuation"));
2928             
2929             m_out.branch(
2930                 m_out.aboveOrEqual(
2931                     prevLength, m_out.load32(storage, m_heaps.Butterfly_vectorLength)),
2932                 rarely(slowPath), usually(fastPath));
2933             
2934             LBasicBlock lastNext = m_out.appendTo(fastPath, slowPath);
2935             m_out.store(
2936                 value, m_out.baseIndex(heap, storage, m_out.zeroExtPtr(prevLength)), refType);
2937             LValue newLength = m_out.add(prevLength, m_out.int32One);
2938             m_out.store32(newLength, storage, m_heaps.Butterfly_publicLength);
2939             
2940             ValueFromBlock fastResult = m_out.anchor(boxInt32(newLength));
2941             m_out.jump(continuation);
2942             
2943             m_out.appendTo(slowPath, continuation);
2944             LValue operation;
2945             if (m_node->arrayMode().type() != Array::Double)
2946                 operation = m_out.operation(operationArrayPush);
2947             else
2948                 operation = m_out.operation(operationArrayPushDouble);
2949             ValueFromBlock slowResult = m_out.anchor(
2950                 vmCall(operation, m_callFrame, value, base));
2951             m_out.jump(continuation);
2952             
2953             m_out.appendTo(continuation, lastNext);
2954             setJSValue(m_out.phi(m_out.int64, fastResult, slowResult));
2955             return;
2956         }
2957             
2958         default:
2959             DFG_CRASH(m_graph, m_node, "Bad array type");
2960             return;
2961         }
2962     }
2963     
2964     void compileArrayPop()
2965     {
2966         LValue base = lowCell(m_node->child1());
2967         LValue storage = lowStorage(m_node->child2());
2968         
2969         switch (m_node->arrayMode().type()) {
2970         case Array::Int32:
2971         case Array::Double:
2972         case Array::Contiguous: {
2973             IndexedAbstractHeap& heap = m_heaps.forArrayType(m_node->arrayMode().type());
2974             
2975             LBasicBlock fastCase = FTL_NEW_BLOCK(m_out, ("ArrayPop fast case"));
2976             LBasicBlock slowCase = FTL_NEW_BLOCK(m_out, ("ArrayPop slow case"));
2977             LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("ArrayPop continuation"));
2978             
2979             LValue prevLength = m_out.load32(storage, m_heaps.Butterfly_publicLength);
2980             
2981             Vector<ValueFromBlock, 3> results;
2982             results.append(m_out.anchor(m_out.constInt64(JSValue::encode(jsUndefined()))));
2983             m_out.branch(
2984                 m_out.isZero32(prevLength), rarely(continuation), usually(fastCase));
2985             
2986             LBasicBlock lastNext = m_out.appendTo(fastCase, slowCase);
2987             LValue newLength = m_out.sub(prevLength, m_out.int32One);
2988             m_out.store32(newLength, storage, m_heaps.Butterfly_publicLength);
2989             TypedPointer pointer = m_out.baseIndex(heap, storage, m_out.zeroExtPtr(newLength));
2990             if (m_node->arrayMode().type() != Array::Double) {
2991                 LValue result = m_out.load64(pointer);
2992                 m_out.store64(m_out.int64Zero, pointer);
2993                 results.append(m_out.anchor(result));
2994                 m_out.branch(
2995                     m_out.notZero64(result), usually(continuation), rarely(slowCase));
2996             } else {
2997                 LValue result = m_out.loadDouble(pointer);
2998                 m_out.store64(m_out.constInt64(bitwise_cast<int64_t>(PNaN)), pointer);
2999                 results.append(m_out.anchor(boxDouble(result)));
3000                 m_out.branch(
3001                     m_out.doubleEqual(result, result),
3002                     usually(continuation), rarely(slowCase));
3003             }
3004             
3005             m_out.appendTo(slowCase, continuation);
3006             results.append(m_out.anchor(vmCall(
3007                 m_out.operation(operationArrayPopAndRecoverLength), m_callFrame, base)));
3008             m_out.jump(continuation);
3009             
3010             m_out.appendTo(continuation, lastNext);
3011             setJSValue(m_out.phi(m_out.int64, results));
3012             return;
3013         }
3014
3015         default:
3016             DFG_CRASH(m_graph, m_node, "Bad array type");
3017             return;
3018         }
3019     }
3020     
3021     void compileCreateActivation()
3022     {
3023         LValue scope = lowCell(m_node->child1());
3024         SymbolTable* table = m_node->castOperand<SymbolTable*>();
3025         Structure* structure = m_graph.globalObjectFor(m_node->origin.semantic)->activationStructure();
3026         JSValue initializationValue = m_node->initializationValueForActivation();
3027         ASSERT(initializationValue.isUndefined() || initializationValue == jsTDZValue());
3028         if (table->singletonScope()->isStillValid()) {
3029             LValue callResult = vmCall(
3030                 m_out.operation(operationCreateActivationDirect), m_callFrame, weakPointer(structure),
3031                 scope, weakPointer(table), m_out.constInt64(JSValue::encode(initializationValue)));
3032             setJSValue(callResult);
3033             return;
3034         }
3035         
3036         LBasicBlock slowPath = FTL_NEW_BLOCK(m_out, ("CreateActivation slow path"));
3037         LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("CreateActivation continuation"));
3038         
3039         LBasicBlock lastNext = m_out.insertNewBlocksBefore(slowPath);
3040         
3041         LValue fastObject = allocateObject<JSLexicalEnvironment>(
3042             JSLexicalEnvironment::allocationSize(table), structure, m_out.intPtrZero, slowPath);
3043         
3044         // We don't need memory barriers since we just fast-created the activation, so the
3045         // activation must be young.
3046         m_out.storePtr(scope, fastObject, m_heaps.JSScope_next);
3047         m_out.storePtr(weakPointer(table), fastObject, m_heaps.JSSymbolTableObject_symbolTable);
3048         
3049         for (unsigned i = 0; i < table->scopeSize(); ++i) {
3050             m_out.store64(
3051                 m_out.constInt64(JSValue::encode(initializationValue)),