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