1/*
2 * Copyright (C) 2013, 2014 Apple Inc. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 *    notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 *    notice, this list of conditions and the following disclaimer in the
11 *    documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 */
25
26#include "config.h"
27#include "FTLLowerDFGToLLVM.h"
28
29#if ENABLE(FTL_JIT)
30
31#include "CodeBlockWithJITType.h"
32#include "DFGAbstractInterpreterInlines.h"
33#include "DFGInPlaceAbstractState.h"
34#include "FTLAbstractHeapRepository.h"
35#include "FTLAvailableRecovery.h"
36#include "FTLForOSREntryJITCode.h"
37#include "FTLFormattedValue.h"
38#include "FTLInlineCacheSize.h"
39#include "FTLLoweredNodeValue.h"
40#include "FTLOutput.h"
41#include "FTLThunks.h"
42#include "FTLWeightedTarget.h"
43#include "OperandsInlines.h"
44#include "JSCInlines.h"
45#include "VirtualRegister.h"
46#include <atomic>
47#include <wtf/ProcessID.h>
48
49namespace JSC { namespace FTL {
50
51using namespace DFG;
52
53static std::atomic<int> compileCounter;
54
55// Using this instead of typeCheck() helps to reduce the load on LLVM, by creating
56// significantly less dead code.
57#define FTL_TYPE_CHECK(lowValue, highValue, typesPassedThrough, failCondition) do { \
58        FormattedValue _ftc_lowValue = (lowValue);                      \
59        Edge _ftc_highValue = (highValue);                              \
60        SpeculatedType _ftc_typesPassedThrough = (typesPassedThrough);  \
61        if (!m_interpreter.needsTypeCheck(_ftc_highValue, _ftc_typesPassedThrough)) \
62            break;                                                      \
63        typeCheck(_ftc_lowValue, _ftc_highValue, _ftc_typesPassedThrough, (failCondition)); \
64    } while (false)
65
66class LowerDFGToLLVM {
67public:
68    LowerDFGToLLVM(State& state)
69        : m_graph(state.graph)
70        , m_ftlState(state)
71        , m_heaps(state.context)
72        , m_out(state.context)
73        , m_availability(OperandsLike, state.graph.block(0)->variablesAtHead)
74        , m_state(state.graph)
75        , m_interpreter(state.graph, m_state)
76        , m_stackmapIDs(0)
77    {
78    }
79
80    void lower()
81    {
82        CString name;
83        if (verboseCompilationEnabled()) {
84            name = toCString(
85                "jsBody_", ++compileCounter, "_", codeBlock()->inferredName(),
86                "_", codeBlock()->hash());
87        } else
88            name = "jsBody";
89
90        m_graph.m_dominators.computeIfNecessary(m_graph);
91
92        m_ftlState.module =
93            llvm->ModuleCreateWithNameInContext(name.data(), m_ftlState.context);
94
95        m_ftlState.function = addFunction(
96            m_ftlState.module, name.data(), functionType(m_out.int64));
97        setFunctionCallingConv(m_ftlState.function, LLVMCCallConv);
98        if (isX86() && Options::llvmDisallowAVX()) {
99            // AVX makes V8/raytrace 80% slower. It makes Kraken/audio-oscillator 4.5x
100            // slower. It should be disabled.
101            addTargetDependentFunctionAttr(m_ftlState.function, "target-features", "-avx");
102        }
103
104        if (verboseCompilationEnabled())
105            dataLog("Function ready, beginning lowering.\n");
106
107        m_out.initialize(m_ftlState.module, m_ftlState.function, m_heaps);
108
109        m_prologue = FTL_NEW_BLOCK(m_out, ("Prologue"));
110        LBasicBlock stackOverflow = FTL_NEW_BLOCK(m_out, ("Stack overflow"));
111        m_handleExceptions = FTL_NEW_BLOCK(m_out, ("Handle Exceptions"));
112
113        for (BlockIndex blockIndex = 0; blockIndex < m_graph.numBlocks(); ++blockIndex) {
114            m_highBlock = m_graph.block(blockIndex);
115            if (!m_highBlock)
116                continue;
117            m_blocks.add(m_highBlock, FTL_NEW_BLOCK(m_out, ("Block ", *m_highBlock)));
118        }
119
120        m_out.appendTo(m_prologue, stackOverflow);
121        createPhiVariables();
122        LValue capturedAlloca = m_out.alloca(arrayType(m_out.int64, m_graph.m_nextMachineLocal));
123        m_captured = m_out.add(
124            m_out.ptrToInt(capturedAlloca, m_out.intPtr),
125            m_out.constIntPtr(m_graph.m_nextMachineLocal * sizeof(Register)));
126
127        // We should not create any alloca's after this point, since they will cease to
128        // be mem2reg candidates.
129
130        m_ftlState.capturedStackmapID = m_stackmapIDs++;
131        m_out.call(
132            m_out.stackmapIntrinsic(), m_out.constInt64(m_ftlState.capturedStackmapID),
133            m_out.int32Zero, capturedAlloca);
134
135        m_callFrame = m_out.ptrToInt(
136            m_out.call(m_out.frameAddressIntrinsic(), m_out.int32Zero), m_out.intPtr);
137        m_tagTypeNumber = m_out.constInt64(TagTypeNumber);
138        m_tagMask = m_out.constInt64(TagMask);
139
140        m_out.storePtr(m_out.constIntPtr(codeBlock()), addressFor(JSStack::CodeBlock));
141
142        m_out.branch(
143            didOverflowStack(), rarely(stackOverflow), usually(lowBlock(m_graph.block(0))));
144
145        m_out.appendTo(stackOverflow, m_handleExceptions);
146        m_out.call(m_out.operation(operationThrowStackOverflowError), m_callFrame, m_out.constIntPtr(codeBlock()));
147        m_ftlState.handleStackOverflowExceptionStackmapID = m_stackmapIDs++;
148        m_out.call(
149            m_out.stackmapIntrinsic(), m_out.constInt64(m_ftlState.handleStackOverflowExceptionStackmapID),
150            m_out.constInt32(MacroAssembler::maxJumpReplacementSize()));
151        m_out.unreachable();
152
153        m_out.appendTo(m_handleExceptions, lowBlock(m_graph.block(0)));
154        m_ftlState.handleExceptionStackmapID = m_stackmapIDs++;
155        m_out.call(
156            m_out.stackmapIntrinsic(), m_out.constInt64(m_ftlState.handleExceptionStackmapID),
157            m_out.constInt32(MacroAssembler::maxJumpReplacementSize()));
158        m_out.unreachable();
159
160        Vector<BasicBlock*> depthFirst;
161        m_graph.getBlocksInDepthFirstOrder(depthFirst);
162        for (unsigned i = 0; i < depthFirst.size(); ++i)
163            compileBlock(depthFirst[i]);
164
165        if (Options::dumpLLVMIR())
166            dumpModule(m_ftlState.module);
167
168        if (verboseCompilationEnabled())
169            m_ftlState.dumpState("after lowering");
170        if (validationEnabled())
171            verifyModule(m_ftlState.module);
172    }
173
174private:
175
176    void createPhiVariables()
177    {
178        for (BlockIndex blockIndex = m_graph.numBlocks(); blockIndex--;) {
179            BasicBlock* block = m_graph.block(blockIndex);
180            if (!block)
181                continue;
182            for (unsigned nodeIndex = block->size(); nodeIndex--;) {
183                Node* node = block->at(nodeIndex);
184                if (node->op() != Phi)
185                    continue;
186                LType type;
187                switch (node->flags() & NodeResultMask) {
188                case NodeResultDouble:
189                    type = m_out.doubleType;
190                    break;
191                case NodeResultInt32:
192                    type = m_out.int32;
193                    break;
194                case NodeResultInt52:
195                    type = m_out.int64;
196                    break;
197                case NodeResultBoolean:
198                    type = m_out.boolean;
199                    break;
200                case NodeResultJS:
201                    type = m_out.int64;
202                    break;
203                default:
204                    RELEASE_ASSERT_NOT_REACHED();
205                    break;
206                }
207                m_phis.add(node, buildAlloca(m_out.m_builder, type));
208            }
209        }
210    }
211
212    void compileBlock(BasicBlock* block)
213    {
214        if (!block)
215            return;
216
217        if (verboseCompilationEnabled())
218            dataLog("Compiling block ", *block, "\n");
219
220        m_highBlock = block;
221
222        LBasicBlock lowBlock = m_blocks.get(m_highBlock);
223
224        m_nextHighBlock = 0;
225        for (BlockIndex nextBlockIndex = m_highBlock->index + 1; nextBlockIndex < m_graph.numBlocks(); ++nextBlockIndex) {
226            m_nextHighBlock = m_graph.block(nextBlockIndex);
227            if (m_nextHighBlock)
228                break;
229        }
230        m_nextLowBlock = m_nextHighBlock ? m_blocks.get(m_nextHighBlock) : 0;
231
232        // All of this effort to find the next block gives us the ability to keep the
233        // generated IR in roughly program order. This ought not affect the performance
234        // of the generated code (since we expect LLVM to reorder things) but it will
235        // make IR dumps easier to read.
236        m_out.appendTo(lowBlock, m_nextLowBlock);
237
238        if (Options::ftlCrashes())
239            m_out.crashNonTerminal();
240
241        if (!m_highBlock->cfaHasVisited) {
242            m_out.crash();
243            return;
244        }
245
246        initializeOSRExitStateForBlock();
247
248        m_state.reset();
249        m_state.beginBasicBlock(m_highBlock);
250
251        for (m_nodeIndex = 0; m_nodeIndex < m_highBlock->size(); ++m_nodeIndex) {
252            if (!compileNode(m_nodeIndex))
253                break;
254        }
255    }
256
257    bool compileNode(unsigned nodeIndex)
258    {
259        if (!m_state.isValid()) {
260            m_out.unreachable();
261            return false;
262        }
263
264        m_node = m_highBlock->at(nodeIndex);
265        m_codeOriginForExitProfile = m_node->origin.semantic;
266        m_codeOriginForExitTarget = m_node->origin.forExit;
267
268        if (verboseCompilationEnabled())
269            dataLog("Lowering ", m_node, "\n");
270
271        m_availableRecoveries.resize(0);
272
273        bool shouldExecuteEffects = m_interpreter.startExecuting(m_node);
274
275        switch (m_node->op()) {
276        case Upsilon:
277            compileUpsilon();
278            break;
279        case Phi:
280            compilePhi();
281            break;
282        case JSConstant:
283            break;
284        case DoubleConstant:
285            compileDoubleConstant();
286            break;
287        case Int52Constant:
288            compileInt52Constant();
289            break;
290        case WeakJSConstant:
291            compileWeakJSConstant();
292            break;
293        case PhantomArguments:
294            compilePhantomArguments();
295            break;
296        case DoubleRep:
297            compileDoubleRep();
298            break;
299        case ValueRep:
300            compileValueRep();
301            break;
302        case Int52Rep:
303            compileInt52Rep();
304            break;
305        case ValueToInt32:
306            compileValueToInt32();
307            break;
308        case BooleanToNumber:
309            compileBooleanToNumber();
310            break;
311        case GetArgument:
312            compileGetArgument();
313            break;
314        case ExtractOSREntryLocal:
315            compileExtractOSREntryLocal();
316            break;
317        case GetLocal:
318            compileGetLocal();
319            break;
320        case SetLocal:
321            compileSetLocal();
322            break;
323        case MovHint:
324            compileMovHint();
325            break;
326        case GetMyArgumentsLength:
327            compileGetMyArgumentsLength();
328            break;
329        case GetMyArgumentByVal:
330            compileGetMyArgumentByVal();
331            break;
332        case ZombieHint:
333            compileZombieHint();
334            break;
335        case Phantom:
336        case HardPhantom:
337            compilePhantom();
338            break;
339        case ToThis:
340            compileToThis();
341            break;
342        case ValueAdd:
343            compileValueAdd();
344            break;
345        case ArithAdd:
346        case ArithSub:
347            compileArithAddOrSub();
348            break;
349        case ArithMul:
350            compileArithMul();
351            break;
352        case ArithDiv:
353            compileArithDiv();
354            break;
355        case ArithMod:
356            compileArithMod();
357            break;
358        case ArithMin:
359        case ArithMax:
360            compileArithMinOrMax();
361            break;
362        case ArithAbs:
363            compileArithAbs();
364            break;
365        case ArithSin:
366            compileArithSin();
367            break;
368        case ArithCos:
369            compileArithCos();
370            break;
371        case ArithSqrt:
372            compileArithSqrt();
373            break;
374        case ArithFRound:
375            compileArithFRound();
376            break;
377        case ArithNegate:
378            compileArithNegate();
379            break;
380        case BitAnd:
381            compileBitAnd();
382            break;
383        case BitOr:
384            compileBitOr();
385            break;
386        case BitXor:
387            compileBitXor();
388            break;
389        case BitRShift:
390            compileBitRShift();
391            break;
392        case BitLShift:
393            compileBitLShift();
394            break;
395        case BitURShift:
396            compileBitURShift();
397            break;
398        case UInt32ToNumber:
399            compileUInt32ToNumber();
400            break;
401        case CheckStructure:
402            compileCheckStructure();
403            break;
404        case StructureTransitionWatchpoint:
405            compileStructureTransitionWatchpoint();
406            break;
407        case CheckFunction:
408            compileCheckFunction();
409            break;
410        case CheckExecutable:
411            compileCheckExecutable();
412            break;
413        case ArrayifyToStructure:
414            compileArrayifyToStructure();
415            break;
416        case PutStructure:
417            compilePutStructure();
418            break;
419        case PhantomPutStructure:
420            compilePhantomPutStructure();
421            break;
422        case GetById:
423            compileGetById();
424            break;
425        case PutByIdDirect:
426        case PutById:
427            compilePutById();
428            break;
429        case GetButterfly:
430            compileGetButterfly();
431            break;
432        case ConstantStoragePointer:
433            compileConstantStoragePointer();
434            break;
435        case GetIndexedPropertyStorage:
436            compileGetIndexedPropertyStorage();
437            break;
438        case CheckArray:
439            compileCheckArray();
440            break;
441        case GetArrayLength:
442            compileGetArrayLength();
443            break;
444        case CheckInBounds:
445            compileCheckInBounds();
446            break;
447        case GetByVal:
448            compileGetByVal();
449            break;
450        case PutByVal:
451        case PutByValAlias:
452        case PutByValDirect:
453            compilePutByVal();
454            break;
455        case ArrayPush:
456            compileArrayPush();
457            break;
458        case ArrayPop:
459            compileArrayPop();
460            break;
461        case NewObject:
462            compileNewObject();
463            break;
464        case NewArray:
465            compileNewArray();
466            break;
467        case NewArrayBuffer:
468            compileNewArrayBuffer();
469            break;
470        case NewArrayWithSize:
471            compileNewArrayWithSize();
472            break;
473        case GetTypedArrayByteOffset:
474            compileGetTypedArrayByteOffset();
475            break;
476        case AllocatePropertyStorage:
477            compileAllocatePropertyStorage();
478            break;
479        case ReallocatePropertyStorage:
480            compileReallocatePropertyStorage();
481            break;
482        case ToString:
483            compileToString();
484            break;
485        case ToPrimitive:
486            compileToPrimitive();
487            break;
488        case MakeRope:
489            compileMakeRope();
490            break;
491        case StringCharAt:
492            compileStringCharAt();
493            break;
494        case StringCharCodeAt:
495            compileStringCharCodeAt();
496            break;
497        case GetByOffset:
498            compileGetByOffset();
499            break;
500        case MultiGetByOffset:
501            compileMultiGetByOffset();
502            break;
503        case PutByOffset:
504            compilePutByOffset();
505            break;
506        case MultiPutByOffset:
507            compileMultiPutByOffset();
508            break;
509        case GetGlobalVar:
510            compileGetGlobalVar();
511            break;
512        case PutGlobalVar:
513            compilePutGlobalVar();
514            break;
515        case NotifyWrite:
516            compileNotifyWrite();
517            break;
518        case GetCallee:
519            compileGetCallee();
520            break;
521        case GetScope:
522            compileGetScope();
523            break;
524        case GetMyScope:
525            compileGetMyScope();
526            break;
527        case SkipScope:
528            compileSkipScope();
529            break;
530        case GetClosureRegisters:
531            compileGetClosureRegisters();
532            break;
533        case GetClosureVar:
534            compileGetClosureVar();
535            break;
536        case PutClosureVar:
537            compilePutClosureVar();
538            break;
539        case CompareEq:
540            compileCompareEq();
541            break;
542        case CompareEqConstant:
543            compileCompareEqConstant();
544            break;
545        case CompareStrictEq:
546            compileCompareStrictEq();
547            break;
548        case CompareLess:
549            compileCompareLess();
550            break;
551        case CompareLessEq:
552            compileCompareLessEq();
553            break;
554        case CompareGreater:
555            compileCompareGreater();
556            break;
557        case CompareGreaterEq:
558            compileCompareGreaterEq();
559            break;
560        case LogicalNot:
561            compileLogicalNot();
562            break;
563        case Call:
564        case Construct:
565            compileCallOrConstruct();
566            break;
567        case Jump:
568            compileJump();
569            break;
570        case Branch:
571            compileBranch();
572            break;
573        case Switch:
574            compileSwitch();
575            break;
576        case Return:
577            compileReturn();
578            break;
579        case ForceOSRExit:
580            compileForceOSRExit();
581            break;
582        case Throw:
583        case ThrowReferenceError:
584            compileThrow();
585            break;
586        case InvalidationPoint:
587            compileInvalidationPoint();
588            break;
589        case CheckArgumentsNotCreated:
590            compileCheckArgumentsNotCreated();
591            break;
592        case IsUndefined:
593            compileIsUndefined();
594            break;
595        case IsBoolean:
596            compileIsBoolean();
597            break;
598        case IsNumber:
599            compileIsNumber();
600            break;
601        case IsString:
602            compileIsString();
603            break;
604        case IsObject:
605            compileIsObject();
606            break;
607        case IsFunction:
608            compileIsFunction();
609            break;
610        case CheckHasInstance:
611            compileCheckHasInstance();
612            break;
613        case InstanceOf:
614            compileInstanceOf();
615            break;
616        case CountExecution:
617            compileCountExecution();
618            break;
619        case StoreBarrier:
620            compileStoreBarrier();
621            break;
622        case StoreBarrierWithNullCheck:
623            compileStoreBarrierWithNullCheck();
624            break;
625        case PhantomLocal:
626        case SetArgument:
627        case LoopHint:
628        case VariableWatchpoint:
629        case FunctionReentryWatchpoint:
630        case TypedArrayWatchpoint:
631        case AllocationProfileWatchpoint:
632            break;
633        default:
634            dataLog("Unrecognized node in FTL backend:\n");
635            m_graph.dump(WTF::dataFile(), "    ", m_node);
636            dataLog("\n");
637            dataLog("Full graph dump:\n");
638            m_graph.dump();
639            RELEASE_ASSERT_NOT_REACHED();
640            break;
641        }
642
643        if (shouldExecuteEffects)
644            m_interpreter.executeEffects(nodeIndex);
645
646        return true;
647    }
648
649    void compileUpsilon()
650    {
651        LValue destination = m_phis.get(m_node->phi());
652
653        switch (m_node->child1().useKind()) {
654        case DoubleRepUse:
655            m_out.set(lowDouble(m_node->child1()), destination);
656            break;
657        case Int32Use:
658            m_out.set(lowInt32(m_node->child1()), destination);
659            break;
660        case Int52RepUse:
661            m_out.set(lowInt52(m_node->child1()), destination);
662            break;
663        case BooleanUse:
664            m_out.set(lowBoolean(m_node->child1()), destination);
665            break;
666        case CellUse:
667            m_out.set(lowCell(m_node->child1()), destination);
668            break;
669        case UntypedUse:
670            m_out.set(lowJSValue(m_node->child1()), destination);
671            break;
672        default:
673            RELEASE_ASSERT_NOT_REACHED();
674            break;
675        }
676    }
677
678    void compilePhi()
679    {
680        LValue source = m_phis.get(m_node);
681
682        switch (m_node->flags() & NodeResultMask) {
683        case NodeResultDouble:
684            setDouble(m_out.get(source));
685            break;
686        case NodeResultInt32:
687            setInt32(m_out.get(source));
688            break;
689        case NodeResultInt52:
690            setInt52(m_out.get(source));
691            break;
692        case NodeResultBoolean:
693            setBoolean(m_out.get(source));
694            break;
695        case NodeResultJS:
696            setJSValue(m_out.get(source));
697            break;
698        default:
699            RELEASE_ASSERT_NOT_REACHED();
700            break;
701        }
702    }
703
704    void compileDoubleConstant()
705    {
706        setDouble(m_out.constDouble(m_graph.valueOfNumberConstant(m_node)));
707    }
708
709    void compileInt52Constant()
710    {
711        int64_t value = m_graph.valueOfJSConstant(m_node).asMachineInt();
712
713        setInt52(m_out.constInt64(value << JSValue::int52ShiftAmount));
714        setStrictInt52(m_out.constInt64(value));
715    }
716
717    void compileWeakJSConstant()
718    {
719        setJSValue(weakPointer(m_node->weakConstant()));
720    }
721
722    void compilePhantomArguments()
723    {
724        setJSValue(m_out.constInt64(JSValue::encode(JSValue())));
725    }
726
727    void compileDoubleRep()
728    {
729        switch (m_node->child1().useKind()) {
730        case NumberUse: {
731            LValue value = lowJSValue(m_node->child1(), ManualOperandSpeculation);
732            setDouble(jsValueToDouble(m_node->child1(), value));
733            return;
734        }
735
736        case Int52RepUse: {
737            setDouble(strictInt52ToDouble(lowStrictInt52(m_node->child1())));
738            return;
739        }
740
741        default:
742            RELEASE_ASSERT_NOT_REACHED();
743        }
744    }
745
746    void compileValueRep()
747    {
748        switch (m_node->child1().useKind()) {
749        case DoubleRepUse: {
750            LValue value = lowDouble(m_node->child1());
751
752            if (m_interpreter.needsTypeCheck(m_node->child1(), ~SpecDoubleImpureNaN)) {
753                value = m_out.select(
754                    m_out.doubleEqual(value, value), value, m_out.constDouble(PNaN));
755            }
756
757            setJSValue(boxDouble(value));
758            return;
759        }
760
761        case Int52RepUse: {
762            setJSValue(strictInt52ToJSValue(lowStrictInt52(m_node->child1())));
763            return;
764        }
765
766        default:
767            RELEASE_ASSERT_NOT_REACHED();
768        }
769    }
770
771    void compileInt52Rep()
772    {
773        switch (m_node->child1().useKind()) {
774        case Int32Use:
775            setStrictInt52(m_out.signExt(lowInt32(m_node->child1()), m_out.int64));
776            return;
777
778        case MachineIntUse:
779            setStrictInt52(
780                jsValueToStrictInt52(
781                    m_node->child1(), lowJSValue(m_node->child1(), ManualOperandSpeculation)));
782            return;
783
784        case DoubleRepMachineIntUse:
785            setStrictInt52(
786                doubleToStrictInt52(
787                    m_node->child1(), lowDouble(m_node->child1())));
788            return;
789
790        default:
791            RELEASE_ASSERT_NOT_REACHED();
792        }
793    }
794
795    void compileValueToInt32()
796    {
797        switch (m_node->child1().useKind()) {
798        case Int52RepUse:
799            setInt32(m_out.castToInt32(lowStrictInt52(m_node->child1())));
800            break;
801
802        case DoubleRepUse:
803            setInt32(doubleToInt32(lowDouble(m_node->child1())));
804            break;
805
806        case NumberUse:
807        case NotCellUse: {
808            LoweredNodeValue value = m_int32Values.get(m_node->child1().node());
809            if (isValid(value)) {
810                setInt32(value.value());
811                break;
812            }
813
814            value = m_jsValueValues.get(m_node->child1().node());
815            if (isValid(value)) {
816                setInt32(numberOrNotCellToInt32(m_node->child1(), value.value()));
817                break;
818            }
819
820            // We'll basically just get here for constants. But it's good to have this
821            // catch-all since we often add new representations into the mix.
822            setInt32(
823                numberOrNotCellToInt32(
824                    m_node->child1(),
825                    lowJSValue(m_node->child1(), ManualOperandSpeculation)));
826            break;
827        }
828
829        default:
830            RELEASE_ASSERT_NOT_REACHED();
831            break;
832        }
833    }
834
835    void compileBooleanToNumber()
836    {
837        switch (m_node->child1().useKind()) {
838        case BooleanUse: {
839            setInt32(m_out.zeroExt(lowBoolean(m_node->child1()), m_out.int32));
840            return;
841        }
842
843        case UntypedUse: {
844            LValue value = lowJSValue(m_node->child1());
845
846            LBasicBlock booleanCase = FTL_NEW_BLOCK(m_out, ("BooleanToNumber boolean case"));
847            LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("BooleanToNumber continuation"));
848
849            ValueFromBlock notBooleanResult = m_out.anchor(value);
850            m_out.branch(isBoolean(value), unsure(booleanCase), unsure(continuation));
851
852            LBasicBlock lastNext = m_out.appendTo(booleanCase, continuation);
853            ValueFromBlock booleanResult = m_out.anchor(m_out.bitOr(
854                m_out.zeroExt(unboxBoolean(value), m_out.int64), m_tagTypeNumber));
855            m_out.jump(continuation);
856
857            m_out.appendTo(continuation, lastNext);
858            setJSValue(m_out.phi(m_out.int64, booleanResult, notBooleanResult));
859            return;
860        }
861
862        default:
863            RELEASE_ASSERT_NOT_REACHED();
864            return;
865        }
866    }
867
868    void compileGetArgument()
869    {
870        VariableAccessData* variable = m_node->variableAccessData();
871        VirtualRegister operand = variable->machineLocal();
872        RELEASE_ASSERT(operand.isArgument());
873
874        LValue jsValue = m_out.load64(addressFor(operand));
875
876        switch (useKindFor(variable->flushFormat())) {
877        case Int32Use:
878            speculate(BadType, jsValueValue(jsValue), m_node, isNotInt32(jsValue));
879            setInt32(unboxInt32(jsValue));
880            break;
881        case CellUse:
882            speculate(BadType, jsValueValue(jsValue), m_node, isNotCell(jsValue));
883            setJSValue(jsValue);
884            break;
885        case BooleanUse:
886            speculate(BadType, jsValueValue(jsValue), m_node, isNotBoolean(jsValue));
887            setBoolean(unboxBoolean(jsValue));
888            break;
889        case UntypedUse:
890            setJSValue(jsValue);
891            break;
892        default:
893            RELEASE_ASSERT_NOT_REACHED();
894            break;
895        }
896    }
897
898    void compileExtractOSREntryLocal()
899    {
900        EncodedJSValue* buffer = static_cast<EncodedJSValue*>(
901            m_ftlState.jitCode->ftlForOSREntry()->entryBuffer()->dataBuffer());
902        setJSValue(m_out.load64(m_out.absolute(buffer + m_node->unlinkedLocal().toLocal())));
903    }
904
905    void compileGetLocal()
906    {
907        // GetLocals arise only for captured variables.
908
909        VariableAccessData* variable = m_node->variableAccessData();
910        AbstractValue& value = m_state.variables().operand(variable->local());
911
912        RELEASE_ASSERT(variable->isCaptured());
913
914        if (isInt32Speculation(value.m_type))
915            setInt32(m_out.load32(payloadFor(variable->machineLocal())));
916        else
917            setJSValue(m_out.load64(addressFor(variable->machineLocal())));
918    }
919
920    void compileSetLocal()
921    {
922        VariableAccessData* variable = m_node->variableAccessData();
923        switch (variable->flushFormat()) {
924        case FlushedJSValue:
925        case FlushedArguments: {
926            LValue value = lowJSValue(m_node->child1());
927            m_out.store64(value, addressFor(variable->machineLocal()));
928            break;
929        }
930
931        case FlushedDouble: {
932            LValue value = lowDouble(m_node->child1());
933            m_out.storeDouble(value, addressFor(variable->machineLocal()));
934            break;
935        }
936
937        case FlushedInt32: {
938            LValue value = lowInt32(m_node->child1());
939            m_out.store32(value, payloadFor(variable->machineLocal()));
940            break;
941        }
942
943        case FlushedInt52: {
944            LValue value = lowInt52(m_node->child1());
945            m_out.store64(value, addressFor(variable->machineLocal()));
946            break;
947        }
948
949        case FlushedCell: {
950            LValue value = lowCell(m_node->child1());
951            m_out.store64(value, addressFor(variable->machineLocal()));
952            break;
953        }
954
955        case FlushedBoolean: {
956            speculateBoolean(m_node->child1());
957            m_out.store64(
958                lowJSValue(m_node->child1(), ManualOperandSpeculation),
959                addressFor(variable->machineLocal()));
960            break;
961        }
962
963        default:
964            RELEASE_ASSERT_NOT_REACHED();
965            break;
966        }
967
968        m_availability.operand(variable->local()) = Availability(variable->flushedAt());
969    }
970
971    void compileMovHint()
972    {
973        ASSERT(m_node->containsMovHint());
974        ASSERT(m_node->op() != ZombieHint);
975
976        VirtualRegister operand = m_node->unlinkedLocal();
977        m_availability.operand(operand) = Availability(m_node->child1().node());
978    }
979
980    void compileZombieHint()
981    {
982        m_availability.operand(m_node->unlinkedLocal()) = Availability::unavailable();
983    }
984
985    void compilePhantom()
986    {
987        DFG_NODE_DO_TO_CHILDREN(m_graph, m_node, speculate);
988    }
989
990    void compileToThis()
991    {
992        LValue value = lowJSValue(m_node->child1());
993
994        LBasicBlock isCellCase = FTL_NEW_BLOCK(m_out, ("ToThis is cell case"));
995        LBasicBlock slowCase = FTL_NEW_BLOCK(m_out, ("ToThis slow case"));
996        LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("ToThis continuation"));
997
998        m_out.branch(isCell(value), usually(isCellCase), rarely(slowCase));
999
1000        LBasicBlock lastNext = m_out.appendTo(isCellCase, slowCase);
1001        ValueFromBlock fastResult = m_out.anchor(value);
1002        m_out.branch(isType(value, FinalObjectType), usually(continuation), rarely(slowCase));
1003
1004        m_out.appendTo(slowCase, continuation);
1005        J_JITOperation_EJ function;
1006        if (m_graph.isStrictModeFor(m_node->origin.semantic))
1007            function = operationToThisStrict;
1008        else
1009            function = operationToThis;
1010        ValueFromBlock slowResult = m_out.anchor(
1011            vmCall(m_out.operation(function), m_callFrame, value));
1012        m_out.jump(continuation);
1013
1014        m_out.appendTo(continuation, lastNext);
1015        setJSValue(m_out.phi(m_out.int64, fastResult, slowResult));
1016    }
1017
1018    void compileValueAdd()
1019    {
1020        J_JITOperation_EJJ operation;
1021        if (!(m_state.forNode(m_node->child1()).m_type & SpecFullNumber)
1022            && !(m_state.forNode(m_node->child2()).m_type & SpecFullNumber))
1023            operation = operationValueAddNotNumber;
1024        else
1025            operation = operationValueAdd;
1026        setJSValue(vmCall(
1027            m_out.operation(operation), m_callFrame,
1028            lowJSValue(m_node->child1()), lowJSValue(m_node->child2())));
1029    }
1030
1031    void compileArithAddOrSub()
1032    {
1033        bool isSub =  m_node->op() == ArithSub;
1034        switch (m_node->binaryUseKind()) {
1035        case Int32Use: {
1036            LValue left = lowInt32(m_node->child1());
1037            LValue right = lowInt32(m_node->child2());
1038
1039            if (!shouldCheckOverflow(m_node->arithMode())) {
1040                setInt32(isSub ? m_out.sub(left, right) : m_out.add(left, right));
1041                break;
1042            }
1043
1044            LValue result;
1045            if (!isSub) {
1046                result = m_out.addWithOverflow32(left, right);
1047
1048                if (doesKill(m_node->child2())) {
1049                    addAvailableRecovery(
1050                        m_node->child2(), SubRecovery,
1051                        m_out.extractValue(result, 0), left, ValueFormatInt32);
1052                } else if (doesKill(m_node->child1())) {
1053                    addAvailableRecovery(
1054                        m_node->child1(), SubRecovery,
1055                        m_out.extractValue(result, 0), right, ValueFormatInt32);
1056                }
1057            } else {
1058                result = m_out.subWithOverflow32(left, right);
1059
1060                if (doesKill(m_node->child2())) {
1061                    // result = left - right
1062                    // result - left = -right
1063                    // right = left - result
1064                    addAvailableRecovery(
1065                        m_node->child2(), SubRecovery,
1066                        left, m_out.extractValue(result, 0), ValueFormatInt32);
1067                } else if (doesKill(m_node->child1())) {
1068                    // result = left - right
1069                    // result + right = left
1070                    addAvailableRecovery(
1071                        m_node->child1(), AddRecovery,
1072                        m_out.extractValue(result, 0), right, ValueFormatInt32);
1073                }
1074            }
1075
1076            speculate(Overflow, noValue(), 0, m_out.extractValue(result, 1));
1077            setInt32(m_out.extractValue(result, 0));
1078            break;
1079        }
1080
1081        case Int52RepUse: {
1082            if (!m_state.forNode(m_node->child1()).couldBeType(SpecInt52)
1083                && !m_state.forNode(m_node->child2()).couldBeType(SpecInt52)) {
1084                Int52Kind kind;
1085                LValue left = lowWhicheverInt52(m_node->child1(), kind);
1086                LValue right = lowInt52(m_node->child2(), kind);
1087                setInt52(isSub ? m_out.sub(left, right) : m_out.add(left, right), kind);
1088                break;
1089            }
1090
1091            LValue left = lowInt52(m_node->child1());
1092            LValue right = lowInt52(m_node->child2());
1093
1094            LValue result;
1095            if (!isSub) {
1096                result = m_out.addWithOverflow64(left, right);
1097
1098                if (doesKill(m_node->child2())) {
1099                    addAvailableRecovery(
1100                        m_node->child2(), SubRecovery,
1101                        m_out.extractValue(result, 0), left, ValueFormatInt52);
1102                } else if (doesKill(m_node->child1())) {
1103                    addAvailableRecovery(
1104                        m_node->child1(), SubRecovery,
1105                        m_out.extractValue(result, 0), right, ValueFormatInt52);
1106                }
1107            } else {
1108                result = m_out.subWithOverflow64(left, right);
1109
1110                if (doesKill(m_node->child2())) {
1111                    // result = left - right
1112                    // result - left = -right
1113                    // right = left - result
1114                    addAvailableRecovery(
1115                        m_node->child2(), SubRecovery,
1116                        left, m_out.extractValue(result, 0), ValueFormatInt52);
1117                } else if (doesKill(m_node->child1())) {
1118                    // result = left - right
1119                    // result + right = left
1120                    addAvailableRecovery(
1121                        m_node->child1(), AddRecovery,
1122                        m_out.extractValue(result, 0), right, ValueFormatInt52);
1123                }
1124            }
1125
1126            speculate(Int52Overflow, noValue(), 0, m_out.extractValue(result, 1));
1127            setInt52(m_out.extractValue(result, 0));
1128            break;
1129        }
1130
1131        case DoubleRepUse: {
1132            LValue C1 = lowDouble(m_node->child1());
1133            LValue C2 = lowDouble(m_node->child2());
1134
1135            setDouble(isSub ? m_out.doubleSub(C1, C2) : m_out.doubleAdd(C1, C2));
1136            break;
1137        }
1138
1139        default:
1140            RELEASE_ASSERT_NOT_REACHED();
1141            break;
1142        }
1143    }
1144
1145    void compileArithMul()
1146    {
1147        switch (m_node->binaryUseKind()) {
1148        case Int32Use: {
1149            LValue left = lowInt32(m_node->child1());
1150            LValue right = lowInt32(m_node->child2());
1151
1152            LValue result;
1153
1154            if (!shouldCheckOverflow(m_node->arithMode()))
1155                result = m_out.mul(left, right);
1156            else {
1157                LValue overflowResult = m_out.mulWithOverflow32(left, right);
1158                speculate(Overflow, noValue(), 0, m_out.extractValue(overflowResult, 1));
1159                result = m_out.extractValue(overflowResult, 0);
1160            }
1161
1162            if (shouldCheckNegativeZero(m_node->arithMode())) {
1163                LBasicBlock slowCase = FTL_NEW_BLOCK(m_out, ("ArithMul slow case"));
1164                LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("ArithMul continuation"));
1165
1166                m_out.branch(
1167                    m_out.notZero32(result), usually(continuation), rarely(slowCase));
1168
1169                LBasicBlock lastNext = m_out.appendTo(slowCase, continuation);
1170                LValue cond = m_out.bitOr(m_out.lessThan(left, m_out.int32Zero), m_out.lessThan(right, m_out.int32Zero));
1171                speculate(NegativeZero, noValue(), 0, cond);
1172                m_out.jump(continuation);
1173                m_out.appendTo(continuation, lastNext);
1174            }
1175
1176            setInt32(result);
1177            break;
1178        }
1179
1180        case Int52RepUse: {
1181            Int52Kind kind;
1182            LValue left = lowWhicheverInt52(m_node->child1(), kind);
1183            LValue right = lowInt52(m_node->child2(), opposite(kind));
1184
1185            LValue overflowResult = m_out.mulWithOverflow64(left, right);
1186            speculate(Int52Overflow, noValue(), 0, m_out.extractValue(overflowResult, 1));
1187            LValue result = m_out.extractValue(overflowResult, 0);
1188
1189            if (shouldCheckNegativeZero(m_node->arithMode())) {
1190                LBasicBlock slowCase = FTL_NEW_BLOCK(m_out, ("ArithMul slow case"));
1191                LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("ArithMul continuation"));
1192
1193                m_out.branch(
1194                    m_out.notZero64(result), usually(continuation), rarely(slowCase));
1195
1196                LBasicBlock lastNext = m_out.appendTo(slowCase, continuation);
1197                LValue cond = m_out.bitOr(m_out.lessThan(left, m_out.int64Zero), m_out.lessThan(right, m_out.int64Zero));
1198                speculate(NegativeZero, noValue(), 0, cond);
1199                m_out.jump(continuation);
1200                m_out.appendTo(continuation, lastNext);
1201            }
1202
1203            setInt52(result);
1204            break;
1205        }
1206
1207        case DoubleRepUse: {
1208            setDouble(
1209                m_out.doubleMul(lowDouble(m_node->child1()), lowDouble(m_node->child2())));
1210            break;
1211        }
1212
1213        default:
1214            RELEASE_ASSERT_NOT_REACHED();
1215            break;
1216        }
1217    }
1218
1219    void compileArithDiv()
1220    {
1221        switch (m_node->binaryUseKind()) {
1222        case Int32Use: {
1223            LValue numerator = lowInt32(m_node->child1());
1224            LValue denominator = lowInt32(m_node->child2());
1225
1226            LBasicBlock unsafeDenominator = FTL_NEW_BLOCK(m_out, ("ArithDiv unsafe denominator"));
1227            LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("ArithDiv continuation"));
1228            LBasicBlock done = FTL_NEW_BLOCK(m_out, ("ArithDiv done"));
1229
1230            Vector<ValueFromBlock, 3> results;
1231
1232            LValue adjustedDenominator = m_out.add(denominator, m_out.int32One);
1233
1234            m_out.branch(
1235                m_out.above(adjustedDenominator, m_out.int32One),
1236                usually(continuation), rarely(unsafeDenominator));
1237
1238            LBasicBlock lastNext = m_out.appendTo(unsafeDenominator, continuation);
1239
1240            LValue neg2ToThe31 = m_out.constInt32(-2147483647-1);
1241
1242            if (shouldCheckOverflow(m_node->arithMode())) {
1243                LValue cond = m_out.bitOr(m_out.isZero32(denominator), m_out.equal(numerator, neg2ToThe31));
1244                speculate(Overflow, noValue(), 0, cond);
1245                m_out.jump(continuation);
1246            } else {
1247                // This is the case where we convert the result to an int after we're done. So,
1248                // if the denominator is zero, then the result should be zero.
1249                // If the denominator is not zero (i.e. it's -1 because we're guarded by the
1250                // check above) and the numerator is -2^31 then the result should be -2^31.
1251
1252                LBasicBlock divByZero = FTL_NEW_BLOCK(m_out, ("ArithDiv divide by zero"));
1253                LBasicBlock notDivByZero = FTL_NEW_BLOCK(m_out, ("ArithDiv not divide by zero"));
1254                LBasicBlock neg2ToThe31ByNeg1 = FTL_NEW_BLOCK(m_out, ("ArithDiv -2^31/-1"));
1255
1256                m_out.branch(
1257                    m_out.isZero32(denominator), rarely(divByZero), usually(notDivByZero));
1258
1259                m_out.appendTo(divByZero, notDivByZero);
1260                results.append(m_out.anchor(m_out.int32Zero));
1261                m_out.jump(done);
1262
1263                m_out.appendTo(notDivByZero, neg2ToThe31ByNeg1);
1264                m_out.branch(
1265                    m_out.equal(numerator, neg2ToThe31),
1266                    rarely(neg2ToThe31ByNeg1), usually(continuation));
1267
1268                m_out.appendTo(neg2ToThe31ByNeg1, continuation);
1269                results.append(m_out.anchor(neg2ToThe31));
1270                m_out.jump(done);
1271            }
1272
1273            m_out.appendTo(continuation, done);
1274
1275            if (shouldCheckNegativeZero(m_node->arithMode())) {
1276                LBasicBlock zeroNumerator = FTL_NEW_BLOCK(m_out, ("ArithDiv zero numerator"));
1277                LBasicBlock numeratorContinuation = FTL_NEW_BLOCK(m_out, ("ArithDiv numerator continuation"));
1278
1279                m_out.branch(
1280                    m_out.isZero32(numerator),
1281                    rarely(zeroNumerator), usually(numeratorContinuation));
1282
1283                LBasicBlock innerLastNext = m_out.appendTo(zeroNumerator, numeratorContinuation);
1284
1285                speculate(
1286                    NegativeZero, noValue(), 0, m_out.lessThan(denominator, m_out.int32Zero));
1287
1288                m_out.jump(numeratorContinuation);
1289
1290                m_out.appendTo(numeratorContinuation, innerLastNext);
1291            }
1292
1293            LValue result = m_out.div(numerator, denominator);
1294
1295            if (shouldCheckOverflow(m_node->arithMode())) {
1296                speculate(
1297                    Overflow, noValue(), 0,
1298                    m_out.notEqual(m_out.mul(result, denominator), numerator));
1299            }
1300
1301            results.append(m_out.anchor(result));
1302            m_out.jump(done);
1303
1304            m_out.appendTo(done, lastNext);
1305
1306            setInt32(m_out.phi(m_out.int32, results));
1307            break;
1308        }
1309
1310        case DoubleRepUse: {
1311            setDouble(m_out.doubleDiv(
1312                lowDouble(m_node->child1()), lowDouble(m_node->child2())));
1313            break;
1314        }
1315
1316        default:
1317            RELEASE_ASSERT_NOT_REACHED();
1318            break;
1319        }
1320    }
1321
1322    void compileArithMod()
1323    {
1324        switch (m_node->binaryUseKind()) {
1325        case Int32Use: {
1326            LValue numerator = lowInt32(m_node->child1());
1327            LValue denominator = lowInt32(m_node->child2());
1328
1329            LBasicBlock unsafeDenominator = FTL_NEW_BLOCK(m_out, ("ArithMod unsafe denominator"));
1330            LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("ArithMod continuation"));
1331            LBasicBlock done = FTL_NEW_BLOCK(m_out, ("ArithMod done"));
1332
1333            Vector<ValueFromBlock, 3> results;
1334
1335            LValue adjustedDenominator = m_out.add(denominator, m_out.int32One);
1336
1337            m_out.branch(
1338                m_out.above(adjustedDenominator, m_out.int32One),
1339                usually(continuation), rarely(unsafeDenominator));
1340
1341            LBasicBlock lastNext = m_out.appendTo(unsafeDenominator, continuation);
1342
1343            LValue neg2ToThe31 = m_out.constInt32(-2147483647-1);
1344
1345            // FIXME: -2^31 / -1 will actually yield negative zero, so we could have a
1346            // separate case for that. But it probably doesn't matter so much.
1347            if (shouldCheckOverflow(m_node->arithMode())) {
1348                LValue cond = m_out.bitOr(m_out.isZero32(denominator), m_out.equal(numerator, neg2ToThe31));
1349                speculate(Overflow, noValue(), 0, cond);
1350                m_out.jump(continuation);
1351            } else {
1352                // This is the case where we convert the result to an int after we're done. So,
1353                // if the denominator is zero, then the result should be result should be zero.
1354                // If the denominator is not zero (i.e. it's -1 because we're guarded by the
1355                // check above) and the numerator is -2^31 then the result should be -2^31.
1356
1357                LBasicBlock modByZero = FTL_NEW_BLOCK(m_out, ("ArithMod modulo by zero"));
1358                LBasicBlock notModByZero = FTL_NEW_BLOCK(m_out, ("ArithMod not modulo by zero"));
1359                LBasicBlock neg2ToThe31ByNeg1 = FTL_NEW_BLOCK(m_out, ("ArithMod -2^31/-1"));
1360
1361                m_out.branch(
1362                    m_out.isZero32(denominator), rarely(modByZero), usually(notModByZero));
1363
1364                m_out.appendTo(modByZero, notModByZero);
1365                results.append(m_out.anchor(m_out.int32Zero));
1366                m_out.jump(done);
1367
1368                m_out.appendTo(notModByZero, neg2ToThe31ByNeg1);
1369                m_out.branch(
1370                    m_out.equal(numerator, neg2ToThe31),
1371                    rarely(neg2ToThe31ByNeg1), usually(continuation));
1372
1373                m_out.appendTo(neg2ToThe31ByNeg1, continuation);
1374                results.append(m_out.anchor(m_out.int32Zero));
1375                m_out.jump(done);
1376            }
1377
1378            m_out.appendTo(continuation, done);
1379
1380            LValue remainder = m_out.rem(numerator, denominator);
1381
1382            if (shouldCheckNegativeZero(m_node->arithMode())) {
1383                LBasicBlock negativeNumerator = FTL_NEW_BLOCK(m_out, ("ArithMod negative numerator"));
1384                LBasicBlock numeratorContinuation = FTL_NEW_BLOCK(m_out, ("ArithMod numerator continuation"));
1385
1386                m_out.branch(
1387                    m_out.lessThan(numerator, m_out.int32Zero),
1388                    unsure(negativeNumerator), unsure(numeratorContinuation));
1389
1390                LBasicBlock innerLastNext = m_out.appendTo(negativeNumerator, numeratorContinuation);
1391
1392                speculate(NegativeZero, noValue(), 0, m_out.isZero32(remainder));
1393
1394                m_out.jump(numeratorContinuation);
1395
1396                m_out.appendTo(numeratorContinuation, innerLastNext);
1397            }
1398
1399            results.append(m_out.anchor(remainder));
1400            m_out.jump(done);
1401
1402            m_out.appendTo(done, lastNext);
1403
1404            setInt32(m_out.phi(m_out.int32, results));
1405            break;
1406        }
1407
1408        case DoubleRepUse: {
1409            setDouble(
1410                m_out.doubleRem(lowDouble(m_node->child1()), lowDouble(m_node->child2())));
1411            break;
1412        }
1413
1414        default:
1415            RELEASE_ASSERT_NOT_REACHED();
1416            break;
1417        }
1418    }
1419
1420    void compileArithMinOrMax()
1421    {
1422        switch (m_node->binaryUseKind()) {
1423        case Int32Use: {
1424            LValue left = lowInt32(m_node->child1());
1425            LValue right = lowInt32(m_node->child2());
1426
1427            setInt32(
1428                m_out.select(
1429                    m_node->op() == ArithMin
1430                        ? m_out.lessThan(left, right)
1431                        : m_out.lessThan(right, left),
1432                    left, right));
1433            break;
1434        }
1435
1436        case DoubleRepUse: {
1437            LValue left = lowDouble(m_node->child1());
1438            LValue right = lowDouble(m_node->child2());
1439
1440            LBasicBlock notLessThan = FTL_NEW_BLOCK(m_out, ("ArithMin/ArithMax not less than"));
1441            LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("ArithMin/ArithMax continuation"));
1442
1443            Vector<ValueFromBlock, 2> results;
1444
1445            results.append(m_out.anchor(left));
1446            m_out.branch(
1447                m_node->op() == ArithMin
1448                    ? m_out.doubleLessThan(left, right)
1449                    : m_out.doubleGreaterThan(left, right),
1450                unsure(continuation), unsure(notLessThan));
1451
1452            LBasicBlock lastNext = m_out.appendTo(notLessThan, continuation);
1453            results.append(m_out.anchor(m_out.select(
1454                m_node->op() == ArithMin
1455                    ? m_out.doubleGreaterThanOrEqual(left, right)
1456                    : m_out.doubleLessThanOrEqual(left, right),
1457                right, m_out.constDouble(PNaN))));
1458            m_out.jump(continuation);
1459
1460            m_out.appendTo(continuation, lastNext);
1461            setDouble(m_out.phi(m_out.doubleType, results));
1462            break;
1463        }
1464
1465        default:
1466            RELEASE_ASSERT_NOT_REACHED();
1467            break;
1468        }
1469    }
1470
1471    void compileArithAbs()
1472    {
1473        switch (m_node->child1().useKind()) {
1474        case Int32Use: {
1475            LValue value = lowInt32(m_node->child1());
1476
1477            LValue mask = m_out.aShr(value, m_out.constInt32(31));
1478            LValue result = m_out.bitXor(mask, m_out.add(mask, value));
1479
1480            speculate(Overflow, noValue(), 0, m_out.equal(result, m_out.constInt32(1 << 31)));
1481
1482            setInt32(result);
1483            break;
1484        }
1485
1486        case DoubleRepUse: {
1487            setDouble(m_out.doubleAbs(lowDouble(m_node->child1())));
1488            break;
1489        }
1490
1491        default:
1492            RELEASE_ASSERT_NOT_REACHED();
1493            break;
1494        }
1495    }
1496
1497    void compileArithSin() { setDouble(m_out.doubleSin(lowDouble(m_node->child1()))); }
1498
1499    void compileArithCos() { setDouble(m_out.doubleCos(lowDouble(m_node->child1()))); }
1500
1501    void compileArithSqrt() { setDouble(m_out.doubleSqrt(lowDouble(m_node->child1()))); }
1502
1503    void compileArithFRound()
1504    {
1505        LValue floatValue = m_out.fpCast(lowDouble(m_node->child1()), m_out.floatType);
1506        setDouble(m_out.fpCast(floatValue, m_out.doubleType));
1507    }
1508
1509    void compileArithNegate()
1510    {
1511        switch (m_node->child1().useKind()) {
1512        case Int32Use: {
1513            LValue value = lowInt32(m_node->child1());
1514
1515            LValue result;
1516            if (!shouldCheckOverflow(m_node->arithMode()))
1517                result = m_out.neg(value);
1518            else if (!shouldCheckNegativeZero(m_node->arithMode())) {
1519                // We don't have a negate-with-overflow intrinsic. Hopefully this
1520                // does the trick, though.
1521                LValue overflowResult = m_out.subWithOverflow32(m_out.int32Zero, value);
1522                speculate(Overflow, noValue(), 0, m_out.extractValue(overflowResult, 1));
1523                result = m_out.extractValue(overflowResult, 0);
1524            } else {
1525                speculate(Overflow, noValue(), 0, m_out.testIsZero32(value, m_out.constInt32(0x7fffffff)));
1526                result = m_out.neg(value);
1527            }
1528
1529            setInt32(result);
1530            break;
1531        }
1532
1533        case Int52RepUse: {
1534            if (!m_state.forNode(m_node->child1()).couldBeType(SpecInt52)) {
1535                Int52Kind kind;
1536                LValue value = lowWhicheverInt52(m_node->child1(), kind);
1537                LValue result = m_out.neg(value);
1538                if (shouldCheckNegativeZero(m_node->arithMode()))
1539                    speculate(NegativeZero, noValue(), 0, m_out.isZero64(result));
1540                setInt52(result, kind);
1541                break;
1542            }
1543
1544            LValue value = lowInt52(m_node->child1());
1545            LValue overflowResult = m_out.subWithOverflow64(m_out.int64Zero, value);
1546            speculate(Int52Overflow, noValue(), 0, m_out.extractValue(overflowResult, 1));
1547            LValue result = m_out.extractValue(overflowResult, 0);
1548            speculate(NegativeZero, noValue(), 0, m_out.isZero64(result));
1549            setInt52(result);
1550            break;
1551        }
1552
1553        case DoubleRepUse: {
1554            setDouble(m_out.doubleNeg(lowDouble(m_node->child1())));
1555            break;
1556        }
1557
1558        default:
1559            RELEASE_ASSERT_NOT_REACHED();
1560            break;
1561        }
1562    }
1563
1564    void compileBitAnd()
1565    {
1566        setInt32(m_out.bitAnd(lowInt32(m_node->child1()), lowInt32(m_node->child2())));
1567    }
1568
1569    void compileBitOr()
1570    {
1571        setInt32(m_out.bitOr(lowInt32(m_node->child1()), lowInt32(m_node->child2())));
1572    }
1573
1574    void compileBitXor()
1575    {
1576        setInt32(m_out.bitXor(lowInt32(m_node->child1()), lowInt32(m_node->child2())));
1577    }
1578
1579    void compileBitRShift()
1580    {
1581        setInt32(m_out.aShr(
1582            lowInt32(m_node->child1()),
1583            m_out.bitAnd(lowInt32(m_node->child2()), m_out.constInt32(31))));
1584    }
1585
1586    void compileBitLShift()
1587    {
1588        setInt32(m_out.shl(
1589            lowInt32(m_node->child1()),
1590            m_out.bitAnd(lowInt32(m_node->child2()), m_out.constInt32(31))));
1591    }
1592
1593    void compileBitURShift()
1594    {
1595        setInt32(m_out.lShr(
1596            lowInt32(m_node->child1()),
1597            m_out.bitAnd(lowInt32(m_node->child2()), m_out.constInt32(31))));
1598    }
1599
1600    void compileUInt32ToNumber()
1601    {
1602        LValue value = lowInt32(m_node->child1());
1603
1604        if (doesOverflow(m_node->arithMode())) {
1605            setDouble(m_out.unsignedToDouble(value));
1606            return;
1607        }
1608
1609        speculate(Overflow, noValue(), 0, m_out.lessThan(value, m_out.int32Zero));
1610        setInt32(value);
1611    }
1612
1613    void compileCheckStructure()
1614    {
1615        LValue cell = lowCell(m_node->child1());
1616
1617        ExitKind exitKind;
1618        if (m_node->child1()->op() == WeakJSConstant)
1619            exitKind = BadWeakConstantCache;
1620        else
1621            exitKind = BadCache;
1622
1623        LValue structureID = m_out.load32(cell, m_heaps.JSCell_structureID);
1624
1625        if (m_node->structureSet().size() == 1) {
1626            speculate(
1627                exitKind, jsValueValue(cell), 0,
1628                m_out.notEqual(structureID, weakStructure(m_node->structureSet()[0])));
1629            return;
1630        }
1631
1632        LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("CheckStructure continuation"));
1633
1634        LBasicBlock lastNext = m_out.insertNewBlocksBefore(continuation);
1635        for (unsigned i = 0; i < m_node->structureSet().size() - 1; ++i) {
1636            LBasicBlock nextStructure = FTL_NEW_BLOCK(m_out, ("CheckStructure nextStructure"));
1637            m_out.branch(
1638                m_out.equal(structureID, weakStructure(m_node->structureSet()[i])),
1639                unsure(continuation), unsure(nextStructure));
1640            m_out.appendTo(nextStructure);
1641        }
1642
1643        speculate(
1644            exitKind, jsValueValue(cell), 0,
1645            m_out.notEqual(structureID, weakStructure(m_node->structureSet().last())));
1646
1647        m_out.jump(continuation);
1648        m_out.appendTo(continuation, lastNext);
1649    }
1650
1651    void compileStructureTransitionWatchpoint()
1652    {
1653        addWeakReference(m_node->structure());
1654        speculateCell(m_node->child1());
1655    }
1656
1657    void compileCheckFunction()
1658    {
1659        LValue cell = lowCell(m_node->child1());
1660
1661        speculate(
1662            BadFunction, jsValueValue(cell), m_node->child1().node(),
1663            m_out.notEqual(cell, weakPointer(m_node->function())));
1664    }
1665
1666    void compileCheckExecutable()
1667    {
1668        LValue cell = lowCell(m_node->child1());
1669
1670        speculate(
1671            BadExecutable, jsValueValue(cell), m_node->child1().node(),
1672            m_out.notEqual(
1673                m_out.loadPtr(cell, m_heaps.JSFunction_executable),
1674                weakPointer(m_node->executable())));
1675    }
1676
1677    void compileArrayifyToStructure()
1678    {
1679        LValue cell = lowCell(m_node->child1());
1680        LValue property = !!m_node->child2() ? lowInt32(m_node->child2()) : 0;
1681
1682        LBasicBlock unexpectedStructure = FTL_NEW_BLOCK(m_out, ("ArrayifyToStructure unexpected structure"));
1683        LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("ArrayifyToStructure continuation"));
1684
1685        LValue structureID = m_out.load32(cell, m_heaps.JSCell_structureID);
1686
1687        m_out.branch(
1688            m_out.notEqual(structureID, weakStructure(m_node->structure())),
1689            rarely(unexpectedStructure), usually(continuation));
1690
1691        LBasicBlock lastNext = m_out.appendTo(unexpectedStructure, continuation);
1692
1693        if (property) {
1694            switch (m_node->arrayMode().type()) {
1695            case Array::Int32:
1696            case Array::Double:
1697            case Array::Contiguous:
1698                speculate(
1699                    Uncountable, noValue(), 0,
1700                    m_out.aboveOrEqual(property, m_out.constInt32(MIN_SPARSE_ARRAY_INDEX)));
1701                break;
1702            default:
1703                break;
1704            }
1705        }
1706
1707        switch (m_node->arrayMode().type()) {
1708        case Array::Int32:
1709            vmCall(m_out.operation(operationEnsureInt32), m_callFrame, cell);
1710            break;
1711        case Array::Double:
1712            vmCall(m_out.operation(operationEnsureDouble), m_callFrame, cell);
1713            break;
1714        case Array::Contiguous:
1715            if (m_node->arrayMode().conversion() == Array::RageConvert)
1716                vmCall(m_out.operation(operationRageEnsureContiguous), m_callFrame, cell);
1717            else
1718                vmCall(m_out.operation(operationEnsureContiguous), m_callFrame, cell);
1719            break;
1720        case Array::ArrayStorage:
1721        case Array::SlowPutArrayStorage:
1722            vmCall(m_out.operation(operationEnsureArrayStorage), m_callFrame, cell);
1723            break;
1724        default:
1725            RELEASE_ASSERT_NOT_REACHED();
1726            break;
1727        }
1728
1729        structureID = m_out.load32(cell, m_heaps.JSCell_structureID);
1730        speculate(
1731            BadIndexingType, jsValueValue(cell), 0,
1732            m_out.notEqual(structureID, weakStructure(m_node->structure())));
1733        m_out.jump(continuation);
1734
1735        m_out.appendTo(continuation, lastNext);
1736    }
1737
1738    void compilePutStructure()
1739    {
1740        m_ftlState.jitCode->common.notifyCompilingStructureTransition(m_graph.m_plan, codeBlock(), m_node);
1741
1742        Structure* oldStructure = m_node->structureTransitionData().previousStructure;
1743        Structure* newStructure = m_node->structureTransitionData().newStructure;
1744        ASSERT_UNUSED(oldStructure, oldStructure->indexingType() == newStructure->indexingType());
1745        ASSERT(oldStructure->typeInfo().inlineTypeFlags() == newStructure->typeInfo().inlineTypeFlags());
1746        ASSERT(oldStructure->typeInfo().type() == newStructure->typeInfo().type());
1747
1748        LValue cell = lowCell(m_node->child1());
1749        m_out.store32(
1750            weakStructure(newStructure),
1751            cell, m_heaps.JSCell_structureID);
1752    }
1753
1754    void compilePhantomPutStructure()
1755    {
1756        m_ftlState.jitCode->common.notifyCompilingStructureTransition(m_graph.m_plan, codeBlock(), m_node);
1757    }
1758
1759    void compileGetById()
1760    {
1761        // Pretty much the only reason why we don't also support GetByIdFlush is because:
1762        // https://bugs.webkit.org/show_bug.cgi?id=125711
1763
1764        switch (m_node->child1().useKind()) {
1765        case CellUse: {
1766            setJSValue(getById(lowCell(m_node->child1())));
1767            return;
1768        }
1769
1770        case UntypedUse: {
1771            // This is pretty weird, since we duplicate the slow path both here and in the
1772            // code generated by the IC. We should investigate making this less bad.
1773            // https://bugs.webkit.org/show_bug.cgi?id=127830
1774            LValue value = lowJSValue(m_node->child1());
1775
1776            LBasicBlock cellCase = FTL_NEW_BLOCK(m_out, ("GetById untyped cell case"));
1777            LBasicBlock notCellCase = FTL_NEW_BLOCK(m_out, ("GetById untyped not cell case"));
1778            LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("GetById untyped continuation"));
1779
1780            m_out.branch(isCell(value), unsure(cellCase), unsure(notCellCase));
1781
1782            LBasicBlock lastNext = m_out.appendTo(cellCase, notCellCase);
1783            ValueFromBlock cellResult = m_out.anchor(getById(value));
1784            m_out.jump(continuation);
1785
1786            m_out.appendTo(notCellCase, continuation);
1787            ValueFromBlock notCellResult = m_out.anchor(vmCall(
1788                m_out.operation(operationGetById),
1789                m_callFrame, getUndef(m_out.intPtr), value,
1790                m_out.constIntPtr(m_graph.identifiers()[m_node->identifierNumber()])));
1791            m_out.jump(continuation);
1792
1793            m_out.appendTo(continuation, lastNext);
1794            setJSValue(m_out.phi(m_out.int64, cellResult, notCellResult));
1795            return;
1796        }
1797
1798        default:
1799            RELEASE_ASSERT_NOT_REACHED();
1800            return;
1801        }
1802    }
1803
1804    void compilePutById()
1805    {
1806        // See above; CellUse is easier so we do only that for now.
1807        ASSERT(m_node->child1().useKind() == CellUse);
1808
1809        LValue base = lowCell(m_node->child1());
1810        LValue value = lowJSValue(m_node->child2());
1811        StringImpl* uid = m_graph.identifiers()[m_node->identifierNumber()];
1812
1813        // Arguments: id, bytes, target, numArgs, args...
1814        unsigned stackmapID = m_stackmapIDs++;
1815
1816        if (Options::verboseCompilation())
1817            dataLog("    Emitting PutById patchpoint with stackmap #", stackmapID, "\n");
1818
1819        LValue call = m_out.call(
1820            m_out.patchpointVoidIntrinsic(),
1821            m_out.constInt64(stackmapID), m_out.constInt32(sizeOfPutById()),
1822            constNull(m_out.ref8), m_out.constInt32(2), base, value);
1823        setInstructionCallingConvention(call, LLVMAnyRegCallConv);
1824
1825        m_ftlState.putByIds.append(PutByIdDescriptor(
1826            stackmapID, m_node->origin.semantic, uid,
1827            m_graph.executableFor(m_node->origin.semantic)->ecmaMode(),
1828            m_node->op() == PutByIdDirect ? Direct : NotDirect));
1829    }
1830
1831    void compileGetButterfly()
1832    {
1833        setStorage(m_out.loadPtr(lowCell(m_node->child1()), m_heaps.JSObject_butterfly));
1834    }
1835
1836    void compileConstantStoragePointer()
1837    {
1838        setStorage(m_out.constIntPtr(m_node->storagePointer()));
1839    }
1840
1841    void compileGetIndexedPropertyStorage()
1842    {
1843        LValue cell = lowCell(m_node->child1());
1844
1845        if (m_node->arrayMode().type() == Array::String) {
1846            LBasicBlock slowPath = FTL_NEW_BLOCK(m_out, ("GetIndexedPropertyStorage String slow case"));
1847            LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("GetIndexedPropertyStorage String continuation"));
1848
1849            ValueFromBlock fastResult = m_out.anchor(
1850                m_out.loadPtr(cell, m_heaps.JSString_value));
1851
1852            m_out.branch(
1853                m_out.notNull(fastResult.value()), usually(continuation), rarely(slowPath));
1854
1855            LBasicBlock lastNext = m_out.appendTo(slowPath, continuation);
1856
1857            ValueFromBlock slowResult = m_out.anchor(
1858                vmCall(m_out.operation(operationResolveRope), m_callFrame, cell));
1859
1860            m_out.jump(continuation);
1861
1862            m_out.appendTo(continuation, lastNext);
1863
1864            setStorage(m_out.loadPtr(m_out.phi(m_out.intPtr, fastResult, slowResult), m_heaps.StringImpl_data));
1865            return;
1866        }
1867
1868        setStorage(m_out.loadPtr(cell, m_heaps.JSArrayBufferView_vector));
1869    }
1870
1871    void compileCheckArray()
1872    {
1873        Edge edge = m_node->child1();
1874        LValue cell = lowCell(edge);
1875
1876        if (m_node->arrayMode().alreadyChecked(m_graph, m_node, m_state.forNode(edge)))
1877            return;
1878
1879        speculate(
1880            BadIndexingType, jsValueValue(cell), 0,
1881            m_out.bitNot(isArrayType(cell, m_node->arrayMode())));
1882    }
1883
1884    void compileGetTypedArrayByteOffset()
1885    {
1886        LValue basePtr = lowCell(m_node->child1());
1887
1888        LBasicBlock simpleCase = FTL_NEW_BLOCK(m_out, ("wasteless typed array"));
1889        LBasicBlock wastefulCase = FTL_NEW_BLOCK(m_out, ("wasteful typed array"));
1890        LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("continuation branch"));
1891
1892        LValue baseAddress = m_out.addPtr(basePtr, JSArrayBufferView::offsetOfMode());
1893        m_out.branch(
1894            m_out.notEqual(baseAddress , m_out.constIntPtr(WastefulTypedArray)),
1895            unsure(simpleCase), unsure(wastefulCase));
1896
1897        // begin simple case
1898        LBasicBlock lastNext = m_out.appendTo(simpleCase, wastefulCase);
1899
1900        ValueFromBlock simpleOut = m_out.anchor(m_out.constIntPtr(0));
1901
1902        m_out.jump(continuation);
1903
1904        // begin wasteful case
1905        m_out.appendTo(wastefulCase, continuation);
1906
1907        LValue vectorPtr = m_out.loadPtr(basePtr, m_heaps.JSArrayBufferView_vector);
1908        LValue butterflyPtr = m_out.loadPtr(basePtr, m_heaps.JSObject_butterfly);
1909        LValue arrayBufferPtr = m_out.loadPtr(butterflyPtr, m_heaps.Butterfly_arrayBuffer);
1910        LValue dataPtr = m_out.loadPtr(arrayBufferPtr, m_heaps.ArrayBuffer_data);
1911
1912        ValueFromBlock wastefulOut = m_out.anchor(m_out.sub(dataPtr, vectorPtr));
1913
1914        m_out.jump(continuation);
1915        m_out.appendTo(continuation, lastNext);
1916
1917        // output
1918        setInt32(m_out.castToInt32(m_out.phi(m_out.intPtr, simpleOut, wastefulOut)));
1919    }
1920
1921    void compileGetMyArgumentsLength()
1922    {
1923        checkArgumentsNotCreated();
1924
1925        RELEASE_ASSERT(!m_node->origin.semantic.inlineCallFrame);
1926        setInt32(m_out.add(m_out.load32NonNegative(payloadFor(JSStack::ArgumentCount)), m_out.constInt32(-1)));
1927    }
1928
1929    void compileGetMyArgumentByVal()
1930    {
1931        checkArgumentsNotCreated();
1932
1933        CodeOrigin codeOrigin = m_node->origin.semantic;
1934
1935        LValue zeroBasedIndex = lowInt32(m_node->child1());
1936        LValue oneBasedIndex = m_out.add(zeroBasedIndex, m_out.int32One);
1937
1938        LValue limit;
1939        if (codeOrigin.inlineCallFrame)
1940            limit = m_out.constInt32(codeOrigin.inlineCallFrame->arguments.size());
1941        else
1942            limit = m_out.load32(payloadFor(JSStack::ArgumentCount));
1943
1944        speculate(Uncountable, noValue(), 0, m_out.aboveOrEqual(oneBasedIndex, limit));
1945
1946        SymbolTable* symbolTable = m_graph.baselineCodeBlockFor(codeOrigin)->symbolTable();
1947        if (symbolTable->slowArguments()) {
1948            // FIXME: FTL should support activations.
1949            // https://bugs.webkit.org/show_bug.cgi?id=129576
1950
1951            RELEASE_ASSERT_NOT_REACHED();
1952        }
1953
1954        TypedPointer base;
1955        if (codeOrigin.inlineCallFrame)
1956            base = addressFor(codeOrigin.inlineCallFrame->arguments[1].virtualRegister());
1957        else
1958            base = addressFor(virtualRegisterForArgument(1));
1959
1960        LValue pointer = m_out.baseIndex(
1961            base.value(), m_out.zeroExt(zeroBasedIndex, m_out.intPtr), ScaleEight);
1962        setJSValue(m_out.load64(TypedPointer(m_heaps.variables.atAnyIndex(), pointer)));
1963    }
1964
1965    void compileGetArrayLength()
1966    {
1967        switch (m_node->arrayMode().type()) {
1968        case Array::Int32:
1969        case Array::Double:
1970        case Array::Contiguous: {
1971            setInt32(m_out.load32NonNegative(lowStorage(m_node->child2()), m_heaps.Butterfly_publicLength));
1972            return;
1973        }
1974
1975        case Array::String: {
1976            LValue string = lowCell(m_node->child1());
1977            setInt32(m_out.load32NonNegative(string, m_heaps.JSString_length));
1978            return;
1979        }
1980
1981        default:
1982            if (isTypedView(m_node->arrayMode().typedArrayType())) {
1983                setInt32(
1984                    m_out.load32NonNegative(lowCell(m_node->child1()), m_heaps.JSArrayBufferView_length));
1985                return;
1986            }
1987
1988            RELEASE_ASSERT_NOT_REACHED();
1989            return;
1990        }
1991    }
1992
1993    void compileCheckInBounds()
1994    {
1995        speculate(
1996            OutOfBounds, noValue(), 0,
1997            m_out.aboveOrEqual(lowInt32(m_node->child1()), lowInt32(m_node->child2())));
1998    }
1999
2000    void compileGetByVal()
2001    {
2002        switch (m_node->arrayMode().type()) {
2003        case Array::Int32:
2004        case Array::Contiguous: {
2005            LValue index = lowInt32(m_node->child2());
2006            LValue storage = lowStorage(m_node->child3());
2007
2008            IndexedAbstractHeap& heap = m_node->arrayMode().type() == Array::Int32 ?
2009                m_heaps.indexedInt32Properties : m_heaps.indexedContiguousProperties;
2010
2011            if (m_node->arrayMode().isInBounds()) {
2012                LValue result = m_out.load64(baseIndex(heap, storage, index, m_node->child2()));
2013                speculate(LoadFromHole, noValue(), 0, m_out.isZero64(result));
2014                setJSValue(result);
2015                return;
2016            }
2017
2018            LValue base = lowCell(m_node->child1());
2019
2020            LBasicBlock fastCase = FTL_NEW_BLOCK(m_out, ("GetByVal int/contiguous fast case"));
2021            LBasicBlock slowCase = FTL_NEW_BLOCK(m_out, ("GetByVal int/contiguous slow case"));
2022            LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("GetByVal int/contiguous continuation"));
2023
2024            m_out.branch(
2025                m_out.aboveOrEqual(
2026                    index, m_out.load32NonNegative(storage, m_heaps.Butterfly_publicLength)),
2027                rarely(slowCase), usually(fastCase));
2028
2029            LBasicBlock lastNext = m_out.appendTo(fastCase, slowCase);
2030
2031            ValueFromBlock fastResult = m_out.anchor(
2032                m_out.load64(baseIndex(heap, storage, index, m_node->child2())));
2033            m_out.branch(
2034                m_out.isZero64(fastResult.value()), rarely(slowCase), usually(continuation));
2035
2036            m_out.appendTo(slowCase, continuation);
2037            ValueFromBlock slowResult = m_out.anchor(
2038                vmCall(m_out.operation(operationGetByValArrayInt), m_callFrame, base, index));
2039            m_out.jump(continuation);
2040
2041            m_out.appendTo(continuation, lastNext);
2042            setJSValue(m_out.phi(m_out.int64, fastResult, slowResult));
2043            return;
2044        }
2045
2046        case Array::Double: {
2047            LValue index = lowInt32(m_node->child2());
2048            LValue storage = lowStorage(m_node->child3());
2049
2050            IndexedAbstractHeap& heap = m_heaps.indexedDoubleProperties;
2051
2052            if (m_node->arrayMode().isInBounds()) {
2053                LValue result = m_out.loadDouble(
2054                    baseIndex(heap, storage, index, m_node->child2()));
2055
2056                if (!m_node->arrayMode().isSaneChain()) {
2057                    speculate(
2058                        LoadFromHole, noValue(), 0,
2059                        m_out.doubleNotEqualOrUnordered(result, result));
2060                }
2061                setDouble(result);
2062                break;
2063            }
2064
2065            LValue base = lowCell(m_node->child1());
2066
2067            LBasicBlock inBounds = FTL_NEW_BLOCK(m_out, ("GetByVal double in bounds"));
2068            LBasicBlock boxPath = FTL_NEW_BLOCK(m_out, ("GetByVal double boxing"));
2069            LBasicBlock slowCase = FTL_NEW_BLOCK(m_out, ("GetByVal double slow case"));
2070            LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("GetByVal double continuation"));
2071
2072            m_out.branch(
2073                m_out.aboveOrEqual(
2074                    index, m_out.load32NonNegative(storage, m_heaps.Butterfly_publicLength)),
2075                rarely(slowCase), usually(inBounds));
2076
2077            LBasicBlock lastNext = m_out.appendTo(inBounds, boxPath);
2078            LValue doubleValue = m_out.loadDouble(
2079                baseIndex(heap, storage, index, m_node->child2()));
2080            m_out.branch(
2081                m_out.doubleNotEqualOrUnordered(doubleValue, doubleValue),
2082                rarely(slowCase), usually(boxPath));
2083
2084            m_out.appendTo(boxPath, slowCase);
2085            ValueFromBlock fastResult = m_out.anchor(boxDouble(doubleValue));
2086            m_out.jump(continuation);
2087
2088            m_out.appendTo(slowCase, continuation);
2089            ValueFromBlock slowResult = m_out.anchor(
2090                vmCall(m_out.operation(operationGetByValArrayInt), m_callFrame, base, index));
2091            m_out.jump(continuation);
2092
2093            m_out.appendTo(continuation, lastNext);
2094            setJSValue(m_out.phi(m_out.int64, fastResult, slowResult));
2095            return;
2096        }
2097
2098        case Array::Generic: {
2099            setJSValue(vmCall(
2100                m_out.operation(operationGetByVal), m_callFrame,
2101                lowJSValue(m_node->child1()), lowJSValue(m_node->child2())));
2102            return;
2103        }
2104
2105        case Array::String: {
2106            compileStringCharAt();
2107            return;
2108        }
2109
2110        default: {
2111            LValue index = lowInt32(m_node->child2());
2112            LValue storage = lowStorage(m_node->child3());
2113
2114            TypedArrayType type = m_node->arrayMode().typedArrayType();
2115
2116            if (isTypedView(type)) {
2117                TypedPointer pointer = TypedPointer(
2118                    m_heaps.typedArrayProperties,
2119                    m_out.add(
2120                        storage,
2121                        m_out.shl(
2122                            m_out.zeroExt(index, m_out.intPtr),
2123                            m_out.constIntPtr(logElementSize(type)))));
2124
2125                if (isInt(type)) {
2126                    LValue result;
2127                    switch (elementSize(type)) {
2128                    case 1:
2129                        result = m_out.load8(pointer);
2130                        break;
2131                    case 2:
2132                        result = m_out.load16(pointer);
2133                        break;
2134                    case 4:
2135                        result = m_out.load32(pointer);
2136                        break;
2137                    default:
2138                        RELEASE_ASSERT_NOT_REACHED();
2139                    }
2140
2141                    if (elementSize(type) < 4) {
2142                        if (isSigned(type))
2143                            result = m_out.signExt(result, m_out.int32);
2144                        else
2145                            result = m_out.zeroExt(result, m_out.int32);
2146                        setInt32(result);
2147                        return;
2148                    }
2149
2150                    if (isSigned(type)) {
2151                        setInt32(result);
2152                        return;
2153                    }
2154
2155                    if (m_node->shouldSpeculateInt32()) {
2156                        speculate(
2157                            Overflow, noValue(), 0, m_out.lessThan(result, m_out.int32Zero));
2158                        setInt32(result);
2159                        return;
2160                    }
2161
2162                    if (m_node->shouldSpeculateMachineInt()) {
2163                        setStrictInt52(m_out.zeroExt(result, m_out.int64));
2164                        return;
2165                    }
2166
2167                    setDouble(m_out.unsignedToFP(result, m_out.doubleType));
2168                    return;
2169                }
2170
2171                ASSERT(isFloat(type));
2172
2173                LValue result;
2174                switch (type) {
2175                case TypeFloat32:
2176                    result = m_out.fpCast(m_out.loadFloat(pointer), m_out.doubleType);
2177                    break;
2178                case TypeFloat64:
2179                    result = m_out.loadDouble(pointer);
2180                    break;
2181                default:
2182                    RELEASE_ASSERT_NOT_REACHED();
2183                }
2184
2185                setDouble(result);
2186                return;
2187            }
2188
2189            RELEASE_ASSERT_NOT_REACHED();
2190            return;
2191        } }
2192    }
2193
2194    void compilePutByVal()
2195    {
2196        Edge child1 = m_graph.varArgChild(m_node, 0);
2197        Edge child2 = m_graph.varArgChild(m_node, 1);
2198        Edge child3 = m_graph.varArgChild(m_node, 2);
2199        Edge child4 = m_graph.varArgChild(m_node, 3);
2200        Edge child5 = m_graph.varArgChild(m_node, 4);
2201
2202        switch (m_node->arrayMode().type()) {
2203        case Array::Generic: {
2204            V_JITOperation_EJJJ operation;
2205            if (m_node->op() == PutByValDirect) {
2206                if (m_graph.isStrictModeFor(m_node->origin.semantic))
2207                    operation = operationPutByValDirectStrict;
2208                else
2209                    operation = operationPutByValDirectNonStrict;
2210            } else {
2211                if (m_graph.isStrictModeFor(m_node->origin.semantic))
2212                    operation = operationPutByValStrict;
2213                else
2214                    operation = operationPutByValNonStrict;
2215            }
2216
2217            vmCall(
2218                m_out.operation(operation), m_callFrame,
2219                lowJSValue(child1), lowJSValue(child2), lowJSValue(child3));
2220            return;
2221        }
2222
2223        default:
2224            break;
2225        }
2226
2227        LValue base = lowCell(child1);
2228        LValue index = lowInt32(child2);
2229        LValue storage = lowStorage(child4);
2230
2231        switch (m_node->arrayMode().type()) {
2232        case Array::Int32:
2233        case Array::Double:
2234        case Array::Contiguous: {
2235            LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("PutByVal continuation"));
2236            LBasicBlock outerLastNext = m_out.appendTo(m_out.m_block, continuation);
2237
2238            switch (m_node->arrayMode().type()) {
2239            case Array::Int32:
2240            case Array::Contiguous: {
2241                LValue value = lowJSValue(child3, ManualOperandSpeculation);
2242
2243                if (m_node->arrayMode().type() == Array::Int32)
2244                    FTL_TYPE_CHECK(jsValueValue(value), child3, SpecInt32, isNotInt32(value));
2245
2246                TypedPointer elementPointer = m_out.baseIndex(
2247                    m_node->arrayMode().type() == Array::Int32 ?
2248                    m_heaps.indexedInt32Properties : m_heaps.indexedContiguousProperties,
2249                    storage, m_out.zeroExt(index, m_out.intPtr),
2250                    m_state.forNode(child2).m_value);
2251
2252                if (m_node->op() == PutByValAlias) {
2253                    m_out.store64(value, elementPointer);
2254                    break;
2255                }
2256
2257                contiguousPutByValOutOfBounds(
2258                    codeBlock()->isStrictMode()
2259                    ? operationPutByValBeyondArrayBoundsStrict
2260                    : operationPutByValBeyondArrayBoundsNonStrict,
2261                    base, storage, index, value, continuation);
2262
2263                m_out.store64(value, elementPointer);
2264                break;
2265            }
2266
2267            case Array::Double: {
2268                LValue value = lowDouble(child3);
2269
2270                FTL_TYPE_CHECK(
2271                    doubleValue(value), child3, SpecDoubleReal,
2272                    m_out.doubleNotEqualOrUnordered(value, value));
2273
2274                TypedPointer elementPointer = m_out.baseIndex(
2275                    m_heaps.indexedDoubleProperties,
2276                    storage, m_out.zeroExt(index, m_out.intPtr),
2277                    m_state.forNode(child2).m_value);
2278
2279                if (m_node->op() == PutByValAlias) {
2280                    m_out.storeDouble(value, elementPointer);
2281                    break;
2282                }
2283
2284                contiguousPutByValOutOfBounds(
2285                    codeBlock()->isStrictMode()
2286                    ? operationPutDoubleByValBeyondArrayBoundsStrict
2287                    : operationPutDoubleByValBeyondArrayBoundsNonStrict,
2288                    base, storage, index, value, continuation);
2289
2290                m_out.storeDouble(value, elementPointer);
2291                break;
2292            }
2293
2294            default:
2295                RELEASE_ASSERT_NOT_REACHED();
2296            }
2297
2298            m_out.jump(continuation);
2299            m_out.appendTo(continuation, outerLastNext);
2300            return;
2301        }
2302
2303        default:
2304            TypedArrayType type = m_node->arrayMode().typedArrayType();
2305
2306            if (isTypedView(type)) {
2307                TypedPointer pointer = TypedPointer(
2308                    m_heaps.typedArrayProperties,
2309                    m_out.add(
2310                        storage,
2311                        m_out.shl(
2312                            m_out.zeroExt(index, m_out.intPtr),
2313                            m_out.constIntPtr(logElementSize(type)))));
2314
2315                LType refType;
2316                LValue valueToStore;
2317
2318                if (isInt(type)) {
2319                    LValue intValue;
2320                    switch (child3.useKind()) {
2321                    case Int52RepUse:
2322                    case Int32Use: {
2323                        if (child3.useKind() == Int32Use)
2324                            intValue = lowInt32(child3);
2325                        else
2326                            intValue = m_out.castToInt32(lowStrictInt52(child3));
2327
2328                        if (isClamped(type)) {
2329                            ASSERT(elementSize(type) == 1);
2330
2331                            LBasicBlock atLeastZero = FTL_NEW_BLOCK(m_out, ("PutByVal int clamp atLeastZero"));
2332                            LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("PutByVal int clamp continuation"));
2333
2334                            Vector<ValueFromBlock, 2> intValues;
2335                            intValues.append(m_out.anchor(m_out.int32Zero));
2336                            m_out.branch(
2337                                m_out.lessThan(intValue, m_out.int32Zero),
2338                                unsure(continuation), unsure(atLeastZero));
2339
2340                            LBasicBlock lastNext = m_out.appendTo(atLeastZero, continuation);
2341
2342                            intValues.append(m_out.anchor(m_out.select(
2343                                m_out.greaterThan(intValue, m_out.constInt32(255)),
2344                                m_out.constInt32(255),
2345                                intValue)));
2346                            m_out.jump(continuation);
2347
2348                            m_out.appendTo(continuation, lastNext);
2349                            intValue = m_out.phi(m_out.int32, intValues);
2350                        }
2351                        break;
2352                    }
2353
2354                    case DoubleRepUse: {
2355                        LValue doubleValue = lowDouble(child3);
2356
2357                        if (isClamped(type)) {
2358                            ASSERT(elementSize(type) == 1);
2359
2360                            LBasicBlock atLeastZero = FTL_NEW_BLOCK(m_out, ("PutByVal double clamp atLeastZero"));
2361                            LBasicBlock withinRange = FTL_NEW_BLOCK(m_out, ("PutByVal double clamp withinRange"));
2362                            LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("PutByVal double clamp continuation"));
2363
2364                            Vector<ValueFromBlock, 3> intValues;
2365                            intValues.append(m_out.anchor(m_out.int32Zero));
2366                            m_out.branch(
2367                                m_out.doubleLessThanOrUnordered(doubleValue, m_out.doubleZero),
2368                                unsure(continuation), unsure(atLeastZero));
2369
2370                            LBasicBlock lastNext = m_out.appendTo(atLeastZero, withinRange);
2371                            intValues.append(m_out.anchor(m_out.constInt32(255)));
2372                            m_out.branch(
2373                                m_out.doubleGreaterThan(doubleValue, m_out.constDouble(255)),
2374                                unsure(continuation), unsure(withinRange));
2375
2376                            m_out.appendTo(withinRange, continuation);
2377                            intValues.append(m_out.anchor(m_out.fpToInt32(doubleValue)));
2378                            m_out.jump(continuation);
2379
2380                            m_out.appendTo(continuation, lastNext);
2381                            intValue = m_out.phi(m_out.int32, intValues);
2382                        } else
2383                            intValue = doubleToInt32(doubleValue);
2384                        break;
2385                    }
2386
2387                    default:
2388                        RELEASE_ASSERT_NOT_REACHED();
2389                    }
2390
2391                    switch (elementSize(type)) {
2392                    case 1:
2393                        valueToStore = m_out.intCast(intValue, m_out.int8);
2394                        refType = m_out.ref8;
2395                        break;
2396                    case 2:
2397                        valueToStore = m_out.intCast(intValue, m_out.int16);
2398                        refType = m_out.ref16;
2399                        break;
2400                    case 4:
2401                        valueToStore = intValue;
2402                        refType = m_out.ref32;
2403                        break;
2404                    default:
2405                        RELEASE_ASSERT_NOT_REACHED();
2406                    }
2407                } else /* !isInt(type) */ {
2408                    LValue value = lowDouble(child3);
2409                    switch (type) {
2410                    case TypeFloat32:
2411                        valueToStore = m_out.fpCast(value, m_out.floatType);
2412                        refType = m_out.refFloat;
2413                        break;
2414                    case TypeFloat64:
2415                        valueToStore = value;
2416                        refType = m_out.refDouble;
2417                        break;
2418                    default:
2419                        RELEASE_ASSERT_NOT_REACHED();
2420                    }
2421                }
2422
2423                if (m_node->arrayMode().isInBounds() || m_node->op() == PutByValAlias)
2424                    m_out.store(valueToStore, pointer, refType);
2425                else {
2426                    LBasicBlock isInBounds = FTL_NEW_BLOCK(m_out, ("PutByVal typed array in bounds case"));
2427                    LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("PutByVal typed array continuation"));
2428
2429                    m_out.branch(
2430                        m_out.aboveOrEqual(index, lowInt32(child5)),
2431                        unsure(continuation), unsure(isInBounds));
2432
2433                    LBasicBlock lastNext = m_out.appendTo(isInBounds, continuation);
2434                    m_out.store(valueToStore, pointer, refType);
2435                    m_out.jump(continuation);
2436
2437                    m_out.appendTo(continuation, lastNext);
2438                }
2439
2440                return;
2441            }
2442
2443            RELEASE_ASSERT_NOT_REACHED();
2444            break;
2445        }
2446    }
2447
2448    void compileArrayPush()
2449    {
2450        LValue base = lowCell(m_node->child1());
2451        LValue storage = lowStorage(m_node->child3());
2452
2453        switch (m_node->arrayMode().type()) {
2454        case Array::Int32:
2455        case Array::Contiguous:
2456        case Array::Double: {
2457            LValue value;
2458            LType refType;
2459
2460            if (m_node->arrayMode().type() != Array::Double) {
2461                value = lowJSValue(m_node->child2(), ManualOperandSpeculation);
2462                if (m_node->arrayMode().type() == Array::Int32) {
2463                    FTL_TYPE_CHECK(
2464                        jsValueValue(value), m_node->child2(), SpecInt32, isNotInt32(value));
2465                }
2466                refType = m_out.ref64;
2467            } else {
2468                value = lowDouble(m_node->child2());
2469                FTL_TYPE_CHECK(
2470                    doubleValue(value), m_node->child2(), SpecDoubleReal,
2471                    m_out.doubleNotEqualOrUnordered(value, value));
2472                refType = m_out.refDouble;
2473            }
2474
2475            IndexedAbstractHeap& heap = m_heaps.forArrayType(m_node->arrayMode().type());
2476
2477            LValue prevLength = m_out.load32(storage, m_heaps.Butterfly_publicLength);
2478
2479            LBasicBlock fastPath = FTL_NEW_BLOCK(m_out, ("ArrayPush fast path"));
2480            LBasicBlock slowPath = FTL_NEW_BLOCK(m_out, ("ArrayPush slow path"));
2481            LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("ArrayPush continuation"));
2482
2483            m_out.branch(
2484                m_out.aboveOrEqual(
2485                    prevLength, m_out.load32(storage, m_heaps.Butterfly_vectorLength)),
2486                rarely(slowPath), usually(fastPath));
2487
2488            LBasicBlock lastNext = m_out.appendTo(fastPath, slowPath);
2489            m_out.store(
2490                value,
2491                m_out.baseIndex(heap, storage, m_out.zeroExt(prevLength, m_out.intPtr)),
2492                refType);
2493            LValue newLength = m_out.add(prevLength, m_out.int32One);
2494            m_out.store32(newLength, storage, m_heaps.Butterfly_publicLength);
2495
2496            ValueFromBlock fastResult = m_out.anchor(boxInt32(newLength));
2497            m_out.jump(continuation);
2498
2499            m_out.appendTo(slowPath, continuation);
2500            LValue operation;
2501            if (m_node->arrayMode().type() != Array::Double)
2502                operation = m_out.operation(operationArrayPush);
2503            else
2504                operation = m_out.operation(operationArrayPushDouble);
2505            ValueFromBlock slowResult = m_out.anchor(
2506                vmCall(operation, m_callFrame, value, base));
2507            m_out.jump(continuation);
2508
2509            m_out.appendTo(continuation, lastNext);
2510            setJSValue(m_out.phi(m_out.int64, fastResult, slowResult));
2511            return;
2512        }
2513
2514        default:
2515            RELEASE_ASSERT_NOT_REACHED();
2516            return;
2517        }
2518    }
2519
2520    void compileArrayPop()
2521    {
2522        LValue base = lowCell(m_node->child1());
2523        LValue storage = lowStorage(m_node->child2());
2524
2525        switch (m_node->arrayMode().type()) {
2526        case Array::Int32:
2527        case Array::Double:
2528        case Array::Contiguous: {
2529            IndexedAbstractHeap& heap = m_heaps.forArrayType(m_node->arrayMode().type());
2530
2531            LBasicBlock fastCase = FTL_NEW_BLOCK(m_out, ("ArrayPop fast case"));
2532            LBasicBlock slowCase = FTL_NEW_BLOCK(m_out, ("ArrayPop slow case"));
2533            LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("ArrayPop continuation"));
2534
2535            LValue prevLength = m_out.load32(storage, m_heaps.Butterfly_publicLength);
2536
2537            Vector<ValueFromBlock, 3> results;
2538            results.append(m_out.anchor(m_out.constInt64(JSValue::encode(jsUndefined()))));
2539            m_out.branch(
2540                m_out.isZero32(prevLength), rarely(continuation), usually(fastCase));
2541
2542            LBasicBlock lastNext = m_out.appendTo(fastCase, slowCase);
2543            LValue newLength = m_out.sub(prevLength, m_out.int32One);
2544            m_out.store32(newLength, storage, m_heaps.Butterfly_publicLength);
2545            TypedPointer pointer = m_out.baseIndex(
2546                heap, storage, m_out.zeroExt(newLength, m_out.intPtr));
2547            if (m_node->arrayMode().type() != Array::Double) {
2548                LValue result = m_out.load64(pointer);
2549                m_out.store64(m_out.int64Zero, pointer);
2550                results.append(m_out.anchor(result));
2551                m_out.branch(
2552                    m_out.notZero64(result), usually(continuation), rarely(slowCase));
2553            } else {
2554                LValue result = m_out.loadDouble(pointer);
2555                m_out.store64(m_out.constInt64(bitwise_cast<int64_t>(PNaN)), pointer);
2556                results.append(m_out.anchor(boxDouble(result)));
2557                m_out.branch(
2558                    m_out.doubleEqual(result, result),
2559                    usually(continuation), rarely(slowCase));
2560            }
2561
2562            m_out.appendTo(slowCase, continuation);
2563            results.append(m_out.anchor(vmCall(
2564                m_out.operation(operationArrayPopAndRecoverLength), m_callFrame, base)));
2565            m_out.jump(continuation);
2566
2567            m_out.appendTo(continuation, lastNext);
2568            setJSValue(m_out.phi(m_out.int64, results));
2569            return;
2570        }
2571
2572        default:
2573            RELEASE_ASSERT_NOT_REACHED();
2574            return;
2575        }
2576    }
2577
2578    void compileNewObject()
2579    {
2580        Structure* structure = m_node->structure();
2581        size_t allocationSize = JSFinalObject::allocationSize(structure->inlineCapacity());
2582        MarkedAllocator* allocator = &vm().heap.allocatorForObjectWithoutDestructor(allocationSize);
2583
2584        LBasicBlock slowPath = FTL_NEW_BLOCK(m_out, ("NewObject slow path"));
2585        LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("NewObject continuation"));
2586
2587        LBasicBlock lastNext = m_out.insertNewBlocksBefore(slowPath);
2588
2589        ValueFromBlock fastResult = m_out.anchor(allocateObject(
2590            m_out.constIntPtr(allocator), structure, m_out.intPtrZero, slowPath));
2591
2592        m_out.jump(continuation);
2593
2594        m_out.appendTo(slowPath, continuation);
2595
2596        ValueFromBlock slowResult = m_out.anchor(vmCall(
2597            m_out.operation(operationNewObject), m_callFrame, m_out.constIntPtr(structure)));
2598        m_out.jump(continuation);
2599
2600        m_out.appendTo(continuation, lastNext);
2601        setJSValue(m_out.phi(m_out.intPtr, fastResult, slowResult));
2602    }
2603
2604    void compileNewArray()
2605    {
2606        // First speculate appropriately on all of the children. Do this unconditionally up here
2607        // because some of the slow paths may otherwise forget to do it. It's sort of arguable
2608        // that doing the speculations up here might be unprofitable for RA - so we can consider
2609        // sinking this to below the allocation fast path if we find that this has a lot of
2610        // register pressure.
2611        for (unsigned operandIndex = 0; operandIndex < m_node->numChildren(); ++operandIndex)
2612            speculate(m_graph.varArgChild(m_node, operandIndex));
2613
2614        JSGlobalObject* globalObject = m_graph.globalObjectFor(m_node->origin.semantic);
2615        Structure* structure = globalObject->arrayStructureForIndexingTypeDuringAllocation(
2616            m_node->indexingType());
2617
2618        RELEASE_ASSERT(structure->indexingType() == m_node->indexingType());
2619
2620        if (!globalObject->isHavingABadTime() && !hasAnyArrayStorage(m_node->indexingType())) {
2621            unsigned numElements = m_node->numChildren();
2622
2623            ArrayValues arrayValues = allocateJSArray(structure, numElements);
2624
2625            for (unsigned operandIndex = 0; operandIndex < m_node->numChildren(); ++operandIndex) {
2626                Edge edge = m_graph.varArgChild(m_node, operandIndex);
2627
2628                switch (m_node->indexingType()) {
2629                case ALL_BLANK_INDEXING_TYPES:
2630                case ALL_UNDECIDED_INDEXING_TYPES:
2631                    CRASH();
2632                    break;
2633
2634                case ALL_DOUBLE_INDEXING_TYPES:
2635                    m_out.storeDouble(
2636                        lowDouble(edge),
2637                        arrayValues.butterfly, m_heaps.indexedDoubleProperties[operandIndex]);
2638                    break;
2639
2640                case ALL_INT32_INDEXING_TYPES:
2641                case ALL_CONTIGUOUS_INDEXING_TYPES:
2642                    m_out.store64(
2643                        lowJSValue(edge, ManualOperandSpeculation),
2644                        arrayValues.butterfly,
2645                        m_heaps.forIndexingType(m_node->indexingType())->at(operandIndex));
2646                    break;
2647
2648                default:
2649                    CRASH();
2650                }
2651            }
2652
2653            setJSValue(arrayValues.array);
2654            return;
2655        }
2656
2657        if (!m_node->numChildren()) {
2658            setJSValue(vmCall(
2659                m_out.operation(operationNewEmptyArray), m_callFrame,
2660                m_out.constIntPtr(structure)));
2661            return;
2662        }
2663
2664        size_t scratchSize = sizeof(EncodedJSValue) * m_node->numChildren();
2665        ASSERT(scratchSize);
2666        ScratchBuffer* scratchBuffer = vm().scratchBufferForSize(scratchSize);
2667        EncodedJSValue* buffer = static_cast<EncodedJSValue*>(scratchBuffer->dataBuffer());
2668
2669        for (unsigned operandIndex = 0; operandIndex < m_node->numChildren(); ++operandIndex) {
2670            Edge edge = m_graph.varArgChild(m_node, operandIndex);
2671            m_out.store64(
2672                lowJSValue(edge, ManualOperandSpeculation),
2673                m_out.absolute(buffer + operandIndex));
2674        }
2675
2676        m_out.storePtr(
2677            m_out.constIntPtr(scratchSize), m_out.absolute(scratchBuffer->activeLengthPtr()));
2678
2679        LValue result = vmCall(
2680            m_out.operation(operationNewArray), m_callFrame,
2681            m_out.constIntPtr(structure), m_out.constIntPtr(buffer),
2682            m_out.constIntPtr(m_node->numChildren()));
2683
2684        m_out.storePtr(m_out.intPtrZero, m_out.absolute(scratchBuffer->activeLengthPtr()));
2685
2686        setJSValue(result);
2687    }
2688
2689    void compileNewArrayBuffer()
2690    {
2691        JSGlobalObject* globalObject = m_graph.globalObjectFor(m_node->origin.semantic);
2692        Structure* structure = globalObject->arrayStructureForIndexingTypeDuringAllocation(
2693            m_node->indexingType());
2694
2695        RELEASE_ASSERT(structure->indexingType() == m_node->indexingType());
2696
2697        if (!globalObject->isHavingABadTime() && !hasAnyArrayStorage(m_node->indexingType())) {
2698            unsigned numElements = m_node->numConstants();
2699
2700            ArrayValues arrayValues = allocateJSArray(structure, numElements);
2701
2702            JSValue* data = codeBlock()->constantBuffer(m_node->startConstant());
2703            for (unsigned index = 0; index < m_node->numConstants(); ++index) {
2704                int64_t value;
2705                if (hasDouble(m_node->indexingType()))
2706                    value = bitwise_cast<int64_t>(data[index].asNumber());
2707                else
2708                    value = JSValue::encode(data[index]);
2709
2710                m_out.store64(
2711                    m_out.constInt64(value),
2712                    arrayValues.butterfly,
2713                    m_heaps.forIndexingType(m_node->indexingType())->at(index));
2714            }
2715
2716            setJSValue(arrayValues.array);
2717            return;
2718        }
2719
2720        setJSValue(vmCall(
2721            m_out.operation(operationNewArrayBuffer), m_callFrame,
2722            m_out.constIntPtr(structure), m_out.constIntPtr(m_node->startConstant()),
2723            m_out.constIntPtr(m_node->numConstants())));
2724    }
2725
2726    void compileNewArrayWithSize()
2727    {
2728        LValue publicLength = lowInt32(m_node->child1());
2729
2730        JSGlobalObject* globalObject = m_graph.globalObjectFor(m_node->origin.semantic);
2731        Structure* structure = globalObject->arrayStructureForIndexingTypeDuringAllocation(
2732            m_node->indexingType());
2733
2734        if (!globalObject->isHavingABadTime() && !hasAnyArrayStorage(m_node->indexingType())) {
2735            ASSERT(
2736                hasUndecided(structure->indexingType())
2737                || hasInt32(structure->indexingType())
2738                || hasDouble(structure->indexingType())
2739                || hasContiguous(structure->indexingType()));
2740
2741            LBasicBlock fastCase = FTL_NEW_BLOCK(m_out, ("NewArrayWithSize fast case"));
2742            LBasicBlock largeCase = FTL_NEW_BLOCK(m_out, ("NewArrayWithSize large case"));
2743            LBasicBlock failCase = FTL_NEW_BLOCK(m_out, ("NewArrayWithSize fail case"));
2744            LBasicBlock slowCase = FTL_NEW_BLOCK(m_out, ("NewArrayWithSize slow case"));
2745            LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("NewArrayWithSize continuation"));
2746
2747            m_out.branch(
2748                m_out.aboveOrEqual(publicLength, m_out.constInt32(MIN_SPARSE_ARRAY_INDEX)),
2749                rarely(largeCase), usually(fastCase));
2750
2751            LBasicBlock lastNext = m_out.appendTo(fastCase, largeCase);
2752
2753            // We don't round up to BASE_VECTOR_LEN for new Array(blah).
2754            LValue vectorLength = publicLength;
2755
2756            LValue payloadSize =
2757                m_out.shl(m_out.zeroExt(vectorLength, m_out.intPtr), m_out.constIntPtr(3));
2758
2759            LValue butterflySize = m_out.add(
2760                payloadSize, m_out.constIntPtr(sizeof(IndexingHeader)));
2761
2762            LValue endOfStorage = allocateBasicStorageAndGetEnd(butterflySize, failCase);
2763
2764            LValue butterfly = m_out.sub(endOfStorage, payloadSize);
2765
2766            LValue object = allocateObject<JSArray>(
2767                structure, butterfly, failCase);
2768
2769            m_out.store32(publicLength, butterfly, m_heaps.Butterfly_publicLength);
2770            m_out.store32(vectorLength, butterfly, m_heaps.Butterfly_vectorLength);
2771
2772            if (hasDouble(m_node->indexingType())) {
2773                LBasicBlock initLoop = FTL_NEW_BLOCK(m_out, ("NewArrayWithSize double init loop"));
2774                LBasicBlock initDone = FTL_NEW_BLOCK(m_out, ("NewArrayWithSize double init done"));
2775
2776                ValueFromBlock originalIndex = m_out.anchor(vectorLength);
2777                ValueFromBlock originalPointer = m_out.anchor(butterfly);
2778                m_out.branch(
2779                    m_out.notZero32(vectorLength), unsure(initLoop), unsure(initDone));
2780
2781                LBasicBlock initLastNext = m_out.appendTo(initLoop, initDone);
2782                LValue index = m_out.phi(m_out.int32, originalIndex);
2783                LValue pointer = m_out.phi(m_out.intPtr, originalPointer);
2784
2785                m_out.store64(
2786                    m_out.constInt64(bitwise_cast<int64_t>(PNaN)),
2787                    TypedPointer(m_heaps.indexedDoubleProperties.atAnyIndex(), pointer));
2788
2789                LValue nextIndex = m_out.sub(index, m_out.int32One);
2790                addIncoming(index, m_out.anchor(nextIndex));
2791                addIncoming(pointer, m_out.anchor(m_out.add(pointer, m_out.intPtrEight)));
2792                m_out.branch(
2793                    m_out.notZero32(nextIndex), unsure(initLoop), unsure(initDone));
2794
2795                m_out.appendTo(initDone, initLastNext);
2796            }
2797
2798            ValueFromBlock fastResult = m_out.anchor(object);
2799            m_out.jump(continuation);
2800
2801            m_out.appendTo(largeCase, failCase);
2802            ValueFromBlock largeStructure = m_out.anchor(m_out.constIntPtr(
2803                globalObject->arrayStructureForIndexingTypeDuringAllocation(ArrayWithArrayStorage)));
2804            m_out.jump(slowCase);
2805
2806            m_out.appendTo(failCase, slowCase);
2807            ValueFromBlock failStructure = m_out.anchor(m_out.constIntPtr(structure));
2808            m_out.jump(slowCase);
2809
2810            m_out.appendTo(slowCase, continuation);
2811            LValue structureValue = m_out.phi(
2812                m_out.intPtr, largeStructure, failStructure);
2813            ValueFromBlock slowResult = m_out.anchor(vmCall(
2814                m_out.operation(operationNewArrayWithSize),
2815                m_callFrame, structureValue, publicLength));
2816            m_out.jump(continuation);
2817
2818            m_out.appendTo(continuation, lastNext);
2819            setJSValue(m_out.phi(m_out.intPtr, fastResult, slowResult));
2820            return;
2821        }
2822
2823        LValue structureValue = m_out.select(
2824            m_out.aboveOrEqual(publicLength, m_out.constInt32(MIN_SPARSE_ARRAY_INDEX)),
2825            m_out.constIntPtr(
2826                globalObject->arrayStructureForIndexingTypeDuringAllocation(ArrayWithArrayStorage)),
2827            m_out.constIntPtr(structure));
2828        setJSValue(vmCall(m_out.operation(operationNewArrayWithSize), m_callFrame, structureValue, publicLength));
2829    }
2830
2831    void compileAllocatePropertyStorage()
2832    {
2833        StructureTransitionData& data = m_node->structureTransitionData();
2834        LValue object = lowCell(m_node->child1());
2835
2836        setStorage(allocatePropertyStorage(object, data.previousStructure));
2837    }
2838
2839    void compileReallocatePropertyStorage()
2840    {
2841        StructureTransitionData& data = m_node->structureTransitionData();
2842        LValue object = lowCell(m_node->child1());
2843        LValue oldStorage = lowStorage(m_node->child2());
2844
2845        setStorage(
2846            reallocatePropertyStorage(
2847                object, oldStorage, data.previousStructure, data.newStructure));
2848    }
2849
2850    void compileToString()
2851    {
2852        switch (m_node->child1().useKind()) {
2853        case StringObjectUse: {
2854            LValue cell = lowCell(m_node->child1());
2855            speculateStringObjectForCell(m_node->child1(), cell);
2856            m_interpreter.filter(m_node->child1(), SpecStringObject);
2857
2858            setJSValue(m_out.loadPtr(cell, m_heaps.JSWrapperObject_internalValue));
2859            return;
2860        }
2861
2862        case StringOrStringObjectUse: {
2863            LValue cell = lowCell(m_node->child1());
2864            LValue structureID = m_out.load32(cell, m_heaps.JSCell_structureID);
2865
2866            LBasicBlock notString = FTL_NEW_BLOCK(m_out, ("ToString StringOrStringObject not string case"));
2867            LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("ToString StringOrStringObject continuation"));
2868
2869            ValueFromBlock simpleResult = m_out.anchor(cell);
2870            m_out.branch(
2871                m_out.equal(structureID, m_out.constInt32(vm().stringStructure->id())),
2872                unsure(continuation), unsure(notString));
2873
2874            LBasicBlock lastNext = m_out.appendTo(notString, continuation);
2875            speculateStringObjectForStructureID(m_node->child1(), structureID);
2876            ValueFromBlock unboxedResult = m_out.anchor(
2877                m_out.loadPtr(cell, m_heaps.JSWrapperObject_internalValue));
2878            m_out.jump(continuation);
2879
2880            m_out.appendTo(continuation, lastNext);
2881            setJSValue(m_out.phi(m_out.int64, simpleResult, unboxedResult));
2882
2883            m_interpreter.filter(m_node->child1(), SpecString | SpecStringObject);
2884            return;
2885        }
2886
2887        case CellUse:
2888        case UntypedUse: {
2889            LValue value;
2890            if (m_node->child1().useKind() == CellUse)
2891                value = lowCell(m_node->child1());
2892            else
2893                value = lowJSValue(m_node->child1());
2894
2895            LBasicBlock isCell = FTL_NEW_BLOCK(m_out, ("ToString CellUse/UntypedUse is cell"));
2896            LBasicBlock notString = FTL_NEW_BLOCK(m_out, ("ToString CellUse/UntypedUse not string"));
2897            LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("ToString CellUse/UntypedUse continuation"));
2898
2899            LValue isCellPredicate;
2900            if (m_node->child1().useKind() == CellUse)
2901                isCellPredicate = m_out.booleanTrue;
2902            else
2903                isCellPredicate = this->isCell(value);
2904            m_out.branch(isCellPredicate, unsure(isCell), unsure(notString));
2905
2906            LBasicBlock lastNext = m_out.appendTo(isCell, notString);
2907            ValueFromBlock simpleResult = m_out.anchor(value);
2908            LValue isStringPredicate;
2909            if (m_node->child1()->prediction() & SpecString) {
2910                isStringPredicate = m_out.equal(
2911                    m_out.load32(value, m_heaps.JSCell_structureID),
2912                    m_out.constInt32(vm().stringStructure->id()));
2913            } else
2914                isStringPredicate = m_out.booleanFalse;
2915            m_out.branch(isStringPredicate, unsure(continuation), unsure(notString));
2916
2917            m_out.appendTo(notString, continuation);
2918            LValue operation;
2919            if (m_node->child1().useKind() == CellUse)
2920                operation = m_out.operation(operationToStringOnCell);
2921            else
2922                operation = m_out.operation(operationToString);
2923            ValueFromBlock convertedResult = m_out.anchor(vmCall(operation, m_callFrame, value));
2924            m_out.jump(continuation);
2925
2926            m_out.appendTo(continuation, lastNext);
2927            setJSValue(m_out.phi(m_out.int64, simpleResult, convertedResult));
2928            return;
2929        }
2930
2931        default:
2932            RELEASE_ASSERT_NOT_REACHED();
2933            break;
2934        }
2935    }
2936
2937    void compileToPrimitive()
2938    {
2939        LValue value = lowJSValue(m_node->child1());
2940
2941        LBasicBlock isCellCase = FTL_NEW_BLOCK(m_out, ("ToPrimitive cell case"));
2942        LBasicBlock isObjectCase = FTL_NEW_BLOCK(m_out, ("ToPrimitive object case"));
2943        LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("ToPrimitive continuation"));
2944
2945        Vector<ValueFromBlock, 3> results;
2946
2947        results.append(m_out.anchor(value));
2948        m_out.branch(isCell(value), unsure(isCellCase), unsure(continuation));
2949
2950        LBasicBlock lastNext = m_out.appendTo(isCellCase, isObjectCase);
2951        results.append(m_out.anchor(value));
2952        m_out.branch(isObject(value), unsure(isObjectCase), unsure(continuation));
2953
2954        m_out.appendTo(isObjectCase, continuation);
2955        results.append(m_out.anchor(vmCall(
2956            m_out.operation(operationToPrimitive), m_callFrame, value)));
2957        m_out.jump(continuation);
2958
2959        m_out.appendTo(continuation, lastNext);
2960        setJSValue(m_out.phi(m_out.int64, results));
2961    }
2962
2963    void compileMakeRope()
2964    {
2965        LValue kids[3];
2966        unsigned numKids;
2967        kids[0] = lowCell(m_node->child1());
2968        kids[1] = lowCell(m_node->child2());
2969        if (m_node->child3()) {
2970            kids[2] = lowCell(m_node->child3());
2971            numKids = 3;
2972        } else {
2973            kids[2] = 0;
2974            numKids = 2;
2975        }
2976
2977        LBasicBlock slowPath = FTL_NEW_BLOCK(m_out, ("MakeRope slow path"));
2978        LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("MakeRope continuation"));
2979
2980        LBasicBlock lastNext = m_out.insertNewBlocksBefore(slowPath);
2981
2982        MarkedAllocator& allocator =
2983            vm().heap.allocatorForObjectWithImmortalStructureDestructor(sizeof(JSRopeString));
2984
2985        LValue result = allocateCell(
2986            m_out.constIntPtr(&allocator),
2987            vm().stringStructure.get(),
2988            slowPath);
2989
2990        m_out.storePtr(m_out.intPtrZero, result, m_heaps.JSString_value);
2991        for (unsigned i = 0; i < numKids; ++i)
2992            m_out.storePtr(kids[i], result, m_heaps.JSRopeString_fibers[i]);
2993        for (unsigned i = numKids; i < JSRopeString::s_maxInternalRopeLength; ++i)
2994            m_out.storePtr(m_out.intPtrZero, result, m_heaps.JSRopeString_fibers[i]);
2995        LValue flags = m_out.load32(kids[0], m_heaps.JSString_flags);
2996        LValue length = m_out.load32(kids[0], m_heaps.JSString_length);
2997        for (unsigned i = 1; i < numKids; ++i) {
2998            flags = m_out.bitAnd(flags, m_out.load32(kids[i], m_heaps.JSString_flags));
2999            LValue lengthAndOverflow = m_out.addWithOverflow32(
3000                length, m_out.load32(kids[i], m_heaps.JSString_length));
3001            speculate(Uncountable, noValue(), 0, m_out.extractValue(lengthAndOverflow, 1));
3002            length = m_out.extractValue(lengthAndOverflow, 0);
3003        }
3004        m_out.store32(
3005            m_out.bitAnd(m_out.constInt32(JSString::Is8Bit), flags),
3006            result, m_heaps.JSString_flags);
3007        m_out.store32(length, result, m_heaps.JSString_length);
3008
3009        ValueFromBlock fastResult = m_out.anchor(result);
3010        m_out.jump(continuation);
3011
3012        m_out.appendTo(slowPath, continuation);
3013        ValueFromBlock slowResult;
3014        switch (numKids) {
3015        case 2:
3016            slowResult = m_out.anchor(vmCall(
3017                m_out.operation(operationMakeRope2), m_callFrame, kids[0], kids[1]));
3018            break;
3019        case 3:
3020            slowResult = m_out.anchor(vmCall(
3021                m_out.operation(operationMakeRope3), m_callFrame, kids[0], kids[1], kids[2]));
3022            break;
3023        default:
3024            RELEASE_ASSERT_NOT_REACHED();
3025            break;
3026        }
3027        m_out.jump(continuation);
3028
3029        m_out.appendTo(continuation, lastNext);
3030        setJSValue(m_out.phi(m_out.int64, fastResult, slowResult));
3031    }
3032
3033    void compileStringCharAt()
3034    {
3035        LValue base = lowCell(m_node->child1());
3036        LValue index = lowInt32(m_node->child2());
3037        LValue storage = lowStorage(m_node->child3());
3038
3039        LBasicBlock fastPath = FTL_NEW_BLOCK(m_out, ("GetByVal String fast path"));
3040        LBasicBlock slowPath = FTL_NEW_BLOCK(m_out, ("GetByVal String slow path"));
3041        LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("GetByVal String continuation"));
3042
3043        m_out.branch(
3044            m_out.aboveOrEqual(
3045                index, m_out.load32NonNegative(base, m_heaps.JSString_length)),
3046            rarely(slowPath), usually(fastPath));
3047
3048        LBasicBlock lastNext = m_out.appendTo(fastPath, slowPath);
3049
3050        LValue stringImpl = m_out.loadPtr(base, m_heaps.JSString_value);
3051
3052        LBasicBlock is8Bit = FTL_NEW_BLOCK(m_out, ("GetByVal String 8-bit case"));
3053        LBasicBlock is16Bit = FTL_NEW_BLOCK(m_out, ("GetByVal String 16-bit case"));
3054        LBasicBlock bitsContinuation = FTL_NEW_BLOCK(m_out, ("GetByVal String bitness continuation"));
3055        LBasicBlock bigCharacter = FTL_NEW_BLOCK(m_out, ("GetByVal String big character"));
3056
3057        m_out.branch(
3058            m_out.testIsZero32(
3059                m_out.load32(stringImpl, m_heaps.StringImpl_hashAndFlags),
3060                m_out.constInt32(StringImpl::flagIs8Bit())),
3061            unsure(is16Bit), unsure(is8Bit));
3062
3063        m_out.appendTo(is8Bit, is16Bit);
3064
3065        ValueFromBlock char8Bit = m_out.anchor(m_out.zeroExt(
3066            m_out.load8(m_out.baseIndex(
3067                m_heaps.characters8,
3068                storage, m_out.zeroExt(index, m_out.intPtr),
3069                m_state.forNode(m_node->child2()).m_value)),
3070            m_out.int32));
3071        m_out.jump(bitsContinuation);
3072
3073        m_out.appendTo(is16Bit, bigCharacter);
3074
3075        ValueFromBlock char16Bit = m_out.anchor(m_out.zeroExt(
3076            m_out.load16(m_out.baseIndex(
3077                m_heaps.characters16,
3078                storage, m_out.zeroExt(index, m_out.intPtr),
3079                m_state.forNode(m_node->child2()).m_value)),
3080            m_out.int32));
3081        m_out.branch(
3082            m_out.aboveOrEqual(char16Bit.value(), m_out.constInt32(0x100)),
3083            rarely(bigCharacter), usually(bitsContinuation));
3084
3085        m_out.appendTo(bigCharacter, bitsContinuation);
3086
3087        Vector<ValueFromBlock, 4> results;
3088        results.append(m_out.anchor(vmCall(
3089            m_out.operation(operationSingleCharacterString),
3090            m_callFrame, char16Bit.value())));
3091        m_out.jump(continuation);
3092
3093        m_out.appendTo(bitsContinuation, slowPath);
3094
3095        LValue character = m_out.phi(m_out.int32, char8Bit, char16Bit);
3096
3097        LValue smallStrings = m_out.constIntPtr(vm().smallStrings.singleCharacterStrings());
3098
3099        results.append(m_out.anchor(m_out.loadPtr(m_out.baseIndex(
3100            m_heaps.singleCharacterStrings, smallStrings,
3101            m_out.zeroExt(character, m_out.intPtr)))));
3102        m_out.jump(continuation);
3103
3104        m_out.appendTo(slowPath, continuation);
3105
3106        if (m_node->arrayMode().isInBounds()) {
3107            speculate(OutOfBounds, noValue(), 0, m_out.booleanTrue);
3108            results.append(m_out.anchor(m_out.intPtrZero));
3109        } else {
3110            JSGlobalObject* globalObject = m_graph.globalObjectFor(m_node->origin.semantic);
3111
3112            if (globalObject->stringPrototypeChainIsSane()) {
3113                LBasicBlock negativeIndex = FTL_NEW_BLOCK(m_out, ("GetByVal String negative index"));
3114
3115                results.append(m_out.anchor(m_out.constInt64(JSValue::encode(jsUndefined()))));
3116                m_out.branch(
3117                    m_out.lessThan(index, m_out.int32Zero),
3118                    rarely(negativeIndex), usually(continuation));
3119
3120                m_out.appendTo(negativeIndex, continuation);
3121            }
3122
3123            results.append(m_out.anchor(vmCall(
3124                m_out.operation(operationGetByValStringInt), m_callFrame, base, index)));
3125        }
3126
3127        m_out.jump(continuation);
3128
3129        m_out.appendTo(continuation, lastNext);
3130        setJSValue(m_out.phi(m_out.int64, results));
3131    }
3132
3133    void compileStringCharCodeAt()
3134    {
3135        LBasicBlock is8Bit = FTL_NEW_BLOCK(m_out, ("StringCharCodeAt 8-bit case"));
3136        LBasicBlock is16Bit = FTL_NEW_BLOCK(m_out, ("StringCharCodeAt 16-bit case"));
3137        LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("StringCharCodeAt continuation"));
3138
3139        LValue base = lowCell(m_node->child1());
3140        LValue index = lowInt32(m_node->child2());
3141        LValue storage = lowStorage(m_node->child3());
3142
3143        speculate(
3144            Uncountable, noValue(), 0,
3145            m_out.aboveOrEqual(
3146                index, m_out.load32NonNegative(base, m_heaps.JSString_length)));
3147
3148        LValue stringImpl = m_out.loadPtr(base, m_heaps.JSString_value);
3149
3150        m_out.branch(
3151            m_out.testIsZero32(
3152                m_out.load32(stringImpl, m_heaps.StringImpl_hashAndFlags),
3153                m_out.constInt32(StringImpl::flagIs8Bit())),
3154            unsure(is16Bit), unsure(is8Bit));
3155
3156        LBasicBlock lastNext = m_out.appendTo(is8Bit, is16Bit);
3157
3158        ValueFromBlock char8Bit = m_out.anchor(m_out.zeroExt(
3159            m_out.load8(m_out.baseIndex(
3160                m_heaps.characters8,
3161                storage, m_out.zeroExt(index, m_out.intPtr),
3162                m_state.forNode(m_node->child2()).m_value)),
3163            m_out.int32));
3164        m_out.jump(continuation);
3165
3166        m_out.appendTo(is16Bit, continuation);
3167
3168        ValueFromBlock char16Bit = m_out.anchor(m_out.zeroExt(
3169            m_out.load16(m_out.baseIndex(
3170                m_heaps.characters16,
3171                storage, m_out.zeroExt(index, m_out.intPtr),
3172                m_state.forNode(m_node->child2()).m_value)),
3173            m_out.int32));
3174        m_out.jump(continuation);
3175
3176        m_out.appendTo(continuation, lastNext);
3177
3178        setInt32(m_out.phi(m_out.int32, char8Bit, char16Bit));
3179    }
3180
3181    void compileGetByOffset()
3182    {
3183        StorageAccessData& data =
3184            m_graph.m_storageAccessData[m_node->storageAccessDataIndex()];
3185
3186        setJSValue(loadProperty(
3187            lowStorage(m_node->child1()), data.identifierNumber, data.offset));
3188    }
3189
3190    void compileMultiGetByOffset()
3191    {
3192        LValue base = lowCell(m_node->child1());
3193
3194        MultiGetByOffsetData& data = m_node->multiGetByOffsetData();
3195
3196        Vector<LBasicBlock, 2> blocks(data.variants.size());
3197        for (unsigned i = data.variants.size(); i--;)
3198            blocks[i] = FTL_NEW_BLOCK(m_out, ("MultiGetByOffset case ", i));
3199        LBasicBlock exit = FTL_NEW_BLOCK(m_out, ("MultiGetByOffset fail"));
3200        LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("MultiGetByOffset continuation"));
3201
3202        Vector<SwitchCase, 2> cases;
3203        for (unsigned i = data.variants.size(); i--;) {
3204            GetByIdVariant variant = data.variants[i];
3205            for (unsigned j = variant.structureSet().size(); j--;) {
3206                cases.append(SwitchCase(
3207                    weakStructure(variant.structureSet()[j]), blocks[i], Weight(1)));
3208            }
3209        }
3210        m_out.switchInstruction(
3211            m_out.load32(base, m_heaps.JSCell_structureID), cases, exit, Weight(0));
3212
3213        LBasicBlock lastNext = m_out.m_nextBlock;
3214
3215        Vector<ValueFromBlock, 2> results;
3216        for (unsigned i = data.variants.size(); i--;) {
3217            m_out.appendTo(blocks[i], i + 1 < data.variants.size() ? blocks[i + 1] : exit);
3218
3219            GetByIdVariant variant = data.variants[i];
3220            LValue result;
3221            if (variant.specificValue())
3222                result = m_out.constInt64(JSValue::encode(variant.specificValue()));
3223            else {
3224                LValue propertyBase;
3225                if (variant.chain())
3226                    propertyBase = weakPointer(variant.chain()->terminalPrototype());
3227                else
3228                    propertyBase = base;
3229                if (!isInlineOffset(variant.offset()))
3230                    propertyBase = m_out.loadPtr(propertyBase, m_heaps.JSObject_butterfly);
3231                result = loadProperty(propertyBase, data.identifierNumber, variant.offset());
3232            }
3233
3234            results.append(m_out.anchor(result));
3235            m_out.jump(continuation);
3236        }
3237
3238        m_out.appendTo(exit, continuation);
3239        terminate(BadCache);
3240        m_out.unreachable();
3241
3242        m_out.appendTo(continuation, lastNext);
3243        setJSValue(m_out.phi(m_out.int64, results));
3244    }
3245
3246    void compilePutByOffset()
3247    {
3248        StorageAccessData& data =
3249            m_graph.m_storageAccessData[m_node->storageAccessDataIndex()];
3250
3251        storeProperty(
3252            lowJSValue(m_node->child3()),
3253            lowStorage(m_node->child1()), data.identifierNumber, data.offset);
3254    }
3255
3256    void compileMultiPutByOffset()
3257    {
3258        LValue base = lowCell(m_node->child1());
3259        LValue value = lowJSValue(m_node->child2());
3260
3261        MultiPutByOffsetData& data = m_node->multiPutByOffsetData();
3262
3263        Vector<LBasicBlock, 2> blocks(data.variants.size());
3264        for (unsigned i = data.variants.size(); i--;)
3265            blocks[i] = FTL_NEW_BLOCK(m_out, ("MultiPutByOffset case ", i));
3266        LBasicBlock exit = FTL_NEW_BLOCK(m_out, ("MultiPutByOffset fail"));
3267        LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("MultiPutByOffset continuation"));
3268
3269        Vector<SwitchCase, 2> cases;
3270        for (unsigned i = data.variants.size(); i--;) {
3271            PutByIdVariant variant = data.variants[i];
3272            cases.append(
3273                SwitchCase(weakStructure(variant.oldStructure()), blocks[i], Weight(1)));
3274        }
3275        m_out.switchInstruction(
3276            m_out.load32(base, m_heaps.JSCell_structureID), cases, exit, Weight(0));
3277
3278        LBasicBlock lastNext = m_out.m_nextBlock;
3279
3280        for (unsigned i = data.variants.size(); i--;) {
3281            m_out.appendTo(blocks[i], i  + 1 < data.variants.size() ? blocks[i + 1] : exit);
3282
3283            PutByIdVariant variant = data.variants[i];
3284
3285            LValue storage;
3286            if (variant.kind() == PutByIdVariant::Replace) {
3287                if (isInlineOffset(variant.offset()))
3288                    storage = base;
3289                else
3290                    storage = m_out.loadPtr(base, m_heaps.JSObject_butterfly);
3291            } else {
3292                m_graph.m_plan.transitions.addLazily(
3293                    codeBlock(), m_node->origin.semantic.codeOriginOwner(),
3294                    variant.oldStructure(), variant.newStructure());
3295
3296                storage = storageForTransition(
3297                    base, variant.offset(), variant.oldStructure(), variant.newStructure());
3298
3299                ASSERT(variant.oldStructure()->indexingType() == variant.newStructure()->indexingType());
3300                ASSERT(variant.oldStructure()->typeInfo().inlineTypeFlags() == variant.newStructure()->typeInfo().inlineTypeFlags());
3301                ASSERT(variant.oldStructure()->typeInfo().type() == variant.newStructure()->typeInfo().type());
3302                m_out.store32(
3303                    weakStructure(variant.newStructure()), base, m_heaps.JSCell_structureID);
3304            }
3305
3306            storeProperty(value, storage, data.identifierNumber, variant.offset());
3307            m_out.jump(continuation);
3308        }
3309
3310        m_out.appendTo(exit, continuation);
3311        terminate(BadCache);
3312        m_out.unreachable();
3313
3314        m_out.appendTo(continuation, lastNext);
3315    }
3316
3317    void compileGetGlobalVar()
3318    {
3319        setJSValue(m_out.load64(m_out.absolute(m_node->registerPointer())));
3320    }
3321
3322    void compilePutGlobalVar()
3323    {
3324        m_out.store64(
3325            lowJSValue(m_node->child1()), m_out.absolute(m_node->registerPointer()));
3326    }
3327
3328    void compileNotifyWrite()
3329    {
3330        VariableWatchpointSet* set = m_node->variableWatchpointSet();
3331
3332        LValue value = lowJSValue(m_node->child1());
3333
3334        LBasicBlock isNotInvalidated = FTL_NEW_BLOCK(m_out, ("NotifyWrite not invalidated case"));
3335        LBasicBlock notifySlow = FTL_NEW_BLOCK(m_out, ("NotifyWrite notify slow case"));
3336        LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("NotifyWrite continuation"));
3337
3338        LValue state = m_out.load8(m_out.absolute(set->addressOfState()));
3339
3340        m_out.branch(
3341            m_out.equal(state, m_out.constInt8(IsInvalidated)),
3342            usually(continuation), rarely(isNotInvalidated));
3343
3344        LBasicBlock lastNext = m_out.appendTo(isNotInvalidated, notifySlow);
3345
3346        m_out.branch(
3347            m_out.equal(value, m_out.load64(m_out.absolute(set->addressOfInferredValue()))),
3348            unsure(continuation), unsure(notifySlow));
3349
3350        m_out.appendTo(notifySlow, continuation);
3351
3352        vmCall(m_out.operation(operationNotifyWrite), m_callFrame, m_out.constIntPtr(set), value);
3353        m_out.jump(continuation);
3354
3355        m_out.appendTo(continuation, lastNext);
3356    }
3357
3358    void compileGetCallee()
3359    {
3360        setJSValue(m_out.loadPtr(addressFor(JSStack::Callee)));
3361    }
3362
3363    void compileGetScope()
3364    {
3365        setJSValue(m_out.loadPtr(lowCell(m_node->child1()), m_heaps.JSFunction_scope));
3366    }
3367
3368    void compileGetMyScope()
3369    {
3370        setJSValue(m_out.loadPtr(addressFor(
3371            m_node->origin.semantic.stackOffset() + JSStack::ScopeChain)));
3372    }
3373
3374    void compileSkipScope()
3375    {
3376        setJSValue(m_out.loadPtr(lowCell(m_node->child1()), m_heaps.JSScope_next));
3377    }
3378
3379    void compileGetClosureRegisters()
3380    {
3381        if (WriteBarrierBase<Unknown>* registers = m_graph.tryGetRegisters(m_node->child1().node())) {
3382            setStorage(m_out.constIntPtr(registers));
3383            return;
3384        }
3385
3386        setStorage(m_out.loadPtr(
3387            lowCell(m_node->child1()), m_heaps.JSVariableObject_registers));
3388    }
3389
3390    void compileGetClosureVar()
3391    {
3392        setJSValue(m_out.load64(
3393            addressFor(lowStorage(m_node->child1()), m_node->varNumber())));
3394    }
3395
3396    void compilePutClosureVar()
3397    {
3398        m_out.store64(
3399            lowJSValue(m_node->child3()),
3400            addressFor(lowStorage(m_node->child2()), m_node->varNumber()));
3401    }
3402
3403    void compileCompareEq()
3404    {
3405        if (m_node->isBinaryUseKind(Int32Use)
3406            || m_node->isBinaryUseKind(Int52RepUse)
3407            || m_node->isBinaryUseKind(DoubleRepUse)
3408            || m_node->isBinaryUseKind(ObjectUse)
3409            || m_node->isBinaryUseKind(BooleanUse)
3410            || m_node->isBinaryUseKind(StringIdentUse)) {
3411            compileCompareStrictEq();
3412            return;
3413        }
3414
3415        if (m_node->isBinaryUseKind(ObjectUse, ObjectOrOtherUse)) {
3416            compareEqObjectOrOtherToObject(m_node->child2(), m_node->child1());
3417            return;
3418        }
3419
3420        if (m_node->isBinaryUseKind(ObjectOrOtherUse, ObjectUse)) {
3421            compareEqObjectOrOtherToObject(m_node->child1(), m_node->child2());
3422            return;
3423        }
3424
3425        if (m_node->isBinaryUseKind(UntypedUse)) {
3426            nonSpeculativeCompare(LLVMIntEQ, operationCompareEq);
3427            return;
3428        }
3429
3430        RELEASE_ASSERT_NOT_REACHED();
3431    }
3432
3433    void compileCompareEqConstant()
3434    {
3435        ASSERT(m_graph.valueOfJSConstant(m_node->child2().node()).isNull());
3436        setBoolean(
3437            equalNullOrUndefined(
3438                m_node->child1(), AllCellsAreFalse, EqualNullOrUndefined));
3439    }
3440
3441    void compileCompareStrictEq()
3442    {
3443        if (m_node->isBinaryUseKind(Int32Use)) {
3444            setBoolean(
3445                m_out.equal(lowInt32(m_node->child1()), lowInt32(m_node->child2())));
3446            return;
3447        }
3448
3449        if (m_node->isBinaryUseKind(Int52RepUse)) {
3450            Int52Kind kind;
3451            LValue left = lowWhicheverInt52(m_node->child1(), kind);
3452            LValue right = lowInt52(m_node->child2(), kind);
3453            setBoolean(m_out.equal(left, right));
3454            return;
3455        }
3456
3457        if (m_node->isBinaryUseKind(DoubleRepUse)) {
3458            setBoolean(
3459                m_out.doubleEqual(lowDouble(m_node->child1()), lowDouble(m_node->child2())));
3460            return;
3461        }
3462
3463        if (m_node->isBinaryUseKind(StringIdentUse)) {
3464            setBoolean(
3465                m_out.equal(lowStringIdent(m_node->child1()), lowStringIdent(m_node->child2())));
3466            return;
3467        }
3468
3469        if (m_node->isBinaryUseKind(ObjectUse)) {
3470            setBoolean(
3471                m_out.equal(
3472                    lowNonNullObject(m_node->child1()),
3473                    lowNonNullObject(m_node->child2())));
3474            return;
3475        }
3476
3477        if (m_node->isBinaryUseKind(BooleanUse)) {
3478            setBoolean(
3479                m_out.equal(lowBoolean(m_node->child1()), lowBoolean(m_node->child2())));
3480            return;
3481        }
3482
3483        if (m_node->isBinaryUseKind(MiscUse, UntypedUse)
3484            || m_node->isBinaryUseKind(UntypedUse, MiscUse)) {
3485            speculate(m_node->child1());
3486            speculate(m_node->child2());
3487            LValue left = lowJSValue(m_node->child1(), ManualOperandSpeculation);
3488            LValue right = lowJSValue(m_node->child2(), ManualOperandSpeculation);
3489            setBoolean(m_out.equal(left, right));
3490            return;
3491        }
3492
3493        if (m_node->isBinaryUseKind(StringIdentUse, NotStringVarUse)
3494            || m_node->isBinaryUseKind(NotStringVarUse, StringIdentUse)) {
3495            Edge leftEdge = m_node->childFor(StringIdentUse);
3496            Edge rightEdge = m_node->childFor(NotStringVarUse);
3497
3498            LValue left = lowStringIdent(leftEdge);
3499            LValue rightValue = lowJSValue(rightEdge, ManualOperandSpeculation);
3500
3501            LBasicBlock isCellCase = FTL_NEW_BLOCK(m_out, ("CompareStrictEq StringIdent to NotStringVar is cell case"));
3502            LBasicBlock isStringCase = FTL_NEW_BLOCK(m_out, ("CompareStrictEq StringIdent to NotStringVar is string case"));
3503            LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("CompareStrictEq StringIdent to NotStringVar continuation"));
3504
3505            ValueFromBlock notCellResult = m_out.anchor(m_out.booleanFalse);
3506            m_out.branch(isCell(rightValue), unsure(isCellCase), unsure(continuation));
3507
3508            LBasicBlock lastNext = m_out.appendTo(isCellCase, isStringCase);
3509            ValueFromBlock notStringResult = m_out.anchor(m_out.booleanFalse);
3510            m_out.branch(isString(rightValue), unsure(isStringCase), unsure(continuation));
3511
3512            m_out.appendTo(isStringCase, continuation);
3513            LValue right = m_out.loadPtr(rightValue, m_heaps.JSString_value);
3514            speculateStringIdent(rightEdge, rightValue, right);
3515            ValueFromBlock isStringResult = m_out.anchor(m_out.equal(left, right));
3516            m_out.jump(continuation);
3517
3518            m_out.appendTo(continuation, lastNext);
3519            setBoolean(m_out.phi(m_out.boolean, notCellResult, notStringResult, isStringResult));
3520            return;
3521        }
3522
3523        RELEASE_ASSERT_NOT_REACHED();
3524    }
3525
3526    void compileCompareStrictEqConstant()
3527    {
3528        JSValue constant = m_graph.valueOfJSConstant(m_node->child2().node());
3529
3530        setBoolean(
3531            m_out.equal(
3532                lowJSValue(m_node->child1()),
3533                m_out.constInt64(JSValue::encode(constant))));
3534    }
3535
3536    void compileCompareLess()
3537    {
3538        compare(LLVMIntSLT, LLVMRealOLT, operationCompareLess);
3539    }
3540
3541    void compileCompareLessEq()
3542    {
3543        compare(LLVMIntSLE, LLVMRealOLE, operationCompareLessEq);
3544    }
3545
3546    void compileCompareGreater()
3547    {
3548        compare(LLVMIntSGT, LLVMRealOGT, operationCompareGreater);
3549    }
3550
3551    void compileCompareGreaterEq()
3552    {
3553        compare(LLVMIntSGE, LLVMRealOGE, operationCompareGreaterEq);
3554    }
3555
3556    void compileLogicalNot()
3557    {
3558        setBoolean(m_out.bitNot(boolify(m_node->child1())));
3559    }
3560
3561    void compileCallOrConstruct()
3562    {
3563        int dummyThisArgument = m_node->op() == Call ? 0 : 1;
3564        int numPassedArgs = m_node->numChildren() - 1;
3565        int numArgs = numPassedArgs + dummyThisArgument;
3566
3567        LValue callee = lowJSValue(m_graph.varArgChild(m_node, 0));
3568
3569        unsigned stackmapID = m_stackmapIDs++;
3570
3571        Vector<LValue> arguments;
3572        arguments.append(m_out.constInt64(stackmapID));
3573        arguments.append(m_out.constInt32(sizeOfCall()));
3574        arguments.append(constNull(m_out.ref8));
3575        arguments.append(m_out.constInt32(1 + JSStack::CallFrameHeaderSize - JSStack::CallerFrameAndPCSize + numArgs));
3576        arguments.append(callee); // callee -> %rax
3577        arguments.append(getUndef(m_out.int64)); // code block
3578        arguments.append(getUndef(m_out.int64)); // scope chain
3579        arguments.append(callee); // callee -> stack
3580        arguments.append(m_out.constInt64(numArgs)); // argument count and zeros for the tag
3581        if (dummyThisArgument)
3582            arguments.append(getUndef(m_out.int64));
3583        for (int i = 0; i < numPassedArgs; ++i)
3584            arguments.append(lowJSValue(m_graph.varArgChild(m_node, 1 + i)));
3585
3586        callPreflight();
3587
3588        LValue call = m_out.call(m_out.patchpointInt64Intrinsic(), arguments);
3589        setInstructionCallingConvention(call, LLVMWebKitJSCallConv);
3590
3591        m_ftlState.jsCalls.append(JSCall(stackmapID, m_node));
3592
3593        setJSValue(call);
3594    }
3595
3596    void compileJump()
3597    {
3598        m_out.jump(lowBlock(m_node->targetBlock()));
3599    }
3600
3601    void compileBranch()
3602    {
3603        m_out.branch(
3604            boolify(m_node->child1()),
3605            WeightedTarget(
3606                lowBlock(m_node->branchData()->taken.block),
3607                m_node->branchData()->taken.count),
3608            WeightedTarget(
3609                lowBlock(m_node->branchData()->notTaken.block),
3610                m_node->branchData()->notTaken.count));
3611    }
3612
3613    void compileSwitch()
3614    {
3615        SwitchData* data = m_node->switchData();
3616        switch (data->kind) {
3617        case SwitchImm: {
3618            Vector<ValueFromBlock, 2> intValues;
3619            LBasicBlock switchOnInts = FTL_NEW_BLOCK(m_out, ("Switch/SwitchImm int case"));
3620
3621            LBasicBlock lastNext = m_out.appendTo(m_out.m_block, switchOnInts);
3622
3623            switch (m_node->child1().useKind()) {
3624            case Int32Use: {
3625                intValues.append(m_out.anchor(lowInt32(m_node->child1())));
3626                m_out.jump(switchOnInts);
3627                break;
3628            }
3629
3630            case UntypedUse: {
3631                LBasicBlock isInt = FTL_NEW_BLOCK(m_out, ("Switch/SwitchImm is int"));
3632                LBasicBlock isNotInt = FTL_NEW_BLOCK(m_out, ("Switch/SwitchImm is not int"));
3633                LBasicBlock isDouble = FTL_NEW_BLOCK(m_out, ("Switch/SwitchImm is double"));
3634
3635                LValue boxedValue = lowJSValue(m_node->child1());
3636                m_out.branch(isNotInt32(boxedValue), unsure(isNotInt), unsure(isInt));
3637
3638                LBasicBlock innerLastNext = m_out.appendTo(isInt, isNotInt);
3639
3640                intValues.append(m_out.anchor(unboxInt32(boxedValue)));
3641                m_out.jump(switchOnInts);
3642
3643                m_out.appendTo(isNotInt, isDouble);
3644                m_out.branch(
3645                    isCellOrMisc(boxedValue),
3646                    usually(lowBlock(data->fallThrough.block)), rarely(isDouble));
3647
3648                m_out.appendTo(isDouble, innerLastNext);
3649                LValue doubleValue = unboxDouble(boxedValue);
3650                LValue intInDouble = m_out.fpToInt32(doubleValue);
3651                intValues.append(m_out.anchor(intInDouble));
3652                m_out.branch(
3653                    m_out.doubleEqual(m_out.intToDouble(intInDouble), doubleValue),
3654                    unsure(switchOnInts), unsure(lowBlock(data->fallThrough.block)));
3655                break;
3656            }
3657
3658            default:
3659                RELEASE_ASSERT_NOT_REACHED();
3660                break;
3661            }
3662
3663            m_out.appendTo(switchOnInts, lastNext);
3664            buildSwitch(data, m_out.int32, m_out.phi(m_out.int32, intValues));
3665            return;
3666        }
3667
3668        case SwitchChar: {
3669            LValue stringValue;
3670
3671            // FIXME: We should use something other than unsure() for the branch weight
3672            // of the fallThrough block. The main challenge is just that we have multiple
3673            // branches to fallThrough but a single count, so we would need to divvy it up
3674            // among the different lowered branches.
3675            // https://bugs.webkit.org/show_bug.cgi?id=129082
3676
3677            switch (m_node->child1().useKind()) {
3678            case StringUse: {
3679                stringValue = lowString(m_node->child1());
3680                break;
3681            }
3682
3683            case UntypedUse: {
3684                LValue unboxedValue = lowJSValue(m_node->child1());
3685
3686                LBasicBlock isCellCase = FTL_NEW_BLOCK(m_out, ("Switch/SwitchChar is cell"));
3687                LBasicBlock isStringCase = FTL_NEW_BLOCK(m_out, ("Switch/SwitchChar is string"));
3688
3689                m_out.branch(
3690                    isNotCell(unboxedValue),
3691                    unsure(lowBlock(data->fallThrough.block)), unsure(isCellCase));
3692
3693                LBasicBlock lastNext = m_out.appendTo(isCellCase, isStringCase);
3694                LValue cellValue = unboxedValue;
3695                m_out.branch(
3696                    isNotString(cellValue),
3697                    unsure(lowBlock(data->fallThrough.block)), unsure(isStringCase));
3698
3699                m_out.appendTo(isStringCase, lastNext);
3700                stringValue = cellValue;
3701                break;
3702            }
3703
3704            default:
3705                RELEASE_ASSERT_NOT_REACHED();
3706                break;
3707            }
3708
3709            LBasicBlock lengthIs1 = FTL_NEW_BLOCK(m_out, ("Switch/SwitchChar length is 1"));
3710            LBasicBlock needResolution = FTL_NEW_BLOCK(m_out, ("Switch/SwitchChar resolution"));
3711            LBasicBlock resolved = FTL_NEW_BLOCK(m_out, ("Switch/SwitchChar resolved"));
3712            LBasicBlock is8Bit = FTL_NEW_BLOCK(m_out, ("Switch/SwitchChar 8bit"));
3713            LBasicBlock is16Bit = FTL_NEW_BLOCK(m_out, ("Switch/SwitchChar 16bit"));
3714            LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("Switch/SwitchChar continuation"));
3715
3716            m_out.branch(
3717                m_out.notEqual(
3718                    m_out.load32NonNegative(stringValue, m_heaps.JSString_length),
3719                    m_out.int32One),
3720                unsure(lowBlock(data->fallThrough.block)), unsure(lengthIs1));
3721
3722            LBasicBlock lastNext = m_out.appendTo(lengthIs1, needResolution);
3723            Vector<ValueFromBlock, 2> values;
3724            LValue fastValue = m_out.loadPtr(stringValue, m_heaps.JSString_value);
3725            values.append(m_out.anchor(fastValue));
3726            m_out.branch(m_out.isNull(fastValue), rarely(needResolution), usually(resolved));
3727
3728            m_out.appendTo(needResolution, resolved);
3729            values.append(m_out.anchor(
3730                vmCall(m_out.operation(operationResolveRope), m_callFrame, stringValue)));
3731            m_out.jump(resolved);
3732
3733            m_out.appendTo(resolved, is8Bit);
3734            LValue value = m_out.phi(m_out.intPtr, values);
3735            LValue characterData = m_out.loadPtr(value, m_heaps.StringImpl_data);
3736            m_out.branch(
3737                m_out.testNonZero32(
3738                    m_out.load32(value, m_heaps.StringImpl_hashAndFlags),
3739                    m_out.constInt32(StringImpl::flagIs8Bit())),
3740                unsure(is8Bit), unsure(is16Bit));
3741
3742            Vector<ValueFromBlock, 2> characters;
3743            m_out.appendTo(is8Bit, is16Bit);
3744            characters.append(m_out.anchor(
3745                m_out.zeroExt(m_out.load8(characterData, m_heaps.characters8[0]), m_out.int16)));
3746            m_out.jump(continuation);
3747
3748            m_out.appendTo(is16Bit, continuation);
3749            characters.append(m_out.anchor(m_out.load16(characterData, m_heaps.characters16[0])));
3750            m_out.jump(continuation);
3751
3752            m_out.appendTo(continuation, lastNext);
3753            buildSwitch(data, m_out.int16, m_out.phi(m_out.int16, characters));
3754            return;
3755        }
3756
3757        case SwitchString:
3758            RELEASE_ASSERT_NOT_REACHED();
3759            break;
3760        }
3761
3762        RELEASE_ASSERT_NOT_REACHED();
3763    }
3764
3765    void compileReturn()
3766    {
3767        m_out.ret(lowJSValue(m_node->child1()));
3768    }
3769
3770    void compileForceOSRExit()
3771    {
3772        terminate(InadequateCoverage);
3773    }
3774
3775    void compileThrow()
3776    {
3777        terminate(Uncountable);
3778    }
3779
3780    void compileInvalidationPoint()
3781    {
3782        if (verboseCompilationEnabled())
3783            dataLog("    Invalidation point with availability: ", m_availability, "\n");
3784
3785        m_ftlState.jitCode->osrExit.append(OSRExit(
3786            UncountableInvalidation, InvalidValueFormat, MethodOfGettingAValueProfile(),
3787            m_codeOriginForExitTarget, m_codeOriginForExitProfile,
3788            m_availability.numberOfArguments(), m_availability.numberOfLocals()));
3789        m_ftlState.finalizer->osrExit.append(OSRExitCompilationInfo());
3790
3791        OSRExit& exit = m_ftlState.jitCode->osrExit.last();
3792        OSRExitCompilationInfo& info = m_ftlState.finalizer->osrExit.last();
3793
3794        ExitArgumentList arguments;
3795
3796        buildExitArguments(exit, arguments, FormattedValue(), exit.m_codeOrigin);
3797        callStackmap(exit, arguments);
3798
3799        info.m_isInvalidationPoint = true;
3800    }
3801
3802    void compileCheckArgumentsNotCreated()
3803    {
3804        ASSERT(!isEmptySpeculation(
3805            m_state.variables().operand(
3806                m_graph.argumentsRegisterFor(m_node->origin.semantic)).m_type));
3807
3808        checkArgumentsNotCreated();
3809    }
3810
3811    void compileIsUndefined()
3812    {
3813        setBoolean(equalNullOrUndefined(m_node->child1(), AllCellsAreFalse, EqualUndefined));
3814    }
3815
3816    void compileIsBoolean()
3817    {
3818        setBoolean(isBoolean(lowJSValue(m_node->child1())));
3819    }
3820
3821    void compileIsNumber()
3822    {
3823        setBoolean(isNumber(lowJSValue(m_node->child1())));
3824    }
3825
3826    void compileIsString()
3827    {
3828        LValue value = lowJSValue(m_node->child1());
3829
3830        LBasicBlock isCellCase = FTL_NEW_BLOCK(m_out, ("IsString cell case"));
3831        LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("IsString continuation"));
3832
3833        ValueFromBlock notCellResult = m_out.anchor(m_out.booleanFalse);
3834        m_out.branch(isCell(value), unsure(isCellCase), unsure(continuation));
3835
3836        LBasicBlock lastNext = m_out.appendTo(isCellCase, continuation);
3837        ValueFromBlock cellResult = m_out.anchor(isString(value));
3838        m_out.jump(continuation);
3839
3840        m_out.appendTo(continuation, lastNext);
3841        setBoolean(m_out.phi(m_out.boolean, notCellResult, cellResult));
3842    }
3843
3844    void compileIsObject()
3845    {
3846        LValue pointerResult = vmCall(
3847            m_out.operation(operationIsObject), m_callFrame, lowJSValue(m_node->child1()));
3848        setBoolean(m_out.notNull(pointerResult));
3849    }
3850
3851    void compileIsFunction()
3852    {
3853        LValue pointerResult = vmCall(
3854            m_out.operation(operationIsFunction), lowJSValue(m_node->child1()));
3855        setBoolean(m_out.notNull(pointerResult));
3856    }
3857
3858    void compileCheckHasInstance()
3859    {
3860        speculate(
3861            Uncountable, noValue(), 0,
3862            m_out.testIsZero8(
3863                m_out.load8(lowCell(m_node->child1()), m_heaps.JSCell_typeInfoFlags),
3864                m_out.constInt8(ImplementsDefaultHasInstance)));
3865    }
3866
3867    void compileInstanceOf()
3868    {
3869        LValue cell;
3870
3871        if (m_node->child1().useKind() == UntypedUse)
3872            cell = lowJSValue(m_node->child1());
3873        else
3874            cell = lowCell(m_node->child1());
3875
3876        LValue prototype = lowCell(m_node->child2());
3877
3878        LBasicBlock isCellCase = FTL_NEW_BLOCK(m_out, ("InstanceOf cell case"));
3879        LBasicBlock loop = FTL_NEW_BLOCK(m_out, ("InstanceOf loop"));
3880        LBasicBlock notYetInstance = FTL_NEW_BLOCK(m_out, ("InstanceOf not yet instance"));
3881        LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("InstanceOf continuation"));
3882
3883        LValue condition;
3884        if (m_node->child1().useKind() == UntypedUse)
3885            condition = isCell(cell);
3886        else
3887            condition = m_out.booleanTrue;
3888
3889        ValueFromBlock notCellResult = m_out.anchor(m_out.booleanFalse);
3890        m_out.branch(condition, unsure(isCellCase), unsure(continuation));
3891
3892        LBasicBlock lastNext = m_out.appendTo(isCellCase, loop);
3893
3894        speculate(BadType, noValue(), 0, isNotObject(prototype));
3895
3896        ValueFromBlock originalValue = m_out.anchor(cell);
3897        m_out.jump(loop);
3898
3899        m_out.appendTo(loop, notYetInstance);
3900        LValue value = m_out.phi(m_out.int64, originalValue);
3901        LValue structure = loadStructure(value);
3902        LValue currentPrototype = m_out.load64(structure, m_heaps.Structure_prototype);
3903        ValueFromBlock isInstanceResult = m_out.anchor(m_out.booleanTrue);
3904        m_out.branch(
3905            m_out.equal(currentPrototype, prototype),
3906            unsure(continuation), unsure(notYetInstance));
3907
3908        m_out.appendTo(notYetInstance, continuation);
3909        ValueFromBlock notInstanceResult = m_out.anchor(m_out.booleanFalse);
3910        addIncoming(value, m_out.anchor(currentPrototype));
3911        m_out.branch(isCell(currentPrototype), unsure(loop), unsure(continuation));
3912
3913        m_out.appendTo(continuation, lastNext);
3914        setBoolean(
3915            m_out.phi(m_out.boolean, notCellResult, isInstanceResult, notInstanceResult));
3916    }
3917
3918    void compileCountExecution()
3919    {
3920        TypedPointer counter = m_out.absolute(m_node->executionCounter()->address());
3921        m_out.store64(m_out.add(m_out.load64(counter), m_out.constInt64(1)), counter);
3922    }
3923
3924    void compileStoreBarrier()
3925    {
3926        emitStoreBarrier(lowCell(m_node->child1()));
3927    }
3928
3929    void compileStoreBarrierWithNullCheck()
3930    {
3931#if ENABLE(GGC)
3932        LBasicBlock isNotNull = FTL_NEW_BLOCK(m_out, ("Store barrier with null check value not null"));
3933        LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("Store barrier continuation"));
3934
3935        LValue base = lowJSValue(m_node->child1());
3936        m_out.branch(m_out.isZero64(base), unsure(continuation), unsure(isNotNull));
3937        LBasicBlock lastNext = m_out.appendTo(isNotNull, continuation);
3938        emitStoreBarrier(base);
3939        m_out.appendTo(continuation, lastNext);
3940#else
3941        speculate(m_node->child1());
3942#endif
3943    }
3944
3945    LValue didOverflowStack()
3946    {
3947        // This does a very simple leaf function analysis. The invariant of FTL call
3948        // frames is that the caller had already done enough of a stack check to
3949        // prove that this call frame has enough stack to run, and also enough stack
3950        // to make runtime calls. So, we only need to stack check when making calls
3951        // to other JS functions. If we don't find such calls then we don't need to
3952        // do any stack checks.
3953
3954        for (BlockIndex blockIndex = 0; blockIndex < m_graph.numBlocks(); ++blockIndex) {
3955            BasicBlock* block = m_graph.block(blockIndex);
3956            if (!block)
3957                continue;
3958
3959            for (unsigned nodeIndex = block->size(); nodeIndex--;) {
3960                Node* node = block->at(nodeIndex);
3961
3962                switch (node->op()) {
3963                case GetById:
3964                case PutById:
3965                case Call:
3966                case Construct:
3967                    return m_out.below(
3968                        m_callFrame,
3969                        m_out.loadPtr(
3970                            m_out.absolute(vm().addressOfFTLStackLimit())));
3971
3972                default:
3973                    break;
3974                }
3975            }
3976        }
3977
3978        return m_out.booleanFalse;
3979    }
3980
3981    LValue numberOrNotCellToInt32(Edge edge, LValue value)
3982    {
3983        LBasicBlock intCase = FTL_NEW_BLOCK(m_out, ("ValueToInt32 int case"));
3984        LBasicBlock notIntCase = FTL_NEW_BLOCK(m_out, ("ValueToInt32 not int case"));
3985        LBasicBlock doubleCase = 0;
3986        LBasicBlock notNumberCase = 0;
3987        if (edge.useKind() == NotCellUse) {
3988            doubleCase = FTL_NEW_BLOCK(m_out, ("ValueToInt32 double case"));
3989            notNumberCase = FTL_NEW_BLOCK(m_out, ("ValueToInt32 not number case"));
3990        }
3991        LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("ValueToInt32 continuation"));
3992
3993        Vector<ValueFromBlock> results;
3994
3995        m_out.branch(isNotInt32(value), unsure(notIntCase), unsure(intCase));
3996
3997        LBasicBlock lastNext = m_out.appendTo(intCase, notIntCase);
3998        results.append(m_out.anchor(unboxInt32(value)));
3999        m_out.jump(continuation);
4000
4001        if (edge.useKind() == NumberUse) {
4002            m_out.appendTo(notIntCase, continuation);
4003            FTL_TYPE_CHECK(jsValueValue(value), edge, SpecBytecodeNumber, isCellOrMisc(value));
4004            results.append(m_out.anchor(doubleToInt32(unboxDouble(value))));
4005            m_out.jump(continuation);
4006        } else {
4007            m_out.appendTo(notIntCase, doubleCase);
4008            m_out.branch(isCellOrMisc(value), unsure(notNumberCase), unsure(doubleCase));
4009
4010            m_out.appendTo(doubleCase, notNumberCase);
4011            results.append(m_out.anchor(doubleToInt32(unboxDouble(value))));
4012            m_out.jump(continuation);
4013
4014            m_out.appendTo(notNumberCase, continuation);
4015
4016            FTL_TYPE_CHECK(jsValueValue(value), edge, ~SpecCell, isCell(value));
4017
4018            LValue specialResult = m_out.select(
4019                m_out.equal(value, m_out.constInt64(JSValue::encode(jsBoolean(true)))),
4020                m_out.int32One, m_out.int32Zero);
4021            results.append(m_out.anchor(specialResult));
4022            m_out.jump(continuation);
4023        }
4024
4025        m_out.appendTo(continuation, lastNext);
4026        return m_out.phi(m_out.int32, results);
4027    }
4028
4029    LValue loadProperty(LValue storage, unsigned identifierNumber, PropertyOffset offset)
4030    {
4031        return m_out.load64(addressOfProperty(storage, identifierNumber, offset));
4032    }
4033
4034    void storeProperty(
4035        LValue value, LValue storage, unsigned identifierNumber, PropertyOffset offset)
4036    {
4037        m_out.store64(value, addressOfProperty(storage, identifierNumber, offset));
4038    }
4039
4040    TypedPointer addressOfProperty(
4041        LValue storage, unsigned identifierNumber, PropertyOffset offset)
4042    {
4043        return m_out.address(
4044            m_heaps.properties[identifierNumber], storage, offsetRelativeToBase(offset));
4045    }
4046
4047    LValue storageForTransition(
4048        LValue object, PropertyOffset offset,
4049        Structure* previousStructure, Structure* nextStructure)
4050    {
4051        if (isInlineOffset(offset))
4052            return object;
4053
4054        if (previousStructure->outOfLineCapacity() == nextStructure->outOfLineCapacity())
4055            return m_out.loadPtr(object, m_heaps.JSObject_butterfly);
4056
4057        LValue result;
4058        if (!previousStructure->outOfLineCapacity())
4059            result = allocatePropertyStorage(object, previousStructure);
4060        else {
4061            result = reallocatePropertyStorage(
4062                object, m_out.loadPtr(object, m_heaps.JSObject_butterfly),
4063                previousStructure, nextStructure);
4064        }
4065
4066        emitStoreBarrier(object);
4067
4068        return result;
4069    }
4070
4071    LValue allocatePropertyStorage(LValue object, Structure* previousStructure)
4072    {
4073        if (previousStructure->couldHaveIndexingHeader()) {
4074            return vmCall(
4075                m_out.operation(
4076                    operationReallocateButterflyToHavePropertyStorageWithInitialCapacity),
4077                m_callFrame, object);
4078        }
4079
4080        LBasicBlock slowPath = FTL_NEW_BLOCK(m_out, ("allocatePropertyStorage slow path"));
4081        LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("allocatePropertyStorage continuation"));
4082
4083        LBasicBlock lastNext = m_out.insertNewBlocksBefore(slowPath);
4084
4085        LValue endOfStorage = allocateBasicStorageAndGetEnd(
4086            m_out.constIntPtr(initialOutOfLineCapacity * sizeof(JSValue)), slowPath);
4087
4088        ValueFromBlock fastButterfly = m_out.anchor(
4089            m_out.add(m_out.constIntPtr(sizeof(IndexingHeader)), endOfStorage));
4090
4091        m_out.jump(continuation);
4092
4093        m_out.appendTo(slowPath, continuation);
4094
4095        ValueFromBlock slowButterfly = m_out.anchor(vmCall(
4096            m_out.operation(operationAllocatePropertyStorageWithInitialCapacity), m_callFrame));
4097
4098        m_out.jump(continuation);
4099
4100        m_out.appendTo(continuation, lastNext);
4101
4102        LValue result = m_out.phi(m_out.intPtr, fastButterfly, slowButterfly);
4103        m_out.storePtr(result, object, m_heaps.JSObject_butterfly);
4104
4105        return result;
4106    }
4107
4108    LValue reallocatePropertyStorage(
4109        LValue object, LValue oldStorage, Structure* previous, Structure* next)
4110    {
4111        size_t oldSize = previous->outOfLineCapacity() * sizeof(JSValue);
4112        size_t newSize = oldSize * outOfLineGrowthFactor;
4113
4114        ASSERT_UNUSED(next, newSize == next->outOfLineCapacity() * sizeof(JSValue));
4115
4116        if (previous->couldHaveIndexingHeader()) {
4117            LValue newAllocSize = m_out.constInt64(newSize / sizeof(JSValue));
4118            return vmCall(m_out.operation(operationReallocateButterflyToGrowPropertyStorage), m_callFrame, object, newAllocSize);
4119        }
4120
4121        LBasicBlock slowPath = FTL_NEW_BLOCK(m_out, ("reallocatePropertyStorage slow path"));
4122        LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("reallocatePropertyStorage continuation"));
4123        LBasicBlock lastNext = m_out.insertNewBlocksBefore(slowPath);
4124
4125        LValue endOfStorage =
4126            allocateBasicStorageAndGetEnd(m_out.constIntPtr(newSize), slowPath);
4127
4128        ValueFromBlock fastButterfly = m_out.anchor(m_out.add(m_out.constIntPtr(sizeof(IndexingHeader)), endOfStorage));
4129
4130        m_out.jump(continuation);
4131
4132        m_out.appendTo(slowPath, continuation);
4133
4134        LValue newAllocSize = m_out.constInt64(newSize / sizeof(JSValue));
4135
4136        LValue storageLocation = vmCall(m_out.operation(operationAllocatePropertyStorage), m_callFrame, newAllocSize);
4137
4138        ValueFromBlock slowButterfly = m_out.anchor(storageLocation);
4139
4140        m_out.jump(continuation);
4141
4142        m_out.appendTo(continuation, lastNext);
4143
4144        LValue result = m_out.phi(m_out.intPtr, fastButterfly, slowButterfly);
4145
4146        ptrdiff_t headerSize = -sizeof(JSValue) - sizeof(void *);
4147        ptrdiff_t endStorage = headerSize - static_cast<ptrdiff_t>(oldSize);
4148
4149        for (ptrdiff_t offset = headerSize; offset > endStorage; offset -= sizeof(void*)) {
4150            LValue loaded =
4151                m_out.loadPtr(m_out.address(m_heaps.properties.atAnyNumber(), oldStorage, offset));
4152            m_out.storePtr(loaded, m_out.address(m_heaps.properties.atAnyNumber(), result, offset));
4153        }
4154
4155        m_out.storePtr(result, m_out.address(object, m_heaps.JSObject_butterfly));
4156
4157        return result;
4158    }
4159
4160    LValue getById(LValue base)
4161    {
4162        StringImpl* uid = m_graph.identifiers()[m_node->identifierNumber()];
4163
4164        // Arguments: id, bytes, target, numArgs, args...
4165        unsigned stackmapID = m_stackmapIDs++;
4166
4167        if (Options::verboseCompilation())
4168            dataLog("    Emitting GetById patchpoint with stackmap #", stackmapID, "\n");
4169
4170        LValue call = m_out.call(
4171            m_out.patchpointInt64Intrinsic(),
4172            m_out.constInt64(stackmapID), m_out.constInt32(sizeOfGetById()),
4173            constNull(m_out.ref8), m_out.constInt32(1), base);
4174        setInstructionCallingConvention(call, LLVMAnyRegCallConv);
4175
4176        m_ftlState.getByIds.append(GetByIdDescriptor(stackmapID, m_node->origin.semantic, uid));
4177
4178        return call;
4179    }
4180
4181    TypedPointer baseIndex(IndexedAbstractHeap& heap, LValue storage, LValue index, Edge edge)
4182    {
4183        return m_out.baseIndex(
4184            heap, storage, m_out.zeroExt(index, m_out.intPtr),
4185            m_state.forNode(edge).m_value);
4186    }
4187
4188    void compare(
4189        LIntPredicate intCondition, LRealPredicate realCondition,
4190        S_JITOperation_EJJ helperFunction)
4191    {
4192        if (m_node->isBinaryUseKind(Int32Use)) {
4193            LValue left = lowInt32(m_node->child1());
4194            LValue right = lowInt32(m_node->child2());
4195            setBoolean(m_out.icmp(intCondition, left, right));
4196            return;
4197        }
4198
4199        if (m_node->isBinaryUseKind(Int52RepUse)) {
4200            Int52Kind kind;
4201            LValue left = lowWhicheverInt52(m_node->child1(), kind);
4202            LValue right = lowInt52(m_node->child2(), kind);
4203            setBoolean(m_out.icmp(intCondition, left, right));
4204            return;
4205        }
4206
4207        if (m_node->isBinaryUseKind(DoubleRepUse)) {
4208            LValue left = lowDouble(m_node->child1());
4209            LValue right = lowDouble(m_node->child2());
4210            setBoolean(m_out.fcmp(realCondition, left, right));
4211            return;
4212        }
4213
4214        if (m_node->isBinaryUseKind(UntypedUse)) {
4215            nonSpeculativeCompare(intCondition, helperFunction);
4216            return;
4217        }
4218
4219        RELEASE_ASSERT_NOT_REACHED();
4220    }
4221
4222    void compareEqObjectOrOtherToObject(Edge leftChild, Edge rightChild)
4223    {
4224        LValue rightCell = lowCell(rightChild);
4225        LValue leftValue = lowJSValue(leftChild, ManualOperandSpeculation);
4226
4227        speculateTruthyObject(rightChild, rightCell, SpecObject);
4228
4229        LBasicBlock leftCellCase = FTL_NEW_BLOCK(m_out, ("CompareEqObjectOrOtherToObject left cell case"));
4230        LBasicBlock leftNotCellCase = FTL_NEW_BLOCK(m_out, ("CompareEqObjectOrOtherToObject left not cell case"));
4231        LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("CompareEqObjectOrOtherToObject continuation"));
4232
4233        m_out.branch(isCell(leftValue), unsure(leftCellCase), unsure(leftNotCellCase));
4234
4235        LBasicBlock lastNext = m_out.appendTo(leftCellCase, leftNotCellCase);
4236        speculateTruthyObject(leftChild, leftValue, SpecObject | (~SpecCell));
4237        ValueFromBlock cellResult = m_out.anchor(m_out.equal(rightCell, leftValue));
4238        m_out.jump(continuation);
4239
4240        m_out.appendTo(leftNotCellCase, continuation);
4241        FTL_TYPE_CHECK(
4242            jsValueValue(leftValue), leftChild, SpecOther | SpecCell, isNotOther(leftValue));
4243        ValueFromBlock notCellResult = m_out.anchor(m_out.booleanFalse);
4244        m_out.jump(continuation);
4245
4246        m_out.appendTo(continuation, lastNext);
4247        setBoolean(m_out.phi(m_out.boolean, cellResult, notCellResult));
4248    }
4249
4250    void speculateTruthyObject(Edge edge, LValue cell, SpeculatedType filter)
4251    {
4252        if (masqueradesAsUndefinedWatchpointIsStillValid()) {
4253            FTL_TYPE_CHECK(jsValueValue(cell), edge, filter, isNotObject(cell));
4254            return;
4255        }
4256
4257        LValue structureID = m_out.load32(cell, m_heaps.JSCell_structureID);
4258        FTL_TYPE_CHECK(
4259            jsValueValue(cell), edge, filter,
4260            m_out.equal(structureID, m_out.constInt32(vm().stringStructure->id())));
4261        speculate(
4262            BadType, jsValueValue(cell), edge.node(),
4263            m_out.testNonZero8(
4264                m_out.load8(cell, m_heaps.JSCell_typeInfoFlags),
4265                m_out.constInt8(MasqueradesAsUndefined)));
4266    }
4267
4268    void nonSpeculativeCompare(LIntPredicate intCondition, S_JITOperation_EJJ helperFunction)
4269    {
4270        LValue left = lowJSValue(m_node->child1());
4271        LValue right = lowJSValue(m_node->child2());
4272
4273        LBasicBlock leftIsInt = FTL_NEW_BLOCK(m_out, ("CompareEq untyped left is int"));
4274        LBasicBlock fastPath = FTL_NEW_BLOCK(m_out, ("CompareEq untyped fast path"));
4275        LBasicBlock slowPath = FTL_NEW_BLOCK(m_out, ("CompareEq untyped slow path"));
4276        LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("CompareEq untyped continuation"));
4277
4278        m_out.branch(isNotInt32(left), rarely(slowPath), usually(leftIsInt));
4279
4280        LBasicBlock lastNext = m_out.appendTo(leftIsInt, fastPath);
4281        m_out.branch(isNotInt32(right), rarely(slowPath), usually(fastPath));
4282
4283        m_out.appendTo(fastPath, slowPath);
4284        ValueFromBlock fastResult = m_out.anchor(
4285            m_out.icmp(intCondition, unboxInt32(left), unboxInt32(right)));
4286        m_out.jump(continuation);
4287
4288        m_out.appendTo(slowPath, continuation);
4289        ValueFromBlock slowResult = m_out.anchor(m_out.notNull(vmCall(
4290            m_out.operation(helperFunction), m_callFrame, left, right)));
4291        m_out.jump(continuation);
4292
4293        m_out.appendTo(continuation, lastNext);
4294        setBoolean(m_out.phi(m_out.boolean, fastResult, slowResult));
4295    }
4296
4297    LValue allocateCell(LValue allocator, Structure* structure, LBasicBlock slowPath)
4298    {
4299        LBasicBlock success = FTL_NEW_BLOCK(m_out, ("object allocation success"));
4300
4301        LValue result = m_out.loadPtr(
4302            allocator, m_heaps.MarkedAllocator_freeListHead);
4303
4304        m_out.branch(m_out.notNull(result), usually(success), rarely(slowPath));
4305
4306        m_out.appendTo(success);
4307
4308        m_out.storePtr(
4309            m_out.loadPtr(result, m_heaps.JSCell_freeListNext),
4310            allocator, m_heaps.MarkedAllocator_freeListHead);
4311
4312        m_out.store32(m_out.constInt32(structure->id()), result, m_heaps.JSCell_structureID);
4313        m_out.store8(m_out.constInt8(structure->indexingType()), result, m_heaps.JSCell_indexingType);
4314        m_out.store8(m_out.constInt8(structure->typeInfo().type()), result, m_heaps.JSCell_typeInfoType);
4315        m_out.store8(m_out.constInt8(structure->typeInfo().inlineTypeFlags()), result, m_heaps.JSCell_typeInfoFlags);
4316        m_out.store8(m_out.constInt8(JSCell::NotMarked), result, m_heaps.JSCell_gcData);
4317
4318        return result;
4319    }
4320
4321    LValue allocateObject(
4322        LValue allocator, Structure* structure, LValue butterfly, LBasicBlock slowPath)
4323    {
4324        LValue result = allocateCell(allocator, structure, slowPath);
4325        m_out.storePtr(butterfly, result, m_heaps.JSObject_butterfly);
4326        return result;
4327    }
4328
4329    template<typename ClassType>
4330    LValue allocateObject(Structure* structure, LValue butterfly, LBasicBlock slowPath)
4331    {
4332        MarkedAllocator* allocator;
4333        size_t size = ClassType::allocationSize(0);
4334        if (ClassType::needsDestruction && ClassType::hasImmortalStructure)
4335            allocator = &vm().heap.allocatorForObjectWithImmortalStructureDestructor(size);
4336        else if (ClassType::needsDestruction)
4337            allocator = &vm().heap.allocatorForObjectWithNormalDestructor(size);
4338        else
4339            allocator = &vm().heap.allocatorForObjectWithoutDestructor(size);
4340        return allocateObject(m_out.constIntPtr(allocator), structure, butterfly, slowPath);
4341    }
4342
4343    // Returns a pointer to the end of the allocation.
4344    LValue allocateBasicStorageAndGetEnd(LValue size, LBasicBlock slowPath)
4345    {
4346        CopiedAllocator& allocator = vm().heap.storageAllocator();
4347
4348        LBasicBlock success = FTL_NEW_BLOCK(m_out, ("storage allocation success"));
4349
4350        LValue remaining = m_out.loadPtr(m_out.absolute(&allocator.m_currentRemaining));
4351        LValue newRemaining = m_out.sub(remaining, size);
4352
4353        m_out.branch(
4354            m_out.lessThan(newRemaining, m_out.intPtrZero),
4355            rarely(slowPath), usually(success));
4356
4357        m_out.appendTo(success);
4358
4359        m_out.storePtr(newRemaining, m_out.absolute(&allocator.m_currentRemaining));
4360        return m_out.sub(
4361            m_out.loadPtr(m_out.absolute(&allocator.m_currentPayloadEnd)), newRemaining);
4362    }
4363
4364    struct ArrayValues {
4365        ArrayValues()
4366            : array(0)
4367            , butterfly(0)
4368        {
4369        }
4370
4371        ArrayValues(LValue array, LValue butterfly)
4372            : array(array)
4373            , butterfly(butterfly)
4374        {
4375        }
4376
4377        LValue array;
4378        LValue butterfly;
4379    };
4380    ArrayValues allocateJSArray(
4381        Structure* structure, unsigned numElements, LBasicBlock slowPath)
4382    {
4383        ASSERT(
4384            hasUndecided(structure->indexingType())
4385            || hasInt32(structure->indexingType())
4386            || hasDouble(structure->indexingType())
4387            || hasContiguous(structure->indexingType()));
4388
4389        unsigned vectorLength = std::max(BASE_VECTOR_LEN, numElements);
4390
4391        LValue endOfStorage = allocateBasicStorageAndGetEnd(
4392            m_out.constIntPtr(sizeof(JSValue) * vectorLength + sizeof(IndexingHeader)),
4393            slowPath);
4394
4395        LValue butterfly = m_out.sub(
4396            endOfStorage, m_out.constIntPtr(sizeof(JSValue) * vectorLength));
4397
4398        LValue object = allocateObject<JSArray>(
4399            structure, butterfly, slowPath);
4400
4401        m_out.store32(m_out.constInt32(numElements), butterfly, m_heaps.Butterfly_publicLength);
4402        m_out.store32(m_out.constInt32(vectorLength), butterfly, m_heaps.Butterfly_vectorLength);
4403
4404        if (hasDouble(structure->indexingType())) {
4405            for (unsigned i = numElements; i < vectorLength; ++i) {
4406                m_out.store64(
4407                    m_out.constInt64(bitwise_cast<int64_t>(PNaN)),
4408                    butterfly, m_heaps.indexedDoubleProperties[i]);
4409            }
4410        }
4411
4412        return ArrayValues(object, butterfly);
4413    }
4414
4415    ArrayValues allocateJSArray(Structure* structure, unsigned numElements)
4416    {
4417        LBasicBlock slowPath = FTL_NEW_BLOCK(m_out, ("JSArray allocation slow path"));
4418        LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("JSArray allocation continuation"));
4419
4420        LBasicBlock lastNext = m_out.insertNewBlocksBefore(slowPath);
4421
4422        ArrayValues fastValues = allocateJSArray(structure, numElements, slowPath);
4423        ValueFromBlock fastArray = m_out.anchor(fastValues.array);
4424        ValueFromBlock fastButterfly = m_out.anchor(fastValues.butterfly);
4425
4426        m_out.jump(continuation);
4427
4428        m_out.appendTo(slowPath, continuation);
4429
4430        ValueFromBlock slowArray = m_out.anchor(vmCall(
4431            m_out.operation(operationNewArrayWithSize), m_callFrame,
4432            m_out.constIntPtr(structure), m_out.constInt32(numElements)));
4433        ValueFromBlock slowButterfly = m_out.anchor(
4434            m_out.loadPtr(slowArray.value(), m_heaps.JSObject_butterfly));
4435
4436        m_out.jump(continuation);
4437
4438        m_out.appendTo(continuation, lastNext);
4439
4440        return ArrayValues(
4441            m_out.phi(m_out.intPtr, fastArray, slowArray),
4442            m_out.phi(m_out.intPtr, fastButterfly, slowButterfly));
4443    }
4444
4445    LValue typedArrayLength(Edge baseEdge, ArrayMode arrayMode, LValue base)
4446    {
4447        if (JSArrayBufferView* view = m_graph.tryGetFoldableView(baseEdge.node(), arrayMode))
4448            return m_out.constInt32(view->length());
4449        return m_out.load32NonNegative(base, m_heaps.JSArrayBufferView_length);
4450    }
4451
4452    LValue typedArrayLength(Edge baseEdge, ArrayMode arrayMode)
4453    {
4454        return typedArrayLength(baseEdge, arrayMode, lowCell(baseEdge));
4455    }
4456
4457    LValue boolify(Edge edge)
4458    {
4459        switch (edge.useKind()) {
4460        case BooleanUse:
4461            return lowBoolean(m_node->child1());
4462        case Int32Use:
4463            return m_out.notZero32(lowInt32(m_node->child1()));
4464        case DoubleRepUse:
4465            return m_out.doubleNotEqual(lowDouble(edge), m_out.doubleZero);
4466        case ObjectOrOtherUse:
4467            return m_out.bitNot(
4468                equalNullOrUndefined(
4469                    edge, CellCaseSpeculatesObject, SpeculateNullOrUndefined,
4470                    ManualOperandSpeculation));
4471        case StringUse: {
4472            LValue stringValue = lowString(m_node->child1());
4473            LValue length = m_out.load32NonNegative(stringValue, m_heaps.JSString_length);
4474            return m_out.notEqual(length, m_out.int32Zero);
4475        }
4476        case UntypedUse: {
4477            LValue value = lowJSValue(m_node->child1());
4478
4479            LBasicBlock slowCase = FTL_NEW_BLOCK(m_out, ("Boolify untyped slow case"));
4480            LBasicBlock fastCase = FTL_NEW_BLOCK(m_out, ("Boolify untyped fast case"));
4481            LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("Boolify untyped continuation"));
4482
4483            m_out.branch(isNotBoolean(value), rarely(slowCase), usually(fastCase));
4484
4485            LBasicBlock lastNext = m_out.appendTo(fastCase, slowCase);
4486            ValueFromBlock fastResult = m_out.anchor(unboxBoolean(value));
4487            m_out.jump(continuation);
4488
4489            m_out.appendTo(slowCase, continuation);
4490            ValueFromBlock slowResult = m_out.anchor(m_out.notNull(vmCall(
4491                m_out.operation(operationConvertJSValueToBoolean), m_callFrame, value)));
4492            m_out.jump(continuation);
4493
4494            m_out.appendTo(continuation, lastNext);
4495            return m_out.phi(m_out.boolean, fastResult, slowResult);
4496        }
4497        default:
4498            RELEASE_ASSERT_NOT_REACHED();
4499            return 0;
4500        }
4501    }
4502
4503    enum StringOrObjectMode {
4504        AllCellsAreFalse,
4505        CellCaseSpeculatesObject
4506    };
4507    enum EqualNullOrUndefinedMode {
4508        EqualNull,
4509        EqualUndefined,
4510        EqualNullOrUndefined,
4511        SpeculateNullOrUndefined
4512    };
4513    LValue equalNullOrUndefined(
4514        Edge edge, StringOrObjectMode cellMode, EqualNullOrUndefinedMode primitiveMode,
4515        OperandSpeculationMode operandMode = AutomaticOperandSpeculation)
4516    {
4517        bool validWatchpoint = masqueradesAsUndefinedWatchpointIsStillValid();
4518
4519        LValue value = lowJSValue(edge, operandMode);
4520
4521        LBasicBlock cellCase = FTL_NEW_BLOCK(m_out, ("EqualNullOrUndefined cell case"));
4522        LBasicBlock primitiveCase = FTL_NEW_BLOCK(m_out, ("EqualNullOrUndefined primitive case"));
4523        LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("EqualNullOrUndefined continuation"));
4524
4525        m_out.branch(isNotCell(value), unsure(primitiveCase), unsure(cellCase));
4526
4527        LBasicBlock lastNext = m_out.appendTo(cellCase, primitiveCase);
4528
4529        Vector<ValueFromBlock, 3> results;
4530
4531        switch (cellMode) {
4532        case AllCellsAreFalse:
4533            break;
4534        case CellCaseSpeculatesObject:
4535            FTL_TYPE_CHECK(
4536                jsValueValue(value), edge, (~SpecCell) | SpecObject,
4537                m_out.equal(
4538                    m_out.load32(value, m_heaps.JSCell_structureID),
4539                    m_out.constInt32(vm().stringStructure->id())));
4540            break;
4541        }
4542
4543        if (validWatchpoint) {
4544            results.append(m_out.anchor(m_out.booleanFalse));
4545            m_out.jump(continuation);
4546        } else {
4547            LBasicBlock masqueradesCase =
4548                FTL_NEW_BLOCK(m_out, ("EqualNullOrUndefined masquerades case"));
4549
4550            results.append(m_out.anchor(m_out.booleanFalse));
4551
4552            m_out.branch(
4553                m_out.testNonZero8(
4554                    m_out.load8(value, m_heaps.JSCell_typeInfoFlags),
4555                    m_out.constInt8(MasqueradesAsUndefined)),
4556                rarely(masqueradesCase), usually(continuation));
4557
4558            m_out.appendTo(masqueradesCase, primitiveCase);
4559
4560            LValue structure = loadStructure(value);
4561
4562            results.append(m_out.anchor(
4563                m_out.equal(
4564                    m_out.constIntPtr(m_graph.globalObjectFor(m_node->origin.semantic)),
4565                    m_out.loadPtr(structure, m_heaps.Structure_globalObject))));
4566            m_out.jump(continuation);
4567        }
4568
4569        m_out.appendTo(primitiveCase, continuation);
4570
4571        LValue primitiveResult;
4572        switch (primitiveMode) {
4573        case EqualNull:
4574            primitiveResult = m_out.equal(value, m_out.constInt64(ValueNull));
4575            break;
4576        case EqualUndefined:
4577            primitiveResult = m_out.equal(value, m_out.constInt64(ValueUndefined));
4578            break;
4579        case EqualNullOrUndefined:
4580            primitiveResult = isOther(value);
4581            break;
4582        case SpeculateNullOrUndefined:
4583            FTL_TYPE_CHECK(
4584                jsValueValue(value), edge, SpecCell | SpecOther, isNotOther(value));
4585            primitiveResult = m_out.booleanTrue;
4586            break;
4587        }
4588        results.append(m_out.anchor(primitiveResult));
4589        m_out.jump(continuation);
4590
4591        m_out.appendTo(continuation, lastNext);
4592
4593        return m_out.phi(m_out.boolean, results);
4594    }
4595
4596    template<typename FunctionType>
4597    void contiguousPutByValOutOfBounds(
4598        FunctionType slowPathFunction, LValue base, LValue storage, LValue index, LValue value,
4599        LBasicBlock continuation)
4600    {
4601        LValue isNotInBounds = m_out.aboveOrEqual(
4602            index, m_out.load32NonNegative(storage, m_heaps.Butterfly_publicLength));
4603        if (!m_node->arrayMode().isInBounds()) {
4604            LBasicBlock notInBoundsCase =
4605                FTL_NEW_BLOCK(m_out, ("PutByVal not in bounds"));
4606            LBasicBlock performStore =
4607                FTL_NEW_BLOCK(m_out, ("PutByVal perform store"));
4608
4609            m_out.branch(isNotInBounds, unsure(notInBoundsCase), unsure(performStore));
4610
4611            LBasicBlock lastNext = m_out.appendTo(notInBoundsCase, performStore);
4612
4613            LValue isOutOfBounds = m_out.aboveOrEqual(
4614                index, m_out.load32NonNegative(storage, m_heaps.Butterfly_vectorLength));
4615
4616            if (!m_node->arrayMode().isOutOfBounds())
4617                speculate(OutOfBounds, noValue(), 0, isOutOfBounds);
4618            else {
4619                LBasicBlock outOfBoundsCase =
4620                    FTL_NEW_BLOCK(m_out, ("PutByVal out of bounds"));
4621                LBasicBlock holeCase =
4622                    FTL_NEW_BLOCK(m_out, ("PutByVal hole case"));
4623
4624                m_out.branch(isOutOfBounds, unsure(outOfBoundsCase), unsure(holeCase));
4625
4626                LBasicBlock innerLastNext = m_out.appendTo(outOfBoundsCase, holeCase);
4627
4628                vmCall(
4629                    m_out.operation(slowPathFunction),
4630                    m_callFrame, base, index, value);
4631
4632                m_out.jump(continuation);
4633
4634                m_out.appendTo(holeCase, innerLastNext);
4635            }
4636
4637            m_out.store32(
4638                m_out.add(index, m_out.int32One),
4639                storage, m_heaps.Butterfly_publicLength);
4640
4641            m_out.jump(performStore);
4642            m_out.appendTo(performStore, lastNext);
4643        }
4644    }
4645
4646    void buildSwitch(SwitchData* data, LType type, LValue switchValue)
4647    {
4648        Vector<SwitchCase> cases;
4649        for (unsigned i = 0; i < data->cases.size(); ++i) {
4650            cases.append(SwitchCase(
4651                constInt(type, data->cases[i].value.switchLookupValue()),
4652                lowBlock(data->cases[i].target.block), Weight(data->cases[i].target.count)));
4653        }
4654
4655        m_out.switchInstruction(
4656            switchValue, cases,
4657            lowBlock(data->fallThrough.block), Weight(data->fallThrough.count));
4658    }
4659
4660    LValue doubleToInt32(LValue doubleValue, double low, double high, bool isSigned = true)
4661    {
4662        LBasicBlock greatEnough = FTL_NEW_BLOCK(m_out, ("doubleToInt32 greatEnough"));
4663        LBasicBlock withinRange = FTL_NEW_BLOCK(m_out, ("doubleToInt32 withinRange"));
4664        LBasicBlock slowPath = FTL_NEW_BLOCK(m_out, ("doubleToInt32 slowPath"));
4665        LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("doubleToInt32 continuation"));
4666
4667        Vector<ValueFromBlock, 2> results;
4668
4669        m_out.branch(
4670            m_out.doubleGreaterThanOrEqual(doubleValue, m_out.constDouble(low)),
4671            unsure(greatEnough), unsure(slowPath));
4672
4673        LBasicBlock lastNext = m_out.appendTo(greatEnough, withinRange);
4674        m_out.branch(
4675            m_out.doubleLessThanOrEqual(doubleValue, m_out.constDouble(high)),
4676            unsure(withinRange), unsure(slowPath));
4677
4678        m_out.appendTo(withinRange, slowPath);
4679        LValue fastResult;
4680        if (isSigned)
4681            fastResult = m_out.fpToInt32(doubleValue);
4682        else
4683            fastResult = m_out.fpToUInt32(doubleValue);
4684        results.append(m_out.anchor(fastResult));
4685        m_out.jump(continuation);
4686
4687        m_out.appendTo(slowPath, continuation);
4688        results.append(m_out.anchor(m_out.call(m_out.operation(toInt32), doubleValue)));
4689        m_out.jump(continuation);
4690
4691        m_out.appendTo(continuation, lastNext);
4692        return m_out.phi(m_out.int32, results);
4693    }
4694
4695    LValue doubleToInt32(LValue doubleValue)
4696    {
4697        if (Output::hasSensibleDoubleToInt())
4698            return sensibleDoubleToInt32(doubleValue);
4699
4700        double limit = pow(2, 31) - 1;
4701        return doubleToInt32(doubleValue, -limit, limit);
4702    }
4703
4704    LValue sensibleDoubleToInt32(LValue doubleValue)
4705    {
4706        LBasicBlock slowPath = FTL_NEW_BLOCK(m_out, ("sensible doubleToInt32 slow path"));
4707        LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("sensible doubleToInt32 continuation"));
4708
4709        ValueFromBlock fastResult = m_out.anchor(
4710            m_out.sensibleDoubleToInt(doubleValue));
4711        m_out.branch(
4712            m_out.equal(fastResult.value(), m_out.constInt32(0x80000000)),
4713            rarely(slowPath), usually(continuation));
4714
4715        LBasicBlock lastNext = m_out.appendTo(slowPath, continuation);
4716        ValueFromBlock slowResult = m_out.anchor(
4717            m_out.call(m_out.operation(toInt32), doubleValue));
4718        m_out.jump(continuation);
4719
4720        m_out.appendTo(continuation, lastNext);
4721        return m_out.phi(m_out.int32, fastResult, slowResult);
4722    }
4723
4724    void checkArgumentsNotCreated()
4725    {
4726        CodeOrigin codeOrigin = m_node->origin.semantic;
4727        VirtualRegister argumentsRegister = m_graph.argumentsRegisterFor(codeOrigin);
4728        if (isEmptySpeculation(m_state.variables().operand(argumentsRegister).m_type))
4729            return;
4730
4731        VirtualRegister argsReg = m_graph.machineArgumentsRegisterFor(codeOrigin);
4732        speculate(
4733            ArgumentsEscaped, noValue(), 0,
4734            m_out.notZero64(m_out.load64(addressFor(argsReg))));
4735    }
4736
4737    void speculate(
4738        ExitKind kind, FormattedValue lowValue, Node* highValue, LValue failCondition)
4739    {
4740        appendOSRExit(kind, lowValue, highValue, failCondition);
4741    }
4742
4743    void terminate(ExitKind kind)
4744    {
4745        speculate(kind, noValue(), 0, m_out.booleanTrue);
4746    }
4747
4748    void typeCheck(
4749        FormattedValue lowValue, Edge highValue, SpeculatedType typesPassedThrough,
4750        LValue failCondition)
4751    {
4752        appendTypeCheck(lowValue, highValue, typesPassedThrough, failCondition);
4753    }
4754
4755    void appendTypeCheck(
4756        FormattedValue lowValue, Edge highValue, SpeculatedType typesPassedThrough,
4757        LValue failCondition)
4758    {
4759        if (!m_interpreter.needsTypeCheck(highValue, typesPassedThrough))
4760            return;
4761        ASSERT(mayHaveTypeCheck(highValue.useKind()));
4762        appendOSRExit(BadType, lowValue, highValue.node(), failCondition);
4763        m_interpreter.filter(highValue, typesPassedThrough);
4764    }
4765
4766    LValue lowInt32(Edge edge, OperandSpeculationMode mode = AutomaticOperandSpeculation)
4767    {
4768        ASSERT_UNUSED(mode, mode == ManualOperandSpeculation || (edge.useKind() == Int32Use || edge.useKind() == KnownInt32Use));
4769
4770        if (edge->hasConstant()) {
4771            JSValue value = m_graph.valueOfJSConstant(edge.node());
4772            if (!value.isInt32()) {
4773                terminate(Uncountable);
4774                return m_out.int32Zero;
4775            }
4776            return m_out.constInt32(value.asInt32());
4777        }
4778
4779        LoweredNodeValue value = m_int32Values.get(edge.node());
4780        if (isValid(value))
4781            return value.value();
4782
4783        value = m_strictInt52Values.get(edge.node());
4784        if (isValid(value))
4785            return strictInt52ToInt32(edge, value.value());
4786
4787        value = m_int52Values.get(edge.node());
4788        if (isValid(value))
4789            return strictInt52ToInt32(edge, int52ToStrictInt52(value.value()));
4790
4791        value = m_jsValueValues.get(edge.node());
4792        if (isValid(value)) {
4793            LValue boxedResult = value.value();
4794            FTL_TYPE_CHECK(
4795                jsValueValue(boxedResult), edge, SpecInt32, isNotInt32(boxedResult));
4796            LValue result = unboxInt32(boxedResult);
4797            setInt32(edge.node(), result);
4798            return result;
4799        }
4800
4801        RELEASE_ASSERT(!(m_state.forNode(edge).m_type & SpecInt32));
4802        terminate(Uncountable);
4803        return m_out.int32Zero;
4804    }
4805
4806    enum Int52Kind { StrictInt52, Int52 };
4807    LValue lowInt52(Edge edge, Int52Kind kind)
4808    {
4809        RELEASE_ASSERT(edge.useKind() == Int52RepUse);
4810
4811        LoweredNodeValue value;
4812
4813        switch (kind) {
4814        case Int52:
4815            value = m_int52Values.get(edge.node());
4816            if (isValid(value))
4817                return value.value();
4818
4819            value = m_strictInt52Values.get(edge.node());
4820            if (isValid(value))
4821                return strictInt52ToInt52(value.value());
4822            break;
4823
4824        case StrictInt52:
4825            value = m_strictInt52Values.get(edge.node());
4826            if (isValid(value))
4827                return value.value();
4828
4829            value = m_int52Values.get(edge.node());
4830            if (isValid(value))
4831                return int52ToStrictInt52(value.value());
4832            break;
4833        }
4834
4835        RELEASE_ASSERT(!m_state.forNode(edge).m_type);
4836        terminate(Uncountable);
4837        return m_out.int64Zero;
4838    }
4839
4840    LValue lowInt52(Edge edge)
4841    {
4842        return lowInt52(edge, Int52);
4843    }
4844
4845    LValue lowStrictInt52(Edge edge)
4846    {
4847        return lowInt52(edge, StrictInt52);
4848    }
4849
4850    bool betterUseStrictInt52(Node* node)
4851    {
4852        return !isValid(m_int52Values.get(node));
4853    }
4854    bool betterUseStrictInt52(Edge edge)
4855    {
4856        return betterUseStrictInt52(edge.node());
4857    }
4858    template<typename T>
4859    Int52Kind bestInt52Kind(T node)
4860    {
4861        return betterUseStrictInt52(node) ? StrictInt52 : Int52;
4862    }
4863    Int52Kind opposite(Int52Kind kind)
4864    {
4865        switch (kind) {
4866        case Int52:
4867            return StrictInt52;
4868        case StrictInt52:
4869            return Int52;
4870        }
4871        RELEASE_ASSERT_NOT_REACHED();
4872        return Int52;
4873    }
4874
4875    LValue lowWhicheverInt52(Edge edge, Int52Kind& kind)
4876    {
4877        kind = bestInt52Kind(edge);
4878        return lowInt52(edge, kind);
4879    }
4880
4881    LValue lowCell(Edge edge, OperandSpeculationMode mode = AutomaticOperandSpeculation)
4882    {
4883        ASSERT_UNUSED(mode, mode == ManualOperandSpeculation || DFG::isCell(edge.useKind()));
4884
4885        if (edge->op() == JSConstant) {
4886            JSValue value = m_graph.valueOfJSConstant(edge.node());
4887            if (!value.isCell()) {
4888                terminate(Uncountable);
4889                return m_out.intPtrZero;
4890            }
4891            return m_out.constIntPtr(value.asCell());
4892        }
4893
4894        LoweredNodeValue value = m_jsValueValues.get(edge.node());
4895        if (isValid(value)) {
4896            LValue uncheckedValue = value.value();
4897            FTL_TYPE_CHECK(
4898                jsValueValue(uncheckedValue), edge, SpecCell, isNotCell(uncheckedValue));
4899            return uncheckedValue;
4900        }
4901
4902        RELEASE_ASSERT(!(m_state.forNode(edge).m_type & SpecCell));
4903        terminate(Uncountable);
4904        return m_out.intPtrZero;
4905    }
4906
4907    LValue lowObject(Edge edge, OperandSpeculationMode mode = AutomaticOperandSpeculation)
4908    {
4909        ASSERT_UNUSED(mode, mode == ManualOperandSpeculation || edge.useKind() == ObjectUse);
4910
4911        LValue result = lowCell(edge, mode);
4912        speculateObject(edge, result);
4913        return result;
4914    }
4915
4916    LValue lowString(Edge edge, OperandSpeculationMode mode = AutomaticOperandSpeculation)
4917    {
4918        ASSERT_UNUSED(mode, mode == ManualOperandSpeculation || edge.useKind() == StringUse || edge.useKind() == KnownStringUse || edge.useKind() == StringIdentUse);
4919
4920        LValue result = lowCell(edge, mode);
4921        speculateString(edge, result);
4922        return result;
4923    }
4924
4925    LValue lowStringIdent(Edge edge, OperandSpeculationMode mode = AutomaticOperandSpeculation)
4926    {
4927        ASSERT_UNUSED(mode, mode == ManualOperandSpeculation || edge.useKind() == StringIdentUse);
4928
4929        LValue string = lowString(edge, mode);
4930        LValue stringImpl = m_out.loadPtr(string, m_heaps.JSString_value);
4931        speculateStringIdent(edge, string, stringImpl);
4932        return stringImpl;
4933    }
4934
4935    LValue lowNonNullObject(Edge edge, OperandSpeculationMode mode = AutomaticOperandSpeculation)
4936    {
4937        ASSERT_UNUSED(mode, mode == ManualOperandSpeculation || edge.useKind() == ObjectUse);
4938
4939        LValue result = lowCell(edge, mode);
4940        speculateNonNullObject(edge, result);
4941        return result;
4942    }
4943
4944    LValue lowBoolean(Edge edge, OperandSpeculationMode mode = AutomaticOperandSpeculation)
4945    {
4946        ASSERT_UNUSED(mode, mode == ManualOperandSpeculation || edge.useKind() == BooleanUse);
4947
4948        if (edge->hasConstant()) {
4949            JSValue value = m_graph.valueOfJSConstant(edge.node());
4950            if (!value.isBoolean()) {
4951                terminate(Uncountable);
4952                return m_out.booleanFalse;
4953            }
4954            return m_out.constBool(value.asBoolean());
4955        }
4956
4957        LoweredNodeValue value = m_booleanValues.get(edge.node());
4958        if (isValid(value))
4959            return value.value();
4960
4961        value = m_jsValueValues.get(edge.node());
4962        if (isValid(value)) {
4963            LValue unboxedResult = value.value();
4964            FTL_TYPE_CHECK(
4965                jsValueValue(unboxedResult), edge, SpecBoolean, isNotBoolean(unboxedResult));
4966            LValue result = unboxBoolean(unboxedResult);
4967            setBoolean(edge.node(), result);
4968            return result;
4969        }
4970
4971        RELEASE_ASSERT(!(m_state.forNode(edge).m_type & SpecBoolean));
4972        terminate(Uncountable);
4973        return m_out.booleanFalse;
4974    }
4975
4976    LValue lowDouble(Edge edge)
4977    {
4978        RELEASE_ASSERT(isDouble(edge.useKind()));
4979
4980        LoweredNodeValue value = m_doubleValues.get(edge.node());
4981        if (isValid(value))
4982            return value.value();
4983
4984        RELEASE_ASSERT(!m_state.forNode(edge).m_type);
4985        terminate(Uncountable);
4986        return m_out.doubleZero;
4987    }
4988
4989    LValue lowJSValue(Edge edge, OperandSpeculationMode mode = AutomaticOperandSpeculation)
4990    {
4991        ASSERT_UNUSED(mode, mode == ManualOperandSpeculation || edge.useKind() == UntypedUse);
4992        RELEASE_ASSERT(!isDouble(edge.useKind()));
4993        RELEASE_ASSERT(edge.useKind() != Int52RepUse);
4994
4995        if (edge->hasConstant())
4996            return m_out.constInt64(JSValue::encode(m_graph.valueOfJSConstant(edge.node())));
4997
4998        LoweredNodeValue value = m_jsValueValues.get(edge.node());
4999        if (isValid(value))
5000            return value.value();
5001
5002        value = m_int32Values.get(edge.node());
5003        if (isValid(value)) {
5004            LValue result = boxInt32(value.value());
5005            setJSValue(edge.node(), result);
5006            return result;
5007        }
5008
5009        value = m_booleanValues.get(edge.node());
5010        if (isValid(value)) {
5011            LValue result = boxBoolean(value.value());
5012            setJSValue(edge.node(), result);
5013            return result;
5014        }
5015
5016        RELEASE_ASSERT_NOT_REACHED();
5017        return 0;
5018    }
5019
5020    LValue lowStorage(Edge edge)
5021    {
5022        LoweredNodeValue value = m_storageValues.get(edge.node());
5023        if (isValid(value))
5024            return value.value();
5025
5026        LValue result = lowCell(edge);
5027        setStorage(edge.node(), result);
5028        return result;
5029    }
5030
5031    LValue strictInt52ToInt32(Edge edge, LValue value)
5032    {
5033        LValue result = m_out.castToInt32(value);
5034        FTL_TYPE_CHECK(
5035            noValue(), edge, SpecInt32,
5036            m_out.notEqual(m_out.signExt(result, m_out.int64), value));
5037        setInt32(edge.node(), result);
5038        return result;
5039    }
5040
5041    LValue strictInt52ToDouble(LValue value)
5042    {
5043        return m_out.intToDouble(value);
5044    }
5045
5046    LValue strictInt52ToJSValue(LValue value)
5047    {
5048        LBasicBlock isInt32 = FTL_NEW_BLOCK(m_out, ("strictInt52ToJSValue isInt32 case"));
5049        LBasicBlock isDouble = FTL_NEW_BLOCK(m_out, ("strictInt52ToJSValue isDouble case"));
5050        LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("strictInt52ToJSValue continuation"));
5051
5052        Vector<ValueFromBlock, 2> results;
5053
5054        LValue int32Value = m_out.castToInt32(value);
5055        m_out.branch(
5056            m_out.equal(m_out.signExt(int32Value, m_out.int64), value),
5057            unsure(isInt32), unsure(isDouble));
5058
5059        LBasicBlock lastNext = m_out.appendTo(isInt32, isDouble);
5060
5061        results.append(m_out.anchor(boxInt32(int32Value)));
5062        m_out.jump(continuation);
5063
5064        m_out.appendTo(isDouble, continuation);
5065
5066        results.append(m_out.anchor(boxDouble(m_out.intToDouble(value))));
5067        m_out.jump(continuation);
5068
5069        m_out.appendTo(continuation, lastNext);
5070        return m_out.phi(m_out.int64, results);
5071    }
5072
5073    LValue strictInt52ToInt52(LValue value)
5074    {
5075        return m_out.shl(value, m_out.constInt64(JSValue::int52ShiftAmount));
5076    }
5077
5078    LValue int52ToStrictInt52(LValue value)
5079    {
5080        return m_out.aShr(value, m_out.constInt64(JSValue::int52ShiftAmount));
5081    }
5082
5083    LValue isNotInt32(LValue jsValue)
5084    {
5085        return m_out.below(jsValue, m_tagTypeNumber);
5086    }
5087    LValue unboxInt32(LValue jsValue)
5088    {
5089        return m_out.castToInt32(jsValue);
5090    }
5091    LValue boxInt32(LValue value)
5092    {
5093        return m_out.add(m_out.zeroExt(value, m_out.int64), m_tagTypeNumber);
5094    }
5095
5096    LValue isCellOrMisc(LValue jsValue)
5097    {
5098        return m_out.testIsZero64(jsValue, m_tagTypeNumber);
5099    }
5100    LValue isNotCellOrMisc(LValue jsValue)
5101    {
5102        return m_out.testNonZero64(jsValue, m_tagTypeNumber);
5103    }
5104
5105    LValue unboxDouble(LValue jsValue)
5106    {
5107        return m_out.bitCast(m_out.add(jsValue, m_tagTypeNumber), m_out.doubleType);
5108    }
5109    LValue boxDouble(LValue doubleValue)
5110    {
5111        return m_out.sub(m_out.bitCast(doubleValue, m_out.int64), m_tagTypeNumber);
5112    }
5113    LValue jsValueToDouble(Edge edge, LValue boxedValue)
5114    {
5115        LBasicBlock intCase = FTL_NEW_BLOCK(m_out, ("jsValueToDouble unboxing int case"));
5116        LBasicBlock doubleCase = FTL_NEW_BLOCK(m_out, ("jsValueToDouble unboxing double case"));
5117        LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("jsValueToDouble unboxing continuation"));
5118
5119        LValue isNotInt32;
5120        if (!m_interpreter.needsTypeCheck(edge, SpecInt32))
5121            isNotInt32 = m_out.booleanFalse;
5122        else if (!m_interpreter.needsTypeCheck(edge, ~SpecInt32))
5123            isNotInt32 = m_out.booleanTrue;
5124        else
5125            isNotInt32 = this->isNotInt32(boxedValue);
5126        m_out.branch(isNotInt32, unsure(doubleCase), unsure(intCase));
5127
5128        LBasicBlock lastNext = m_out.appendTo(intCase, doubleCase);
5129
5130        ValueFromBlock intToDouble = m_out.anchor(
5131            m_out.intToDouble(unboxInt32(boxedValue)));
5132        m_out.jump(continuation);
5133
5134        m_out.appendTo(doubleCase, continuation);
5135
5136        FTL_TYPE_CHECK(
5137            jsValueValue(boxedValue), edge, SpecBytecodeNumber, isCellOrMisc(boxedValue));
5138
5139        ValueFromBlock unboxedDouble = m_out.anchor(unboxDouble(boxedValue));
5140        m_out.jump(continuation);
5141
5142        m_out.appendTo(continuation, lastNext);
5143
5144        return m_out.phi(m_out.doubleType, intToDouble, unboxedDouble);
5145    }
5146
5147    LValue jsValueToStrictInt52(Edge edge, LValue boxedValue)
5148    {
5149        LBasicBlock intCase = FTL_NEW_BLOCK(m_out, ("jsValueToInt52 unboxing int case"));
5150        LBasicBlock doubleCase = FTL_NEW_BLOCK(m_out, ("jsValueToInt52 unboxing double case"));
5151        LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("jsValueToInt52 unboxing continuation"));
5152
5153        LValue isNotInt32;
5154        if (!m_interpreter.needsTypeCheck(edge, SpecInt32))
5155            isNotInt32 = m_out.booleanFalse;
5156        else if (!m_interpreter.needsTypeCheck(edge, ~SpecInt32))
5157            isNotInt32 = m_out.booleanTrue;
5158        else
5159            isNotInt32 = this->isNotInt32(boxedValue);
5160        m_out.branch(isNotInt32, unsure(doubleCase), unsure(intCase));
5161
5162        LBasicBlock lastNext = m_out.appendTo(intCase, doubleCase);
5163
5164        ValueFromBlock intToInt52 = m_out.anchor(
5165            m_out.signExt(unboxInt32(boxedValue), m_out.int64));
5166        m_out.jump(continuation);
5167
5168        m_out.appendTo(doubleCase, continuation);
5169
5170        LValue possibleResult = m_out.call(
5171            m_out.operation(operationConvertBoxedDoubleToInt52), boxedValue);
5172        FTL_TYPE_CHECK(
5173            jsValueValue(boxedValue), edge, SpecInt32 | SpecInt52AsDouble,
5174            m_out.equal(possibleResult, m_out.constInt64(JSValue::notInt52)));
5175
5176        ValueFromBlock doubleToInt52 = m_out.anchor(possibleResult);
5177        m_out.jump(continuation);
5178
5179        m_out.appendTo(continuation, lastNext);
5180
5181        return m_out.phi(m_out.int64, intToInt52, doubleToInt52);
5182    }
5183
5184    LValue doubleToStrictInt52(Edge edge, LValue value)
5185    {
5186        LValue possibleResult = m_out.call(
5187            m_out.operation(operationConvertDoubleToInt52), value);
5188        FTL_TYPE_CHECK(
5189            doubleValue(value), edge, SpecInt52AsDouble,
5190            m_out.equal(possibleResult, m_out.constInt64(JSValue::notInt52)));
5191
5192        return possibleResult;
5193    }
5194
5195    LValue isNumber(LValue jsValue)
5196    {
5197        return isNotCellOrMisc(jsValue);
5198    }
5199    LValue isNotNumber(LValue jsValue)
5200    {
5201        return isCellOrMisc(jsValue);
5202    }
5203
5204    LValue isNotCell(LValue jsValue)
5205    {
5206        return m_out.testNonZero64(jsValue, m_tagMask);
5207    }
5208
5209    LValue isCell(LValue jsValue)
5210    {
5211        return m_out.testIsZero64(jsValue, m_tagMask);
5212    }
5213
5214    LValue isNotMisc(LValue value)
5215    {
5216        return m_out.above(value, m_out.constInt64(TagBitTypeOther | TagBitBool | TagBitUndefined));
5217    }
5218
5219    LValue isMisc(LValue value)
5220    {
5221        return m_out.bitNot(isNotMisc(value));
5222    }
5223
5224    LValue isNotBoolean(LValue jsValue)
5225    {
5226        return m_out.testNonZero64(
5227            m_out.bitXor(jsValue, m_out.constInt64(ValueFalse)),
5228            m_out.constInt64(~1));
5229    }
5230    LValue isBoolean(LValue jsValue)
5231    {
5232        return m_out.bitNot(isNotBoolean(jsValue));
5233    }
5234    LValue unboxBoolean(LValue jsValue)
5235    {
5236        // We want to use a cast that guarantees that LLVM knows that even the integer
5237        // value is just 0 or 1. But for now we do it the dumb way.
5238        return m_out.notZero64(m_out.bitAnd(jsValue, m_out.constInt64(1)));
5239    }
5240    LValue boxBoolean(LValue value)
5241    {
5242        return m_out.select(
5243            value, m_out.constInt64(ValueTrue), m_out.constInt64(ValueFalse));
5244    }
5245
5246    LValue isNotOther(LValue value)
5247    {
5248        return m_out.notEqual(
5249            m_out.bitAnd(value, m_out.constInt64(~TagBitUndefined)),
5250            m_out.constInt64(ValueNull));
5251    }
5252    LValue isOther(LValue value)
5253    {
5254        return m_out.equal(
5255            m_out.bitAnd(value, m_out.constInt64(~TagBitUndefined)),
5256            m_out.constInt64(ValueNull));
5257    }
5258
5259    void speculate(Edge edge)
5260    {
5261        switch (edge.useKind()) {
5262        case UntypedUse:
5263            break;
5264        case KnownInt32Use:
5265        case KnownStringUse:
5266        case DoubleRepUse:
5267        case Int52RepUse:
5268            ASSERT(!m_interpreter.needsTypeCheck(edge));
5269            break;
5270        case Int32Use:
5271            speculateInt32(edge);
5272            break;
5273        case CellUse:
5274            speculateCell(edge);
5275            break;
5276        case KnownCellUse:
5277            ASSERT(!m_interpreter.needsTypeCheck(edge));
5278            break;
5279        case MachineIntUse:
5280            speculateMachineInt(edge);
5281            break;
5282        case ObjectUse:
5283            speculateObject(edge);
5284            break;
5285        case ObjectOrOtherUse:
5286            speculateObjectOrOther(edge);
5287            break;
5288        case FinalObjectUse:
5289            speculateFinalObject(edge);
5290            break;
5291        case StringUse:
5292            speculateString(edge);
5293            break;
5294        case StringIdentUse:
5295            speculateStringIdent(edge);
5296            break;
5297        case StringObjectUse:
5298            speculateStringObject(edge);
5299            break;
5300        case StringOrStringObjectUse:
5301            speculateStringOrStringObject(edge);
5302            break;
5303        case NumberUse:
5304            speculateNumber(edge);
5305            break;
5306        case DoubleRepRealUse:
5307            speculateDoubleReal(edge);
5308            break;
5309        case DoubleRepMachineIntUse:
5310            speculateDoubleRepMachineInt(edge);
5311            break;
5312        case BooleanUse:
5313            speculateBoolean(edge);
5314            break;
5315        case NotStringVarUse:
5316            speculateNotStringVar(edge);
5317            break;
5318        case NotCellUse:
5319            speculateNotCell(edge);
5320            break;
5321        case OtherUse:
5322            speculateOther(edge);
5323            break;
5324        case MiscUse:
5325            speculateMisc(edge);
5326            break;
5327        default:
5328            dataLog("Unsupported speculation use kind: ", edge.useKind(), "\n");
5329            RELEASE_ASSERT_NOT_REACHED();
5330        }
5331    }
5332
5333    void speculate(Node*, Edge edge)
5334    {
5335        speculate(edge);
5336    }
5337
5338    void speculateInt32(Edge edge)
5339    {
5340        lowInt32(edge);
5341    }
5342
5343    void speculateCell(Edge edge)
5344    {
5345        lowCell(edge);
5346    }
5347
5348    void speculateMachineInt(Edge edge)
5349    {
5350        if (!m_interpreter.needsTypeCheck(edge))
5351            return;
5352
5353        jsValueToStrictInt52(edge, lowJSValue(edge, ManualOperandSpeculation));
5354    }
5355
5356    LValue isObject(LValue cell)
5357    {
5358        return m_out.notEqual(
5359            m_out.load32(cell, m_heaps.JSCell_structureID),
5360            m_out.constInt32(vm().stringStructure->id()));
5361    }
5362
5363    LValue isNotString(LValue cell)
5364    {
5365        return isObject(cell);
5366    }
5367
5368    LValue isString(LValue cell)
5369    {
5370        return m_out.equal(
5371            m_out.load32(cell, m_heaps.JSCell_structureID),
5372            m_out.constInt32(vm().stringStructure->id()));
5373    }
5374
5375    LValue isNotObject(LValue cell)
5376    {
5377        return isString(cell);
5378    }
5379
5380    LValue isArrayType(LValue cell, ArrayMode arrayMode)
5381    {
5382        switch (arrayMode.type()) {
5383        case Array::Int32:
5384        case Array::Double:
5385        case Array::Contiguous: {
5386            LValue indexingType = m_out.load8(cell, m_heaps.JSCell_indexingType);
5387
5388            switch (arrayMode.arrayClass()) {
5389            case Array::OriginalArray:
5390                RELEASE_ASSERT_NOT_REACHED();
5391                return 0;
5392
5393            case Array::Array:
5394                return m_out.equal(
5395                    m_out.bitAnd(indexingType, m_out.constInt8(IsArray | IndexingShapeMask)),
5396                    m_out.constInt8(IsArray | arrayMode.shapeMask()));
5397
5398            case Array::NonArray:
5399            case Array::OriginalNonArray:
5400                return m_out.equal(
5401                    m_out.bitAnd(indexingType, m_out.constInt8(IsArray | IndexingShapeMask)),
5402                    m_out.constInt8(arrayMode.shapeMask()));
5403
5404            case Array::PossiblyArray:
5405                return m_out.equal(
5406                    m_out.bitAnd(indexingType, m_out.constInt8(IndexingShapeMask)),
5407                    m_out.constInt8(arrayMode.shapeMask()));
5408            }
5409
5410            RELEASE_ASSERT_NOT_REACHED();
5411        }
5412
5413        default:
5414            return m_out.equal(
5415                m_out.load8(cell, m_heaps.JSCell_typeInfoType),
5416                m_out.constInt8(typeForTypedArrayType(arrayMode.typedArrayType())));
5417        }
5418    }
5419
5420    LValue isType(LValue cell, JSType type)
5421    {
5422        return m_out.equal(
5423            m_out.load8(cell, m_heaps.JSCell_typeInfoType),
5424            m_out.constInt8(type));
5425    }
5426
5427    LValue isNotType(LValue cell, JSType type)
5428    {
5429        return m_out.bitNot(isType(cell, type));
5430    }
5431
5432    void speculateObject(Edge edge, LValue cell)
5433    {
5434        FTL_TYPE_CHECK(jsValueValue(cell), edge, SpecObject, isNotObject(cell));
5435    }
5436
5437    void speculateObject(Edge edge)
5438    {
5439        speculateObject(edge, lowCell(edge));
5440    }
5441
5442    void speculateObjectOrOther(Edge edge)
5443    {
5444        if (!m_interpreter.needsTypeCheck(edge))
5445            return;
5446
5447        LValue value = lowJSValue(edge);
5448
5449        LBasicBlock cellCase = FTL_NEW_BLOCK(m_out, ("speculateObjectOrOther cell case"));
5450        LBasicBlock primitiveCase = FTL_NEW_BLOCK(m_out, ("speculateObjectOrOther primitive case"));
5451        LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("speculateObjectOrOther continuation"));
5452
5453        m_out.branch(isNotCell(value), unsure(primitiveCase), unsure(cellCase));
5454
5455        LBasicBlock lastNext = m_out.appendTo(cellCase, primitiveCase);
5456
5457        FTL_TYPE_CHECK(
5458            jsValueValue(value), edge, (~SpecCell) | SpecObject, isNotObject(value));
5459
5460        m_out.jump(continuation);
5461
5462        m_out.appendTo(primitiveCase, continuation);
5463
5464        FTL_TYPE_CHECK(
5465            jsValueValue(value), edge, SpecCell | SpecOther, isNotOther(value));
5466
5467        m_out.jump(continuation);
5468
5469        m_out.appendTo(continuation, lastNext);
5470    }
5471
5472    void speculateFinalObject(Edge edge, LValue cell)
5473    {
5474        FTL_TYPE_CHECK(
5475            jsValueValue(cell), edge, SpecFinalObject, isNotType(cell, FinalObjectType));
5476    }
5477
5478    void speculateFinalObject(Edge edge)
5479    {
5480        speculateFinalObject(edge, lowCell(edge));
5481    }
5482
5483    void speculateString(Edge edge, LValue cell)
5484    {
5485        FTL_TYPE_CHECK(jsValueValue(cell), edge, SpecString | ~SpecCell, isNotString(cell));
5486    }
5487
5488    void speculateString(Edge edge)
5489    {
5490        speculateString(edge, lowCell(edge));
5491    }
5492
5493    void speculateStringIdent(Edge edge, LValue string, LValue stringImpl)
5494    {
5495        if (!m_interpreter.needsTypeCheck(edge, SpecStringIdent | ~SpecString))
5496            return;
5497
5498        speculate(BadType, jsValueValue(string), edge.node(), m_out.isNull(stringImpl));
5499        speculate(
5500            BadType, jsValueValue(string), edge.node(),
5501            m_out.testIsZero32(
5502                m_out.load32(stringImpl, m_heaps.StringImpl_hashAndFlags),
5503                m_out.constInt32(StringImpl::flagIsAtomic())));
5504        m_interpreter.filter(edge, SpecStringIdent | ~SpecString);
5505    }
5506
5507    void speculateStringIdent(Edge edge)
5508    {
5509        lowStringIdent(edge);
5510    }
5511
5512    void speculateStringObject(Edge edge)
5513    {
5514        if (!m_interpreter.needsTypeCheck(edge, SpecStringObject))
5515            return;
5516
5517        speculateStringObjectForCell(edge, lowCell(edge));
5518        m_interpreter.filter(edge, SpecStringObject);
5519    }
5520
5521    void speculateStringOrStringObject(Edge edge)
5522    {
5523        if (!m_interpreter.needsTypeCheck(edge, SpecString | SpecStringObject))
5524            return;
5525
5526        LBasicBlock notString = FTL_NEW_BLOCK(m_out, ("Speculate StringOrStringObject not string case"));
5527        LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("Speculate StringOrStringObject continuation"));
5528
5529        LValue structureID = m_out.load32(lowCell(edge), m_heaps.JSCell_structureID);
5530        m_out.branch(
5531            m_out.equal(structureID, m_out.constInt32(vm().stringStructure->id())),
5532            unsure(continuation), unsure(notString));
5533
5534        LBasicBlock lastNext = m_out.appendTo(notString, continuation);
5535        speculateStringObjectForStructureID(edge, structureID);
5536        m_out.jump(continuation);
5537
5538        m_out.appendTo(continuation, lastNext);
5539
5540        m_interpreter.filter(edge, SpecString | SpecStringObject);
5541    }
5542
5543    void speculateStringObjectForCell(Edge edge, LValue cell)
5544    {
5545        speculateStringObjectForStructureID(edge, m_out.load32(cell, m_heaps.JSCell_structureID));
5546    }
5547
5548    void speculateStringObjectForStructureID(Edge edge, LValue structureID)
5549    {
5550        Structure* stringObjectStructure =
5551            m_graph.globalObjectFor(m_node->origin.semantic)->stringObjectStructure();
5552
5553        if (m_state.forNode(edge).m_currentKnownStructure.isSubsetOf(StructureSet(stringObjectStructure)))
5554            return;
5555
5556        speculate(
5557            NotStringObject, noValue(), 0,
5558            m_out.notEqual(structureID, weakStructure(stringObjectStructure)));
5559    }
5560
5561    void speculateNonNullObject(Edge edge, LValue cell)
5562    {
5563        FTL_TYPE_CHECK(
5564            jsValueValue(cell), edge, SpecObject,
5565            m_out.equal(
5566                m_out.load32(cell, m_heaps.JSCell_structureID),
5567                m_out.constInt32(vm().stringStructure->id())));
5568        if (masqueradesAsUndefinedWatchpointIsStillValid())
5569            return;
5570
5571        speculate(
5572            BadType, jsValueValue(cell), edge.node(),
5573            m_out.testNonZero8(
5574                m_out.load8(cell, m_heaps.JSCell_typeInfoFlags),
5575                m_out.constInt8(MasqueradesAsUndefined)));
5576    }
5577
5578    void speculateNumber(Edge edge)
5579    {
5580        LValue value = lowJSValue(edge, ManualOperandSpeculation);
5581        FTL_TYPE_CHECK(jsValueValue(value), edge, SpecBytecodeNumber, isNotNumber(value));
5582    }
5583
5584    void speculateDoubleReal(Edge edge)
5585    {
5586        // Do an early return here because lowDouble() can create a lot of control flow.
5587        if (!m_interpreter.needsTypeCheck(edge))
5588            return;
5589
5590        LValue value = lowDouble(edge);
5591        FTL_TYPE_CHECK(
5592            doubleValue(value), edge, SpecDoubleReal,
5593            m_out.doubleNotEqualOrUnordered(value, value));
5594    }
5595
5596    void speculateDoubleRepMachineInt(Edge edge)
5597    {
5598        if (!m_interpreter.needsTypeCheck(edge))
5599            return;
5600
5601        doubleToStrictInt52(edge, lowDouble(edge));
5602    }
5603
5604    void speculateBoolean(Edge edge)
5605    {
5606        lowBoolean(edge);
5607    }
5608
5609    void speculateNotStringVar(Edge edge)
5610    {
5611        if (!m_interpreter.needsTypeCheck(edge, ~SpecStringVar))
5612            return;
5613
5614        LValue value = lowJSValue(edge, ManualOperandSpeculation);
5615
5616        LBasicBlock isCellCase = FTL_NEW_BLOCK(m_out, ("Speculate NotStringVar is cell case"));
5617        LBasicBlock isStringCase = FTL_NEW_BLOCK(m_out, ("Speculate NotStringVar is string case"));
5618        LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("Speculate NotStringVar continuation"));
5619
5620        m_out.branch(isCell(value), unsure(isCellCase), unsure(continuation));
5621
5622        LBasicBlock lastNext = m_out.appendTo(isCellCase, isStringCase);
5623        m_out.branch(isString(value), unsure(isStringCase), unsure(continuation));
5624
5625        m_out.appendTo(isStringCase, continuation);
5626        speculateStringIdent(edge, value, m_out.loadPtr(value, m_heaps.JSString_value));
5627        m_out.jump(continuation);
5628
5629        m_out.appendTo(continuation, lastNext);
5630    }
5631
5632    void speculateNotCell(Edge edge)
5633    {
5634        if (!m_interpreter.needsTypeCheck(edge))
5635            return;
5636
5637        LValue value = lowJSValue(edge, ManualOperandSpeculation);
5638        typeCheck(jsValueValue(value), edge, ~SpecCell, isCell(value));
5639    }
5640
5641    void speculateOther(Edge edge)
5642    {
5643        if (!m_interpreter.needsTypeCheck(edge))
5644            return;
5645
5646        LValue value = lowJSValue(edge, ManualOperandSpeculation);
5647        typeCheck(jsValueValue(value), edge, SpecOther, isNotOther(value));
5648    }
5649
5650    void speculateMisc(Edge edge)
5651    {
5652        if (!m_interpreter.needsTypeCheck(edge))
5653            return;
5654
5655        LValue value = lowJSValue(edge, ManualOperandSpeculation);
5656        typeCheck(jsValueValue(value), edge, SpecMisc, isNotMisc(value));
5657    }
5658
5659    bool masqueradesAsUndefinedWatchpointIsStillValid()
5660    {
5661        return m_graph.masqueradesAsUndefinedWatchpointIsStillValid(m_node->origin.semantic);
5662    }
5663
5664    LValue loadMarkByte(LValue base)
5665    {
5666        return m_out.load8(base, m_heaps.JSCell_gcData);
5667    }
5668
5669    void emitStoreBarrier(LValue base)
5670    {
5671#if ENABLE(GGC)
5672        LBasicBlock isMarkedAndNotRemembered = FTL_NEW_BLOCK(m_out, ("Store barrier is marked block"));
5673        LBasicBlock bufferHasSpace = FTL_NEW_BLOCK(m_out, ("Store barrier buffer has space"));
5674        LBasicBlock bufferIsFull = FTL_NEW_BLOCK(m_out, ("Store barrier buffer is full"));
5675        LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("Store barrier continuation"));
5676
5677        // Check the mark byte.
5678        m_out.branch(
5679            m_out.notZero8(loadMarkByte(base)), usually(continuation), rarely(isMarkedAndNotRemembered));
5680
5681        // Append to the write barrier buffer.
5682        LBasicBlock lastNext = m_out.appendTo(isMarkedAndNotRemembered, bufferHasSpace);
5683        LValue currentBufferIndex = m_out.load32(m_out.absolute(&vm().heap.writeBarrierBuffer().m_currentIndex));
5684        LValue bufferCapacity = m_out.load32(m_out.absolute(&vm().heap.writeBarrierBuffer().m_capacity));
5685        m_out.branch(
5686            m_out.lessThan(currentBufferIndex, bufferCapacity),
5687            usually(bufferHasSpace), rarely(bufferIsFull));
5688
5689        // Buffer has space, store to it.
5690        m_out.appendTo(bufferHasSpace, bufferIsFull);
5691        LValue writeBarrierBufferBase = m_out.loadPtr(m_out.absolute(&vm().heap.writeBarrierBuffer().m_buffer));
5692        m_out.storePtr(base, m_out.baseIndex(m_heaps.WriteBarrierBuffer_bufferContents, writeBarrierBufferBase, m_out.zeroExt(currentBufferIndex, m_out.intPtr), ScalePtr));
5693        m_out.store32(m_out.add(currentBufferIndex, m_out.constInt32(1)), m_out.absolute(&vm().heap.writeBarrierBuffer().m_currentIndex));
5694        m_out.jump(continuation);
5695
5696        // Buffer is out of space, flush it.
5697        m_out.appendTo(bufferIsFull, continuation);
5698        vmCall(m_out.operation(operationFlushWriteBarrierBuffer), m_callFrame, base, NoExceptions);
5699        m_out.jump(continuation);
5700
5701        m_out.appendTo(continuation, lastNext);
5702#else
5703        UNUSED_PARAM(base);
5704#endif
5705    }
5706
5707    enum ExceptionCheckMode { NoExceptions, CheckExceptions };
5708
5709    LValue vmCall(LValue function, ExceptionCheckMode mode = CheckExceptions)
5710    {
5711        callPreflight();
5712        LValue result = m_out.call(function);
5713        callCheck(mode);
5714        return result;
5715    }
5716    LValue vmCall(LValue function, LValue arg1, ExceptionCheckMode mode = CheckExceptions)
5717    {
5718        callPreflight();
5719        LValue result = m_out.call(function, arg1);
5720        callCheck(mode);
5721        return result;
5722    }
5723    LValue vmCall(LValue function, LValue arg1, LValue arg2, ExceptionCheckMode mode = CheckExceptions)
5724    {
5725        callPreflight();
5726        LValue result = m_out.call(function, arg1, arg2);
5727        callCheck(mode);
5728        return result;
5729    }
5730    LValue vmCall(LValue function, LValue arg1, LValue arg2, LValue arg3, ExceptionCheckMode mode = CheckExceptions)
5731    {
5732        callPreflight();
5733        LValue result = m_out.call(function, arg1, arg2, arg3);
5734        callCheck(mode);
5735        return result;
5736    }
5737    LValue vmCall(LValue function, LValue arg1, LValue arg2, LValue arg3, LValue arg4, ExceptionCheckMode mode = CheckExceptions)
5738    {
5739        callPreflight();
5740        LValue result = m_out.call(function, arg1, arg2, arg3, arg4);
5741        callCheck(mode);
5742        return result;
5743    }
5744
5745    void callPreflight(CodeOrigin codeOrigin)
5746    {
5747        m_out.store32(
5748            m_out.constInt32(
5749                CallFrame::Location::encodeAsCodeOriginIndex(
5750                    m_ftlState.jitCode->common.addCodeOrigin(codeOrigin))),
5751            tagFor(JSStack::ArgumentCount));
5752    }
5753    void callPreflight()
5754    {
5755        callPreflight(m_node->origin.semantic);
5756    }
5757
5758    void callCheck(ExceptionCheckMode mode = CheckExceptions)
5759    {
5760        if (mode == NoExceptions)
5761            return;
5762
5763        if (Options::enableExceptionFuzz())
5764            m_out.call(m_out.operation(operationExceptionFuzz));
5765
5766        LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("Exception check continuation"));
5767
5768        m_out.branch(
5769            m_out.notZero64(m_out.load64(m_out.absolute(vm().addressOfException()))),
5770            rarely(m_handleExceptions), usually(continuation));
5771
5772        m_out.appendTo(continuation);
5773    }
5774
5775    LBasicBlock lowBlock(BasicBlock* block)
5776    {
5777        return m_blocks.get(block);
5778    }
5779
5780    void initializeOSRExitStateForBlock()
5781    {
5782        m_availability = m_highBlock->ssa->availabilityAtHead;
5783    }
5784
5785    void appendOSRExit(
5786        ExitKind kind, FormattedValue lowValue, Node* highValue, LValue failCondition)
5787    {
5788        if (verboseCompilationEnabled()) {
5789            dataLog("    OSR exit #", m_ftlState.jitCode->osrExit.size(), " with availability: ", m_availability, "\n");
5790            if (!m_availableRecoveries.isEmpty())
5791                dataLog("        Available recoveries: ", listDump(m_availableRecoveries), "\n");
5792        }
5793
5794        ASSERT(m_ftlState.jitCode->osrExit.size() == m_ftlState.finalizer->osrExit.size());
5795
5796        m_ftlState.jitCode->osrExit.append(OSRExit(
5797            kind, lowValue.format(), m_graph.methodOfGettingAValueProfileFor(highValue),
5798            m_codeOriginForExitTarget, m_codeOriginForExitProfile,
5799            m_availability.numberOfArguments(), m_availability.numberOfLocals()));
5800        m_ftlState.finalizer->osrExit.append(OSRExitCompilationInfo());
5801
5802        OSRExit& exit = m_ftlState.jitCode->osrExit.last();
5803
5804        LBasicBlock lastNext = 0;
5805        LBasicBlock continuation = 0;
5806
5807        LBasicBlock failCase = FTL_NEW_BLOCK(m_out, ("OSR exit failCase for ", m_node));
5808        continuation = FTL_NEW_BLOCK(m_out, ("OSR exit continuation for ", m_node));
5809
5810        m_out.branch(failCondition, rarely(failCase), usually(continuation));
5811
5812        lastNext = m_out.appendTo(failCase, continuation);
5813
5814        emitOSRExitCall(exit, lowValue);
5815
5816        m_out.unreachable();
5817
5818        m_out.appendTo(continuation, lastNext);
5819    }
5820
5821    void emitOSRExitCall(OSRExit& exit, FormattedValue lowValue)
5822    {
5823        ExitArgumentList arguments;
5824
5825        CodeOrigin codeOrigin = exit.m_codeOrigin;
5826
5827        buildExitArguments(exit, arguments, lowValue, codeOrigin);
5828
5829        callStackmap(exit, arguments);
5830    }
5831
5832    void buildExitArguments(
5833        OSRExit& exit, ExitArgumentList& arguments, FormattedValue lowValue,
5834        CodeOrigin codeOrigin)
5835    {
5836        if (!!lowValue)
5837            arguments.append(lowValue.value());
5838
5839        for (unsigned i = 0; i < exit.m_values.size(); ++i) {
5840            int operand = exit.m_values.operandForIndex(i);
5841            bool isLive = m_graph.isLiveInBytecode(VirtualRegister(operand), codeOrigin);
5842            if (!isLive) {
5843                exit.m_values[i] = ExitValue::dead();
5844                continue;
5845            }
5846
5847            Availability availability = m_availability[i];
5848            FlushedAt flush = availability.flushedAt();
5849            switch (flush.format()) {
5850            case DeadFlush:
5851            case ConflictingFlush:
5852                if (availability.hasNode()) {
5853                    addExitArgumentForNode(exit, arguments, i, availability.node());
5854                    break;
5855                }
5856
5857                if (Options::validateFTLOSRExitLiveness()) {
5858                    dataLog("Expected r", operand, " to be available but it wasn't.\n");
5859                    RELEASE_ASSERT_NOT_REACHED();
5860                }
5861
5862                // This means that the DFG's DCE proved that the value is dead in bytecode
5863                // even though the bytecode liveness analysis thinks it's live. This is
5864                // acceptable since the DFG's DCE is by design more aggressive while still
5865                // being sound.
5866                exit.m_values[i] = ExitValue::dead();
5867                break;
5868
5869            case FlushedJSValue:
5870            case FlushedCell:
5871            case FlushedBoolean:
5872                exit.m_values[i] = ExitValue::inJSStack(flush.virtualRegister());
5873                break;
5874
5875            case FlushedInt32:
5876                exit.m_values[i] = ExitValue::inJSStackAsInt32(flush.virtualRegister());
5877                break;
5878
5879            case FlushedInt52:
5880                exit.m_values[i] = ExitValue::inJSStackAsInt52(flush.virtualRegister());
5881                break;
5882
5883            case FlushedDouble:
5884                exit.m_values[i] = ExitValue::inJSStackAsDouble(flush.virtualRegister());
5885                break;
5886
5887            case FlushedArguments:
5888                exit.m_values[i] = ExitValue::argumentsObjectThatWasNotCreated();
5889                break;
5890            }
5891        }
5892
5893        if (verboseCompilationEnabled())
5894            dataLog("        Exit values: ", exit.m_values, "\n");
5895    }
5896
5897    void callStackmap(OSRExit& exit, ExitArgumentList& arguments)
5898    {
5899        exit.m_stackmapID = m_stackmapIDs++;
5900        arguments.insert(0, m_out.constInt32(MacroAssembler::maxJumpReplacementSize()));
5901        arguments.insert(0, m_out.constInt64(exit.m_stackmapID));
5902
5903        m_out.call(m_out.stackmapIntrinsic(), arguments);
5904    }
5905
5906    void addExitArgumentForNode(
5907        OSRExit& exit, ExitArgumentList& arguments, unsigned index, Node* node)
5908    {
5909        ASSERT(node->shouldGenerate());
5910        ASSERT(node->hasResult());
5911
5912        if (tryToSetConstantExitArgument(exit, index, node))
5913            return;
5914
5915        for (unsigned i = 0; i < m_availableRecoveries.size(); ++i) {
5916            AvailableRecovery recovery = m_availableRecoveries[i];
5917            if (recovery.node() != node)
5918                continue;
5919
5920            exit.m_values[index] = ExitValue::recovery(
5921                recovery.opcode(), arguments.size(), arguments.size() + 1,
5922                recovery.format());
5923            arguments.append(recovery.left());
5924            arguments.append(recovery.right());
5925            return;
5926        }
5927
5928        LoweredNodeValue value = m_int32Values.get(node);
5929        if (isValid(value)) {
5930            addExitArgument(exit, arguments, index, ValueFormatInt32, value.value());
5931            return;
5932        }
5933
5934        value = m_int52Values.get(node);
5935        if (isValid(value)) {
5936            addExitArgument(exit, arguments, index, ValueFormatInt52, value.value());
5937            return;
5938        }
5939
5940        value = m_strictInt52Values.get(node);
5941        if (isValid(value)) {
5942            addExitArgument(exit, arguments, index, ValueFormatStrictInt52, value.value());
5943            return;
5944        }
5945
5946        value = m_booleanValues.get(node);
5947        if (isValid(value)) {
5948            LValue valueToPass = m_out.zeroExt(value.value(), m_out.int32);
5949            addExitArgument(exit, arguments, index, ValueFormatBoolean, valueToPass);
5950            return;
5951        }
5952
5953        value = m_jsValueValues.get(node);
5954        if (isValid(value)) {
5955            addExitArgument(exit, arguments, index, ValueFormatJSValue, value.value());
5956            return;
5957        }
5958
5959        value = m_doubleValues.get(node);
5960        if (isValid(value)) {
5961            addExitArgument(exit, arguments, index, ValueFormatDouble, value.value());
5962            return;
5963        }
5964
5965        startCrashing();
5966        dataLog("Cannot find value for node: ", node, " while compiling exit at ", exit.m_codeOrigin, " in node ", m_node, "\n");
5967        m_graph.dump();
5968        RELEASE_ASSERT_NOT_REACHED();
5969    }
5970
5971    bool tryToSetConstantExitArgument(OSRExit& exit, unsigned index, Node* node)
5972    {
5973        if (!node)
5974            return false;
5975
5976        switch (node->op()) {
5977        case JSConstant:
5978        case Int52Constant:
5979        case DoubleConstant:
5980        case WeakJSConstant:
5981            exit.m_values[index] = ExitValue::constant(m_graph.valueOfJSConstant(node));
5982            return true;
5983        case PhantomArguments:
5984            exit.m_values[index] = ExitValue::argumentsObjectThatWasNotCreated();
5985            return true;
5986        default:
5987            return false;
5988        }
5989    }
5990
5991    void addExitArgument(
5992        OSRExit& exit, ExitArgumentList& arguments, unsigned index, ValueFormat format,
5993        LValue value)
5994    {
5995        exit.m_values[index] = ExitValue::exitArgument(ExitArgument(format, arguments.size()));
5996        arguments.append(value);
5997    }
5998
5999    bool doesKill(Edge edge)
6000    {
6001        if (edge.doesNotKill())
6002            return false;
6003
6004        if (edge->hasConstant())
6005            return false;
6006
6007        return true;
6008    }
6009
6010    void addAvailableRecovery(
6011        Node* node, RecoveryOpcode opcode, LValue left, LValue right, ValueFormat format)
6012    {
6013        m_availableRecoveries.append(AvailableRecovery(node, opcode, left, right, format));
6014    }
6015
6016    void addAvailableRecovery(
6017        Edge edge, RecoveryOpcode opcode, LValue left, LValue right, ValueFormat format)
6018    {
6019        addAvailableRecovery(edge.node(), opcode, left, right, format);
6020    }
6021
6022    void setInt32(Node* node, LValue value)
6023    {
6024        m_int32Values.set(node, LoweredNodeValue(value, m_highBlock));
6025    }
6026    void setInt52(Node* node, LValue value)
6027    {
6028        m_int52Values.set(node, LoweredNodeValue(value, m_highBlock));
6029    }
6030    void setStrictInt52(Node* node, LValue value)
6031    {
6032        m_strictInt52Values.set(node, LoweredNodeValue(value, m_highBlock));
6033    }
6034    void setInt52(Node* node, LValue value, Int52Kind kind)
6035    {
6036        switch (kind) {
6037        case Int52:
6038            setInt52(node, value);
6039            return;
6040
6041        case StrictInt52:
6042            setStrictInt52(node, value);
6043            return;
6044        }
6045
6046        RELEASE_ASSERT_NOT_REACHED();
6047    }
6048    void setJSValue(Node* node, LValue value)
6049    {
6050        m_jsValueValues.set(node, LoweredNodeValue(value, m_highBlock));
6051    }
6052    void setBoolean(Node* node, LValue value)
6053    {
6054        m_booleanValues.set(node, LoweredNodeValue(value, m_highBlock));
6055    }
6056    void setStorage(Node* node, LValue value)
6057    {
6058        m_storageValues.set(node, LoweredNodeValue(value, m_highBlock));
6059    }
6060    void setDouble(Node* node, LValue value)
6061    {
6062        m_doubleValues.set(node, LoweredNodeValue(value, m_highBlock));
6063    }
6064
6065    void setInt32(LValue value)
6066    {
6067        setInt32(m_node, value);
6068    }
6069    void setInt52(LValue value)
6070    {
6071        setInt52(m_node, value);
6072    }
6073    void setStrictInt52(LValue value)
6074    {
6075        setStrictInt52(m_node, value);
6076    }
6077    void setInt52(LValue value, Int52Kind kind)
6078    {
6079        setInt52(m_node, value, kind);
6080    }
6081    void setJSValue(LValue value)
6082    {
6083        setJSValue(m_node, value);
6084    }
6085    void setBoolean(LValue value)
6086    {
6087        setBoolean(m_node, value);
6088    }
6089    void setStorage(LValue value)
6090    {
6091        setStorage(m_node, value);
6092    }
6093    void setDouble(LValue value)
6094    {
6095        setDouble(m_node, value);
6096    }
6097
6098    bool isValid(const LoweredNodeValue& value)
6099    {
6100        if (!value)
6101            return false;
6102        if (!m_graph.m_dominators.dominates(value.block(), m_highBlock))
6103            return false;
6104        return true;
6105    }
6106
6107    void addWeakReference(JSCell* target)
6108    {
6109        m_graph.m_plan.weakReferences.addLazily(target);
6110    }
6111
6112    LValue loadStructure(LValue value)
6113    {
6114        LValue tableIndex = m_out.load32(value, m_heaps.JSCell_structureID);
6115        LValue tableBase = m_out.loadPtr(
6116            m_out.absolute(vm().heap.structureIDTable().base()));
6117        LValue pointerIntoTable = m_out.baseIndex(
6118            tableBase, m_out.zeroExt(tableIndex, m_out.intPtr), ScaleEight);
6119        return m_out.loadPtr(TypedPointer(m_heaps.structureTable, pointerIntoTable));
6120    }
6121
6122    LValue weakPointer(JSCell* pointer)
6123    {
6124        addWeakReference(pointer);
6125        return m_out.constIntPtr(pointer);
6126    }
6127
6128    LValue weakStructure(Structure* structure)
6129    {
6130        addWeakReference(structure);
6131        return m_out.constInt32(structure->id());
6132    }
6133
6134    TypedPointer addressFor(LValue base, int operand, ptrdiff_t offset = 0)
6135    {
6136        return m_out.address(base, m_heaps.variables[operand], offset);
6137    }
6138    TypedPointer payloadFor(LValue base, int operand)
6139    {
6140        return addressFor(base, operand, PayloadOffset);
6141    }
6142    TypedPointer tagFor(LValue base, int operand)
6143    {
6144        return addressFor(base, operand, TagOffset);
6145    }
6146    TypedPointer addressFor(int operand, ptrdiff_t offset = 0)
6147    {
6148        return addressFor(VirtualRegister(operand), offset);
6149    }
6150    TypedPointer addressFor(VirtualRegister operand, ptrdiff_t offset = 0)
6151    {
6152        if (operand.isLocal())
6153            return addressFor(m_captured, operand.offset(), offset);
6154        return addressFor(m_callFrame, operand.offset(), offset);
6155    }
6156    TypedPointer payloadFor(int operand)
6157    {
6158        return payloadFor(VirtualRegister(operand));
6159    }
6160    TypedPointer payloadFor(VirtualRegister operand)
6161    {
6162        return addressFor(operand, PayloadOffset);
6163    }
6164    TypedPointer tagFor(int operand)
6165    {
6166        return tagFor(VirtualRegister(operand));
6167    }
6168    TypedPointer tagFor(VirtualRegister operand)
6169    {
6170        return addressFor(operand, TagOffset);
6171    }
6172
6173    VM& vm() { return m_graph.m_vm; }
6174    CodeBlock* codeBlock() { return m_graph.m_codeBlock; }
6175
6176    Graph& m_graph;
6177    State& m_ftlState;
6178    AbstractHeapRepository m_heaps;
6179    Output m_out;
6180
6181    LBasicBlock m_prologue;
6182    LBasicBlock m_handleExceptions;
6183    HashMap<BasicBlock*, LBasicBlock> m_blocks;
6184
6185    LValue m_callFrame;
6186    LValue m_captured;
6187    LValue m_tagTypeNumber;
6188    LValue m_tagMask;
6189
6190    HashMap<Node*, LoweredNodeValue> m_int32Values;
6191    HashMap<Node*, LoweredNodeValue> m_strictInt52Values;
6192    HashMap<Node*, LoweredNodeValue> m_int52Values;
6193    HashMap<Node*, LoweredNodeValue> m_jsValueValues;
6194    HashMap<Node*, LoweredNodeValue> m_booleanValues;
6195    HashMap<Node*, LoweredNodeValue> m_storageValues;
6196    HashMap<Node*, LoweredNodeValue> m_doubleValues;
6197
6198    HashMap<Node*, LValue> m_phis;
6199
6200    Operands<Availability> m_availability;
6201
6202    Vector<AvailableRecovery, 3> m_availableRecoveries;
6203
6204    InPlaceAbstractState m_state;
6205    AbstractInterpreter<InPlaceAbstractState> m_interpreter;
6206    BasicBlock* m_highBlock;
6207    BasicBlock* m_nextHighBlock;
6208    LBasicBlock m_nextLowBlock;
6209
6210    CodeOrigin m_codeOriginForExitTarget;
6211    CodeOrigin m_codeOriginForExitProfile;
6212    unsigned m_nodeIndex;
6213    Node* m_node;
6214
6215    uint32_t m_stackmapIDs;
6216};
6217
6218void lowerDFGToLLVM(State& state)
6219{
6220    LowerDFGToLLVM lowering(state);
6221    lowering.lower();
6222}
6223
6224} } // namespace JSC::FTL
6225
6226#endif // ENABLE(FTL_JIT)
6227
6228