df074fbbc1361c60ded29c79aa82d053e6a11dc2
[WebKit-https.git] / Source / JavaScriptCore / ftl / FTLLowerDFGToLLVM.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 "FTLLowerDFGToLLVM.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 LLVM, 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 LowerDFGToLLVM {
123     WTF_MAKE_NONCOPYABLE(LowerDFGToLLVM);
124 public:
125     LowerDFGToLLVM(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 LLVM to reorder things) but it will
363         // make IR dumps easier to read.
364         m_out.appendTo(lowBlock, m_nextLowBlock);
365         
366         if (Options::ftlCrashes())
367             m_out.trap();
368         
369         if (!m_highBlock->cfaHasVisited) {
370             if (verboseCompilationEnabled())
371                 dataLog("Bailing because CFA didn't reach.\n");
372             crash(m_highBlock->index, UINT_MAX);
373             return;
374         }
375         
376         m_availabilityCalculator.beginBlock(m_highBlock);
377         
378         m_state.reset();
379         m_state.beginBasicBlock(m_highBlock);
380         
381         for (m_nodeIndex = 0; m_nodeIndex < m_highBlock->size(); ++m_nodeIndex) {
382             if (!compileNode(m_nodeIndex))
383                 break;
384         }
385     }
386
387     void safelyInvalidateAfterTermination()
388     {
389         if (verboseCompilationEnabled())
390             dataLog("Bailing.\n");
391         crash();
392
393         // Invalidate dominated blocks. Under normal circumstances we would expect
394         // them to be invalidated already. But you can have the CFA become more
395         // precise over time because the structures of objects change on the main
396         // thread. Failing to do this would result in weird crashes due to a value
397         // being used but not defined. Race conditions FTW!
398         for (BlockIndex blockIndex = m_graph.numBlocks(); blockIndex--;) {
399             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         // FIXME: investigate llvm.powi to better understand its performance characteristics.
1768         // It might be better to have the inline loop in DFG too.
1769         if (m_node->child2().useKind() == Int32Use)
1770             setDouble(m_out.doublePowi(lowDouble(m_node->child1()), lowInt32(m_node->child2())));
1771         else {
1772             LValue base = lowDouble(m_node->child1());
1773             LValue exponent = lowDouble(m_node->child2());
1774
1775             LBasicBlock integerExponentIsSmallBlock = FTL_NEW_BLOCK(m_out, ("ArithPow test integer exponent is small."));
1776             LBasicBlock integerExponentPowBlock = FTL_NEW_BLOCK(m_out, ("ArithPow pow(double, (int)double)."));
1777             LBasicBlock doubleExponentPowBlockEntry = FTL_NEW_BLOCK(m_out, ("ArithPow pow(double, double)."));
1778             LBasicBlock nanExceptionExponentIsInfinity = FTL_NEW_BLOCK(m_out, ("ArithPow NaN Exception, check exponent is infinity."));
1779             LBasicBlock nanExceptionBaseIsOne = FTL_NEW_BLOCK(m_out, ("ArithPow NaN Exception, check base is one."));
1780             LBasicBlock powBlock = FTL_NEW_BLOCK(m_out, ("ArithPow regular pow"));
1781             LBasicBlock nanExceptionResultIsNaN = FTL_NEW_BLOCK(m_out, ("ArithPow NaN Exception, result is NaN."));
1782             LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("ArithPow continuation"));
1783
1784             LValue integerExponent = m_out.doubleToInt(exponent);
1785             LValue integerExponentConvertedToDouble = m_out.intToDouble(integerExponent);
1786             LValue exponentIsInteger = m_out.doubleEqual(exponent, integerExponentConvertedToDouble);
1787             m_out.branch(exponentIsInteger, unsure(integerExponentIsSmallBlock), unsure(doubleExponentPowBlockEntry));
1788
1789             LBasicBlock lastNext = m_out.appendTo(integerExponentIsSmallBlock, integerExponentPowBlock);
1790             LValue integerExponentBelow1000 = m_out.below(integerExponent, m_out.constInt32(1000));
1791             m_out.branch(integerExponentBelow1000, usually(integerExponentPowBlock), rarely(doubleExponentPowBlockEntry));
1792
1793             m_out.appendTo(integerExponentPowBlock, doubleExponentPowBlockEntry);
1794             ValueFromBlock powDoubleIntResult = m_out.anchor(m_out.doublePowi(base, integerExponent));
1795             m_out.jump(continuation);
1796
1797             // If y is NaN, the result is NaN.
1798             m_out.appendTo(doubleExponentPowBlockEntry, nanExceptionExponentIsInfinity);
1799             LValue exponentIsNaN;
1800             if (provenType(m_node->child2()) & SpecDoubleNaN)
1801                 exponentIsNaN = m_out.doubleNotEqualOrUnordered(exponent, exponent);
1802             else
1803                 exponentIsNaN = m_out.booleanFalse;
1804             m_out.branch(exponentIsNaN, rarely(nanExceptionResultIsNaN), usually(nanExceptionExponentIsInfinity));
1805
1806             // If abs(x) is 1 and y is +infinity, the result is NaN.
1807             // If abs(x) is 1 and y is -infinity, the result is NaN.
1808             m_out.appendTo(nanExceptionExponentIsInfinity, nanExceptionBaseIsOne);
1809             LValue absoluteExponent = m_out.doubleAbs(exponent);
1810             LValue absoluteExponentIsInfinity = m_out.doubleEqual(absoluteExponent, m_out.constDouble(std::numeric_limits<double>::infinity()));
1811             m_out.branch(absoluteExponentIsInfinity, rarely(nanExceptionBaseIsOne), usually(powBlock));
1812
1813             m_out.appendTo(nanExceptionBaseIsOne, powBlock);
1814             LValue absoluteBase = m_out.doubleAbs(base);
1815             LValue absoluteBaseIsOne = m_out.doubleEqual(absoluteBase, m_out.constDouble(1));
1816             m_out.branch(absoluteBaseIsOne, unsure(nanExceptionResultIsNaN), unsure(powBlock));
1817
1818             m_out.appendTo(powBlock, nanExceptionResultIsNaN);
1819             ValueFromBlock powResult = m_out.anchor(m_out.doublePow(base, exponent));
1820             m_out.jump(continuation);
1821
1822             m_out.appendTo(nanExceptionResultIsNaN, continuation);
1823             ValueFromBlock pureNan = m_out.anchor(m_out.constDouble(PNaN));
1824             m_out.jump(continuation);
1825
1826             m_out.appendTo(continuation, lastNext);
1827             setDouble(m_out.phi(m_out.doubleType, powDoubleIntResult, powResult, pureNan));
1828         }
1829     }
1830
1831     void compileArithRandom()
1832     {
1833         JSGlobalObject* globalObject = m_graph.globalObjectFor(m_node->origin.semantic);
1834
1835         // Inlined WeakRandom::advance().
1836         // uint64_t x = m_low;
1837         void* lowAddress = reinterpret_cast<uint8_t*>(globalObject) + JSGlobalObject::weakRandomOffset() + WeakRandom::lowOffset();
1838         LValue low = m_out.load64(m_out.absolute(lowAddress));
1839         // uint64_t y = m_high;
1840         void* highAddress = reinterpret_cast<uint8_t*>(globalObject) + JSGlobalObject::weakRandomOffset() + WeakRandom::highOffset();
1841         LValue high = m_out.load64(m_out.absolute(highAddress));
1842         // m_low = y;
1843         m_out.store64(high, m_out.absolute(lowAddress));
1844
1845         // x ^= x << 23;
1846         LValue phase1 = m_out.bitXor(m_out.shl(low, m_out.constInt64(23)), low);
1847
1848         // x ^= x >> 17;
1849         LValue phase2 = m_out.bitXor(m_out.lShr(phase1, m_out.constInt64(17)), phase1);
1850
1851         // x ^= y ^ (y >> 26);
1852         LValue phase3 = m_out.bitXor(m_out.bitXor(high, m_out.lShr(high, m_out.constInt64(26))), phase2);
1853
1854         // m_high = x;
1855         m_out.store64(phase3, m_out.absolute(highAddress));
1856
1857         // return x + y;
1858         LValue random64 = m_out.add(phase3, high);
1859
1860         // Extract random 53bit. [0, 53] bit is safe integer number ranges in double representation.
1861         LValue random53 = m_out.bitAnd(random64, m_out.constInt64((1ULL << 53) - 1));
1862
1863         LValue double53Integer = m_out.intToDouble(random53);
1864
1865         // Convert `(53bit double integer value) / (1 << 53)` to `(53bit double integer value) * (1.0 / (1 << 53))`.
1866         // In latter case, `1.0 / (1 << 53)` will become a double value represented as (mantissa = 0 & exp = 970, it means 1e-(2**54)).
1867         static const double scale = 1.0 / (1ULL << 53);
1868
1869         // Multiplying 1e-(2**54) with the double integer does not change anything of the mantissa part of the double integer.
1870         // It just reduces the exp part of the given 53bit double integer.
1871         // (Except for 0.0. This is specially handled and in this case, exp just becomes 0.)
1872         // Now we get 53bit precision random double value in [0, 1).
1873         LValue result = m_out.doubleMul(double53Integer, m_out.constDouble(scale));
1874
1875         setDouble(result);
1876     }
1877
1878     void compileArithRound()
1879     {
1880         LBasicBlock realPartIsMoreThanHalf = FTL_NEW_BLOCK(m_out, ("ArithRound should round down"));
1881         LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("ArithRound continuation"));
1882
1883         LValue value = lowDouble(m_node->child1());
1884         LValue integerValue = m_out.doubleCeil(value);
1885         ValueFromBlock integerValueResult = m_out.anchor(integerValue);
1886
1887         LValue realPart = m_out.doubleSub(integerValue, value);
1888
1889         m_out.branch(m_out.doubleGreaterThanOrUnordered(realPart, m_out.constDouble(0.5)), unsure(realPartIsMoreThanHalf), unsure(continuation));
1890
1891         LBasicBlock lastNext = m_out.appendTo(realPartIsMoreThanHalf, continuation);
1892         LValue integerValueRoundedDown = m_out.doubleSub(integerValue, m_out.constDouble(1));
1893         ValueFromBlock integerValueRoundedDownResult = m_out.anchor(integerValueRoundedDown);
1894         m_out.jump(continuation);
1895         m_out.appendTo(continuation, lastNext);
1896
1897         LValue result = m_out.phi(m_out.doubleType, integerValueResult, integerValueRoundedDownResult);
1898
1899         if (producesInteger(m_node->arithRoundingMode())) {
1900             LValue integerValue = convertDoubleToInt32(result, shouldCheckNegativeZero(m_node->arithRoundingMode()));
1901             setInt32(integerValue);
1902         } else
1903             setDouble(result);
1904     }
1905
1906     void compileArithSqrt() { setDouble(m_out.doubleSqrt(lowDouble(m_node->child1()))); }
1907
1908     void compileArithLog() { setDouble(m_out.doubleLog(lowDouble(m_node->child1()))); }
1909     
1910     void compileArithFRound()
1911     {
1912         setDouble(m_out.fround(lowDouble(m_node->child1())));
1913     }
1914     
1915     void compileArithNegate()
1916     {
1917         switch (m_node->child1().useKind()) {
1918         case Int32Use: {
1919             LValue value = lowInt32(m_node->child1());
1920             
1921             LValue result;
1922             if (!shouldCheckOverflow(m_node->arithMode()))
1923                 result = m_out.neg(value);
1924             else if (!shouldCheckNegativeZero(m_node->arithMode())) {
1925                 // "0 - x" is the canonical way of saying "-x" in both B3 and LLVM. This gets
1926                 // lowered to the right thing.
1927                 CheckValue* check = m_out.speculateSub(m_out.int32Zero, value);
1928                 blessSpeculation(check, Overflow, noValue(), nullptr, m_origin);
1929                 result = check;
1930             } else {
1931                 speculate(Overflow, noValue(), 0, m_out.testIsZero32(value, m_out.constInt32(0x7fffffff)));
1932                 result = m_out.neg(value);
1933             }
1934
1935             setInt32(result);
1936             break;
1937         }
1938             
1939         case Int52RepUse: {
1940             if (!abstractValue(m_node->child1()).couldBeType(SpecInt52)) {
1941                 Int52Kind kind;
1942                 LValue value = lowWhicheverInt52(m_node->child1(), kind);
1943                 LValue result = m_out.neg(value);
1944                 if (shouldCheckNegativeZero(m_node->arithMode()))
1945                     speculate(NegativeZero, noValue(), 0, m_out.isZero64(result));
1946                 setInt52(result, kind);
1947                 break;
1948             }
1949             
1950             LValue value = lowInt52(m_node->child1());
1951             CheckValue* result = m_out.speculateSub(m_out.int64Zero, value);
1952             blessSpeculation(result, Int52Overflow, noValue(), nullptr, m_origin);
1953             speculate(NegativeZero, noValue(), 0, m_out.isZero64(result));
1954             setInt52(result);
1955             break;
1956         }
1957             
1958         case DoubleRepUse: {
1959             setDouble(m_out.doubleNeg(lowDouble(m_node->child1())));
1960             break;
1961         }
1962             
1963         default:
1964             DFG_CRASH(m_graph, m_node, "Bad use kind");
1965             break;
1966         }
1967     }
1968     
1969     void compileBitAnd()
1970     {
1971         if (m_node->isBinaryUseKind(UntypedUse)) {
1972             emitBinaryBitOpSnippet<JITBitAndGenerator>(operationValueBitAnd);
1973             return;
1974         }
1975         setInt32(m_out.bitAnd(lowInt32(m_node->child1()), lowInt32(m_node->child2())));
1976     }
1977     
1978     void compileBitOr()
1979     {
1980         if (m_node->isBinaryUseKind(UntypedUse)) {
1981             emitBinaryBitOpSnippet<JITBitOrGenerator>(operationValueBitOr);
1982             return;
1983         }
1984         setInt32(m_out.bitOr(lowInt32(m_node->child1()), lowInt32(m_node->child2())));
1985     }
1986     
1987     void compileBitXor()
1988     {
1989         if (m_node->isBinaryUseKind(UntypedUse)) {
1990             emitBinaryBitOpSnippet<JITBitXorGenerator>(operationValueBitXor);
1991             return;
1992         }
1993         setInt32(m_out.bitXor(lowInt32(m_node->child1()), lowInt32(m_node->child2())));
1994     }
1995     
1996     void compileBitRShift()
1997     {
1998         if (m_node->isBinaryUseKind(UntypedUse)) {
1999             emitRightShiftSnippet(JITRightShiftGenerator::SignedShift);
2000             return;
2001         }
2002         setInt32(m_out.aShr(
2003             lowInt32(m_node->child1()),
2004             m_out.bitAnd(lowInt32(m_node->child2()), m_out.constInt32(31))));
2005     }
2006     
2007     void compileBitLShift()
2008     {
2009         if (m_node->isBinaryUseKind(UntypedUse)) {
2010             emitBinaryBitOpSnippet<JITLeftShiftGenerator>(operationValueBitLShift);
2011             return;
2012         }
2013         setInt32(m_out.shl(
2014             lowInt32(m_node->child1()),
2015             m_out.bitAnd(lowInt32(m_node->child2()), m_out.constInt32(31))));
2016     }
2017     
2018     void compileBitURShift()
2019     {
2020         if (m_node->isBinaryUseKind(UntypedUse)) {
2021             emitRightShiftSnippet(JITRightShiftGenerator::UnsignedShift);
2022             return;
2023         }
2024         setInt32(m_out.lShr(
2025             lowInt32(m_node->child1()),
2026             m_out.bitAnd(lowInt32(m_node->child2()), m_out.constInt32(31))));
2027     }
2028     
2029     void compileUInt32ToNumber()
2030     {
2031         LValue value = lowInt32(m_node->child1());
2032
2033         if (doesOverflow(m_node->arithMode())) {
2034             setDouble(m_out.unsignedToDouble(value));
2035             return;
2036         }
2037         
2038         speculate(Overflow, noValue(), 0, m_out.lessThan(value, m_out.int32Zero));
2039         setInt32(value);
2040     }
2041     
2042     void compileCheckStructure()
2043     {
2044         ExitKind exitKind;
2045         if (m_node->child1()->hasConstant())
2046             exitKind = BadConstantCache;
2047         else
2048             exitKind = BadCache;
2049
2050         switch (m_node->child1().useKind()) {
2051         case CellUse:
2052         case KnownCellUse: {
2053             LValue cell = lowCell(m_node->child1());
2054             
2055             checkStructure(
2056                 m_out.load32(cell, m_heaps.JSCell_structureID), jsValueValue(cell),
2057                 exitKind, m_node->structureSet(),
2058                 [&] (Structure* structure) {
2059                     return weakStructureID(structure);
2060                 });
2061             return;
2062         }
2063
2064         case CellOrOtherUse: {
2065             LValue value = lowJSValue(m_node->child1(), ManualOperandSpeculation);
2066
2067             LBasicBlock cellCase = FTL_NEW_BLOCK(m_out, ("CheckStructure CellOrOtherUse cell case"));
2068             LBasicBlock notCellCase = FTL_NEW_BLOCK(m_out, ("CheckStructure CellOrOtherUse not cell case"));
2069             LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("CheckStructure CellOrOtherUse continuation"));
2070
2071             m_out.branch(
2072                 isCell(value, provenType(m_node->child1())), unsure(cellCase), unsure(notCellCase));
2073
2074             LBasicBlock lastNext = m_out.appendTo(cellCase, notCellCase);
2075             checkStructure(
2076                 m_out.load32(value, m_heaps.JSCell_structureID), jsValueValue(value),
2077                 exitKind, m_node->structureSet(),
2078                 [&] (Structure* structure) {
2079                     return weakStructureID(structure);
2080                 });
2081             m_out.jump(continuation);
2082
2083             m_out.appendTo(notCellCase, continuation);
2084             FTL_TYPE_CHECK(jsValueValue(value), m_node->child1(), SpecCell | SpecOther, isNotOther(value));
2085             m_out.jump(continuation);
2086
2087             m_out.appendTo(continuation, lastNext);
2088             return;
2089         }
2090
2091         default:
2092             DFG_CRASH(m_graph, m_node, "Bad use kind");
2093             return;
2094         }
2095     }
2096     
2097     void compileCheckCell()
2098     {
2099         LValue cell = lowCell(m_node->child1());
2100         
2101         speculate(
2102             BadCell, jsValueValue(cell), m_node->child1().node(),
2103             m_out.notEqual(cell, weakPointer(m_node->cellOperand()->cell())));
2104     }
2105     
2106     void compileCheckBadCell()
2107     {
2108         terminate(BadCell);
2109     }
2110
2111     void compileCheckNotEmpty()
2112     {
2113         speculate(TDZFailure, noValue(), nullptr, m_out.isZero64(lowJSValue(m_node->child1())));
2114     }
2115
2116     void compileCheckIdent()
2117     {
2118         UniquedStringImpl* uid = m_node->uidOperand();
2119         if (uid->isSymbol()) {
2120             LValue symbol = lowSymbol(m_node->child1());
2121             LValue stringImpl = m_out.loadPtr(symbol, m_heaps.Symbol_privateName);
2122             speculate(BadIdent, noValue(), nullptr, m_out.notEqual(stringImpl, m_out.constIntPtr(uid)));
2123         } else {
2124             LValue string = lowStringIdent(m_node->child1());
2125             LValue stringImpl = m_out.loadPtr(string, m_heaps.JSString_value);
2126             speculate(BadIdent, noValue(), nullptr, m_out.notEqual(stringImpl, m_out.constIntPtr(uid)));
2127         }
2128     }
2129
2130     void compileGetExecutable()
2131     {
2132         LValue cell = lowCell(m_node->child1());
2133         speculateFunction(m_node->child1(), cell);
2134         setJSValue(m_out.loadPtr(cell, m_heaps.JSFunction_executable));
2135     }
2136     
2137     void compileArrayifyToStructure()
2138     {
2139         LValue cell = lowCell(m_node->child1());
2140         LValue property = !!m_node->child2() ? lowInt32(m_node->child2()) : 0;
2141         
2142         LBasicBlock unexpectedStructure = FTL_NEW_BLOCK(m_out, ("ArrayifyToStructure unexpected structure"));
2143         LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("ArrayifyToStructure continuation"));
2144         
2145         LValue structureID = m_out.load32(cell, m_heaps.JSCell_structureID);
2146         
2147         m_out.branch(
2148             m_out.notEqual(structureID, weakStructureID(m_node->structure())),
2149             rarely(unexpectedStructure), usually(continuation));
2150         
2151         LBasicBlock lastNext = m_out.appendTo(unexpectedStructure, continuation);
2152         
2153         if (property) {
2154             switch (m_node->arrayMode().type()) {
2155             case Array::Int32:
2156             case Array::Double:
2157             case Array::Contiguous:
2158                 speculate(
2159                     Uncountable, noValue(), 0,
2160                     m_out.aboveOrEqual(property, m_out.constInt32(MIN_SPARSE_ARRAY_INDEX)));
2161                 break;
2162             default:
2163                 break;
2164             }
2165         }
2166         
2167         switch (m_node->arrayMode().type()) {
2168         case Array::Int32:
2169             vmCall(m_out.voidType, m_out.operation(operationEnsureInt32), m_callFrame, cell);
2170             break;
2171         case Array::Double:
2172             vmCall(m_out.voidType, m_out.operation(operationEnsureDouble), m_callFrame, cell);
2173             break;
2174         case Array::Contiguous:
2175             vmCall(m_out.voidType, m_out.operation(operationEnsureContiguous), m_callFrame, cell);
2176             break;
2177         case Array::ArrayStorage:
2178         case Array::SlowPutArrayStorage:
2179             vmCall(m_out.voidType, m_out.operation(operationEnsureArrayStorage), m_callFrame, cell);
2180             break;
2181         default:
2182             DFG_CRASH(m_graph, m_node, "Bad array type");
2183             break;
2184         }
2185         
2186         structureID = m_out.load32(cell, m_heaps.JSCell_structureID);
2187         speculate(
2188             BadIndexingType, jsValueValue(cell), 0,
2189             m_out.notEqual(structureID, weakStructureID(m_node->structure())));
2190         m_out.jump(continuation);
2191         
2192         m_out.appendTo(continuation, lastNext);
2193     }
2194     
2195     void compilePutStructure()
2196     {
2197         m_ftlState.jitCode->common.notifyCompilingStructureTransition(m_graph.m_plan, codeBlock(), m_node);
2198
2199         Structure* oldStructure = m_node->transition()->previous;
2200         Structure* newStructure = m_node->transition()->next;
2201         ASSERT_UNUSED(oldStructure, oldStructure->indexingType() == newStructure->indexingType());
2202         ASSERT(oldStructure->typeInfo().inlineTypeFlags() == newStructure->typeInfo().inlineTypeFlags());
2203         ASSERT(oldStructure->typeInfo().type() == newStructure->typeInfo().type());
2204
2205         LValue cell = lowCell(m_node->child1()); 
2206         m_out.store32(
2207             weakStructureID(newStructure),
2208             cell, m_heaps.JSCell_structureID);
2209     }
2210     
2211     void compileGetById()
2212     {
2213         switch (m_node->child1().useKind()) {
2214         case CellUse: {
2215             setJSValue(getById(lowCell(m_node->child1())));
2216             return;
2217         }
2218             
2219         case UntypedUse: {
2220             // This is pretty weird, since we duplicate the slow path both here and in the
2221             // code generated by the IC. We should investigate making this less bad.
2222             // https://bugs.webkit.org/show_bug.cgi?id=127830
2223             LValue value = lowJSValue(m_node->child1());
2224             
2225             LBasicBlock cellCase = FTL_NEW_BLOCK(m_out, ("GetById untyped cell case"));
2226             LBasicBlock notCellCase = FTL_NEW_BLOCK(m_out, ("GetById untyped not cell case"));
2227             LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("GetById untyped continuation"));
2228             
2229             m_out.branch(
2230                 isCell(value, provenType(m_node->child1())), unsure(cellCase), unsure(notCellCase));
2231             
2232             LBasicBlock lastNext = m_out.appendTo(cellCase, notCellCase);
2233             ValueFromBlock cellResult = m_out.anchor(getById(value));
2234             m_out.jump(continuation);
2235             
2236             m_out.appendTo(notCellCase, continuation);
2237             ValueFromBlock notCellResult = m_out.anchor(vmCall(
2238                 m_out.int64, m_out.operation(operationGetByIdGeneric),
2239                 m_callFrame, value,
2240                 m_out.constIntPtr(m_graph.identifiers()[m_node->identifierNumber()])));
2241             m_out.jump(continuation);
2242             
2243             m_out.appendTo(continuation, lastNext);
2244             setJSValue(m_out.phi(m_out.int64, cellResult, notCellResult));
2245             return;
2246         }
2247             
2248         default:
2249             DFG_CRASH(m_graph, m_node, "Bad use kind");
2250             return;
2251         }
2252     }
2253     
2254     void compilePutById()
2255     {
2256         Node* node = m_node;
2257         
2258         // See above; CellUse is easier so we do only that for now.
2259         ASSERT(node->child1().useKind() == CellUse);
2260
2261         LValue base = lowCell(node->child1());
2262         LValue value = lowJSValue(node->child2());
2263         auto uid = m_graph.identifiers()[node->identifierNumber()];
2264
2265         B3::PatchpointValue* patchpoint = m_out.patchpoint(Void);
2266         patchpoint->appendSomeRegister(base);
2267         patchpoint->appendSomeRegister(value);
2268         patchpoint->clobber(RegisterSet::macroScratchRegisters());
2269
2270         // FIXME: If this is a PutByIdFlush, we might want to late-clobber volatile registers.
2271         // https://bugs.webkit.org/show_bug.cgi?id=152848
2272
2273         RefPtr<PatchpointExceptionHandle> exceptionHandle =
2274             preparePatchpointForExceptions(patchpoint);
2275
2276         State* state = &m_ftlState;
2277         ECMAMode ecmaMode = m_graph.executableFor(node->origin.semantic)->ecmaMode();
2278         
2279         patchpoint->setGenerator(
2280             [=] (CCallHelpers& jit, const StackmapGenerationParams& params) {
2281                 AllowMacroScratchRegisterUsage allowScratch(jit);
2282
2283                 CallSiteIndex callSiteIndex =
2284                     state->jitCode->common.addUniqueCallSiteIndex(node->origin.semantic);
2285
2286                 Box<CCallHelpers::JumpList> exceptions =
2287                     exceptionHandle->scheduleExitCreation(params)->jumps(jit);
2288
2289                 // JS setter call ICs generated by the PutById IC will need this.
2290                 exceptionHandle->scheduleExitCreationForUnwind(params, callSiteIndex);
2291
2292                 auto generator = Box<JITPutByIdGenerator>::create(
2293                     jit.codeBlock(), node->origin.semantic, callSiteIndex,
2294                     params.unavailableRegisters(), JSValueRegs(params[0].gpr()),
2295                     JSValueRegs(params[1].gpr()), GPRInfo::patchpointScratchRegister, ecmaMode,
2296                     node->op() == PutByIdDirect ? Direct : NotDirect);
2297
2298                 generator->generateFastPath(jit);
2299                 CCallHelpers::Label done = jit.label();
2300
2301                 params.addLatePath(
2302                     [=] (CCallHelpers& jit) {
2303                         AllowMacroScratchRegisterUsage allowScratch(jit);
2304
2305                         generator->slowPathJump().link(&jit);
2306                         CCallHelpers::Label slowPathBegin = jit.label();
2307                         CCallHelpers::Call slowPathCall = callOperation(
2308                             *state, params.unavailableRegisters(), jit, node->origin.semantic,
2309                             exceptions.get(), generator->slowPathFunction(), InvalidGPRReg,
2310                             CCallHelpers::TrustedImmPtr(generator->stubInfo()), params[1].gpr(),
2311                             params[0].gpr(), CCallHelpers::TrustedImmPtr(uid)).call();
2312                         jit.jump().linkTo(done, &jit);
2313
2314                         generator->reportSlowPathCall(slowPathBegin, slowPathCall);
2315
2316                         jit.addLinkTask(
2317                             [=] (LinkBuffer& linkBuffer) {
2318                                 generator->finalize(linkBuffer);
2319                             });
2320                     });
2321             });
2322     }
2323     
2324     void compileGetButterfly()
2325     {
2326         setStorage(loadButterflyWithBarrier(lowCell(m_node->child1())));
2327     }
2328
2329     void compileGetButterflyReadOnly()
2330     {
2331         setStorage(loadButterflyReadOnly(lowCell(m_node->child1())));
2332     }
2333     
2334     void compileConstantStoragePointer()
2335     {
2336         setStorage(m_out.constIntPtr(m_node->storagePointer()));
2337     }
2338     
2339     void compileGetIndexedPropertyStorage()
2340     {
2341         LValue cell = lowCell(m_node->child1());
2342         
2343         if (m_node->arrayMode().type() == Array::String) {
2344             LBasicBlock slowPath = FTL_NEW_BLOCK(m_out, ("GetIndexedPropertyStorage String slow case"));
2345             LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("GetIndexedPropertyStorage String continuation"));
2346
2347             LValue fastResultValue = m_out.loadPtr(cell, m_heaps.JSString_value);
2348             ValueFromBlock fastResult = m_out.anchor(fastResultValue);
2349             
2350             m_out.branch(
2351                 m_out.notNull(fastResultValue), usually(continuation), rarely(slowPath));
2352             
2353             LBasicBlock lastNext = m_out.appendTo(slowPath, continuation);
2354             
2355             ValueFromBlock slowResult = m_out.anchor(
2356                 vmCall(m_out.intPtr, m_out.operation(operationResolveRope), m_callFrame, cell));
2357             
2358             m_out.jump(continuation);
2359             
2360             m_out.appendTo(continuation, lastNext);
2361             
2362             setStorage(m_out.loadPtr(m_out.phi(m_out.intPtr, fastResult, slowResult), m_heaps.StringImpl_data));
2363             return;
2364         }
2365         
2366         setStorage(loadVectorWithBarrier(cell));
2367     }
2368     
2369     void compileCheckArray()
2370     {
2371         Edge edge = m_node->child1();
2372         LValue cell = lowCell(edge);
2373         
2374         if (m_node->arrayMode().alreadyChecked(m_graph, m_node, abstractValue(edge)))
2375             return;
2376         
2377         speculate(
2378             BadIndexingType, jsValueValue(cell), 0,
2379             m_out.logicalNot(isArrayType(cell, m_node->arrayMode())));
2380     }
2381
2382     void compileGetTypedArrayByteOffset()
2383     {
2384         LValue basePtr = lowCell(m_node->child1());    
2385
2386         LBasicBlock simpleCase = FTL_NEW_BLOCK(m_out, ("GetTypedArrayByteOffset wasteless typed array"));
2387         LBasicBlock wastefulCase = FTL_NEW_BLOCK(m_out, ("GetTypedArrayByteOffset wasteful typed array"));
2388         LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("GetTypedArrayByteOffset continuation"));
2389         
2390         LValue mode = m_out.load32(basePtr, m_heaps.JSArrayBufferView_mode);
2391         m_out.branch(
2392             m_out.notEqual(mode, m_out.constInt32(WastefulTypedArray)),
2393             unsure(simpleCase), unsure(wastefulCase));
2394
2395         LBasicBlock lastNext = m_out.appendTo(simpleCase, wastefulCase);
2396
2397         ValueFromBlock simpleOut = m_out.anchor(m_out.constIntPtr(0));
2398
2399         m_out.jump(continuation);
2400
2401         m_out.appendTo(wastefulCase, continuation);
2402
2403         LValue vectorPtr = loadVectorReadOnly(basePtr);
2404         LValue butterflyPtr = loadButterflyReadOnly(basePtr);
2405         LValue arrayBufferPtr = m_out.loadPtr(butterflyPtr, m_heaps.Butterfly_arrayBuffer);
2406         LValue dataPtr = m_out.loadPtr(arrayBufferPtr, m_heaps.ArrayBuffer_data);
2407
2408         ValueFromBlock wastefulOut = m_out.anchor(m_out.sub(vectorPtr, dataPtr));
2409
2410         m_out.jump(continuation);
2411         m_out.appendTo(continuation, lastNext);
2412
2413         setInt32(m_out.castToInt32(m_out.phi(m_out.intPtr, simpleOut, wastefulOut)));
2414     }
2415     
2416     void compileGetArrayLength()
2417     {
2418         switch (m_node->arrayMode().type()) {
2419         case Array::Int32:
2420         case Array::Double:
2421         case Array::Contiguous: {
2422             setInt32(m_out.load32NonNegative(lowStorage(m_node->child2()), m_heaps.Butterfly_publicLength));
2423             return;
2424         }
2425             
2426         case Array::String: {
2427             LValue string = lowCell(m_node->child1());
2428             setInt32(m_out.load32NonNegative(string, m_heaps.JSString_length));
2429             return;
2430         }
2431             
2432         case Array::DirectArguments: {
2433             LValue arguments = lowCell(m_node->child1());
2434             speculate(
2435                 ExoticObjectMode, noValue(), nullptr,
2436                 m_out.notNull(m_out.loadPtr(arguments, m_heaps.DirectArguments_overrides)));
2437             setInt32(m_out.load32NonNegative(arguments, m_heaps.DirectArguments_length));
2438             return;
2439         }
2440             
2441         case Array::ScopedArguments: {
2442             LValue arguments = lowCell(m_node->child1());
2443             speculate(
2444                 ExoticObjectMode, noValue(), nullptr,
2445                 m_out.notZero32(m_out.load8ZeroExt32(arguments, m_heaps.ScopedArguments_overrodeThings)));
2446             setInt32(m_out.load32NonNegative(arguments, m_heaps.ScopedArguments_totalLength));
2447             return;
2448         }
2449             
2450         default:
2451             if (m_node->arrayMode().isSomeTypedArrayView()) {
2452                 setInt32(
2453                     m_out.load32NonNegative(lowCell(m_node->child1()), m_heaps.JSArrayBufferView_length));
2454                 return;
2455             }
2456             
2457             DFG_CRASH(m_graph, m_node, "Bad array type");
2458             return;
2459         }
2460     }
2461     
2462     void compileCheckInBounds()
2463     {
2464         speculate(
2465             OutOfBounds, noValue(), 0,
2466             m_out.aboveOrEqual(lowInt32(m_node->child1()), lowInt32(m_node->child2())));
2467     }
2468     
2469     void compileGetByVal()
2470     {
2471         switch (m_node->arrayMode().type()) {
2472         case Array::Int32:
2473         case Array::Contiguous: {
2474             LValue index = lowInt32(m_node->child2());
2475             LValue storage = lowStorage(m_node->child3());
2476             
2477             IndexedAbstractHeap& heap = m_node->arrayMode().type() == Array::Int32 ?
2478                 m_heaps.indexedInt32Properties : m_heaps.indexedContiguousProperties;
2479             
2480             if (m_node->arrayMode().isInBounds()) {
2481                 LValue result = m_out.load64(baseIndex(heap, storage, index, m_node->child2()));
2482                 LValue isHole = m_out.isZero64(result);
2483                 if (m_node->arrayMode().isSaneChain()) {
2484                     DFG_ASSERT(
2485                         m_graph, m_node, m_node->arrayMode().type() == Array::Contiguous);
2486                     result = m_out.select(
2487                         isHole, m_out.constInt64(JSValue::encode(jsUndefined())), result);
2488                 } else
2489                     speculate(LoadFromHole, noValue(), 0, isHole);
2490                 setJSValue(result);
2491                 return;
2492             }
2493             
2494             LValue base = lowCell(m_node->child1());
2495             
2496             LBasicBlock fastCase = FTL_NEW_BLOCK(m_out, ("GetByVal int/contiguous fast case"));
2497             LBasicBlock slowCase = FTL_NEW_BLOCK(m_out, ("GetByVal int/contiguous slow case"));
2498             LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("GetByVal int/contiguous continuation"));
2499             
2500             m_out.branch(
2501                 m_out.aboveOrEqual(
2502                     index, m_out.load32NonNegative(storage, m_heaps.Butterfly_publicLength)),
2503                 rarely(slowCase), usually(fastCase));
2504             
2505             LBasicBlock lastNext = m_out.appendTo(fastCase, slowCase);
2506
2507             LValue fastResultValue = m_out.load64(baseIndex(heap, storage, index, m_node->child2()));
2508             ValueFromBlock fastResult = m_out.anchor(fastResultValue);
2509             m_out.branch(
2510                 m_out.isZero64(fastResultValue), rarely(slowCase), usually(continuation));
2511             
2512             m_out.appendTo(slowCase, continuation);
2513             ValueFromBlock slowResult = m_out.anchor(
2514                 vmCall(m_out.int64, m_out.operation(operationGetByValArrayInt), m_callFrame, base, index));
2515             m_out.jump(continuation);
2516             
2517             m_out.appendTo(continuation, lastNext);
2518             setJSValue(m_out.phi(m_out.int64, fastResult, slowResult));
2519             return;
2520         }
2521             
2522         case Array::Double: {
2523             LValue index = lowInt32(m_node->child2());
2524             LValue storage = lowStorage(m_node->child3());
2525             
2526             IndexedAbstractHeap& heap = m_heaps.indexedDoubleProperties;
2527             
2528             if (m_node->arrayMode().isInBounds()) {
2529                 LValue result = m_out.loadDouble(
2530                     baseIndex(heap, storage, index, m_node->child2()));
2531                 
2532                 if (!m_node->arrayMode().isSaneChain()) {
2533                     speculate(
2534                         LoadFromHole, noValue(), 0,
2535                         m_out.doubleNotEqualOrUnordered(result, result));
2536                 }
2537                 setDouble(result);
2538                 break;
2539             }
2540             
2541             LValue base = lowCell(m_node->child1());
2542             
2543             LBasicBlock inBounds = FTL_NEW_BLOCK(m_out, ("GetByVal double in bounds"));
2544             LBasicBlock boxPath = FTL_NEW_BLOCK(m_out, ("GetByVal double boxing"));
2545             LBasicBlock slowCase = FTL_NEW_BLOCK(m_out, ("GetByVal double slow case"));
2546             LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("GetByVal double continuation"));
2547             
2548             m_out.branch(
2549                 m_out.aboveOrEqual(
2550                     index, m_out.load32NonNegative(storage, m_heaps.Butterfly_publicLength)),
2551                 rarely(slowCase), usually(inBounds));
2552             
2553             LBasicBlock lastNext = m_out.appendTo(inBounds, boxPath);
2554             LValue doubleValue = m_out.loadDouble(
2555                 baseIndex(heap, storage, index, m_node->child2()));
2556             m_out.branch(
2557                 m_out.doubleNotEqualOrUnordered(doubleValue, doubleValue),
2558                 rarely(slowCase), usually(boxPath));
2559             
2560             m_out.appendTo(boxPath, slowCase);
2561             ValueFromBlock fastResult = m_out.anchor(boxDouble(doubleValue));
2562             m_out.jump(continuation);
2563             
2564             m_out.appendTo(slowCase, continuation);
2565             ValueFromBlock slowResult = m_out.anchor(
2566                 vmCall(m_out.int64, m_out.operation(operationGetByValArrayInt), m_callFrame, base, index));
2567             m_out.jump(continuation);
2568             
2569             m_out.appendTo(continuation, lastNext);
2570             setJSValue(m_out.phi(m_out.int64, fastResult, slowResult));
2571             return;
2572         }
2573
2574         case Array::Undecided: {
2575             LValue index = lowInt32(m_node->child2());
2576
2577             speculate(OutOfBounds, noValue(), m_node, m_out.lessThan(index, m_out.int32Zero));
2578             setJSValue(m_out.constInt64(ValueUndefined));
2579             return;
2580         }
2581             
2582         case Array::DirectArguments: {
2583             LValue base = lowCell(m_node->child1());
2584             LValue index = lowInt32(m_node->child2());
2585             
2586             speculate(
2587                 ExoticObjectMode, noValue(), nullptr,
2588                 m_out.notNull(m_out.loadPtr(base, m_heaps.DirectArguments_overrides)));
2589             speculate(
2590                 ExoticObjectMode, noValue(), nullptr,
2591                 m_out.aboveOrEqual(
2592                     index,
2593                     m_out.load32NonNegative(base, m_heaps.DirectArguments_length)));
2594
2595             TypedPointer address = m_out.baseIndex(
2596                 m_heaps.DirectArguments_storage, base, m_out.zeroExtPtr(index));
2597             setJSValue(m_out.load64(address));
2598             return;
2599         }
2600             
2601         case Array::ScopedArguments: {
2602             LValue base = lowCell(m_node->child1());
2603             LValue index = lowInt32(m_node->child2());
2604             
2605             speculate(
2606                 ExoticObjectMode, noValue(), nullptr,
2607                 m_out.aboveOrEqual(
2608                     index,
2609                     m_out.load32NonNegative(base, m_heaps.ScopedArguments_totalLength)));
2610             
2611             LValue table = m_out.loadPtr(base, m_heaps.ScopedArguments_table);
2612             LValue namedLength = m_out.load32(table, m_heaps.ScopedArgumentsTable_length);
2613             
2614             LBasicBlock namedCase = FTL_NEW_BLOCK(m_out, ("GetByVal ScopedArguments named case"));
2615             LBasicBlock overflowCase = FTL_NEW_BLOCK(m_out, ("GetByVal ScopedArguments overflow case"));
2616             LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("GetByVal ScopedArguments continuation"));
2617             
2618             m_out.branch(
2619                 m_out.aboveOrEqual(index, namedLength), unsure(overflowCase), unsure(namedCase));
2620             
2621             LBasicBlock lastNext = m_out.appendTo(namedCase, overflowCase);
2622             
2623             LValue scope = m_out.loadPtr(base, m_heaps.ScopedArguments_scope);
2624             LValue arguments = m_out.loadPtr(table, m_heaps.ScopedArgumentsTable_arguments);
2625             
2626             TypedPointer address = m_out.baseIndex(
2627                 m_heaps.scopedArgumentsTableArguments, arguments, m_out.zeroExtPtr(index));
2628             LValue scopeOffset = m_out.load32(address);
2629             
2630             speculate(
2631                 ExoticObjectMode, noValue(), nullptr,
2632                 m_out.equal(scopeOffset, m_out.constInt32(ScopeOffset::invalidOffset)));
2633             
2634             address = m_out.baseIndex(
2635                 m_heaps.JSEnvironmentRecord_variables, scope, m_out.zeroExtPtr(scopeOffset));
2636             ValueFromBlock namedResult = m_out.anchor(m_out.load64(address));
2637             m_out.jump(continuation);
2638             
2639             m_out.appendTo(overflowCase, continuation);
2640             
2641             address = m_out.baseIndex(
2642                 m_heaps.ScopedArguments_overflowStorage, base,
2643                 m_out.zeroExtPtr(m_out.sub(index, namedLength)));
2644             LValue overflowValue = m_out.load64(address);
2645             speculate(ExoticObjectMode, noValue(), nullptr, m_out.isZero64(overflowValue));
2646             ValueFromBlock overflowResult = m_out.anchor(overflowValue);
2647             m_out.jump(continuation);
2648             
2649             m_out.appendTo(continuation, lastNext);
2650             setJSValue(m_out.phi(m_out.int64, namedResult, overflowResult));
2651             return;
2652         }
2653             
2654         case Array::Generic: {
2655             setJSValue(vmCall(
2656                 m_out.int64, m_out.operation(operationGetByVal), m_callFrame,
2657                 lowJSValue(m_node->child1()), lowJSValue(m_node->child2())));
2658             return;
2659         }
2660             
2661         case Array::String: {
2662             compileStringCharAt();
2663             return;
2664         }
2665             
2666         default: {
2667             LValue index = lowInt32(m_node->child2());
2668             LValue storage = lowStorage(m_node->child3());
2669             
2670             TypedArrayType type = m_node->arrayMode().typedArrayType();
2671             
2672             if (isTypedView(type)) {
2673                 TypedPointer pointer = TypedPointer(
2674                     m_heaps.typedArrayProperties,
2675                     m_out.add(
2676                         storage,
2677                         m_out.shl(
2678                             m_out.zeroExtPtr(index),
2679                             m_out.constIntPtr(logElementSize(type)))));
2680                 
2681                 if (isInt(type)) {
2682                     LValue result;
2683                     switch (elementSize(type)) {
2684                     case 1:
2685                         result = isSigned(type) ? m_out.load8SignExt32(pointer) :  m_out.load8ZeroExt32(pointer);
2686                         break;
2687                     case 2:
2688                         result = isSigned(type) ? m_out.load16SignExt32(pointer) :  m_out.load16ZeroExt32(pointer);
2689                         break;
2690                     case 4:
2691                         result = m_out.load32(pointer);
2692                         break;
2693                     default:
2694                         DFG_CRASH(m_graph, m_node, "Bad element size");
2695                     }
2696                     
2697                     if (elementSize(type) < 4 || isSigned(type)) {
2698                         setInt32(result);
2699                         return;
2700                     }
2701
2702                     if (m_node->shouldSpeculateInt32()) {
2703                         speculate(
2704                             Overflow, noValue(), 0, m_out.lessThan(result, m_out.int32Zero));
2705                         setInt32(result);
2706                         return;
2707                     }
2708                     
2709                     if (m_node->shouldSpeculateMachineInt()) {
2710                         setStrictInt52(m_out.zeroExt(result, m_out.int64));
2711                         return;
2712                     }
2713                     
2714                     setDouble(m_out.unsignedToDouble(result));
2715                     return;
2716                 }
2717             
2718                 ASSERT(isFloat(type));
2719                 
2720                 LValue result;
2721                 switch (type) {
2722                 case TypeFloat32:
2723                     result = m_out.floatToDouble(m_out.loadFloat(pointer));
2724                     break;
2725                 case TypeFloat64:
2726                     result = m_out.loadDouble(pointer);
2727                     break;
2728                 default:
2729                     DFG_CRASH(m_graph, m_node, "Bad typed array type");
2730                 }
2731                 
2732                 setDouble(result);
2733                 return;
2734             }
2735             
2736             DFG_CRASH(m_graph, m_node, "Bad array type");
2737             return;
2738         } }
2739     }
2740     
2741     void compileGetMyArgumentByVal()
2742     {
2743         InlineCallFrame* inlineCallFrame = m_node->child1()->origin.semantic.inlineCallFrame;
2744         
2745         LValue index = lowInt32(m_node->child2());
2746         
2747         LValue limit;
2748         if (inlineCallFrame && !inlineCallFrame->isVarargs())
2749             limit = m_out.constInt32(inlineCallFrame->arguments.size() - 1);
2750         else {
2751             VirtualRegister argumentCountRegister;
2752             if (!inlineCallFrame)
2753                 argumentCountRegister = VirtualRegister(JSStack::ArgumentCount);
2754             else
2755                 argumentCountRegister = inlineCallFrame->argumentCountRegister;
2756             limit = m_out.sub(m_out.load32(payloadFor(argumentCountRegister)), m_out.int32One);
2757         }
2758         
2759         speculate(ExoticObjectMode, noValue(), 0, m_out.aboveOrEqual(index, limit));
2760         
2761         TypedPointer base;
2762         if (inlineCallFrame) {
2763             if (inlineCallFrame->arguments.size() <= 1) {
2764                 // We should have already exited due to the bounds check, above. Just tell the
2765                 // compiler that anything dominated by this instruction is not reachable, so
2766                 // that we don't waste time generating such code. This will also plant some
2767                 // kind of crashing instruction so that if by some fluke the bounds check didn't
2768                 // work, we'll crash in an easy-to-see way.
2769                 didAlreadyTerminate();
2770                 return;
2771             }
2772             base = addressFor(inlineCallFrame->arguments[1].virtualRegister());
2773         } else
2774             base = addressFor(virtualRegisterForArgument(1));
2775         
2776         LValue pointer = m_out.baseIndex(
2777             base.value(), m_out.zeroExt(index, m_out.intPtr), ScaleEight);
2778         setJSValue(m_out.load64(TypedPointer(m_heaps.variables.atAnyIndex(), pointer)));
2779     }
2780     
2781     void compilePutByVal()
2782     {
2783         Edge child1 = m_graph.varArgChild(m_node, 0);
2784         Edge child2 = m_graph.varArgChild(m_node, 1);
2785         Edge child3 = m_graph.varArgChild(m_node, 2);
2786         Edge child4 = m_graph.varArgChild(m_node, 3);
2787         Edge child5 = m_graph.varArgChild(m_node, 4);
2788         
2789         switch (m_node->arrayMode().type()) {
2790         case Array::Generic: {
2791             V_JITOperation_EJJJ operation;
2792             if (m_node->op() == PutByValDirect) {
2793                 if (m_graph.isStrictModeFor(m_node->origin.semantic))
2794                     operation = operationPutByValDirectStrict;
2795                 else
2796                     operation = operationPutByValDirectNonStrict;
2797             } else {
2798                 if (m_graph.isStrictModeFor(m_node->origin.semantic))
2799                     operation = operationPutByValStrict;
2800                 else
2801                     operation = operationPutByValNonStrict;
2802             }
2803                 
2804             vmCall(
2805                 m_out.voidType, m_out.operation(operation), m_callFrame,
2806                 lowJSValue(child1), lowJSValue(child2), lowJSValue(child3));
2807             return;
2808         }
2809             
2810         default:
2811             break;
2812         }
2813
2814         LValue base = lowCell(child1);
2815         LValue index = lowInt32(child2);
2816         LValue storage = lowStorage(child4);
2817         
2818         switch (m_node->arrayMode().type()) {
2819         case Array::Int32:
2820         case Array::Double:
2821         case Array::Contiguous: {
2822             LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("PutByVal continuation"));
2823             LBasicBlock outerLastNext = m_out.appendTo(m_out.m_block, continuation);
2824             
2825             switch (m_node->arrayMode().type()) {
2826             case Array::Int32:
2827             case Array::Contiguous: {
2828                 LValue value = lowJSValue(child3, ManualOperandSpeculation);
2829                 
2830                 if (m_node->arrayMode().type() == Array::Int32)
2831                     FTL_TYPE_CHECK(jsValueValue(value), child3, SpecInt32, isNotInt32(value));
2832                 
2833                 TypedPointer elementPointer = m_out.baseIndex(
2834                     m_node->arrayMode().type() == Array::Int32 ?
2835                     m_heaps.indexedInt32Properties : m_heaps.indexedContiguousProperties,
2836                     storage, m_out.zeroExtPtr(index), provenValue(child2));
2837                 
2838                 if (m_node->op() == PutByValAlias) {
2839                     m_out.store64(value, elementPointer);
2840                     break;
2841                 }
2842                 
2843                 contiguousPutByValOutOfBounds(
2844                     codeBlock()->isStrictMode()
2845                     ? operationPutByValBeyondArrayBoundsStrict
2846                     : operationPutByValBeyondArrayBoundsNonStrict,
2847                     base, storage, index, value, continuation);
2848                 
2849                 m_out.store64(value, elementPointer);
2850                 break;
2851             }
2852                 
2853             case Array::Double: {
2854                 LValue value = lowDouble(child3);
2855                 
2856                 FTL_TYPE_CHECK(
2857                     doubleValue(value), child3, SpecDoubleReal,
2858                     m_out.doubleNotEqualOrUnordered(value, value));
2859                 
2860                 TypedPointer elementPointer = m_out.baseIndex(
2861                     m_heaps.indexedDoubleProperties, storage, m_out.zeroExtPtr(index),
2862                     provenValue(child2));
2863                 
2864                 if (m_node->op() == PutByValAlias) {
2865                     m_out.storeDouble(value, elementPointer);
2866                     break;
2867                 }
2868                 
2869                 contiguousPutByValOutOfBounds(
2870                     codeBlock()->isStrictMode()
2871                     ? operationPutDoubleByValBeyondArrayBoundsStrict
2872                     : operationPutDoubleByValBeyondArrayBoundsNonStrict,
2873                     base, storage, index, value, continuation);
2874                 
2875                 m_out.storeDouble(value, elementPointer);
2876                 break;
2877             }
2878                 
2879             default:
2880                 DFG_CRASH(m_graph, m_node, "Bad array type");
2881             }
2882
2883             m_out.jump(continuation);
2884             m_out.appendTo(continuation, outerLastNext);
2885             return;
2886         }
2887             
2888         default:
2889             TypedArrayType type = m_node->arrayMode().typedArrayType();
2890             
2891             if (isTypedView(type)) {
2892                 TypedPointer pointer = TypedPointer(
2893                     m_heaps.typedArrayProperties,
2894                     m_out.add(
2895                         storage,
2896                         m_out.shl(
2897                             m_out.zeroExt(index, m_out.intPtr),
2898                             m_out.constIntPtr(logElementSize(type)))));
2899                 
2900                 Output::StoreType storeType;
2901                 LValue valueToStore;
2902                 
2903                 if (isInt(type)) {
2904                     LValue intValue;
2905                     switch (child3.useKind()) {
2906                     case Int52RepUse:
2907                     case Int32Use: {
2908                         if (child3.useKind() == Int32Use)
2909                             intValue = lowInt32(child3);
2910                         else
2911                             intValue = m_out.castToInt32(lowStrictInt52(child3));
2912
2913                         if (isClamped(type)) {
2914                             ASSERT(elementSize(type) == 1);
2915                             
2916                             LBasicBlock atLeastZero = FTL_NEW_BLOCK(m_out, ("PutByVal int clamp atLeastZero"));
2917                             LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("PutByVal int clamp continuation"));
2918                             
2919                             Vector<ValueFromBlock, 2> intValues;
2920                             intValues.append(m_out.anchor(m_out.int32Zero));
2921                             m_out.branch(
2922                                 m_out.lessThan(intValue, m_out.int32Zero),
2923                                 unsure(continuation), unsure(atLeastZero));
2924                             
2925                             LBasicBlock lastNext = m_out.appendTo(atLeastZero, continuation);
2926                             
2927                             intValues.append(m_out.anchor(m_out.select(
2928                                 m_out.greaterThan(intValue, m_out.constInt32(255)),
2929                                 m_out.constInt32(255),
2930                                 intValue)));
2931                             m_out.jump(continuation);
2932                             
2933                             m_out.appendTo(continuation, lastNext);
2934                             intValue = m_out.phi(m_out.int32, intValues);
2935                         }
2936                         break;
2937                     }
2938                         
2939                     case DoubleRepUse: {
2940                         LValue doubleValue = lowDouble(child3);
2941                         
2942                         if (isClamped(type)) {
2943                             ASSERT(elementSize(type) == 1);
2944                             
2945                             LBasicBlock atLeastZero = FTL_NEW_BLOCK(m_out, ("PutByVal double clamp atLeastZero"));
2946                             LBasicBlock withinRange = FTL_NEW_BLOCK(m_out, ("PutByVal double clamp withinRange"));
2947                             LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("PutByVal double clamp continuation"));
2948                             
2949                             Vector<ValueFromBlock, 3> intValues;
2950                             intValues.append(m_out.anchor(m_out.int32Zero));
2951                             m_out.branch(
2952                                 m_out.doubleLessThanOrUnordered(doubleValue, m_out.doubleZero),
2953                                 unsure(continuation), unsure(atLeastZero));
2954                             
2955                             LBasicBlock lastNext = m_out.appendTo(atLeastZero, withinRange);
2956                             intValues.append(m_out.anchor(m_out.constInt32(255)));
2957                             m_out.branch(
2958                                 m_out.doubleGreaterThan(doubleValue, m_out.constDouble(255)),
2959                                 unsure(continuation), unsure(withinRange));
2960                             
2961                             m_out.appendTo(withinRange, continuation);
2962                             intValues.append(m_out.anchor(m_out.doubleToInt(doubleValue)));
2963                             m_out.jump(continuation);
2964                             
2965                             m_out.appendTo(continuation, lastNext);
2966                             intValue = m_out.phi(m_out.int32, intValues);
2967                         } else
2968                             intValue = doubleToInt32(doubleValue);
2969                         break;
2970                     }
2971                         
2972                     default:
2973                         DFG_CRASH(m_graph, m_node, "Bad use kind");
2974                     }
2975
2976                     valueToStore = intValue;
2977                     switch (elementSize(type)) {
2978                     case 1:
2979                         storeType = Output::Store32As8;
2980                         break;
2981                     case 2:
2982                         storeType = Output::Store32As16;
2983                         break;
2984                     case 4:
2985                         storeType = Output::Store32;
2986                         break;
2987                     default:
2988                         DFG_CRASH(m_graph, m_node, "Bad element size");
2989                     }
2990                 } else /* !isInt(type) */ {
2991                     LValue value = lowDouble(child3);
2992                     switch (type) {
2993                     case TypeFloat32:
2994                         valueToStore = m_out.doubleToFloat(value);
2995                         storeType = Output::StoreFloat;
2996                         break;
2997                     case TypeFloat64:
2998                         valueToStore = value;
2999                         storeType = Output::StoreDouble;
3000                         break;
3001                     default:
3002                         DFG_CRASH(m_graph, m_node, "Bad typed array type");
3003                     }
3004                 }
3005                 
3006                 if (m_node->arrayMode().isInBounds() || m_node->op() == PutByValAlias)
3007                     m_out.store(valueToStore, pointer, storeType);
3008                 else {
3009                     LBasicBlock isInBounds = FTL_NEW_BLOCK(m_out, ("PutByVal typed array in bounds case"));
3010                     LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("PutByVal typed array continuation"));
3011                     
3012                     m_out.branch(
3013                         m_out.aboveOrEqual(index, lowInt32(child5)),
3014                         unsure(continuation), unsure(isInBounds));
3015                     
3016                     LBasicBlock lastNext = m_out.appendTo(isInBounds, continuation);
3017                     m_out.store(valueToStore, pointer, storeType);
3018                     m_out.jump(continuation);
3019                     
3020                     m_out.appendTo(continuation, lastNext);
3021                 }
3022                 
3023                 return;
3024             }
3025             
3026             DFG_CRASH(m_graph, m_node, "Bad array type");
3027             break;
3028         }
3029     }
3030
3031     void compilePutAccessorById()
3032     {
3033         LValue base = lowCell(m_node->child1());
3034         LValue accessor = lowCell(m_node->child2());
3035         auto uid = m_graph.identifiers()[m_node->identifierNumber()];
3036         vmCall(
3037             m_out.voidType,
3038             m_out.operation(m_node->op() == PutGetterById ? operationPutGetterById : operationPutSetterById),
3039             m_callFrame, base, m_out.constIntPtr(uid), m_out.constInt32(m_node->accessorAttributes()), accessor);
3040     }
3041
3042     void compilePutGetterSetterById()
3043     {
3044         LValue base = lowCell(m_node->child1());
3045         LValue getter = lowJSValue(m_node->child2());
3046         LValue setter = lowJSValue(m_node->child3());
3047         auto uid = m_graph.identifiers()[m_node->identifierNumber()];
3048         vmCall(
3049             m_out.voidType, m_out.operation(operationPutGetterSetter),
3050             m_callFrame, base, m_out.constIntPtr(uid), m_out.constInt32(m_node->accessorAttributes()), getter, setter);
3051
3052     }
3053
3054     void compilePutAccessorByVal()
3055     {
3056         LValue base = lowCell(m_node->child1());
3057         LValue subscript = lowJSValue(m_node->child2());
3058         LValue accessor = lowCell(m_node->child3());
3059         vmCall(
3060             m_out.voidType,
3061             m_out.operation(m_node->op() == PutGetterByVal ? operationPutGetterByVal : operationPutSetterByVal),
3062             m_callFrame, base, subscript, m_out.constInt32(m_node->accessorAttributes()), accessor);
3063     }
3064     
3065     void compileArrayPush()
3066     {
3067         LValue base = lowCell(m_node->child1());
3068         LValue storage = lowStorage(m_node->child3());
3069         
3070         switch (m_node->arrayMode().type()) {
3071         case Array::Int32:
3072         case Array::Contiguous:
3073         case Array::Double: {
3074             LValue value;
3075             Output::StoreType storeType;
3076             
3077             if (m_node->arrayMode().type() != Array::Double) {
3078                 value = lowJSValue(m_node->child2(), ManualOperandSpeculation);
3079                 if (m_node->arrayMode().type() == Array::Int32) {
3080                     FTL_TYPE_CHECK(
3081                         jsValueValue(value), m_node->child2(), SpecInt32, isNotInt32(value));
3082                 }
3083                 storeType = Output::Store64;
3084             } else {
3085                 value = lowDouble(m_node->child2());
3086                 FTL_TYPE_CHECK(
3087                     doubleValue(value), m_node->child2(), SpecDoubleReal,
3088                     m_out.doubleNotEqualOrUnordered(value, value));
3089                 storeType = Output::StoreDouble;
3090             }
3091             
3092             IndexedAbstractHeap& heap = m_heaps.forArrayType(m_node->arrayMode().type());
3093
3094             LValue prevLength = m_out.load32(storage, m_heaps.Butterfly_publicLength);
3095             
3096             LBasicBlock fastPath = FTL_NEW_BLOCK(m_out, ("ArrayPush fast path"));
3097             LBasicBlock slowPath = FTL_NEW_BLOCK(m_out, ("ArrayPush slow path"));
3098             LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("ArrayPush continuation"));
3099             
3100             m_out.branch(
3101                 m_out.aboveOrEqual(
3102                     prevLength, m_out.load32(storage, m_heaps.Butterfly_vectorLength)),
3103                 unsure(slowPath), unsure(fastPath));
3104             
3105             LBasicBlock lastNext = m_out.appendTo(fastPath, slowPath);
3106             m_out.store(
3107                 value, m_out.baseIndex(heap, storage, m_out.zeroExtPtr(prevLength)), storeType);
3108             LValue newLength = m_out.add(prevLength, m_out.int32One);
3109             m_out.store32(newLength, storage, m_heaps.Butterfly_publicLength);
3110             
3111             ValueFromBlock fastResult = m_out.anchor(boxInt32(newLength));
3112             m_out.jump(continuation);
3113             
3114             m_out.appendTo(slowPath, continuation);
3115             LValue operation;
3116             if (m_node->arrayMode().type() != Array::Double)
3117                 operation = m_out.operation(operationArrayPush);
3118             else
3119                 operation = m_out.operation(operationArrayPushDouble);
3120             ValueFromBlock slowResult = m_out.anchor(
3121                 vmCall(m_out.int64, operation, m_callFrame, value, base));
3122             m_out.jump(continuation);
3123             
3124             m_out.appendTo(continuation, lastNext);
3125             setJSValue(m_out.phi(m_out.int64, fastResult, slowResult));
3126             return;
3127         }
3128             
3129         default:
3130             DFG_CRASH(m_graph, m_node, "Bad array type");
3131             return;
3132         }
3133     }
3134     
3135     void compileArrayPop()
3136     {
3137         LValue base = lowCell(m_node->child1());
3138         LValue storage = lowStorage(m_node->child2());
3139         
3140         switch (m_node->arrayMode().type()) {
3141         case Array::Int32:
3142         case Array::Double:
3143         case Array::Contiguous: {
3144             IndexedAbstractHeap& heap = m_heaps.forArrayType(m_node->arrayMode().type());
3145             
3146             LBasicBlock fastCase = FTL_NEW_BLOCK(m_out, ("ArrayPop fast case"));
3147             LBasicBlock slowCase = FTL_NEW_BLOCK(m_out, ("ArrayPop slow case"));
3148             LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("ArrayPop continuation"));
3149             
3150             LValue prevLength = m_out.load32(storage, m_heaps.Butterfly_publicLength);
3151             
3152             Vector<ValueFromBlock, 3> results;
3153             results.append(m_out.anchor(m_out.constInt64(JSValue::encode(jsUndefined()))));
3154             m_out.branch(
3155                 m_out.isZero32(prevLength), rarely(continuation), usually(fastCase));
3156             
3157             LBasicBlock lastNext = m_out.appendTo(fastCase, slowCase);
3158             LValue newLength = m_out.sub(prevLength, m_out.int32One);
3159             m_out.store32(newLength, storage, m_heaps.Butterfly_publicLength);
3160             TypedPointer pointer = m_out.baseIndex(heap, storage, m_out.zeroExtPtr(newLength));
3161             if (m_node->arrayMode().type() != Array::Double) {
3162                 LValue result = m_out.load64(pointer);
3163                 m_out.store64(m_out.int64Zero, pointer);
3164                 results.append(m_out.anchor(result));
3165                 m_out.branch(
3166                     m_out.notZero64(result), usually(continuation), rarely(slowCase));
3167             } else {
3168                 LValue result = m_out.loadDouble(pointer);
3169                 m_out.store64(m_out.constInt64(bitwise_cast<int64_t>(PNaN)), pointer);
3170                 results.append(m_out.anchor(boxDouble(result)));
3171                 m_out.branch(
3172                     m_out.doubleEqual(result, result),
3173                     usually(continuation), rarely(slowCase));
3174             }
3175             
3176             m_out.appendTo(slowCase, continuation);
3177             results.append(m_out.anchor(vmCall(
3178                 m_out.int64, m_out.operation(operationArrayPopAndRecoverLength), m_callFrame, base)));
3179             m_out.jump(continuation);
3180             
3181             m_out.appendTo(continuation, lastNext);
3182             setJSValue(m_out.phi(m_out.int64, results));
3183             return;
3184         }
3185
3186         default:
3187             DFG_CRASH(m_graph, m_node, "Bad array type");
3188             return;
3189         }
3190     }
3191     
3192     void compileCreateActivation()
3193     {
3194         LValue scope = lowCell(m_node->child1());
3195         SymbolTable* table = m_node->castOperand<SymbolTable*>();
3196         Structure* structure = m_graph.globalObjectFor(m_node->origin.semantic)->activationStructure();
3197         JSValue initializationValue = m_node->initializationValueForActivation();
3198         ASSERT(initializationValue.isUndefined() || initializationValue == jsTDZValue());
3199         if (table->singletonScope()->isStillValid()) {
3200             LValue callResult = vmCall(
3201                 m_out.int64,
3202                 m_out.operation(operationCreateActivationDirect), m_callFrame, weakPointer(structure),
3203                 scope, weakPointer(table), m_out.constInt64(JSValue::encode(initializationValue)));
3204             setJSValue(callResult);
3205             return;
3206         }
3207         
3208         LBasicBlock slowPath = FTL_NEW_BLOCK(m_out, ("CreateActivation slow path"));
3209         LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("CreateActivation continuation"));
3210         
3211         LBasicBlock lastNext = m_out.insertNewBlocksBefore(slowPath);
3212         
3213         LValue fastObject = allocateObject<JSLexicalEnvironment>(
3214             JSLexicalEnvironment::allocationSize(table), structure, m_out.intPtrZero, slowPath);
3215         
3216         // We don't need memory barriers since we just fast-created the activation, so the
3217         // activation must be young.
3218         m_out.storePtr(scope, fastObject, m_heaps.JSScope_next);
3219         m_out.storePtr(weakPointer(table), fastObject, m_heaps.JSSymbolTableObject_symbolTable);
3220         
3221         for (unsigned i = 0; i < table->scopeSize(); ++i) {
3222             m_out.store64(
3223                 m_out.constInt64(JSValue::encode(initializationValue)),
3224                 fastObject, m_heaps.JSEnvironmentRecord_variables[i]);
3225         }
3226         
3227         ValueFromBlock fastResult = m_out.anchor(fastObject);
3228         m_out.jump(continuation);
3229         
3230         m_out.appendTo(slowPath, continuation);
3231         LValue callResult = lazySlowPath(
3232             [=] (const Vector<Location>& locations) -> RefPtr<LazySlowPath::Generator> {
3233                 return createLazyCallGenerator(
3234                     operationCreateActivationDirect, locations[0].directGPR(),
3235                     CCallHelpers::TrustedImmPtr(structure), locations[1].directGPR(),
3236                     CCallHelpers::TrustedImmPtr(table),
3237                     CCallHelpers::TrustedImm64(JSValue::encode(initializationValue)));
3238             },
3239             scope);
3240         ValueFromBlock slowResult = m_out.anchor(callResult);
3241         m_out.jump(continuation);
3242         
3243         m_out.appendTo(continuation, lastNext);
3244         setJSValue(m_out.phi(m_out.intPtr, fastResult, slowResult));
3245     }
3246     
3247     void compileNewFunction()
3248     {
3249         ASSERT(m_node->op() == NewFunction || m_node->op() == NewArrowFunction || m_node->op() == NewGeneratorFunction);
3250         bool isGeneratorFunction = m_node->op() == NewGeneratorFunction;
3251         
3252         LValue scope = lowCell(m_node->child1());
3253         
3254         FunctionExecutable* executable = m_node->castOperand<FunctionExecutable*>();
3255         if (executable->singletonFunction()->isStillValid()) {
3256             LValue callResult =
3257                 isGeneratorFunction ? vmCall(m_out.int64, m_out.operation(operationNewGeneratorFunction), m_callFrame, scope, weakPointer(executable)) :
3258                 vmCall(m_out.int64, m_out.operation(operationNewFunction), m_callFrame, scope, weakPointer(executable));
3259             setJSValue(callResult);
3260             return;
3261         }
3262         
3263         Structure* structure =
3264             isGeneratorFunction ? m_graph.globalObjectFor(m_node->origin.semantic)->generatorFunctionStructure() :
3265             m_graph.globalObjectFor(m_node->origin.semantic)->functionStructure();
3266         
3267         LBasicBlock slowPath = FTL_NEW_BLOCK(m_out, ("NewFunction slow path"));
3268         LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("NewFunction continuation"));
3269         
3270         LBasicBlock lastNext = m_out.insertNewBlocksBefore(slowPath);
3271         
3272         LValue fastObject =
3273             isGeneratorFunction ? allocateObject<JSGeneratorFunction>(structure, m_out.intPtrZero, slowPath) :
3274             allocateObject<JSFunction>(structure, m_out.intPtrZero, slowPath);
3275         
3276         
3277         // We don't need memory barriers since we just fast-created the function, so it
3278         // must be young.
3279         m_out.storePtr(scope, fastObject, m_heaps.JSFunction_scope);
3280         m_out.storePtr(weakPointer(executable), fastObject, m_heaps.JSFunction_executable);
3281         m_out.storePtr(m_out.intPtrZero, fastObject, m_heaps.JSFunction_rareData);
3282         
3283         ValueFromBlock fastResult = m_out.anchor(fastObject);
3284         m_out.jump(continuation);
3285         
3286         m_out.appendTo(slowPath, continuation);
3287
3288         Vector<LValue> slowPathArguments;
3289         slowPathArguments.append(scope);
3290         LValue callResult = lazySlowPath(
3291             [=] (const Vector<Location>& locations) -> RefPtr<LazySlowPath::Generator> {
3292                 if (isGeneratorFunction) {
3293                     return createLazyCallGenerator(
3294                         operationNewGeneratorFunctionWithInvalidatedReallocationWatchpoint,
3295                         locations[0].directGPR(), locations[1].directGPR(),
3296                         CCallHelpers::TrustedImmPtr(executable));
3297                 }
3298                 return createLazyCallGenerator(
3299                     operationNewFunctionWithInvalidatedReallocationWatchpoint,
3300                     locations[0].directGPR(), locations[1].directGPR(),
3301                     CCallHelpers::TrustedImmPtr(executable));
3302             },
3303             slowPathArguments);
3304         ValueFromBlock slowResult = m_out.anchor(callResult);
3305         m_out.jump(continuation);
3306         
3307         m_out.appendTo(continuation, lastNext);
3308         setJSValue(m_out.phi(m_out.intPtr, fastResult, slowResult));
3309     }
3310     
3311     void compileCreateDirectArguments()
3312     {
3313         // FIXME: A more effective way of dealing with the argument count and callee is to have
3314         // them be explicit arguments to this node.
3315         // https://bugs.webkit.org/show_bug.cgi?id=142207
3316         
3317         Structure* structure =
3318             m_graph.globalObjectFor(m_node->origin.semantic)->directArgumentsStructure();
3319         
3320         unsigned minCapacity = m_graph.baselineCodeBlockFor(m_node->origin.semantic)->numParameters() - 1;
3321         
3322         LBasicBlock slowPath = FTL_NEW_BLOCK(m_out, ("CreateDirectArguments slow path"));
3323         LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("CreateDirectArguments continuation"));
3324         
3325         LBasicBlock lastNext = m_out.insertNewBlocksBefore(slowPath);
3326         
3327         ArgumentsLength length = getArgumentsLength();
3328         
3329         LValue fastObject;
3330         if (length.isKnown) {
3331             fastObject = allocateObject<DirectArguments>(
3332                 DirectArguments::allocationSize(std::max(length.known, minCapacity)), structure,
3333                 m_out.intPtrZero, slowPath);
3334         } else {
3335             LValue size = m_out.add(
3336                 m_out.shl(length.value, m_out.constInt32(3)),
3337                 m_out.constInt32(DirectArguments::storageOffset()));
3338             
3339             size = m_out.select(
3340                 m_out.aboveOrEqual(length.value, m_out.constInt32(minCapacity)),
3341                 size, m_out.constInt32(DirectArguments::allocationSize(minCapacity)));
3342             
3343             fastObject = allocateVariableSizedObject<DirectArguments>(
3344                 size, structure, m_out.intPtrZero, slowPath);
3345         }
3346         
3347         m_out.store32(length.value, fastObject, m_heaps.DirectArguments_length);
3348         m_out.store32(m_out.constInt32(minCapacity), fastObject, m_heaps.DirectArguments_minCapacity);
3349         m_out.storePtr(m_out.intPtrZero, fastObject, m_heaps.DirectArguments_overrides);
3350         
3351         ValueFromBlock fastResult = m_out.anchor(fastObject);
3352         m_out.jump(continuation);
3353         
3354         m_out.appendTo(slowPath, continuation);
3355         LValue callResult = lazySlowPath(
3356             [=] (const Vector<Location>& locations) -> RefPtr<LazySlowPath::Generator> {
3357                 return createLazyCallGenerator(
3358                     operationCreateDirectArguments, locations[0].directGPR(),
3359                     CCallHelpers::TrustedImmPtr(structure), locations[1].directGPR(),
3360                     CCallHelpers::TrustedImm32(minCapacity));
3361             }, length.value);
3362         ValueFromBlock slowResult = m_out.anchor(callResult);
3363         m_out.jump(continuation);
3364         
3365         m_out.appendTo(continuation, lastNext);
3366         LValue result = m_out.phi(m_out.intPtr, fastResult, slowResult);
3367
3368         m_out.storePtr(getCurrentCallee(), result, m_heaps.DirectArguments_callee);
3369         
3370         if (length.isKnown) {
3371             VirtualRegister start = AssemblyHelpers::argumentsStart(m_node->origin.semantic);
3372             for (unsigned i = 0; i < std::max(length.known, minCapacity); ++i) {
3373                 m_out.store64(
3374                     m_out.load64(addressFor(start + i)),
3375                     result, m_heaps.DirectArguments_storage[i]);
3376             }
3377         } else {
3378             LValue stackBase = getArgumentsStart();
3379             
3380             LBasicBlock loop = FTL_NEW_BLOCK(m_out, ("CreateDirectArguments loop body"));
3381             LBasicBlock end = FTL_NEW_BLOCK(m_out, ("CreateDirectArguments loop end"));
3382
3383             ValueFromBlock originalLength;
3384             if (minCapacity) {
3385                 LValue capacity = m_out.select(
3386                     m_out.aboveOrEqual(length.value, m_out.constInt32(minCapacity)),
3387                     length.value,
3388                     m_out.constInt32(minCapacity));
3389                 LValue originalLengthValue = m_out.zeroExtPtr(capacity);
3390                 originalLength = m_out.anchor(originalLengthValue);
3391                 m_out.jump(loop);
3392             } else {
3393                 LValue originalLengthValue = m_out.zeroExtPtr(length.value);
3394                 originalLength = m_out.anchor(originalLengthValue);
3395                 m_out.branch(m_out.isNull(originalLengthValue), unsure(end), unsure(loop));
3396             }
3397             
3398             lastNext = m_out.appendTo(loop, end);
3399             LValue previousIndex = m_out.phi(m_out.intPtr, originalLength);
3400             LValue index = m_out.sub(previousIndex, m_out.intPtrOne);
3401             m_out.store64(
3402                 m_out.load64(m_out.baseIndex(m_heaps.variables, stackBase, index)),
3403                 m_out.baseIndex(m_heaps.DirectArguments_storage, result, index));
3404             ValueFromBlock nextIndex = m_out.anchor(index);
3405             m_out.addIncomingToPhi(previousIndex, nextIndex);
3406             m_out.branch(m_out.isNull(index), unsure(end), unsure(loop));
3407             
3408             m_out.appendTo(end, lastNext);
3409         }
3410         
3411         setJSValue(result);
3412     }
3413     
3414     void compileCreateScopedArguments()
3415     {
3416         LValue scope = lowCell(m_node->child1());
3417         
3418         LValue result = vmCall(
3419             m_out.int64, m_out.operation(operationCreateScopedArguments), m_callFrame,
3420             weakPointer(
3421                 m_graph.globalObjectFor(m_node->origin.semantic)->scopedArgumentsStructure()),
3422             getArgumentsStart(), getArgumentsLength().value, getCurrentCallee(), scope);
3423         
3424         setJSValue(result);
3425     }
3426     
3427     void compileCreateClonedArguments()
3428     {
3429         LValue result = vmCall(
3430             m_out.int64, m_out.operation(operationCreateClonedArguments), m_callFrame,
3431             weakPointer(
3432                 m_graph.globalObjectFor(m_node->origin.semantic)->outOfBandArgumentsStructure()),
3433             getArgumentsStart(), getArgumentsLength().value, getCurrentCallee());
3434         
3435         setJSValue(result);
3436     }
3437
3438     void compileCopyRest()
3439     {            
3440         LBasicBlock doCopyRest = FTL_NEW_BLOCK(m_out, ("CopyRest C call"));
3441         LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("FillRestParameter continuation"));
3442
3443         LValue arrayLength = lowInt32(m_node->child2());
3444
3445         m_out.branch(
3446             m_out.equal(arrayLength, m_out.constInt32(0)),
3447             unsure(continuation), unsure(doCopyRest));
3448             
3449         LBasicBlock lastNext = m_out.appendTo(doCopyRest, continuation);
3450         // Arguments: 0:exec, 1:JSCell* array, 2:arguments start, 3:number of arguments to skip, 4:array length
3451         LValue numberOfArgumentsToSkip = m_out.constInt32(m_node->numberOfArgumentsToSkip());
3452         vmCall(
3453             m_out.voidType,m_out.operation(operationCopyRest), m_callFrame, lowCell(m_node->child1()),
3454             getArgumentsStart(), numberOfArgumentsToSkip, arrayLength);
3455         m_out.jump(continuation);
3456
3457         m_out.appendTo(continuation, lastNext);
3458     }
3459
3460     void compileGetRestLength()
3461     {
3462         LBasicBlock nonZeroLength = FTL_NEW_BLOCK(m_out, ("GetRestLength non zero"));
3463         LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("GetRestLength continuation"));
3464         
3465         ValueFromBlock zeroLengthResult = m_out.anchor(m_out.constInt32(0));
3466
3467         LValue numberOfArgumentsToSkip = m_out.constInt32(m_node->numberOfArgumentsToSkip());
3468         LValue argumentsLength = getArgumentsLength().value;
3469         m_out.branch(m_out.above(argumentsLength, numberOfArgumentsToSkip),
3470             unsure(nonZeroLength), unsure(continuation));
3471         
3472         LBasicBlock lastNext = m_out.appendTo(nonZeroLength, continuation);
3473         ValueFromBlock nonZeroLengthResult = m_out.anchor(m_out.sub(argumentsLength, numberOfArgumentsToSkip));
3474         m_out.jump(continuation);
3475         
3476         m_out.appendTo(continuation, lastNext);
3477         setInt32(m_out.phi(m_out.int32, zeroLengthResult, nonZeroLengthResult));
3478     }
3479     
3480     void compileNewObject()
3481     {
3482         setJSValue(allocateObject(m_node->structure()));
3483     }
3484     
3485     void compileNewArray()
3486     {
3487         // First speculate appropriately on all of the children. Do this unconditionally up here
3488         // because some of the slow paths may otherwise forget to do it. It's sort of arguable
3489         // that doing the speculations up here might be unprofitable for RA - so we can consider
3490         // sinking this to below the allocation fast path if we find that this has a lot of
3491         // register pressure.
3492         for (unsigned operandIndex = 0; operandIndex < m_node->numChildren(); ++operandIndex)
3493             speculate(m_graph.varArgChild(m_node, operandIndex));
3494         
3495         JSGlobalObject* globalObject = m_graph.globalObjectFor(m_node->origin.semantic);
3496         Structure* structure = globalObject->arrayStructureForIndexingTypeDuringAllocation(
3497             m_node->indexingType());
3498
3499         if (!globalObject->isHavingABadTime() && !hasAnyArrayStorage(m_node->indexingType())) {
3500             unsigned numElements = m_node->numChildren();
3501             
3502             ArrayValues arrayValues = allocateJSArray(structure, numElements);
3503             
3504             for (unsigned operandIndex = 0; operandIndex < m_node->numChildren(); ++operandIndex) {
3505                 Edge edge = m_graph.varArgChild(m_node, operandIndex);
3506                 
3507                 switch (m_node->indexingType()) {
3508                 case ALL_BLANK_INDEXING_TYPES:
3509                 case ALL_UNDECIDED_INDEXING_TYPES:
3510                     DFG_CRASH(m_graph, m_node, "Bad indexing type");
3511                     break;
3512                     
3513                 case ALL_DOUBLE_INDEXING_TYPES:
3514                     m_out.storeDouble(
3515                         lowDouble(edge),
3516                         arrayValues.butterfly, m_heaps.indexedDoubleProperties[operandIndex]);
3517                     break;
3518                     
3519                 case ALL_INT32_INDEXING_TYPES:
3520                 case ALL_CONTIGUOUS_INDEXING_TYPES:
3521                     m_out.store64(
3522                         lowJSValue(edge, ManualOperandSpeculation),
3523                         arrayValues.butterfly,
3524                         m_heaps.forIndexingType(m_node->indexingType())->at(operandIndex));
3525                     break;
3526                     
3527                 default:
3528                     DFG_CRASH(m_graph, m_node, "Corrupt indexing type");
3529                     break;
3530                 }
3531             }
3532             
3533             setJSValue(arrayValues.array);