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