arguments[-1] should have well-defined behavior
[WebKit-https.git] / Source / JavaScriptCore / ftl / FTLLowerDFGToLLVM.cpp
1 /*
2  * Copyright (C) 2013-2015 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
24  */
25
26 #include "config.h"
27 #include "FTLLowerDFGToLLVM.h"
28
29 #if ENABLE(FTL_JIT)
30
31 #include "CodeBlockWithJITType.h"
32 #include "DFGAbstractInterpreterInlines.h"
33 #include "DFGInPlaceAbstractState.h"
34 #include "DFGOSRAvailabilityAnalysisPhase.h"
35 #include "FTLAbstractHeapRepository.h"
36 #include "FTLAvailableRecovery.h"
37 #include "FTLForOSREntryJITCode.h"
38 #include "FTLFormattedValue.h"
39 #include "FTLInlineCacheSize.h"
40 #include "FTLLoweredNodeValue.h"
41 #include "FTLOperations.h"
42 #include "FTLOutput.h"
43 #include "FTLThunks.h"
44 #include "FTLWeightedTarget.h"
45 #include "JSCInlines.h"
46 #include "OperandsInlines.h"
47 #include "VirtualRegister.h"
48 #include <atomic>
49 #include <dlfcn.h>
50 #include <llvm/InitializeLLVM.h>
51 #include <wtf/ProcessID.h>
52
53 #if ENABLE(FTL_NATIVE_CALL_INLINING)
54 #include "BundlePath.h"
55 #endif
56
57 namespace JSC { namespace FTL {
58
59 using namespace DFG;
60
61 static std::atomic<int> compileCounter;
62
63 #if ASSERT_DISABLED
64 NO_RETURN_DUE_TO_CRASH static void ftlUnreachable()
65 {
66     CRASH();
67 }
68 #else
69 NO_RETURN_DUE_TO_CRASH static void ftlUnreachable(
70     CodeBlock* codeBlock, BlockIndex blockIndex, unsigned nodeIndex)
71 {
72     dataLog("Crashing in thought-to-be-unreachable FTL-generated code for ", pointerDump(codeBlock), " at basic block #", blockIndex);
73     if (nodeIndex != UINT_MAX)
74         dataLog(", node @", nodeIndex);
75     dataLog(".\n");
76     CRASH();
77 }
78 #endif
79
80 // Using this instead of typeCheck() helps to reduce the load on LLVM, by creating
81 // significantly less dead code.
82 #define FTL_TYPE_CHECK(lowValue, highValue, typesPassedThrough, failCondition) do { \
83         FormattedValue _ftc_lowValue = (lowValue);                      \
84         Edge _ftc_highValue = (highValue);                              \
85         SpeculatedType _ftc_typesPassedThrough = (typesPassedThrough);  \
86         if (!m_interpreter.needsTypeCheck(_ftc_highValue, _ftc_typesPassedThrough)) \
87             break;                                                      \
88         typeCheck(_ftc_lowValue, _ftc_highValue, _ftc_typesPassedThrough, (failCondition)); \
89     } while (false)
90
91 class LowerDFGToLLVM {
92 public:
93     LowerDFGToLLVM(State& state)
94         : m_graph(state.graph)
95         , m_ftlState(state)
96         , m_heaps(state.context)
97         , m_out(state.context)
98         , m_state(state.graph)
99         , m_interpreter(state.graph, m_state)
100         , m_stackmapIDs(0)
101         , m_tbaaKind(mdKindID(state.context, "tbaa"))
102         , m_tbaaStructKind(mdKindID(state.context, "tbaa.struct"))
103     {
104     }
105     
106     void lower()
107     {
108         CString name;
109         if (verboseCompilationEnabled()) {
110             name = toCString(
111                 "jsBody_", ++compileCounter, "_", codeBlock()->inferredName(),
112                 "_", codeBlock()->hash());
113         } else
114             name = "jsBody";
115         
116         m_graph.m_dominators.computeIfNecessary(m_graph);
117         
118         m_ftlState.module =
119             moduleCreateWithNameInContext(name.data(), m_ftlState.context);
120         
121         m_ftlState.function = addFunction(
122             m_ftlState.module, name.data(), functionType(m_out.int64));
123         setFunctionCallingConv(m_ftlState.function, LLVMCCallConv);
124         if (isX86() && Options::llvmDisallowAVX()) {
125             // AVX makes V8/raytrace 80% slower. It makes Kraken/audio-oscillator 4.5x
126             // slower. It should be disabled.
127             addTargetDependentFunctionAttr(m_ftlState.function, "target-features", "-avx");
128         }
129         
130         if (verboseCompilationEnabled())
131             dataLog("Function ready, beginning lowering.\n");
132         
133         m_out.initialize(m_ftlState.module, m_ftlState.function, m_heaps);
134         
135         m_prologue = FTL_NEW_BLOCK(m_out, ("Prologue"));
136         LBasicBlock stackOverflow = FTL_NEW_BLOCK(m_out, ("Stack overflow"));
137         m_handleExceptions = FTL_NEW_BLOCK(m_out, ("Handle Exceptions"));
138
139         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();
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 index = lowInt32(m_node->child1());
2001         
2002         LValue limit;
2003         if (codeOrigin.inlineCallFrame)
2004             limit = m_out.constInt32(codeOrigin.inlineCallFrame->arguments.size() - 1);
2005         else
2006             limit = m_out.sub(m_out.load32(payloadFor(JSStack::ArgumentCount)), m_out.int32One);
2007         
2008         speculate(Uncountable, noValue(), 0, m_out.aboveOrEqual(index, limit));
2009         
2010         SymbolTable* symbolTable = m_graph.baselineCodeBlockFor(codeOrigin)->symbolTable();
2011         if (symbolTable->slowArguments()) {
2012             // FIXME: FTL should support activations.
2013             // https://bugs.webkit.org/show_bug.cgi?id=129576
2014             
2015             DFG_CRASH(m_graph, m_node, "Unimplemented");
2016         }
2017         
2018         TypedPointer base;
2019         if (codeOrigin.inlineCallFrame) {
2020             if (codeOrigin.inlineCallFrame->arguments.size() <= 1) {
2021                 // We should have already exited due to the bounds check, above. Just tell the
2022                 // compiler that anything dominated by this instruction is not reachable, so
2023                 // that we don't waste time generating such code. This will also plant some
2024                 // kind of crashing instruction so that if by some fluke the bounds check didn't
2025                 // work, we'll crash in an easy-to-see way.
2026                 didAlreadyTerminate();
2027                 return;
2028             }
2029             base = addressFor(codeOrigin.inlineCallFrame->arguments[1].virtualRegister());
2030         } else
2031             base = addressFor(virtualRegisterForArgument(1));
2032         
2033         LValue pointer = m_out.baseIndex(
2034             base.value(), m_out.zeroExt(index, m_out.intPtr), ScaleEight);
2035         setJSValue(m_out.load64(TypedPointer(m_heaps.variables.atAnyIndex(), pointer)));
2036     }
2037
2038     void compileGetArrayLength()
2039     {
2040         switch (m_node->arrayMode().type()) {
2041         case Array::Int32:
2042         case Array::Double:
2043         case Array::Contiguous: {
2044             setInt32(m_out.load32NonNegative(lowStorage(m_node->child2()), m_heaps.Butterfly_publicLength));
2045             return;
2046         }
2047             
2048         case Array::String: {
2049             LValue string = lowCell(m_node->child1());
2050             setInt32(m_out.load32NonNegative(string, m_heaps.JSString_length));
2051             return;
2052         }
2053             
2054         default:
2055             if (isTypedView(m_node->arrayMode().typedArrayType())) {
2056                 setInt32(
2057                     m_out.load32NonNegative(lowCell(m_node->child1()), m_heaps.JSArrayBufferView_length));
2058                 return;
2059             }
2060             
2061             DFG_CRASH(m_graph, m_node, "Bad array type");
2062             return;
2063         }
2064     }
2065     
2066     void compileCheckInBounds()
2067     {
2068         speculate(
2069             OutOfBounds, noValue(), 0,
2070             m_out.aboveOrEqual(lowInt32(m_node->child1()), lowInt32(m_node->child2())));
2071     }
2072     
2073     void compileGetByVal()
2074     {
2075         switch (m_node->arrayMode().type()) {
2076         case Array::Int32:
2077         case Array::Contiguous: {
2078             LValue index = lowInt32(m_node->child2());
2079             LValue storage = lowStorage(m_node->child3());
2080             
2081             IndexedAbstractHeap& heap = m_node->arrayMode().type() == Array::Int32 ?
2082                 m_heaps.indexedInt32Properties : m_heaps.indexedContiguousProperties;
2083             
2084             if (m_node->arrayMode().isInBounds()) {
2085                 LValue result = m_out.load64(baseIndex(heap, storage, index, m_node->child2()));
2086                 speculate(LoadFromHole, noValue(), 0, m_out.isZero64(result));
2087                 setJSValue(result);
2088                 return;
2089             }
2090             
2091             LValue base = lowCell(m_node->child1());
2092             
2093             LBasicBlock fastCase = FTL_NEW_BLOCK(m_out, ("GetByVal int/contiguous fast case"));
2094             LBasicBlock slowCase = FTL_NEW_BLOCK(m_out, ("GetByVal int/contiguous slow case"));
2095             LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("GetByVal int/contiguous continuation"));
2096             
2097             m_out.branch(
2098                 m_out.aboveOrEqual(
2099                     index, m_out.load32NonNegative(storage, m_heaps.Butterfly_publicLength)),
2100                 rarely(slowCase), usually(fastCase));
2101             
2102             LBasicBlock lastNext = m_out.appendTo(fastCase, slowCase);
2103             
2104             ValueFromBlock fastResult = m_out.anchor(
2105                 m_out.load64(baseIndex(heap, storage, index, m_node->child2())));
2106             m_out.branch(
2107                 m_out.isZero64(fastResult.value()), rarely(slowCase), usually(continuation));
2108             
2109             m_out.appendTo(slowCase, continuation);
2110             ValueFromBlock slowResult = m_out.anchor(
2111                 vmCall(m_out.operation(operationGetByValArrayInt), m_callFrame, base, index));
2112             m_out.jump(continuation);
2113             
2114             m_out.appendTo(continuation, lastNext);
2115             setJSValue(m_out.phi(m_out.int64, fastResult, slowResult));
2116             return;
2117         }
2118             
2119         case Array::Double: {
2120             LValue index = lowInt32(m_node->child2());
2121             LValue storage = lowStorage(m_node->child3());
2122             
2123             IndexedAbstractHeap& heap = m_heaps.indexedDoubleProperties;
2124             
2125             if (m_node->arrayMode().isInBounds()) {
2126                 LValue result = m_out.loadDouble(
2127                     baseIndex(heap, storage, index, m_node->child2()));
2128                 
2129                 if (!m_node->arrayMode().isSaneChain()) {
2130                     speculate(
2131                         LoadFromHole, noValue(), 0,
2132                         m_out.doubleNotEqualOrUnordered(result, result));
2133                 }
2134                 setDouble(result);
2135                 break;
2136             }
2137             
2138             LValue base = lowCell(m_node->child1());
2139             
2140             LBasicBlock inBounds = FTL_NEW_BLOCK(m_out, ("GetByVal double in bounds"));
2141             LBasicBlock boxPath = FTL_NEW_BLOCK(m_out, ("GetByVal double boxing"));
2142             LBasicBlock slowCase = FTL_NEW_BLOCK(m_out, ("GetByVal double slow case"));
2143             LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("GetByVal double continuation"));
2144             
2145             m_out.branch(
2146                 m_out.aboveOrEqual(
2147                     index, m_out.load32NonNegative(storage, m_heaps.Butterfly_publicLength)),
2148                 rarely(slowCase), usually(inBounds));
2149             
2150             LBasicBlock lastNext = m_out.appendTo(inBounds, boxPath);
2151             LValue doubleValue = m_out.loadDouble(
2152                 baseIndex(heap, storage, index, m_node->child2()));
2153             m_out.branch(
2154                 m_out.doubleNotEqualOrUnordered(doubleValue, doubleValue),
2155                 rarely(slowCase), usually(boxPath));
2156             
2157             m_out.appendTo(boxPath, slowCase);
2158             ValueFromBlock fastResult = m_out.anchor(boxDouble(doubleValue));
2159             m_out.jump(continuation);
2160             
2161             m_out.appendTo(slowCase, continuation);
2162             ValueFromBlock slowResult = m_out.anchor(
2163                 vmCall(m_out.operation(operationGetByValArrayInt), m_callFrame, base, index));
2164             m_out.jump(continuation);
2165             
2166             m_out.appendTo(continuation, lastNext);
2167             setJSValue(m_out.phi(m_out.int64, fastResult, slowResult));
2168             return;
2169         }
2170             
2171         case Array::Generic: {
2172             setJSValue(vmCall(
2173                 m_out.operation(operationGetByVal), m_callFrame,
2174                 lowJSValue(m_node->child1()), lowJSValue(m_node->child2())));
2175             return;
2176         }
2177             
2178         case Array::String: {
2179             compileStringCharAt();
2180             return;
2181         }
2182             
2183         default: {
2184             LValue index = lowInt32(m_node->child2());
2185             LValue storage = lowStorage(m_node->child3());
2186             
2187             TypedArrayType type = m_node->arrayMode().typedArrayType();
2188             
2189             if (isTypedView(type)) {
2190                 TypedPointer pointer = TypedPointer(
2191                     m_heaps.typedArrayProperties,
2192                     m_out.add(
2193                         storage,
2194                         m_out.shl(
2195                             m_out.zeroExt(index, m_out.intPtr),
2196                             m_out.constIntPtr(logElementSize(type)))));
2197                 
2198                 if (isInt(type)) {
2199                     LValue result;
2200                     switch (elementSize(type)) {
2201                     case 1:
2202                         result = m_out.load8(pointer);
2203                         break;
2204                     case 2:
2205                         result = m_out.load16(pointer);
2206                         break;
2207                     case 4:
2208                         result = m_out.load32(pointer);
2209                         break;
2210                     default:
2211                         DFG_CRASH(m_graph, m_node, "Bad element size");
2212                     }
2213                     
2214                     if (elementSize(type) < 4) {
2215                         if (isSigned(type))
2216                             result = m_out.signExt(result, m_out.int32);
2217                         else
2218                             result = m_out.zeroExt(result, m_out.int32);
2219                         setInt32(result);
2220                         return;
2221                     }
2222                     
2223                     if (isSigned(type)) {
2224                         setInt32(result);
2225                         return;
2226                     }
2227                     
2228                     if (m_node->shouldSpeculateInt32()) {
2229                         speculate(
2230                             Overflow, noValue(), 0, m_out.lessThan(result, m_out.int32Zero));
2231                         setInt32(result);
2232                         return;
2233                     }
2234                     
2235                     if (m_node->shouldSpeculateMachineInt()) {
2236                         setStrictInt52(m_out.zeroExt(result, m_out.int64));
2237                         return;
2238                     }
2239                     
2240                     setDouble(m_out.unsignedToFP(result, m_out.doubleType));
2241                     return;
2242                 }
2243             
2244                 ASSERT(isFloat(type));
2245                 
2246                 LValue result;
2247                 switch (type) {
2248                 case TypeFloat32:
2249                     result = m_out.fpCast(m_out.loadFloat(pointer), m_out.doubleType);
2250                     break;
2251                 case TypeFloat64:
2252                     result = m_out.loadDouble(pointer);
2253                     break;
2254                 default:
2255                     DFG_CRASH(m_graph, m_node, "Bad typed array type");
2256                 }
2257                 
2258                 setDouble(result);
2259                 return;
2260             }
2261             
2262             DFG_CRASH(m_graph, m_node, "Bad array type");
2263             return;
2264         } }
2265     }
2266     
2267     void compilePutByVal()
2268     {
2269         Edge child1 = m_graph.varArgChild(m_node, 0);
2270         Edge child2 = m_graph.varArgChild(m_node, 1);
2271         Edge child3 = m_graph.varArgChild(m_node, 2);
2272         Edge child4 = m_graph.varArgChild(m_node, 3);
2273         Edge child5 = m_graph.varArgChild(m_node, 4);
2274         
2275         switch (m_node->arrayMode().type()) {
2276         case Array::Generic: {
2277             V_JITOperation_EJJJ operation;
2278             if (m_node->op() == PutByValDirect) {
2279                 if (m_graph.isStrictModeFor(m_node->origin.semantic))
2280                     operation = operationPutByValDirectStrict;
2281                 else
2282                     operation = operationPutByValDirectNonStrict;
2283             } else {
2284                 if (m_graph.isStrictModeFor(m_node->origin.semantic))
2285                     operation = operationPutByValStrict;
2286                 else
2287                     operation = operationPutByValNonStrict;
2288             }
2289                 
2290             vmCall(
2291                 m_out.operation(operation), m_callFrame,
2292                 lowJSValue(child1), lowJSValue(child2), lowJSValue(child3));
2293             return;
2294         }
2295             
2296         default:
2297             break;
2298         }
2299
2300         LValue base = lowCell(child1);
2301         LValue index = lowInt32(child2);
2302         LValue storage = lowStorage(child4);
2303         
2304         switch (m_node->arrayMode().type()) {
2305         case Array::Int32:
2306         case Array::Double:
2307         case Array::Contiguous: {
2308             LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("PutByVal continuation"));
2309             LBasicBlock outerLastNext = m_out.appendTo(m_out.m_block, continuation);
2310             
2311             switch (m_node->arrayMode().type()) {
2312             case Array::Int32:
2313             case Array::Contiguous: {
2314                 LValue value = lowJSValue(child3, ManualOperandSpeculation);
2315                 
2316                 if (m_node->arrayMode().type() == Array::Int32)
2317                     FTL_TYPE_CHECK(jsValueValue(value), child3, SpecInt32, isNotInt32(value));
2318                 
2319                 TypedPointer elementPointer = m_out.baseIndex(
2320                     m_node->arrayMode().type() == Array::Int32 ?
2321                     m_heaps.indexedInt32Properties : m_heaps.indexedContiguousProperties,
2322                     storage, m_out.zeroExt(index, m_out.intPtr),
2323                     m_state.forNode(child2).m_value);
2324                 
2325                 if (m_node->op() == PutByValAlias) {
2326                     m_out.store64(value, elementPointer);
2327                     break;
2328                 }
2329                 
2330                 contiguousPutByValOutOfBounds(
2331                     codeBlock()->isStrictMode()
2332                     ? operationPutByValBeyondArrayBoundsStrict
2333                     : operationPutByValBeyondArrayBoundsNonStrict,
2334                     base, storage, index, value, continuation);
2335                 
2336                 m_out.store64(value, elementPointer);
2337                 break;
2338             }
2339                 
2340             case Array::Double: {
2341                 LValue value = lowDouble(child3);
2342                 
2343                 FTL_TYPE_CHECK(
2344                     doubleValue(value), child3, SpecDoubleReal,
2345                     m_out.doubleNotEqualOrUnordered(value, value));
2346                 
2347                 TypedPointer elementPointer = m_out.baseIndex(
2348                     m_heaps.indexedDoubleProperties,
2349                     storage, m_out.zeroExt(index, m_out.intPtr),
2350                     m_state.forNode(child2).m_value);
2351                 
2352                 if (m_node->op() == PutByValAlias) {
2353                     m_out.storeDouble(value, elementPointer);
2354                     break;
2355                 }
2356                 
2357                 contiguousPutByValOutOfBounds(
2358                     codeBlock()->isStrictMode()
2359                     ? operationPutDoubleByValBeyondArrayBoundsStrict
2360                     : operationPutDoubleByValBeyondArrayBoundsNonStrict,
2361                     base, storage, index, value, continuation);
2362                 
2363                 m_out.storeDouble(value, elementPointer);
2364                 break;
2365             }
2366                 
2367             default:
2368                 DFG_CRASH(m_graph, m_node, "Bad array type");
2369             }
2370
2371             m_out.jump(continuation);
2372             m_out.appendTo(continuation, outerLastNext);
2373             return;
2374         }
2375             
2376         default:
2377             TypedArrayType type = m_node->arrayMode().typedArrayType();
2378             
2379             if (isTypedView(type)) {
2380                 TypedPointer pointer = TypedPointer(
2381                     m_heaps.typedArrayProperties,
2382                     m_out.add(
2383                         storage,
2384                         m_out.shl(
2385                             m_out.zeroExt(index, m_out.intPtr),
2386                             m_out.constIntPtr(logElementSize(type)))));
2387                 
2388                 LType refType;
2389                 LValue valueToStore;
2390                 
2391                 if (isInt(type)) {
2392                     LValue intValue;
2393                     switch (child3.useKind()) {
2394                     case Int52RepUse:
2395                     case Int32Use: {
2396                         if (child3.useKind() == Int32Use)
2397                             intValue = lowInt32(child3);
2398                         else
2399                             intValue = m_out.castToInt32(lowStrictInt52(child3));
2400
2401                         if (isClamped(type)) {
2402                             ASSERT(elementSize(type) == 1);
2403                             
2404                             LBasicBlock atLeastZero = FTL_NEW_BLOCK(m_out, ("PutByVal int clamp atLeastZero"));
2405                             LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("PutByVal int clamp continuation"));
2406                             
2407                             Vector<ValueFromBlock, 2> intValues;
2408                             intValues.append(m_out.anchor(m_out.int32Zero));
2409                             m_out.branch(
2410                                 m_out.lessThan(intValue, m_out.int32Zero),
2411                                 unsure(continuation), unsure(atLeastZero));
2412                             
2413                             LBasicBlock lastNext = m_out.appendTo(atLeastZero, continuation);
2414                             
2415                             intValues.append(m_out.anchor(m_out.select(
2416                                 m_out.greaterThan(intValue, m_out.constInt32(255)),
2417                                 m_out.constInt32(255),
2418                                 intValue)));
2419                             m_out.jump(continuation);
2420                             
2421                             m_out.appendTo(continuation, lastNext);
2422                             intValue = m_out.phi(m_out.int32, intValues);
2423                         }
2424                         break;
2425                     }
2426                         
2427                     case DoubleRepUse: {
2428                         LValue doubleValue = lowDouble(child3);
2429                         
2430                         if (isClamped(type)) {
2431                             ASSERT(elementSize(type) == 1);
2432                             
2433                             LBasicBlock atLeastZero = FTL_NEW_BLOCK(m_out, ("PutByVal double clamp atLeastZero"));
2434                             LBasicBlock withinRange = FTL_NEW_BLOCK(m_out, ("PutByVal double clamp withinRange"));
2435                             LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("PutByVal double clamp continuation"));
2436                             
2437                             Vector<ValueFromBlock, 3> intValues;
2438                             intValues.append(m_out.anchor(m_out.int32Zero));
2439                             m_out.branch(
2440                                 m_out.doubleLessThanOrUnordered(doubleValue, m_out.doubleZero),
2441                                 unsure(continuation), unsure(atLeastZero));
2442                             
2443                             LBasicBlock lastNext = m_out.appendTo(atLeastZero, withinRange);
2444                             intValues.append(m_out.anchor(m_out.constInt32(255)));
2445                             m_out.branch(
2446                                 m_out.doubleGreaterThan(doubleValue, m_out.constDouble(255)),
2447                                 unsure(continuation), unsure(withinRange));
2448                             
2449                             m_out.appendTo(withinRange, continuation);
2450                             intValues.append(m_out.anchor(m_out.fpToInt32(doubleValue)));
2451                             m_out.jump(continuation);
2452                             
2453                             m_out.appendTo(continuation, lastNext);
2454                             intValue = m_out.phi(m_out.int32, intValues);
2455                         } else
2456                             intValue = doubleToInt32(doubleValue);
2457                         break;
2458                     }
2459                         
2460                     default:
2461                         DFG_CRASH(m_graph, m_node, "Bad use kind");
2462                     }
2463                     
2464                     switch (elementSize(type)) {
2465                     case 1:
2466                         valueToStore = m_out.intCast(intValue, m_out.int8);
2467                         refType = m_out.ref8;
2468                         break;
2469                     case 2:
2470                         valueToStore = m_out.intCast(intValue, m_out.int16);
2471                         refType = m_out.ref16;
2472                         break;
2473                     case 4:
2474                         valueToStore = intValue;
2475                         refType = m_out.ref32;
2476                         break;
2477                     default:
2478                         DFG_CRASH(m_graph, m_node, "Bad element size");
2479                     }
2480                 } else /* !isInt(type) */ {
2481                     LValue value = lowDouble(child3);
2482                     switch (type) {
2483                     case TypeFloat32:
2484                         valueToStore = m_out.fpCast(value, m_out.floatType);
2485                         refType = m_out.refFloat;
2486                         break;
2487                     case TypeFloat64:
2488                         valueToStore = value;
2489                         refType = m_out.refDouble;
2490                         break;
2491                     default:
2492                         DFG_CRASH(m_graph, m_node, "Bad typed array type");
2493                     }
2494                 }
2495                 
2496                 if (m_node->arrayMode().isInBounds() || m_node->op() == PutByValAlias)
2497                     m_out.store(valueToStore, pointer, refType);
2498                 else {
2499                     LBasicBlock isInBounds = FTL_NEW_BLOCK(m_out, ("PutByVal typed array in bounds case"));
2500                     LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("PutByVal typed array continuation"));
2501                     
2502                     m_out.branch(
2503                         m_out.aboveOrEqual(index, lowInt32(child5)),
2504                         unsure(continuation), unsure(isInBounds));
2505                     
2506                     LBasicBlock lastNext = m_out.appendTo(isInBounds, continuation);
2507                     m_out.store(valueToStore, pointer, refType);
2508                     m_out.jump(continuation);
2509                     
2510                     m_out.appendTo(continuation, lastNext);
2511                 }
2512                 
2513                 return;
2514             }
2515             
2516             DFG_CRASH(m_graph, m_node, "Bad array type");
2517             break;
2518         }
2519     }
2520     
2521     void compileArrayPush()
2522     {
2523         LValue base = lowCell(m_node->child1());
2524         LValue storage = lowStorage(m_node->child3());
2525         
2526         switch (m_node->arrayMode().type()) {
2527         case Array::Int32:
2528         case Array::Contiguous:
2529         case Array::Double: {
2530             LValue value;
2531             LType refType;
2532             
2533             if (m_node->arrayMode().type() != Array::Double) {
2534                 value = lowJSValue(m_node->child2(), ManualOperandSpeculation);
2535                 if (m_node->arrayMode().type() == Array::Int32) {
2536                     FTL_TYPE_CHECK(
2537                         jsValueValue(value), m_node->child2(), SpecInt32, isNotInt32(value));
2538                 }
2539                 refType = m_out.ref64;
2540             } else {
2541                 value = lowDouble(m_node->child2());
2542                 FTL_TYPE_CHECK(
2543                     doubleValue(value), m_node->child2(), SpecDoubleReal,
2544                     m_out.doubleNotEqualOrUnordered(value, value));
2545                 refType = m_out.refDouble;
2546             }
2547             
2548             IndexedAbstractHeap& heap = m_heaps.forArrayType(m_node->arrayMode().type());
2549
2550             LValue prevLength = m_out.load32(storage, m_heaps.Butterfly_publicLength);
2551             
2552             LBasicBlock fastPath = FTL_NEW_BLOCK(m_out, ("ArrayPush fast path"));
2553             LBasicBlock slowPath = FTL_NEW_BLOCK(m_out, ("ArrayPush slow path"));
2554             LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("ArrayPush continuation"));
2555             
2556             m_out.branch(
2557                 m_out.aboveOrEqual(
2558                     prevLength, m_out.load32(storage, m_heaps.Butterfly_vectorLength)),
2559                 rarely(slowPath), usually(fastPath));
2560             
2561             LBasicBlock lastNext = m_out.appendTo(fastPath, slowPath);
2562             m_out.store(
2563                 value,
2564                 m_out.baseIndex(heap, storage, m_out.zeroExt(prevLength, m_out.intPtr)),
2565                 refType);
2566             LValue newLength = m_out.add(prevLength, m_out.int32One);
2567             m_out.store32(newLength, storage, m_heaps.Butterfly_publicLength);
2568             
2569             ValueFromBlock fastResult = m_out.anchor(boxInt32(newLength));
2570             m_out.jump(continuation);
2571             
2572             m_out.appendTo(slowPath, continuation);
2573             LValue operation;
2574             if (m_node->arrayMode().type() != Array::Double)
2575                 operation = m_out.operation(operationArrayPush);
2576             else
2577                 operation = m_out.operation(operationArrayPushDouble);
2578             ValueFromBlock slowResult = m_out.anchor(
2579                 vmCall(operation, m_callFrame, value, base));
2580             m_out.jump(continuation);
2581             
2582             m_out.appendTo(continuation, lastNext);
2583             setJSValue(m_out.phi(m_out.int64, fastResult, slowResult));
2584             return;
2585         }
2586             
2587         default:
2588             DFG_CRASH(m_graph, m_node, "Bad array type");
2589             return;
2590         }
2591     }
2592     
2593     void compileArrayPop()
2594     {
2595         LValue base = lowCell(m_node->child1());
2596         LValue storage = lowStorage(m_node->child2());
2597         
2598         switch (m_node->arrayMode().type()) {
2599         case Array::Int32:
2600         case Array::Double:
2601         case Array::Contiguous: {
2602             IndexedAbstractHeap& heap = m_heaps.forArrayType(m_node->arrayMode().type());
2603             
2604             LBasicBlock fastCase = FTL_NEW_BLOCK(m_out, ("ArrayPop fast case"));
2605             LBasicBlock slowCase = FTL_NEW_BLOCK(m_out, ("ArrayPop slow case"));
2606             LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("ArrayPop continuation"));
2607             
2608             LValue prevLength = m_out.load32(storage, m_heaps.Butterfly_publicLength);
2609             
2610             Vector<ValueFromBlock, 3> results;
2611             results.append(m_out.anchor(m_out.constInt64(JSValue::encode(jsUndefined()))));
2612             m_out.branch(
2613                 m_out.isZero32(prevLength), rarely(continuation), usually(fastCase));
2614             
2615             LBasicBlock lastNext = m_out.appendTo(fastCase, slowCase);
2616             LValue newLength = m_out.sub(prevLength, m_out.int32One);
2617             m_out.store32(newLength, storage, m_heaps.Butterfly_publicLength);
2618             TypedPointer pointer = m_out.baseIndex(
2619                 heap, storage, m_out.zeroExt(newLength, m_out.intPtr));
2620             if (m_node->arrayMode().type() != Array::Double) {
2621                 LValue result = m_out.load64(pointer);
2622                 m_out.store64(m_out.int64Zero, pointer);
2623                 results.append(m_out.anchor(result));
2624                 m_out.branch(
2625                     m_out.notZero64(result), usually(continuation), rarely(slowCase));
2626             } else {
2627                 LValue result = m_out.loadDouble(pointer);
2628                 m_out.store64(m_out.constInt64(bitwise_cast<int64_t>(PNaN)), pointer);
2629                 results.append(m_out.anchor(boxDouble(result)));
2630                 m_out.branch(
2631                     m_out.doubleEqual(result, result),
2632                     usually(continuation), rarely(slowCase));
2633             }
2634             
2635             m_out.appendTo(slowCase, continuation);
2636             results.append(m_out.anchor(vmCall(
2637                 m_out.operation(operationArrayPopAndRecoverLength), m_callFrame, base)));
2638             m_out.jump(continuation);
2639             
2640             m_out.appendTo(continuation, lastNext);
2641             setJSValue(m_out.phi(m_out.int64, results));
2642             return;
2643         }
2644
2645         default:
2646             DFG_CRASH(m_graph, m_node, "Bad array type");
2647             return;
2648         }
2649     }
2650     
2651     void compileNewObject()
2652     {
2653         setJSValue(allocateObject(m_node->structure()));
2654     }
2655     
2656     void compileNewArray()
2657     {
2658         // First speculate appropriately on all of the children. Do this unconditionally up here
2659         // because some of the slow paths may otherwise forget to do it. It's sort of arguable
2660         // that doing the speculations up here might be unprofitable for RA - so we can consider
2661         // sinking this to below the allocation fast path if we find that this has a lot of
2662         // register pressure.
2663         for (unsigned operandIndex = 0; operandIndex < m_node->numChildren(); ++operandIndex)
2664             speculate(m_graph.varArgChild(m_node, operandIndex));
2665         
2666         JSGlobalObject* globalObject = m_graph.globalObjectFor(m_node->origin.semantic);
2667         Structure* structure = globalObject->arrayStructureForIndexingTypeDuringAllocation(
2668             m_node->indexingType());
2669         
2670         DFG_ASSERT(m_graph, m_node, structure->indexingType() == m_node->indexingType());
2671         
2672         if (!globalObject->isHavingABadTime() && !hasAnyArrayStorage(m_node->indexingType())) {
2673             unsigned numElements = m_node->numChildren();
2674             
2675             ArrayValues arrayValues = allocateJSArray(structure, numElements);
2676             
2677             for (unsigned operandIndex = 0; operandIndex < m_node->numChildren(); ++operandIndex) {
2678                 Edge edge = m_graph.varArgChild(m_node, operandIndex);
2679                 
2680                 switch (m_node->indexingType()) {
2681                 case ALL_BLANK_INDEXING_TYPES:
2682                 case ALL_UNDECIDED_INDEXING_TYPES:
2683                     DFG_CRASH(m_graph, m_node, "Bad indexing type");
2684                     break;
2685                     
2686                 case ALL_DOUBLE_INDEXING_TYPES:
2687                     m_out.storeDouble(
2688                         lowDouble(edge),
2689                         arrayValues.butterfly, m_heaps.indexedDoubleProperties[operandIndex]);
2690                     break;
2691                     
2692                 case ALL_INT32_INDEXING_TYPES:
2693                 case ALL_CONTIGUOUS_INDEXING_TYPES:
2694                     m_out.store64(
2695                         lowJSValue(edge, ManualOperandSpeculation),
2696                         arrayValues.butterfly,
2697                         m_heaps.forIndexingType(m_node->indexingType())->at(operandIndex));
2698                     break;
2699                     
2700                 default:
2701                     DFG_CRASH(m_graph, m_node, "Corrupt indexing type");
2702                     break;
2703                 }
2704             }
2705             
2706             setJSValue(arrayValues.array);
2707             return;
2708         }
2709         
2710         if (!m_node->numChildren()) {
2711             setJSValue(vmCall(
2712                 m_out.operation(operationNewEmptyArray), m_callFrame,
2713                 m_out.constIntPtr(structure)));
2714             return;
2715         }
2716         
2717         size_t scratchSize = sizeof(EncodedJSValue) * m_node->numChildren();
2718         ASSERT(scratchSize);
2719         ScratchBuffer* scratchBuffer = vm().scratchBufferForSize(scratchSize);
2720         EncodedJSValue* buffer = static_cast<EncodedJSValue*>(scratchBuffer->dataBuffer());
2721         
2722         for (unsigned operandIndex = 0; operandIndex < m_node->numChildren(); ++operandIndex) {
2723             Edge edge = m_graph.varArgChild(m_node, operandIndex);
2724             m_out.store64(
2725                 lowJSValue(edge, ManualOperandSpeculation),
2726                 m_out.absolute(buffer + operandIndex));
2727         }
2728         
2729         m_out.storePtr(
2730             m_out.constIntPtr(scratchSize), m_out.absolute(scratchBuffer->activeLengthPtr()));
2731         
2732         LValue result = vmCall(
2733             m_out.operation(operationNewArray), m_callFrame,
2734             m_out.constIntPtr(structure), m_out.constIntPtr(buffer),
2735             m_out.constIntPtr(m_node->numChildren()));
2736         
2737         m_out.storePtr(m_out.intPtrZero, m_out.absolute(scratchBuffer->activeLengthPtr()));
2738         
2739         setJSValue(result);
2740     }
2741     
2742     void compileNewArrayBuffer()
2743     {
2744         JSGlobalObject* globalObject = m_graph.globalObjectFor(m_node->origin.semantic);
2745         Structure* structure = globalObject->arrayStructureForIndexingTypeDuringAllocation(
2746             m_node->indexingType());
2747         
2748         DFG_ASSERT(m_graph, m_node, structure->indexingType() == m_node->indexingType());
2749         
2750         if (!globalObject->isHavingABadTime() && !hasAnyArrayStorage(m_node->indexingType())) {
2751             unsigned numElements = m_node->numConstants();
2752             
2753             ArrayValues arrayValues = allocateJSArray(structure, numElements);
2754             
2755             JSValue* data = codeBlock()->constantBuffer(m_node->startConstant());
2756             for (unsigned index = 0; index < m_node->numConstants(); ++index) {
2757                 int64_t value;
2758                 if (hasDouble(m_node->indexingType()))
2759                     value = bitwise_cast<int64_t>(data[index].asNumber());
2760                 else
2761                     value = JSValue::encode(data[index]);
2762                 
2763                 m_out.store64(
2764                     m_out.constInt64(value),
2765                     arrayValues.butterfly,
2766                     m_heaps.forIndexingType(m_node->indexingType())->at(index));
2767             }
2768             
2769             setJSValue(arrayValues.array);
2770             return;
2771         }
2772         
2773         setJSValue(vmCall(
2774             m_out.operation(operationNewArrayBuffer), m_callFrame,
2775             m_out.constIntPtr(structure), m_out.constIntPtr(m_node->startConstant()),
2776             m_out.constIntPtr(m_node->numConstants())));
2777     }
2778     
2779     void compileNewArrayWithSize()
2780     {
2781         LValue publicLength = lowInt32(m_node->child1());
2782         
2783         JSGlobalObject* globalObject = m_graph.globalObjectFor(m_node->origin.semantic);
2784         Structure* structure = globalObject->arrayStructureForIndexingTypeDuringAllocation(
2785             m_node->indexingType());
2786         
2787         if (!globalObject->isHavingABadTime() && !hasAnyArrayStorage(m_node->indexingType())) {
2788             ASSERT(
2789                 hasUndecided(structure->indexingType())
2790                 || hasInt32(structure->indexingType())
2791                 || hasDouble(structure->indexingType())
2792                 || hasContiguous(structure->indexingType()));
2793
2794             LBasicBlock fastCase = FTL_NEW_BLOCK(m_out, ("NewArrayWithSize fast case"));
2795             LBasicBlock largeCase = FTL_NEW_BLOCK(m_out, ("NewArrayWithSize large case"));
2796             LBasicBlock failCase = FTL_NEW_BLOCK(m_out, ("NewArrayWithSize fail case"));
2797             LBasicBlock slowCase = FTL_NEW_BLOCK(m_out, ("NewArrayWithSize slow case"));
2798             LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("NewArrayWithSize continuation"));
2799             
2800             m_out.branch(
2801                 m_out.aboveOrEqual(publicLength, m_out.constInt32(MIN_SPARSE_ARRAY_INDEX)),
2802                 rarely(largeCase), usually(fastCase));
2803
2804             LBasicBlock lastNext = m_out.appendTo(fastCase, largeCase);
2805             
2806             // We don't round up to BASE_VECTOR_LEN for new Array(blah).
2807             LValue vectorLength = publicLength;
2808             
2809             LValue payloadSize =
2810                 m_out.shl(m_out.zeroExt(vectorLength, m_out.intPtr), m_out.constIntPtr(3));
2811             
2812             LValue butterflySize = m_out.add(
2813                 payloadSize, m_out.constIntPtr(sizeof(IndexingHeader)));
2814             
2815             LValue endOfStorage = allocateBasicStorageAndGetEnd(butterflySize, failCase);
2816             
2817             LValue butterfly = m_out.sub(endOfStorage, payloadSize);
2818             
2819             LValue object = allocateObject<JSArray>(
2820                 structure, butterfly, failCase);
2821             
2822             m_out.store32(publicLength, butterfly, m_heaps.Butterfly_publicLength);
2823             m_out.store32(vectorLength, butterfly, m_heaps.Butterfly_vectorLength);
2824             
2825             if (hasDouble(m_node->indexingType())) {
2826                 LBasicBlock initLoop = FTL_NEW_BLOCK(m_out, ("NewArrayWithSize double init loop"));
2827                 LBasicBlock initDone = FTL_NEW_BLOCK(m_out, ("NewArrayWithSize double init done"));
2828                 
2829                 ValueFromBlock originalIndex = m_out.anchor(vectorLength);
2830                 ValueFromBlock originalPointer = m_out.anchor(butterfly);
2831                 m_out.branch(
2832                     m_out.notZero32(vectorLength), unsure(initLoop), unsure(initDone));
2833                 
2834                 LBasicBlock initLastNext = m_out.appendTo(initLoop, initDone);
2835                 LValue index = m_out.phi(m_out.int32, originalIndex);
2836                 LValue pointer = m_out.phi(m_out.intPtr, originalPointer);
2837                 
2838                 m_out.store64(
2839                     m_out.constInt64(bitwise_cast<int64_t>(PNaN)),
2840                     TypedPointer(m_heaps.indexedDoubleProperties.atAnyIndex(), pointer));
2841                 
2842                 LValue nextIndex = m_out.sub(index, m_out.int32One);
2843                 addIncoming(index, m_out.anchor(nextIndex));
2844                 addIncoming(pointer, m_out.anchor(m_out.add(pointer, m_out.intPtrEight)));
2845                 m_out.branch(
2846                     m_out.notZero32(nextIndex), unsure(initLoop), unsure(initDone));
2847                 
2848                 m_out.appendTo(initDone, initLastNext);
2849             }
2850             
2851             ValueFromBlock fastResult = m_out.anchor(object);
2852             m_out.jump(continuation);
2853             
2854             m_out.appendTo(largeCase, failCase);
2855             ValueFromBlock largeStructure = m_out.anchor(m_out.constIntPtr(
2856                 globalObject->arrayStructureForIndexingTypeDuringAllocation(ArrayWithArrayStorage)));
2857             m_out.jump(slowCase);
2858             
2859             m_out.appendTo(failCase, slowCase);
2860             ValueFromBlock failStructure = m_out.anchor(m_out.constIntPtr(structure));
2861             m_out.jump(slowCase);
2862             
2863             m_out.appendTo(slowCase, continuation);
2864             LValue structureValue = m_out.phi(
2865                 m_out.intPtr, largeStructure, failStructure);
2866             ValueFromBlock slowResult = m_out.anchor(vmCall(
2867                 m_out.operation(operationNewArrayWithSize),
2868                 m_callFrame, structureValue, publicLength));
2869             m_out.jump(continuation);
2870             
2871             m_out.appendTo(continuation, lastNext);
2872             setJSValue(m_out.phi(m_out.intPtr, fastResult, slowResult));
2873             return;
2874         }
2875         
2876         LValue structureValue = m_out.select(
2877             m_out.aboveOrEqual(publicLength, m_out.constInt32(MIN_SPARSE_ARRAY_INDEX)),
2878             m_out.constIntPtr(
2879                 globalObject->arrayStructureForIndexingTypeDuringAllocation(ArrayWithArrayStorage)),
2880             m_out.constIntPtr(structure));
2881         setJSValue(vmCall(m_out.operation(operationNewArrayWithSize), m_callFrame, structureValue, publicLength));
2882     }
2883     
2884     void compileAllocatePropertyStorage()
2885     {
2886         LValue object = lowCell(m_node->child1());
2887         setStorage(allocatePropertyStorage(object, m_node->transition()->previous));
2888     }
2889
2890     void compileReallocatePropertyStorage()
2891     {
2892         Transition* transition = m_node->transition();
2893         LValue object = lowCell(m_node->child1());
2894         LValue oldStorage = lowStorage(m_node->child2());
2895         
2896         setStorage(
2897             reallocatePropertyStorage(
2898                 object, oldStorage, transition->previous, transition->next));
2899     }
2900     
2901     void compileToString()
2902     {
2903         switch (m_node->child1().useKind()) {
2904         case StringObjectUse: {
2905             LValue cell = lowCell(m_node->child1());
2906             speculateStringObjectForCell(m_node->child1(), cell);
2907             m_interpreter.filter(m_node->child1(), SpecStringObject);
2908             
2909             setJSValue(m_out.loadPtr(cell, m_heaps.JSWrapperObject_internalValue));
2910             return;
2911         }
2912             
2913         case StringOrStringObjectUse: {
2914             LValue cell = lowCell(m_node->child1());
2915             LValue structureID = m_out.load32(cell, m_heaps.JSCell_structureID);
2916             
2917             LBasicBlock notString = FTL_NEW_BLOCK(m_out, ("ToString StringOrStringObject not string case"));
2918             LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("ToString StringOrStringObject continuation"));
2919             
2920             ValueFromBlock simpleResult = m_out.anchor(cell);
2921             m_out.branch(
2922                 m_out.equal(structureID, m_out.constInt32(vm().stringStructure->id())),
2923                 unsure(continuation), unsure(notString));
2924             
2925             LBasicBlock lastNext = m_out.appendTo(notString, continuation);
2926             speculateStringObjectForStructureID(m_node->child1(), structureID);
2927             ValueFromBlock unboxedResult = m_out.anchor(
2928                 m_out.loadPtr(cell, m_heaps.JSWrapperObject_internalValue));
2929             m_out.jump(continuation);
2930             
2931             m_out.appendTo(continuation, lastNext);
2932             setJSValue(m_out.phi(m_out.int64, simpleResult, unboxedResult));
2933             
2934             m_interpreter.filter(m_node->child1(), SpecString | SpecStringObject);
2935             return;
2936         }
2937             
2938         case CellUse:
2939         case UntypedUse: {
2940             LValue value;
2941             if (m_node->child1().useKind() == CellUse)
2942                 value = lowCell(m_node->child1());
2943             else
2944                 value = lowJSValue(m_node->child1());
2945             
2946             LBasicBlock isCell = FTL_NEW_BLOCK(m_out, ("ToString CellUse/UntypedUse is cell"));
2947             LBasicBlock notString = FTL_NEW_BLOCK(m_out, ("ToString CellUse/UntypedUse not string"));
2948             LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("ToString CellUse/UntypedUse continuation"));
2949             
2950             LValue isCellPredicate;
2951             if (m_node->child1().useKind() == CellUse)
2952                 isCellPredicate = m_out.booleanTrue;
2953             else
2954                 isCellPredicate = this->isCell(value);
2955             m_out.branch(isCellPredicate, unsure(isCell), unsure(notString));
2956             
2957             LBasicBlock lastNext = m_out.appendTo(isCell, notString);
2958             ValueFromBlock simpleResult = m_out.anchor(value);
2959             LValue isStringPredicate;
2960             if (m_node->child1()->prediction() & SpecString) {
2961                 isStringPredicate = m_out.equal(
2962                     m_out.load32(value, m_heaps.JSCell_structureID),
2963                     m_out.constInt32(vm().stringStructure->id()));
2964             } else
2965                 isStringPredicate = m_out.booleanFalse;
2966             m_out.branch(isStringPredicate, unsure(continuation), unsure(notString));
2967             
2968             m_out.appendTo(notString, continuation);
2969             LValue operation;
2970             if (m_node->child1().useKind() == CellUse)
2971                 operation = m_out.operation(operationToStringOnCell);
2972             else
2973                 operation = m_out.operation(operationToString);
2974             ValueFromBlock convertedResult = m_out.anchor(vmCall(operation, m_callFrame, value));
2975             m_out.jump(continuation);
2976             
2977             m_out.appendTo(continuation, lastNext);
2978             setJSValue(m_out.phi(m_out.int64, simpleResult, convertedResult));
2979             return;
2980         }
2981             
2982         default:
2983             DFG_CRASH(m_graph, m_node, "Bad use kind");
2984             break;
2985         }
2986     }
2987     
2988     void compileToPrimitive()
2989     {
2990         LValue value = lowJSValue(m_node->child1());
2991         
2992         LBasicBlock isCellCase = FTL_NEW_BLOCK(m_out, ("ToPrimitive cell case"));
2993         LBasicBlock isObjectCase = FTL_NEW_BLOCK(m_out, ("ToPrimitive object case"));
2994         LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("ToPrimitive continuation"));
2995         
2996         Vector<ValueFromBlock, 3> results;
2997         
2998         results.append(m_out.anchor(value));
2999         m_out.branch(isCell(value), unsure(isCellCase), unsure(continuation));
3000         
3001         LBasicBlock lastNext = m_out.appendTo(isCellCase, isObjectCase);
3002         results.append(m_out.anchor(value));
3003         m_out.branch(isObject(value), unsure(isObjectCase), unsure(continuation));
3004         
3005         m_out.appendTo(isObjectCase, continuation);
3006         results.append(m_out.anchor(vmCall(
3007             m_out.operation(operationToPrimitive), m_callFrame, value)));
3008         m_out.jump(continuation);
3009         
3010         m_out.appendTo(continuation, lastNext);
3011         setJSValue(m_out.phi(m_out.int64, results));
3012     }
3013     
3014     void compileMakeRope()
3015     {
3016         LValue kids[3];
3017         unsigned numKids;
3018         kids[0] = lowCell(m_node->child1());
3019         kids[1] = lowCell(m_node->child2());
3020         if (m_node->child3()) {
3021             kids[2] = lowCell(m_node->child3());
3022             numKids = 3;
3023         } else {
3024             kids[2] = 0;
3025             numKids = 2;
3026         }
3027         
3028         LBasicBlock slowPath = FTL_NEW_BLOCK(m_out, ("MakeRope slow path"));
3029         LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("MakeRope continuation"));
3030         
3031         LBasicBlock lastNext = m_out.insertNewBlocksBefore(slowPath);
3032         
3033         MarkedAllocator& allocator =
3034             vm().heap.allocatorForObjectWithImmortalStructureDestructor(sizeof(JSRopeString));
3035         
3036         LValue result = allocateCell(
3037             m_out.constIntPtr(&allocator),
3038             vm().stringStructure.get(),
3039             slowPath);
3040         
3041         m_out.storePtr(m_out.intPtrZero, result, m_heaps.JSString_value);
3042         for (unsigned i = 0; i < numKids; ++i)
3043             m_out.storePtr(kids[i], result, m_heaps.JSRopeString_fibers[i]);
3044         for (unsigned i = numKids; i < JSRopeString::s_maxInternalRopeLength; ++i)
3045             m_out.storePtr(m_out.intPtrZero, result, m_heaps.JSRopeString_fibers[i]);
3046         LValue flags = m_out.load32(kids[0], m_heaps.JSString_flags);
3047         LValue length = m_out.load32(kids[0], m_heaps.JSString_length);
3048         for (unsigned i = 1; i < numKids; ++i) {
3049             flags = m_out.bitAnd(flags, m_out.load32(kids[i], m_heaps.JSString_flags));
3050             LValue lengthAndOverflow = m_out.addWithOverflow32(
3051                 length, m_out.load32(kids[i], m_heaps.JSString_length));
3052             speculate(Uncountable, noValue(), 0, m_out.extractValue(lengthAndOverflow, 1));
3053             length = m_out.extractValue(lengthAndOverflow, 0);
3054         }
3055         m_out.store32(
3056             m_out.bitAnd(m_out.constInt32(JSString::Is8Bit), flags),
3057             result, m_heaps.JSString_flags);
3058         m_out.store32(length, result, m_heaps.JSString_length);
3059