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