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