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