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