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