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