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