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