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