[DFG] DFG should handle String#toString
[WebKit-https.git] / Source / JavaScriptCore / dfg / DFGSpeculativeJIT.h
1 /*
2  * Copyright (C) 2011-2018 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 #pragma once
27
28 #if ENABLE(DFG_JIT)
29
30 #include "BlockDirectory.h"
31 #include "DFGAbstractInterpreter.h"
32 #include "DFGGenerationInfo.h"
33 #include "DFGInPlaceAbstractState.h"
34 #include "DFGJITCompiler.h"
35 #include "DFGOSRExit.h"
36 #include "DFGOSRExitJumpPlaceholder.h"
37 #include "DFGRegisterBank.h"
38 #include "DFGSilentRegisterSavePlan.h"
39 #include "JITMathIC.h"
40 #include "JITOperations.h"
41 #include "PutKind.h"
42 #include "SpillRegistersMode.h"
43 #include "StructureStubInfo.h"
44 #include "ValueRecovery.h"
45 #include "VirtualRegister.h"
46
47 namespace JSC { namespace DFG {
48
49 class GPRTemporary;
50 class JSValueOperand;
51 class SlowPathGenerator;
52 class SpeculativeJIT;
53 class SpeculateInt32Operand;
54 class SpeculateStrictInt32Operand;
55 class SpeculateDoubleOperand;
56 class SpeculateCellOperand;
57 class SpeculateBooleanOperand;
58
59 enum GeneratedOperandType { GeneratedOperandTypeUnknown, GeneratedOperandInteger, GeneratedOperandJSValue};
60
61 // === SpeculativeJIT ===
62 //
63 // The SpeculativeJIT is used to generate a fast, but potentially
64 // incomplete code path for the dataflow. When code generating
65 // we may make assumptions about operand types, dynamically check,
66 // and bail-out to an alternate code path if these checks fail.
67 // Importantly, the speculative code path cannot be reentered once
68 // a speculative check has failed. This allows the SpeculativeJIT
69 // to propagate type information (including information that has
70 // only speculatively been asserted) through the dataflow.
71 class SpeculativeJIT {
72     WTF_MAKE_FAST_ALLOCATED;
73
74     friend struct OSRExit;
75 private:
76     typedef JITCompiler::TrustedImm32 TrustedImm32;
77     typedef JITCompiler::Imm32 Imm32;
78     typedef JITCompiler::ImmPtr ImmPtr;
79     typedef JITCompiler::TrustedImm64 TrustedImm64;
80     typedef JITCompiler::Imm64 Imm64;
81
82     // These constants are used to set priorities for spill order for
83     // the register allocator.
84 #if USE(JSVALUE64)
85     enum SpillOrder {
86         SpillOrderConstant = 1, // no spill, and cheap fill
87         SpillOrderSpilled  = 2, // no spill
88         SpillOrderJS       = 4, // needs spill
89         SpillOrderCell     = 4, // needs spill
90         SpillOrderStorage  = 4, // needs spill
91         SpillOrderInteger  = 5, // needs spill and box
92         SpillOrderBoolean  = 5, // needs spill and box
93         SpillOrderDouble   = 6, // needs spill and convert
94     };
95 #elif USE(JSVALUE32_64)
96     enum SpillOrder {
97         SpillOrderConstant = 1, // no spill, and cheap fill
98         SpillOrderSpilled  = 2, // no spill
99         SpillOrderJS       = 4, // needs spill
100         SpillOrderStorage  = 4, // needs spill
101         SpillOrderDouble   = 4, // needs spill
102         SpillOrderInteger  = 5, // needs spill and box
103         SpillOrderCell     = 5, // needs spill and box
104         SpillOrderBoolean  = 5, // needs spill and box
105     };
106 #endif
107
108     enum UseChildrenMode { CallUseChildren, UseChildrenCalledExplicitly };
109     
110 public:
111     SpeculativeJIT(JITCompiler&);
112     ~SpeculativeJIT();
113
114     VM& vm()
115     {
116         return *m_jit.vm();
117     }
118
119     struct TrustedImmPtr {
120         template <typename T>
121         explicit TrustedImmPtr(T* value)
122             : m_value(value)
123         {
124             static_assert(!std::is_base_of<JSCell, T>::value, "To use a GC pointer, the graph must be aware of it. Use SpeculativeJIT::TrustedImmPtr::weakPointer instead.");
125         }
126
127         explicit TrustedImmPtr(RegisteredStructure structure)
128             : m_value(structure.get())
129         { }
130         
131         explicit TrustedImmPtr(std::nullptr_t)
132             : m_value(nullptr)
133         { }
134
135         explicit TrustedImmPtr(FrozenValue* value)
136             : m_value(value->cell())
137         {
138             RELEASE_ASSERT(value->value().isCell());
139         }
140
141         explicit TrustedImmPtr(size_t value)
142             : m_value(bitwise_cast<void*>(value))
143         {
144         }
145
146         static TrustedImmPtr weakPointer(Graph& graph, JSCell* cell)
147         {     
148             graph.m_plan.weakReferences().addLazily(cell);
149             return TrustedImmPtr(bitwise_cast<size_t>(cell));
150         }
151
152         template<typename Key>
153         static TrustedImmPtr weakPoisonedPointer(Graph& graph, JSCell* cell)
154         {     
155             graph.m_plan.weakReferences().addLazily(cell);
156             return TrustedImmPtr(bitwise_cast<size_t>(cell) ^ Key::key());
157         }
158
159         operator MacroAssembler::TrustedImmPtr() const { return m_value; }
160         operator MacroAssembler::TrustedImm() const { return m_value; }
161
162         intptr_t asIntptr()
163         {
164             return m_value.asIntptr();
165         }
166
167     private:
168         MacroAssembler::TrustedImmPtr m_value;
169     };
170
171     bool compile();
172     
173     void createOSREntries();
174     void linkOSREntries(LinkBuffer&);
175
176     BasicBlock* nextBlock()
177     {
178         for (BlockIndex resultIndex = m_block->index + 1; ; resultIndex++) {
179             if (resultIndex >= m_jit.graph().numBlocks())
180                 return 0;
181             if (BasicBlock* result = m_jit.graph().block(resultIndex))
182                 return result;
183         }
184     }
185     
186 #if USE(JSVALUE64)
187     GPRReg fillJSValue(Edge);
188 #elif USE(JSVALUE32_64)
189     bool fillJSValue(Edge, GPRReg&, GPRReg&, FPRReg&);
190 #endif
191     GPRReg fillStorage(Edge);
192
193     // lock and unlock GPR & FPR registers.
194     void lock(GPRReg reg)
195     {
196         m_gprs.lock(reg);
197     }
198     void lock(FPRReg reg)
199     {
200         m_fprs.lock(reg);
201     }
202     void unlock(GPRReg reg)
203     {
204         m_gprs.unlock(reg);
205     }
206     void unlock(FPRReg reg)
207     {
208         m_fprs.unlock(reg);
209     }
210
211     // Used to check whether a child node is on its last use,
212     // and its machine registers may be reused.
213     bool canReuse(Node* node)
214     {
215         return generationInfo(node).useCount() == 1;
216     }
217     bool canReuse(Node* nodeA, Node* nodeB)
218     {
219         return nodeA == nodeB && generationInfo(nodeA).useCount() == 2;
220     }
221     bool canReuse(Edge nodeUse)
222     {
223         return canReuse(nodeUse.node());
224     }
225     GPRReg reuse(GPRReg reg)
226     {
227         m_gprs.lock(reg);
228         return reg;
229     }
230     FPRReg reuse(FPRReg reg)
231     {
232         m_fprs.lock(reg);
233         return reg;
234     }
235
236     // Allocate a gpr/fpr.
237     GPRReg allocate()
238     {
239 #if ENABLE(DFG_REGISTER_ALLOCATION_VALIDATION)
240         m_jit.addRegisterAllocationAtOffset(m_jit.debugOffset());
241 #endif
242         VirtualRegister spillMe;
243         GPRReg gpr = m_gprs.allocate(spillMe);
244         if (spillMe.isValid()) {
245 #if USE(JSVALUE32_64)
246             GenerationInfo& info = generationInfoFromVirtualRegister(spillMe);
247             if ((info.registerFormat() & DataFormatJS))
248                 m_gprs.release(info.tagGPR() == gpr ? info.payloadGPR() : info.tagGPR());
249 #endif
250             spill(spillMe);
251         }
252         return gpr;
253     }
254     GPRReg allocate(GPRReg specific)
255     {
256 #if ENABLE(DFG_REGISTER_ALLOCATION_VALIDATION)
257         m_jit.addRegisterAllocationAtOffset(m_jit.debugOffset());
258 #endif
259         VirtualRegister spillMe = m_gprs.allocateSpecific(specific);
260         if (spillMe.isValid()) {
261 #if USE(JSVALUE32_64)
262             GenerationInfo& info = generationInfoFromVirtualRegister(spillMe);
263             RELEASE_ASSERT(info.registerFormat() != DataFormatJSDouble);
264             if ((info.registerFormat() & DataFormatJS))
265                 m_gprs.release(info.tagGPR() == specific ? info.payloadGPR() : info.tagGPR());
266 #endif
267             spill(spillMe);
268         }
269         return specific;
270     }
271     GPRReg tryAllocate()
272     {
273         return m_gprs.tryAllocate();
274     }
275     FPRReg fprAllocate()
276     {
277 #if ENABLE(DFG_REGISTER_ALLOCATION_VALIDATION)
278         m_jit.addRegisterAllocationAtOffset(m_jit.debugOffset());
279 #endif
280         VirtualRegister spillMe;
281         FPRReg fpr = m_fprs.allocate(spillMe);
282         if (spillMe.isValid())
283             spill(spillMe);
284         return fpr;
285     }
286
287     // Check whether a VirtualRegsiter is currently in a machine register.
288     // We use this when filling operands to fill those that are already in
289     // machine registers first (by locking VirtualRegsiters that are already
290     // in machine register before filling those that are not we attempt to
291     // avoid spilling values we will need immediately).
292     bool isFilled(Node* node)
293     {
294         return generationInfo(node).registerFormat() != DataFormatNone;
295     }
296     bool isFilledDouble(Node* node)
297     {
298         return generationInfo(node).registerFormat() == DataFormatDouble;
299     }
300
301     // Called on an operand once it has been consumed by a parent node.
302     void use(Node* node)
303     {
304         if (!node->hasResult())
305             return;
306         GenerationInfo& info = generationInfo(node);
307
308         // use() returns true when the value becomes dead, and any
309         // associated resources may be freed.
310         if (!info.use(*m_stream))
311             return;
312
313         // Release the associated machine registers.
314         DataFormat registerFormat = info.registerFormat();
315 #if USE(JSVALUE64)
316         if (registerFormat == DataFormatDouble)
317             m_fprs.release(info.fpr());
318         else if (registerFormat != DataFormatNone)
319             m_gprs.release(info.gpr());
320 #elif USE(JSVALUE32_64)
321         if (registerFormat == DataFormatDouble)
322             m_fprs.release(info.fpr());
323         else if (registerFormat & DataFormatJS) {
324             m_gprs.release(info.tagGPR());
325             m_gprs.release(info.payloadGPR());
326         } else if (registerFormat != DataFormatNone)
327             m_gprs.release(info.gpr());
328 #endif
329     }
330     void use(Edge nodeUse)
331     {
332         use(nodeUse.node());
333     }
334     
335     RegisterSet usedRegisters();
336     
337     bool masqueradesAsUndefinedWatchpointIsStillValid(const CodeOrigin& codeOrigin)
338     {
339         return m_jit.graph().masqueradesAsUndefinedWatchpointIsStillValid(codeOrigin);
340     }
341     bool masqueradesAsUndefinedWatchpointIsStillValid()
342     {
343         return masqueradesAsUndefinedWatchpointIsStillValid(m_currentNode->origin.semantic);
344     }
345
346     void compileStoreBarrier(Node*);
347
348     // Called by the speculative operand types, below, to fill operand to
349     // machine registers, implicitly generating speculation checks as needed.
350     GPRReg fillSpeculateInt32(Edge, DataFormat& returnFormat);
351     GPRReg fillSpeculateInt32Strict(Edge);
352     GPRReg fillSpeculateInt52(Edge, DataFormat desiredFormat);
353     FPRReg fillSpeculateDouble(Edge);
354     GPRReg fillSpeculateCell(Edge);
355     GPRReg fillSpeculateBoolean(Edge);
356     GeneratedOperandType checkGeneratedTypeForToInt32(Node*);
357
358     void addSlowPathGenerator(std::unique_ptr<SlowPathGenerator>);
359     void addSlowPathGeneratorLambda(Function<void()>&&);
360     void runSlowPathGenerators(PCToCodeOriginMapBuilder&);
361     
362     void compile(Node*);
363     void noticeOSRBirth(Node*);
364     void bail(AbortReason);
365     void compileCurrentBlock();
366
367     void checkArgumentTypes();
368
369     void clearGenerationInfo();
370
371     // These methods are used when generating 'unexpected'
372     // calls out from JIT code to C++ helper routines -
373     // they spill all live values to the appropriate
374     // slots in the JSStack without changing any state
375     // in the GenerationInfo.
376     SilentRegisterSavePlan silentSavePlanForGPR(VirtualRegister spillMe, GPRReg source);
377     SilentRegisterSavePlan silentSavePlanForFPR(VirtualRegister spillMe, FPRReg source);
378     void silentSpill(const SilentRegisterSavePlan&);
379     void silentFill(const SilentRegisterSavePlan&);
380
381     template<typename CollectionType>
382     void silentSpill(const CollectionType& savePlans)
383     {
384         for (unsigned i = 0; i < savePlans.size(); ++i)
385             silentSpill(savePlans[i]);
386     }
387
388     template<typename CollectionType>
389     void silentFill(const CollectionType& savePlans)
390     {
391         for (unsigned i = savePlans.size(); i--;)
392             silentFill(savePlans[i]);
393     }
394
395     template<typename CollectionType>
396     void silentSpillAllRegistersImpl(bool doSpill, CollectionType& plans, GPRReg exclude, GPRReg exclude2 = InvalidGPRReg, FPRReg fprExclude = InvalidFPRReg)
397     {
398         ASSERT(plans.isEmpty());
399         for (gpr_iterator iter = m_gprs.begin(); iter != m_gprs.end(); ++iter) {
400             GPRReg gpr = iter.regID();
401             if (iter.name().isValid() && gpr != exclude && gpr != exclude2) {
402                 SilentRegisterSavePlan plan = silentSavePlanForGPR(iter.name(), gpr);
403                 if (doSpill)
404                     silentSpill(plan);
405                 plans.append(plan);
406             }
407         }
408         for (fpr_iterator iter = m_fprs.begin(); iter != m_fprs.end(); ++iter) {
409             if (iter.name().isValid() && iter.regID() != fprExclude) {
410                 SilentRegisterSavePlan plan = silentSavePlanForFPR(iter.name(), iter.regID());
411                 if (doSpill)
412                     silentSpill(plan);
413                 plans.append(plan);
414             }
415         }
416     }
417     template<typename CollectionType>
418     void silentSpillAllRegistersImpl(bool doSpill, CollectionType& plans, NoResultTag)
419     {
420         silentSpillAllRegistersImpl(doSpill, plans, InvalidGPRReg, InvalidGPRReg, InvalidFPRReg);
421     }
422     template<typename CollectionType>
423     void silentSpillAllRegistersImpl(bool doSpill, CollectionType& plans, FPRReg exclude)
424     {
425         silentSpillAllRegistersImpl(doSpill, plans, InvalidGPRReg, InvalidGPRReg, exclude);
426     }
427     template<typename CollectionType>
428     void silentSpillAllRegistersImpl(bool doSpill, CollectionType& plans, JSValueRegs exclude)
429     {
430 #if USE(JSVALUE32_64)
431         silentSpillAllRegistersImpl(doSpill, plans, exclude.tagGPR(), exclude.payloadGPR());
432 #else
433         silentSpillAllRegistersImpl(doSpill, plans, exclude.gpr());
434 #endif
435     }
436     
437     void silentSpillAllRegisters(GPRReg exclude, GPRReg exclude2 = InvalidGPRReg, FPRReg fprExclude = InvalidFPRReg)
438     {
439         silentSpillAllRegistersImpl(true, m_plans, exclude, exclude2, fprExclude);
440     }
441     void silentSpillAllRegisters(FPRReg exclude)
442     {
443         silentSpillAllRegisters(InvalidGPRReg, InvalidGPRReg, exclude);
444     }
445     void silentSpillAllRegisters(JSValueRegs exclude)
446     {
447 #if USE(JSVALUE64)
448         silentSpillAllRegisters(exclude.payloadGPR());
449 #else
450         silentSpillAllRegisters(exclude.payloadGPR(), exclude.tagGPR());
451 #endif
452     }
453
454     void silentFillAllRegisters()
455     {
456         while (!m_plans.isEmpty()) {
457             SilentRegisterSavePlan& plan = m_plans.last();
458             silentFill(plan);
459             m_plans.removeLast();
460         }
461     }
462
463     // These methods convert between doubles, and doubles boxed and JSValues.
464 #if USE(JSVALUE64)
465     GPRReg boxDouble(FPRReg fpr, GPRReg gpr)
466     {
467         return m_jit.boxDouble(fpr, gpr);
468     }
469     FPRReg unboxDouble(GPRReg gpr, GPRReg resultGPR, FPRReg fpr)
470     {
471         return m_jit.unboxDouble(gpr, resultGPR, fpr);
472     }
473     GPRReg boxDouble(FPRReg fpr)
474     {
475         return boxDouble(fpr, allocate());
476     }
477     
478     void boxInt52(GPRReg sourceGPR, GPRReg targetGPR, DataFormat);
479 #elif USE(JSVALUE32_64)
480     void boxDouble(FPRReg fpr, GPRReg tagGPR, GPRReg payloadGPR)
481     {
482         m_jit.boxDouble(fpr, tagGPR, payloadGPR);
483     }
484     void unboxDouble(GPRReg tagGPR, GPRReg payloadGPR, FPRReg fpr, FPRReg scratchFPR)
485     {
486         m_jit.unboxDouble(tagGPR, payloadGPR, fpr, scratchFPR);
487     }
488 #endif
489     void boxDouble(FPRReg fpr, JSValueRegs regs)
490     {
491         m_jit.boxDouble(fpr, regs);
492     }
493
494     // Spill a VirtualRegister to the JSStack.
495     void spill(VirtualRegister spillMe)
496     {
497         GenerationInfo& info = generationInfoFromVirtualRegister(spillMe);
498
499 #if USE(JSVALUE32_64)
500         if (info.registerFormat() == DataFormatNone) // it has been spilled. JS values which have two GPRs can reach here
501             return;
502 #endif
503         // Check the GenerationInfo to see if this value need writing
504         // to the JSStack - if not, mark it as spilled & return.
505         if (!info.needsSpill()) {
506             info.setSpilled(*m_stream, spillMe);
507             return;
508         }
509
510         DataFormat spillFormat = info.registerFormat();
511         switch (spillFormat) {
512         case DataFormatStorage: {
513             // This is special, since it's not a JS value - as in it's not visible to JS
514             // code.
515             m_jit.storePtr(info.gpr(), JITCompiler::addressFor(spillMe));
516             info.spill(*m_stream, spillMe, DataFormatStorage);
517             return;
518         }
519
520         case DataFormatInt32: {
521             m_jit.store32(info.gpr(), JITCompiler::payloadFor(spillMe));
522             info.spill(*m_stream, spillMe, DataFormatInt32);
523             return;
524         }
525
526 #if USE(JSVALUE64)
527         case DataFormatDouble: {
528             m_jit.storeDouble(info.fpr(), JITCompiler::addressFor(spillMe));
529             info.spill(*m_stream, spillMe, DataFormatDouble);
530             return;
531         }
532
533         case DataFormatInt52:
534         case DataFormatStrictInt52: {
535             m_jit.store64(info.gpr(), JITCompiler::addressFor(spillMe));
536             info.spill(*m_stream, spillMe, spillFormat);
537             return;
538         }
539             
540         default:
541             // The following code handles JSValues, int32s, and cells.
542             RELEASE_ASSERT(spillFormat == DataFormatCell || spillFormat & DataFormatJS);
543             
544             GPRReg reg = info.gpr();
545             // We need to box int32 and cell values ...
546             // but on JSVALUE64 boxing a cell is a no-op!
547             if (spillFormat == DataFormatInt32)
548                 m_jit.or64(GPRInfo::tagTypeNumberRegister, reg);
549             
550             // Spill the value, and record it as spilled in its boxed form.
551             m_jit.store64(reg, JITCompiler::addressFor(spillMe));
552             info.spill(*m_stream, spillMe, (DataFormat)(spillFormat | DataFormatJS));
553             return;
554 #elif USE(JSVALUE32_64)
555         case DataFormatCell:
556         case DataFormatBoolean: {
557             m_jit.store32(info.gpr(), JITCompiler::payloadFor(spillMe));
558             info.spill(*m_stream, spillMe, spillFormat);
559             return;
560         }
561
562         case DataFormatDouble: {
563             // On JSVALUE32_64 boxing a double is a no-op.
564             m_jit.storeDouble(info.fpr(), JITCompiler::addressFor(spillMe));
565             info.spill(*m_stream, spillMe, DataFormatDouble);
566             return;
567         }
568
569         default:
570             // The following code handles JSValues.
571             RELEASE_ASSERT(spillFormat & DataFormatJS);
572             m_jit.store32(info.tagGPR(), JITCompiler::tagFor(spillMe));
573             m_jit.store32(info.payloadGPR(), JITCompiler::payloadFor(spillMe));
574             info.spill(*m_stream, spillMe, spillFormat);
575             return;
576 #endif
577         }
578     }
579     
580     bool isKnownInteger(Node* node) { return m_state.forNode(node).isType(SpecInt32Only); }
581     bool isKnownCell(Node* node) { return m_state.forNode(node).isType(SpecCell); }
582     
583     bool isKnownNotInteger(Node* node) { return !(m_state.forNode(node).m_type & SpecInt32Only); }
584     bool isKnownNotNumber(Node* node) { return !(m_state.forNode(node).m_type & SpecFullNumber); }
585     bool isKnownNotCell(Node* node) { return !(m_state.forNode(node).m_type & SpecCell); }
586     bool isKnownNotOther(Node* node) { return !(m_state.forNode(node).m_type & SpecOther); }
587     
588     UniquedStringImpl* identifierUID(unsigned index)
589     {
590         return m_jit.graph().identifiers()[index];
591     }
592
593     // Spill all VirtualRegisters back to the JSStack.
594     void flushRegisters()
595     {
596         for (gpr_iterator iter = m_gprs.begin(); iter != m_gprs.end(); ++iter) {
597             if (iter.name().isValid()) {
598                 spill(iter.name());
599                 iter.release();
600             }
601         }
602         for (fpr_iterator iter = m_fprs.begin(); iter != m_fprs.end(); ++iter) {
603             if (iter.name().isValid()) {
604                 spill(iter.name());
605                 iter.release();
606             }
607         }
608     }
609
610     // Used to ASSERT flushRegisters() has been called prior to
611     // calling out from JIT code to a C helper function.
612     bool isFlushed()
613     {
614         for (gpr_iterator iter = m_gprs.begin(); iter != m_gprs.end(); ++iter) {
615             if (iter.name().isValid())
616                 return false;
617         }
618         for (fpr_iterator iter = m_fprs.begin(); iter != m_fprs.end(); ++iter) {
619             if (iter.name().isValid())
620                 return false;
621         }
622         return true;
623     }
624
625 #if USE(JSVALUE64)
626     static MacroAssembler::Imm64 valueOfJSConstantAsImm64(Node* node)
627     {
628         return MacroAssembler::Imm64(JSValue::encode(node->asJSValue()));
629     }
630 #endif
631
632     // Helper functions to enable code sharing in implementations of bit/shift ops.
633     void bitOp(NodeType op, int32_t imm, GPRReg op1, GPRReg result)
634     {
635         switch (op) {
636         case BitAnd:
637             m_jit.and32(Imm32(imm), op1, result);
638             break;
639         case BitOr:
640             m_jit.or32(Imm32(imm), op1, result);
641             break;
642         case BitXor:
643             m_jit.xor32(Imm32(imm), op1, result);
644             break;
645         default:
646             RELEASE_ASSERT_NOT_REACHED();
647         }
648     }
649     void bitOp(NodeType op, GPRReg op1, GPRReg op2, GPRReg result)
650     {
651         switch (op) {
652         case BitAnd:
653             m_jit.and32(op1, op2, result);
654             break;
655         case BitOr:
656             m_jit.or32(op1, op2, result);
657             break;
658         case BitXor:
659             m_jit.xor32(op1, op2, result);
660             break;
661         default:
662             RELEASE_ASSERT_NOT_REACHED();
663         }
664     }
665     void shiftOp(NodeType op, GPRReg op1, int32_t shiftAmount, GPRReg result)
666     {
667         switch (op) {
668         case BitRShift:
669             m_jit.rshift32(op1, Imm32(shiftAmount), result);
670             break;
671         case BitLShift:
672             m_jit.lshift32(op1, Imm32(shiftAmount), result);
673             break;
674         case BitURShift:
675             m_jit.urshift32(op1, Imm32(shiftAmount), result);
676             break;
677         default:
678             RELEASE_ASSERT_NOT_REACHED();
679         }
680     }
681     void shiftOp(NodeType op, GPRReg op1, GPRReg shiftAmount, GPRReg result)
682     {
683         switch (op) {
684         case BitRShift:
685             m_jit.rshift32(op1, shiftAmount, result);
686             break;
687         case BitLShift:
688             m_jit.lshift32(op1, shiftAmount, result);
689             break;
690         case BitURShift:
691             m_jit.urshift32(op1, shiftAmount, result);
692             break;
693         default:
694             RELEASE_ASSERT_NOT_REACHED();
695         }
696     }
697     
698     // Returns the index of the branch node if peephole is okay, UINT_MAX otherwise.
699     unsigned detectPeepHoleBranch()
700     {
701         // Check that no intervening nodes will be generated.
702         for (unsigned index = m_indexInBlock + 1; index < m_block->size() - 1; ++index) {
703             Node* node = m_block->at(index);
704             if (!node->shouldGenerate())
705                 continue;
706             // Check if it's a Phantom that can be safely ignored.
707             if (node->op() == Phantom && !node->child1())
708                 continue;
709             return UINT_MAX;
710         }
711
712         // Check if the lastNode is a branch on this node.
713         Node* lastNode = m_block->terminal();
714         return lastNode->op() == Branch && lastNode->child1() == m_currentNode ? m_block->size() - 1 : UINT_MAX;
715     }
716     
717     void compileCheckTraps(Node*);
718
719     void compileMovHint(Node*);
720     void compileMovHintAndCheck(Node*);
721
722     void cachedGetById(CodeOrigin, JSValueRegs base, JSValueRegs result, unsigned identifierNumber, JITCompiler::Jump slowPathTarget, SpillRegistersMode, AccessType);
723     void cachedPutById(CodeOrigin, GPRReg baseGPR, JSValueRegs valueRegs, GPRReg scratchGPR, unsigned identifierNumber, PutKind, JITCompiler::Jump slowPathTarget = JITCompiler::Jump(), SpillRegistersMode = NeedToSpill);
724
725 #if USE(JSVALUE64)
726     void cachedGetById(CodeOrigin, GPRReg baseGPR, GPRReg resultGPR, unsigned identifierNumber, JITCompiler::Jump slowPathTarget, SpillRegistersMode, AccessType);
727     void cachedGetByIdWithThis(CodeOrigin, GPRReg baseGPR, GPRReg thisGPR, GPRReg resultGPR, unsigned identifierNumber, JITCompiler::JumpList slowPathTarget = JITCompiler::JumpList());
728 #elif USE(JSVALUE32_64)
729     void cachedGetById(CodeOrigin, GPRReg baseTagGPROrNone, GPRReg basePayloadGPR, GPRReg resultTagGPR, GPRReg resultPayloadGPR, unsigned identifierNumber, JITCompiler::Jump slowPathTarget, SpillRegistersMode, AccessType);
730     void cachedGetByIdWithThis(CodeOrigin, GPRReg baseTagGPROrNone, GPRReg basePayloadGPR, GPRReg thisTagGPROrNone, GPRReg thisPayloadGPR, GPRReg resultTagGPR, GPRReg resultPayloadGPR, unsigned identifierNumber, JITCompiler::JumpList slowPathTarget = JITCompiler::JumpList());
731 #endif
732
733     void compileDeleteById(Node*);
734     void compileDeleteByVal(Node*);
735     void compilePushWithScope(Node*);
736     void compileGetById(Node*, AccessType);
737     void compileGetByIdFlush(Node*, AccessType);
738     void compileInById(Node*);
739     void compileInByVal(Node*);
740     
741     void nonSpeculativeNonPeepholeCompareNullOrUndefined(Edge operand);
742     void nonSpeculativePeepholeBranchNullOrUndefined(Edge operand, Node* branchNode);
743     
744     void nonSpeculativePeepholeBranch(Node*, Node* branchNode, MacroAssembler::RelationalCondition, S_JITOperation_EJJ helperFunction);
745     void nonSpeculativeNonPeepholeCompare(Node*, MacroAssembler::RelationalCondition, S_JITOperation_EJJ helperFunction);
746     
747     void nonSpeculativePeepholeStrictEq(Node*, Node* branchNode, bool invert = false);
748     void nonSpeculativeNonPeepholeStrictEq(Node*, bool invert = false);
749     bool nonSpeculativeStrictEq(Node*, bool invert = false);
750     
751     void compileInstanceOfForCells(Node*, JSValueRegs valueGPR, JSValueRegs prototypeGPR, GPRReg resultGPT, GPRReg scratchGPR, GPRReg scratch2GPR, JITCompiler::Jump slowCase = JITCompiler::Jump());
752     void compileInstanceOf(Node*);
753     void compileInstanceOfCustom(Node*);
754     void compileOverridesHasInstance(Node*);
755
756     void compileIsCellWithType(Node*);
757     void compileIsTypedArrayView(Node*);
758
759     void emitCall(Node*);
760
761     void emitAllocateButterfly(GPRReg storageGPR, GPRReg sizeGPR, GPRReg scratch1, GPRReg scratch2, GPRReg scratch3, MacroAssembler::JumpList& slowCases);
762     void emitInitializeButterfly(GPRReg storageGPR, GPRReg sizeGPR, JSValueRegs emptyValueRegs, GPRReg scratchGPR);
763     void compileAllocateNewArrayWithSize(JSGlobalObject*, GPRReg resultGPR, GPRReg sizeGPR, IndexingType, bool shouldConvertLargeSizeToArrayStorage = true);
764     
765     // Called once a node has completed code generation but prior to setting
766     // its result, to free up its children. (This must happen prior to setting
767     // the nodes result, since the node may have the same VirtualRegister as
768     // a child, and as such will use the same GeneratioInfo).
769     void useChildren(Node*);
770
771     // These method called to initialize the GenerationInfo
772     // to describe the result of an operation.
773     void int32Result(GPRReg reg, Node* node, DataFormat format = DataFormatInt32, UseChildrenMode mode = CallUseChildren)
774     {
775         if (mode == CallUseChildren)
776             useChildren(node);
777
778         VirtualRegister virtualRegister = node->virtualRegister();
779         GenerationInfo& info = generationInfoFromVirtualRegister(virtualRegister);
780
781         if (format == DataFormatInt32) {
782             m_jit.jitAssertIsInt32(reg);
783             m_gprs.retain(reg, virtualRegister, SpillOrderInteger);
784             info.initInt32(node, node->refCount(), reg);
785         } else {
786 #if USE(JSVALUE64)
787             RELEASE_ASSERT(format == DataFormatJSInt32);
788             m_jit.jitAssertIsJSInt32(reg);
789             m_gprs.retain(reg, virtualRegister, SpillOrderJS);
790             info.initJSValue(node, node->refCount(), reg, format);
791 #elif USE(JSVALUE32_64)
792             RELEASE_ASSERT_NOT_REACHED();
793 #endif
794         }
795     }
796     void int32Result(GPRReg reg, Node* node, UseChildrenMode mode)
797     {
798         int32Result(reg, node, DataFormatInt32, mode);
799     }
800     void int52Result(GPRReg reg, Node* node, DataFormat format, UseChildrenMode mode = CallUseChildren)
801     {
802         if (mode == CallUseChildren)
803             useChildren(node);
804
805         VirtualRegister virtualRegister = node->virtualRegister();
806         GenerationInfo& info = generationInfoFromVirtualRegister(virtualRegister);
807
808         m_gprs.retain(reg, virtualRegister, SpillOrderJS);
809         info.initInt52(node, node->refCount(), reg, format);
810     }
811     void int52Result(GPRReg reg, Node* node, UseChildrenMode mode = CallUseChildren)
812     {
813         int52Result(reg, node, DataFormatInt52, mode);
814     }
815     void strictInt52Result(GPRReg reg, Node* node, UseChildrenMode mode = CallUseChildren)
816     {
817         int52Result(reg, node, DataFormatStrictInt52, mode);
818     }
819     void noResult(Node* node, UseChildrenMode mode = CallUseChildren)
820     {
821         if (mode == UseChildrenCalledExplicitly)
822             return;
823         useChildren(node);
824     }
825     void cellResult(GPRReg reg, Node* node, UseChildrenMode mode = CallUseChildren)
826     {
827         if (mode == CallUseChildren)
828             useChildren(node);
829
830         VirtualRegister virtualRegister = node->virtualRegister();
831         m_gprs.retain(reg, virtualRegister, SpillOrderCell);
832         GenerationInfo& info = generationInfoFromVirtualRegister(virtualRegister);
833         info.initCell(node, node->refCount(), reg);
834     }
835     void blessedBooleanResult(GPRReg reg, Node* node, UseChildrenMode mode = CallUseChildren)
836     {
837 #if USE(JSVALUE64)
838         jsValueResult(reg, node, DataFormatJSBoolean, mode);
839 #else
840         booleanResult(reg, node, mode);
841 #endif
842     }
843     void unblessedBooleanResult(GPRReg reg, Node* node, UseChildrenMode mode = CallUseChildren)
844     {
845 #if USE(JSVALUE64)
846         blessBoolean(reg);
847 #endif
848         blessedBooleanResult(reg, node, mode);
849     }
850 #if USE(JSVALUE64)
851     void jsValueResult(GPRReg reg, Node* node, DataFormat format = DataFormatJS, UseChildrenMode mode = CallUseChildren)
852     {
853         if (format == DataFormatJSInt32)
854             m_jit.jitAssertIsJSInt32(reg);
855         
856         if (mode == CallUseChildren)
857             useChildren(node);
858
859         VirtualRegister virtualRegister = node->virtualRegister();
860         m_gprs.retain(reg, virtualRegister, SpillOrderJS);
861         GenerationInfo& info = generationInfoFromVirtualRegister(virtualRegister);
862         info.initJSValue(node, node->refCount(), reg, format);
863     }
864     void jsValueResult(GPRReg reg, Node* node, UseChildrenMode mode)
865     {
866         jsValueResult(reg, node, DataFormatJS, mode);
867     }
868 #elif USE(JSVALUE32_64)
869     void booleanResult(GPRReg reg, Node* node, UseChildrenMode mode = CallUseChildren)
870     {
871         if (mode == CallUseChildren)
872             useChildren(node);
873
874         VirtualRegister virtualRegister = node->virtualRegister();
875         m_gprs.retain(reg, virtualRegister, SpillOrderBoolean);
876         GenerationInfo& info = generationInfoFromVirtualRegister(virtualRegister);
877         info.initBoolean(node, node->refCount(), reg);
878     }
879     void jsValueResult(GPRReg tag, GPRReg payload, Node* node, DataFormat format = DataFormatJS, UseChildrenMode mode = CallUseChildren)
880     {
881         if (mode == CallUseChildren)
882             useChildren(node);
883
884         VirtualRegister virtualRegister = node->virtualRegister();
885         m_gprs.retain(tag, virtualRegister, SpillOrderJS);
886         m_gprs.retain(payload, virtualRegister, SpillOrderJS);
887         GenerationInfo& info = generationInfoFromVirtualRegister(virtualRegister);
888         info.initJSValue(node, node->refCount(), tag, payload, format);
889     }
890     void jsValueResult(GPRReg tag, GPRReg payload, Node* node, UseChildrenMode mode)
891     {
892         jsValueResult(tag, payload, node, DataFormatJS, mode);
893     }
894 #endif
895     void jsValueResult(JSValueRegs regs, Node* node, DataFormat format = DataFormatJS, UseChildrenMode mode = CallUseChildren)
896     {
897 #if USE(JSVALUE64)
898         jsValueResult(regs.gpr(), node, format, mode);
899 #else
900         jsValueResult(regs.tagGPR(), regs.payloadGPR(), node, format, mode);
901 #endif
902     }
903     void storageResult(GPRReg reg, Node* node, UseChildrenMode mode = CallUseChildren)
904     {
905         if (mode == CallUseChildren)
906             useChildren(node);
907         
908         VirtualRegister virtualRegister = node->virtualRegister();
909         m_gprs.retain(reg, virtualRegister, SpillOrderStorage);
910         GenerationInfo& info = generationInfoFromVirtualRegister(virtualRegister);
911         info.initStorage(node, node->refCount(), reg);
912     }
913     void doubleResult(FPRReg reg, Node* node, UseChildrenMode mode = CallUseChildren)
914     {
915         if (mode == CallUseChildren)
916             useChildren(node);
917
918         VirtualRegister virtualRegister = node->virtualRegister();
919         m_fprs.retain(reg, virtualRegister, SpillOrderDouble);
920         GenerationInfo& info = generationInfoFromVirtualRegister(virtualRegister);
921         info.initDouble(node, node->refCount(), reg);
922     }
923     void initConstantInfo(Node* node)
924     {
925         ASSERT(node->hasConstant());
926         generationInfo(node).initConstant(node, node->refCount());
927     }
928
929 #define FIRST_ARGUMENT_TYPE typename FunctionTraits<OperationType>::template ArgumentType<0>
930
931     template<typename OperationType, typename ResultRegType, typename... Args>
932     std::enable_if_t<
933         FunctionTraits<OperationType>::hasResult,
934     JITCompiler::Call>
935     callOperation(OperationType operation, ResultRegType result, Args... args)
936     {
937         m_jit.setupArguments<OperationType>(args...);
938         return appendCallSetResult(operation, result);
939     }
940
941     template<typename OperationType, typename Arg, typename... Args>
942     std::enable_if_t<
943         !FunctionTraits<OperationType>::hasResult
944         && !std::is_same<Arg, NoResultTag>::value,
945     JITCompiler::Call>
946     callOperation(OperationType operation, Arg arg, Args... args)
947     {
948         m_jit.setupArguments<OperationType>(arg, args...);
949         return appendCall(operation);
950     }
951
952     template<typename OperationType, typename... Args>
953     std::enable_if_t<
954         !FunctionTraits<OperationType>::hasResult,
955     JITCompiler::Call>
956     callOperation(OperationType operation, NoResultTag, Args... args)
957     {
958         m_jit.setupArguments<OperationType>(args...);
959         return appendCall(operation);
960     }
961
962     template<typename OperationType>
963     std::enable_if_t<
964         !FunctionTraits<OperationType>::hasResult,
965     JITCompiler::Call>
966     callOperation(OperationType operation)
967     {
968         m_jit.setupArguments<OperationType>();
969         return appendCall(operation);
970     }
971
972 #undef FIRST_ARGUMENT_TYPE
973
974     JITCompiler::Call callOperationWithCallFrameRollbackOnException(V_JITOperation_ECb operation, void* pointer)
975     {
976         m_jit.setupArguments<V_JITOperation_ECb>(TrustedImmPtr(pointer));
977         return appendCallWithCallFrameRollbackOnException(operation);
978     }
979
980     JITCompiler::Call callOperationWithCallFrameRollbackOnException(Z_JITOperation_E operation, GPRReg result)
981     {
982         m_jit.setupArguments<Z_JITOperation_E>();
983         return appendCallWithCallFrameRollbackOnExceptionSetResult(operation, result);
984     }
985     
986 #if !defined(NDEBUG) && !CPU(ARM) && !CPU(MIPS)
987     void prepareForExternalCall()
988     {
989         // We're about to call out to a "native" helper function. The helper
990         // function is expected to set topCallFrame itself with the ExecState
991         // that is passed to it.
992         //
993         // We explicitly trash topCallFrame here so that we'll know if some of
994         // the helper functions are not setting topCallFrame when they should
995         // be doing so. Note: the previous value in topcallFrame was not valid
996         // anyway since it was not being updated by JIT'ed code by design.
997
998         for (unsigned i = 0; i < sizeof(void*) / 4; i++)
999             m_jit.store32(TrustedImm32(0xbadbeef), reinterpret_cast<char*>(&m_jit.vm()->topCallFrame) + i * 4);
1000     }
1001 #else
1002     void prepareForExternalCall() { }
1003 #endif
1004
1005     // These methods add call instructions, optionally setting results, and optionally rolling back the call frame on an exception.
1006     JITCompiler::Call appendCall(const FunctionPtr<CFunctionPtrTag> function)
1007     {
1008         prepareForExternalCall();
1009         m_jit.emitStoreCodeOrigin(m_currentNode->origin.semantic);
1010         return m_jit.appendCall(function);
1011     }
1012
1013     JITCompiler::Call appendCallWithCallFrameRollbackOnException(const FunctionPtr<CFunctionPtrTag> function)
1014     {
1015         JITCompiler::Call call = appendCall(function);
1016         m_jit.exceptionCheckWithCallFrameRollback();
1017         return call;
1018     }
1019
1020     JITCompiler::Call appendCallWithCallFrameRollbackOnExceptionSetResult(const FunctionPtr<CFunctionPtrTag> function, GPRReg result)
1021     {
1022         JITCompiler::Call call = appendCallWithCallFrameRollbackOnException(function);
1023         if ((result != InvalidGPRReg) && (result != GPRInfo::returnValueGPR))
1024             m_jit.move(GPRInfo::returnValueGPR, result);
1025         return call;
1026     }
1027
1028     JITCompiler::Call appendCallSetResult(const FunctionPtr<CFunctionPtrTag> function, GPRReg result)
1029     {
1030         JITCompiler::Call call = appendCall(function);
1031         if (result != InvalidGPRReg)
1032             m_jit.move(GPRInfo::returnValueGPR, result);
1033         return call;
1034     }
1035
1036     JITCompiler::Call appendCallSetResult(const FunctionPtr<CFunctionPtrTag> function, GPRReg result1, GPRReg result2)
1037     {
1038         JITCompiler::Call call = appendCall(function);
1039         m_jit.setupResults(result1, result2);
1040         return call;
1041     }
1042
1043     JITCompiler::Call appendCallSetResult(const FunctionPtr<CFunctionPtrTag> function, JSValueRegs resultRegs)
1044     {
1045 #if USE(JSVALUE64)
1046         return appendCallSetResult(function, resultRegs.gpr());
1047 #else
1048         return appendCallSetResult(function, resultRegs.payloadGPR(), resultRegs.tagGPR());
1049 #endif
1050     }
1051
1052 #if CPU(X86)
1053     JITCompiler::Call appendCallSetResult(const FunctionPtr<CFunctionPtrTag> function, FPRReg result)
1054     {
1055         JITCompiler::Call call = appendCall(function);
1056         if (result != InvalidFPRReg) {
1057             m_jit.assembler().fstpl(0, JITCompiler::stackPointerRegister);
1058             m_jit.loadDouble(JITCompiler::stackPointerRegister, result);
1059         }
1060         return call;
1061     }
1062 #elif CPU(ARM) && !CPU(ARM_HARDFP)
1063     JITCompiler::Call appendCallSetResult(const FunctionPtr<CFunctionPtrTag> function, FPRReg result)
1064     {
1065         JITCompiler::Call call = appendCall(function);
1066         if (result != InvalidFPRReg)
1067             m_jit.assembler().vmov(result, GPRInfo::returnValueGPR, GPRInfo::returnValueGPR2);
1068         return call;
1069     }
1070 #else // CPU(X86_64) || (CPU(ARM) && CPU(ARM_HARDFP)) || CPU(ARM64) || CPU(MIPS)
1071     JITCompiler::Call appendCallSetResult(const FunctionPtr<CFunctionPtrTag> function, FPRReg result)
1072     {
1073         JITCompiler::Call call = appendCall(function);
1074         if (result != InvalidFPRReg)
1075             m_jit.moveDouble(FPRInfo::returnValueFPR, result);
1076         return call;
1077     }
1078 #endif
1079
1080     void branchDouble(JITCompiler::DoubleCondition cond, FPRReg left, FPRReg right, BasicBlock* destination)
1081     {
1082         return addBranch(m_jit.branchDouble(cond, left, right), destination);
1083     }
1084     
1085     void branchDoubleNonZero(FPRReg value, FPRReg scratch, BasicBlock* destination)
1086     {
1087         return addBranch(m_jit.branchDoubleNonZero(value, scratch), destination);
1088     }
1089     
1090     template<typename T, typename U>
1091     void branch32(JITCompiler::RelationalCondition cond, T left, U right, BasicBlock* destination)
1092     {
1093         return addBranch(m_jit.branch32(cond, left, right), destination);
1094     }
1095     
1096     template<typename T, typename U>
1097     void branchTest32(JITCompiler::ResultCondition cond, T value, U mask, BasicBlock* destination)
1098     {
1099         return addBranch(m_jit.branchTest32(cond, value, mask), destination);
1100     }
1101     
1102     template<typename T>
1103     void branchTest32(JITCompiler::ResultCondition cond, T value, BasicBlock* destination)
1104     {
1105         return addBranch(m_jit.branchTest32(cond, value), destination);
1106     }
1107     
1108 #if USE(JSVALUE64)
1109     template<typename T, typename U>
1110     void branch64(JITCompiler::RelationalCondition cond, T left, U right, BasicBlock* destination)
1111     {
1112         return addBranch(m_jit.branch64(cond, left, right), destination);
1113     }
1114 #endif
1115     
1116     template<typename T, typename U>
1117     void branch8(JITCompiler::RelationalCondition cond, T left, U right, BasicBlock* destination)
1118     {
1119         return addBranch(m_jit.branch8(cond, left, right), destination);
1120     }
1121     
1122     template<typename T, typename U>
1123     void branchPtr(JITCompiler::RelationalCondition cond, T left, U right, BasicBlock* destination)
1124     {
1125         return addBranch(m_jit.branchPtr(cond, left, right), destination);
1126     }
1127     
1128     template<typename T, typename U>
1129     void branchTestPtr(JITCompiler::ResultCondition cond, T value, U mask, BasicBlock* destination)
1130     {
1131         return addBranch(m_jit.branchTestPtr(cond, value, mask), destination);
1132     }
1133     
1134     template<typename T>
1135     void branchTestPtr(JITCompiler::ResultCondition cond, T value, BasicBlock* destination)
1136     {
1137         return addBranch(m_jit.branchTestPtr(cond, value), destination);
1138     }
1139     
1140     template<typename T, typename U>
1141     void branchTest8(JITCompiler::ResultCondition cond, T value, U mask, BasicBlock* destination)
1142     {
1143         return addBranch(m_jit.branchTest8(cond, value, mask), destination);
1144     }
1145     
1146     template<typename T>
1147     void branchTest8(JITCompiler::ResultCondition cond, T value, BasicBlock* destination)
1148     {
1149         return addBranch(m_jit.branchTest8(cond, value), destination);
1150     }
1151     
1152     enum FallThroughMode {
1153         AtFallThroughPoint,
1154         ForceJump
1155     };
1156     void jump(BasicBlock* destination, FallThroughMode fallThroughMode = AtFallThroughPoint)
1157     {
1158         if (destination == nextBlock()
1159             && fallThroughMode == AtFallThroughPoint)
1160             return;
1161         addBranch(m_jit.jump(), destination);
1162     }
1163     
1164     void addBranch(const MacroAssembler::Jump& jump, BasicBlock* destination)
1165     {
1166         m_branches.append(BranchRecord(jump, destination));
1167     }
1168     void addBranch(const MacroAssembler::JumpList& jump, BasicBlock* destination);
1169
1170     void linkBranches();
1171
1172     void dump(const char* label = 0);
1173
1174     bool betterUseStrictInt52(Node* node)
1175     {
1176         return !generationInfo(node).isInt52();
1177     }
1178     bool betterUseStrictInt52(Edge edge)
1179     {
1180         return betterUseStrictInt52(edge.node());
1181     }
1182     
1183     bool compare(Node*, MacroAssembler::RelationalCondition, MacroAssembler::DoubleCondition, S_JITOperation_EJJ);
1184     void compileCompareUnsigned(Node*, MacroAssembler::RelationalCondition);
1185     bool compilePeepHoleBranch(Node*, MacroAssembler::RelationalCondition, MacroAssembler::DoubleCondition, S_JITOperation_EJJ);
1186     void compilePeepHoleInt32Branch(Node*, Node* branchNode, JITCompiler::RelationalCondition);
1187     void compilePeepHoleInt52Branch(Node*, Node* branchNode, JITCompiler::RelationalCondition);
1188     void compilePeepHoleBooleanBranch(Node*, Node* branchNode, JITCompiler::RelationalCondition);
1189     void compilePeepHoleDoubleBranch(Node*, Node* branchNode, JITCompiler::DoubleCondition);
1190     void compilePeepHoleObjectEquality(Node*, Node* branchNode);
1191     void compilePeepHoleObjectStrictEquality(Edge objectChild, Edge otherChild, Node* branchNode);
1192     void compilePeepHoleObjectToObjectOrOtherEquality(Edge leftChild, Edge rightChild, Node* branchNode);
1193     void compileObjectEquality(Node*);
1194     void compileObjectStrictEquality(Edge objectChild, Edge otherChild);
1195     void compileObjectToObjectOrOtherEquality(Edge leftChild, Edge rightChild);
1196     void compileObjectOrOtherLogicalNot(Edge value);
1197     void compileLogicalNot(Node*);
1198     void compileLogicalNotStringOrOther(Node*);
1199     void compileStringEquality(
1200         Node*, GPRReg leftGPR, GPRReg rightGPR, GPRReg lengthGPR,
1201         GPRReg leftTempGPR, GPRReg rightTempGPR, GPRReg leftTemp2GPR,
1202         GPRReg rightTemp2GPR, JITCompiler::JumpList fastTrue,
1203         JITCompiler::JumpList fastSlow);
1204     void compileStringEquality(Node*);
1205     void compileStringIdentEquality(Node*);
1206     void compileStringToUntypedEquality(Node*, Edge stringEdge, Edge untypedEdge);
1207     void compileStringIdentToNotStringVarEquality(Node*, Edge stringEdge, Edge notStringVarEdge);
1208     void compileStringZeroLength(Node*);
1209     void compileMiscStrictEq(Node*);
1210
1211     void compileSymbolEquality(Node*);
1212     void compileBigIntEquality(Node*);
1213     void compilePeepHoleSymbolEquality(Node*, Node* branchNode);
1214     void compileSymbolUntypedEquality(Node*, Edge symbolEdge, Edge untypedEdge);
1215
1216     void emitObjectOrOtherBranch(Edge value, BasicBlock* taken, BasicBlock* notTaken);
1217     void emitStringBranch(Edge value, BasicBlock* taken, BasicBlock* notTaken);
1218     void emitStringOrOtherBranch(Edge value, BasicBlock* taken, BasicBlock* notTaken);
1219     void emitBranch(Node*);
1220     
1221     struct StringSwitchCase {
1222         StringSwitchCase() { }
1223         
1224         StringSwitchCase(StringImpl* string, BasicBlock* target)
1225             : string(string)
1226             , target(target)
1227         {
1228         }
1229         
1230         bool operator<(const StringSwitchCase& other) const
1231         {
1232             return stringLessThan(*string, *other.string);
1233         }
1234         
1235         StringImpl* string;
1236         BasicBlock* target;
1237     };
1238     
1239     void emitSwitchIntJump(SwitchData*, GPRReg value, GPRReg scratch, GPRReg scratch2);
1240     void emitSwitchImm(Node*, SwitchData*);
1241     void emitSwitchCharStringJump(SwitchData*, GPRReg value, GPRReg scratch, GPRReg scratch2);
1242     void emitSwitchChar(Node*, SwitchData*);
1243     void emitBinarySwitchStringRecurse(
1244         SwitchData*, const Vector<StringSwitchCase>&, unsigned numChecked,
1245         unsigned begin, unsigned end, GPRReg buffer, GPRReg length, GPRReg temp,
1246         unsigned alreadyCheckedLength, bool checkedExactLength);
1247     void emitSwitchStringOnString(SwitchData*, GPRReg string);
1248     void emitSwitchString(Node*, SwitchData*);
1249     void emitSwitch(Node*);
1250     
1251     void compileToStringOrCallStringConstructorOrStringValueOf(Node*);
1252     void compileNumberToStringWithRadix(Node*);
1253     void compileNumberToStringWithValidRadixConstant(Node*);
1254     void compileNumberToStringWithValidRadixConstant(Node*, int32_t radix);
1255     void compileNewStringObject(Node*);
1256     
1257     void compileNewTypedArrayWithSize(Node*);
1258     
1259     void compileInt32Compare(Node*, MacroAssembler::RelationalCondition);
1260     void compileInt52Compare(Node*, MacroAssembler::RelationalCondition);
1261     void compileBooleanCompare(Node*, MacroAssembler::RelationalCondition);
1262     void compileDoubleCompare(Node*, MacroAssembler::DoubleCondition);
1263     void compileStringCompare(Node*, MacroAssembler::RelationalCondition);
1264     void compileStringIdentCompare(Node*, MacroAssembler::RelationalCondition);
1265     
1266     bool compileStrictEq(Node*);
1267
1268     void compileSameValue(Node*);
1269     
1270     void compileAllocatePropertyStorage(Node*);
1271     void compileReallocatePropertyStorage(Node*);
1272     void compileNukeStructureAndSetButterfly(Node*);
1273     void compileGetButterfly(Node*);
1274     void compileCallDOMGetter(Node*);
1275     void compileCallDOM(Node*);
1276     void compileCheckSubClass(Node*);
1277     void compileNormalizeMapKey(Node*);
1278     void compileGetMapBucketHead(Node*);
1279     void compileGetMapBucketNext(Node*);
1280     void compileSetAdd(Node*);
1281     void compileMapSet(Node*);
1282     void compileWeakMapGet(Node*);
1283     void compileWeakSetAdd(Node*);
1284     void compileWeakMapSet(Node*);
1285     void compileLoadKeyFromMapBucket(Node*);
1286     void compileLoadValueFromMapBucket(Node*);
1287     void compileExtractValueFromWeakMapGet(Node*);
1288     void compileGetPrototypeOf(Node*);
1289     void compileIdentity(Node*);
1290     
1291 #if USE(JSVALUE32_64)
1292     template<typename BaseOperandType, typename PropertyOperandType, typename ValueOperandType, typename TagType>
1293     void compileContiguousPutByVal(Node*, BaseOperandType&, PropertyOperandType&, ValueOperandType&, GPRReg valuePayloadReg, TagType valueTag);
1294 #endif
1295     void compileDoublePutByVal(Node*, SpeculateCellOperand& base, SpeculateStrictInt32Operand& property);
1296     bool putByValWillNeedExtraRegister(ArrayMode arrayMode)
1297     {
1298         return arrayMode.mayStoreToHole();
1299     }
1300     GPRReg temporaryRegisterForPutByVal(GPRTemporary&, ArrayMode);
1301     GPRReg temporaryRegisterForPutByVal(GPRTemporary& temporary, Node* node)
1302     {
1303         return temporaryRegisterForPutByVal(temporary, node->arrayMode());
1304     }
1305     
1306     void compileGetCharCodeAt(Node*);
1307     void compileGetByValOnString(Node*);
1308     void compileFromCharCode(Node*); 
1309
1310     void compileGetByValOnDirectArguments(Node*);
1311     void compileGetByValOnScopedArguments(Node*);
1312     
1313     void compileGetScope(Node*);
1314     void compileSkipScope(Node*);
1315     void compileGetGlobalObject(Node*);
1316     void compileGetGlobalThis(Node*);
1317
1318     void compileGetArrayLength(Node*);
1319
1320     void compileCheckTypeInfoFlags(Node*);
1321     void compileCheckStringIdent(Node*);
1322
1323     void compileParseInt(Node*);
1324     
1325     void compileValueRep(Node*);
1326     void compileDoubleRep(Node*);
1327     
1328     void compileValueToInt32(Node*);
1329     void compileUInt32ToNumber(Node*);
1330     void compileDoubleAsInt32(Node*);
1331
1332     template<typename SnippetGenerator, J_JITOperation_EJJ slowPathFunction>
1333     void emitUntypedBitOp(Node*);
1334     void compileBitwiseOp(Node*);
1335
1336     void emitUntypedRightShiftBitOp(Node*);
1337     void compileShiftOp(Node*);
1338
1339     template <typename Generator, typename RepatchingFunction, typename NonRepatchingFunction>
1340     void compileMathIC(Node*, JITBinaryMathIC<Generator>*, bool needsScratchGPRReg, bool needsScratchFPRReg, RepatchingFunction, NonRepatchingFunction);
1341     template <typename Generator, typename RepatchingFunction, typename NonRepatchingFunction>
1342     void compileMathIC(Node*, JITUnaryMathIC<Generator>*, bool needsScratchGPRReg, RepatchingFunction, NonRepatchingFunction);
1343
1344     void compileArithDoubleUnaryOp(Node*, double (*doubleFunction)(double), double (*operation)(ExecState*, EncodedJSValue));
1345     void compileValueAdd(Node*);
1346     void compileArithAdd(Node*);
1347     void compileMakeRope(Node*);
1348     void compileArithAbs(Node*);
1349     void compileArithClz32(Node*);
1350     void compileArithSub(Node*);
1351     void compileValueNegate(Node*);
1352     void compileArithNegate(Node*);
1353     void compileArithMul(Node*);
1354     void compileArithDiv(Node*);
1355     void compileArithFRound(Node*);
1356     void compileArithMod(Node*);
1357     void compileArithPow(Node*);
1358     void compileArithRounding(Node*);
1359     void compileArithRandom(Node*);
1360     void compileArithUnary(Node*);
1361     void compileArithSqrt(Node*);
1362     void compileArithMinMax(Node*);
1363     void compileConstantStoragePointer(Node*);
1364     void compileGetIndexedPropertyStorage(Node*);
1365     JITCompiler::Jump jumpForTypedArrayOutOfBounds(Node*, GPRReg baseGPR, GPRReg indexGPR);
1366     JITCompiler::Jump jumpForTypedArrayIsNeuteredIfOutOfBounds(Node*, GPRReg baseGPR, JITCompiler::Jump outOfBounds);
1367     void emitTypedArrayBoundsCheck(Node*, GPRReg baseGPR, GPRReg indexGPR);
1368     void compileGetTypedArrayByteOffset(Node*);
1369     void compileGetByValOnIntTypedArray(Node*, TypedArrayType);
1370     void compilePutByValForIntTypedArray(GPRReg base, GPRReg property, Node*, TypedArrayType);
1371     void compileGetByValOnFloatTypedArray(Node*, TypedArrayType);
1372     void compilePutByValForFloatTypedArray(GPRReg base, GPRReg property, Node*, TypedArrayType);
1373     void compileGetByValForObjectWithString(Node*);
1374     void compileGetByValForObjectWithSymbol(Node*);
1375     void compilePutByValForCellWithString(Node*, Edge& child1, Edge& child2, Edge& child3);
1376     void compilePutByValForCellWithSymbol(Node*, Edge& child1, Edge& child2, Edge& child3);
1377     void compileGetByValWithThis(Node*);
1378     void compileGetByOffset(Node*);
1379     void compilePutByOffset(Node*);
1380     void compileMatchStructure(Node*);
1381     // If this returns false it means that we terminated speculative execution.
1382     bool getIntTypedArrayStoreOperand(
1383         GPRTemporary& value,
1384         GPRReg property,
1385 #if USE(JSVALUE32_64)
1386         GPRTemporary& propertyTag,
1387         GPRTemporary& valueTag,
1388 #endif
1389         Edge valueUse, JITCompiler::JumpList& slowPathCases, bool isClamped = false);
1390     void loadFromIntTypedArray(GPRReg storageReg, GPRReg propertyReg, GPRReg resultReg, TypedArrayType);
1391     void setIntTypedArrayLoadResult(Node*, GPRReg resultReg, TypedArrayType, bool canSpeculate = false);
1392     template <typename ClassType> void compileNewFunctionCommon(GPRReg, RegisteredStructure, GPRReg, GPRReg, GPRReg, MacroAssembler::JumpList&, size_t, FunctionExecutable*);
1393     void compileNewFunction(Node*);
1394     void compileSetFunctionName(Node*);
1395     void compileNewRegexp(Node*);
1396     void compileForwardVarargs(Node*);
1397     void compileLoadVarargs(Node*);
1398     void compileCreateActivation(Node*);
1399     void compileCreateDirectArguments(Node*);
1400     void compileGetFromArguments(Node*);
1401     void compilePutToArguments(Node*);
1402     void compileGetArgument(Node*);
1403     void compileCreateScopedArguments(Node*);
1404     void compileCreateClonedArguments(Node*);
1405     void compileCreateRest(Node*);
1406     void compileSpread(Node*);
1407     void compileNewArray(Node*);
1408     void compileNewArrayWithSpread(Node*);
1409     void compileGetRestLength(Node*);
1410     void compileArraySlice(Node*);
1411     void compileArrayIndexOf(Node*);
1412     void compileArrayPush(Node*);
1413     void compileNotifyWrite(Node*);
1414     void compileRegExpExec(Node*);
1415     void compileRegExpExecNonGlobalOrSticky(Node*);
1416     void compileRegExpMatchFast(Node*);
1417     void compileRegExpMatchFastGlobal(Node*);
1418     void compileRegExpTest(Node*);
1419     void compileStringReplace(Node*);
1420     void compileIsObject(Node*);
1421     void compileIsObjectOrNull(Node*);
1422     void compileIsFunction(Node*);
1423     void compileTypeOf(Node*);
1424     void compileCheckCell(Node*);
1425     void compileCheckNotEmpty(Node*);
1426     void compileCheckStructure(Node*);
1427     void emitStructureCheck(Node*, GPRReg cellGPR, GPRReg tempGPR);
1428     void compilePutAccessorById(Node*);
1429     void compilePutGetterSetterById(Node*);
1430     void compilePutAccessorByVal(Node*);
1431     void compileGetRegExpObjectLastIndex(Node*);
1432     void compileSetRegExpObjectLastIndex(Node*);
1433     void compileLazyJSConstant(Node*);
1434     void compileMaterializeNewObject(Node*);
1435     void compileRecordRegExpCachedResult(Node*);
1436     void compileToObjectOrCallObjectConstructor(Node*);
1437     void compileResolveScope(Node*);
1438     void compileResolveScopeForHoistingFuncDeclInEval(Node*);
1439     void compileGetGlobalVariable(Node*);
1440     void compilePutGlobalVariable(Node*);
1441     void compileGetDynamicVar(Node*);
1442     void compilePutDynamicVar(Node*);
1443     void compileGetClosureVar(Node*);
1444     void compilePutClosureVar(Node*);
1445     void compileCompareEqPtr(Node*);
1446     void compileDefineDataProperty(Node*);
1447     void compileDefineAccessorProperty(Node*);
1448     void compileStringSlice(Node*);
1449     void compileToLowerCase(Node*);
1450     void compileThrow(Node*);
1451     void compileThrowStaticError(Node*);
1452     void compileGetEnumerableLength(Node*);
1453     void compileHasGenericProperty(Node*);
1454     void compileToIndexString(Node*);
1455     void compilePutByIdFlush(Node*);
1456     void compilePutById(Node*);
1457     void compilePutByIdDirect(Node*);
1458     void compilePutByIdWithThis(Node*);
1459     void compileHasStructureProperty(Node*);
1460     void compileGetDirectPname(Node*);
1461     void compileGetPropertyEnumerator(Node*);
1462     void compileGetEnumeratorPname(Node*);
1463     void compileGetExecutable(Node*);
1464     void compileGetGetter(Node*);
1465     void compileGetSetter(Node*);
1466     void compileGetCallee(Node*);
1467     void compileSetCallee(Node*);
1468     void compileGetArgumentCountIncludingThis(Node*);
1469     void compileSetArgumentCountIncludingThis(Node*);
1470     void compileStrCat(Node*);
1471     void compileNewArrayBuffer(Node*);
1472     void compileNewArrayWithSize(Node*);
1473     void compileNewTypedArray(Node*);
1474     void compileToThis(Node*);
1475     void compileObjectCreate(Node*);
1476     void compileCreateThis(Node*);
1477     void compileNewObject(Node*);
1478     void compileToPrimitive(Node*);
1479     void compileLogShadowChickenPrologue(Node*);
1480     void compileLogShadowChickenTail(Node*);
1481     void compileHasIndexedProperty(Node*);
1482     void compileExtractCatchLocal(Node*);
1483     void compileClearCatchLocals(Node*);
1484     void compileProfileType(Node*);
1485
1486     void moveTrueTo(GPRReg);
1487     void moveFalseTo(GPRReg);
1488     void blessBoolean(GPRReg);
1489     
1490     // Allocator for a cell of a specific size.
1491     template <typename StructureType> // StructureType can be GPR or ImmPtr.
1492     void emitAllocateJSCell(
1493         GPRReg resultGPR, const JITAllocator& allocator, GPRReg allocatorGPR, StructureType structure,
1494         GPRReg scratchGPR, MacroAssembler::JumpList& slowPath)
1495     {
1496         m_jit.emitAllocateJSCell(resultGPR, allocator, allocatorGPR, structure, scratchGPR, slowPath);
1497     }
1498
1499     // Allocator for an object of a specific size.
1500     template <typename StructureType, typename StorageType> // StructureType and StorageType can be GPR or ImmPtr.
1501     void emitAllocateJSObject(
1502         GPRReg resultGPR, const JITAllocator& allocator, GPRReg allocatorGPR, StructureType structure,
1503         StorageType storage, GPRReg scratchGPR, MacroAssembler::JumpList& slowPath)
1504     {
1505         m_jit.emitAllocateJSObject(
1506             resultGPR, allocator, allocatorGPR, structure, storage, scratchGPR, slowPath);
1507     }
1508
1509     template <typename ClassType, typename StructureType, typename StorageType> // StructureType and StorageType can be GPR or ImmPtr.
1510     void emitAllocateJSObjectWithKnownSize(
1511         GPRReg resultGPR, StructureType structure, StorageType storage, GPRReg scratchGPR1,
1512         GPRReg scratchGPR2, MacroAssembler::JumpList& slowPath, size_t size)
1513     {
1514         m_jit.emitAllocateJSObjectWithKnownSize<ClassType>(*m_jit.vm(), resultGPR, structure, storage, scratchGPR1, scratchGPR2, slowPath, size);
1515     }
1516
1517     // Convenience allocator for a built-in object.
1518     template <typename ClassType, typename StructureType, typename StorageType> // StructureType and StorageType can be GPR or ImmPtr.
1519     void emitAllocateJSObject(GPRReg resultGPR, StructureType structure, StorageType storage,
1520         GPRReg scratchGPR1, GPRReg scratchGPR2, MacroAssembler::JumpList& slowPath)
1521     {
1522         m_jit.emitAllocateJSObject<ClassType>(*m_jit.vm(), resultGPR, structure, storage, scratchGPR1, scratchGPR2, slowPath);
1523     }
1524
1525     template <typename ClassType, typename StructureType> // StructureType and StorageType can be GPR or ImmPtr.
1526     void emitAllocateVariableSizedJSObject(GPRReg resultGPR, StructureType structure, GPRReg allocationSize, GPRReg scratchGPR1, GPRReg scratchGPR2, MacroAssembler::JumpList& slowPath)
1527     {
1528         m_jit.emitAllocateVariableSizedJSObject<ClassType>(*m_jit.vm(), resultGPR, structure, allocationSize, scratchGPR1, scratchGPR2, slowPath);
1529     }
1530
1531     template<typename ClassType>
1532     void emitAllocateDestructibleObject(GPRReg resultGPR, RegisteredStructure structure, 
1533         GPRReg scratchGPR1, GPRReg scratchGPR2, MacroAssembler::JumpList& slowPath)
1534     {
1535         m_jit.emitAllocateDestructibleObject<ClassType>(*m_jit.vm(), resultGPR, structure.get(), scratchGPR1, scratchGPR2, slowPath);
1536     }
1537
1538     void emitAllocateRawObject(GPRReg resultGPR, RegisteredStructure, GPRReg storageGPR, unsigned numElements, unsigned vectorLength);
1539     
1540     void emitGetLength(InlineCallFrame*, GPRReg lengthGPR, bool includeThis = false);
1541     void emitGetLength(CodeOrigin, GPRReg lengthGPR, bool includeThis = false);
1542     void emitGetCallee(CodeOrigin, GPRReg calleeGPR);
1543     void emitGetArgumentStart(CodeOrigin, GPRReg startGPR);
1544     void emitPopulateSliceIndex(Edge&, GPRReg length, GPRReg result);
1545     
1546     // Generate an OSR exit fuzz check. Returns Jump() if OSR exit fuzz is not enabled, or if
1547     // it's in training mode.
1548     MacroAssembler::Jump emitOSRExitFuzzCheck();
1549     
1550     // Add a speculation check.
1551     void speculationCheck(ExitKind, JSValueSource, Node*, MacroAssembler::Jump jumpToFail);
1552     void speculationCheck(ExitKind, JSValueSource, Node*, const MacroAssembler::JumpList& jumpsToFail);
1553
1554     // Add a speculation check without additional recovery, and with a promise to supply a jump later.
1555     OSRExitJumpPlaceholder speculationCheck(ExitKind, JSValueSource, Node*);
1556     OSRExitJumpPlaceholder speculationCheck(ExitKind, JSValueSource, Edge);
1557     void speculationCheck(ExitKind, JSValueSource, Edge, MacroAssembler::Jump jumpToFail);
1558     void speculationCheck(ExitKind, JSValueSource, Edge, const MacroAssembler::JumpList& jumpsToFail);
1559     // Add a speculation check with additional recovery.
1560     void speculationCheck(ExitKind, JSValueSource, Node*, MacroAssembler::Jump jumpToFail, const SpeculationRecovery&);
1561     void speculationCheck(ExitKind, JSValueSource, Edge, MacroAssembler::Jump jumpToFail, const SpeculationRecovery&);
1562     
1563     void emitInvalidationPoint(Node*);
1564     
1565     void unreachable(Node*);
1566     
1567     // Called when we statically determine that a speculation will fail.
1568     void terminateSpeculativeExecution(ExitKind, JSValueRegs, Node*);
1569     void terminateSpeculativeExecution(ExitKind, JSValueRegs, Edge);
1570     
1571     // Helpers for performing type checks on an edge stored in the given registers.
1572     bool needsTypeCheck(Edge edge, SpeculatedType typesPassedThrough) { return m_interpreter.needsTypeCheck(edge, typesPassedThrough); }
1573     void typeCheck(JSValueSource, Edge, SpeculatedType typesPassedThrough, MacroAssembler::Jump jumpToFail, ExitKind = BadType);
1574     
1575     void speculateCellTypeWithoutTypeFiltering(Edge, GPRReg cellGPR, JSType);
1576     void speculateCellType(Edge, GPRReg cellGPR, SpeculatedType, JSType);
1577     
1578     void speculateInt32(Edge);
1579 #if USE(JSVALUE64)
1580     void convertAnyInt(Edge, GPRReg resultGPR);
1581     void speculateAnyInt(Edge);
1582     void speculateInt32(Edge, JSValueRegs);
1583     void speculateDoubleRepAnyInt(Edge);
1584 #endif // USE(JSVALUE64)
1585     void speculateNumber(Edge);
1586     void speculateRealNumber(Edge);
1587     void speculateDoubleRepReal(Edge);
1588     void speculateBoolean(Edge);
1589     void speculateCell(Edge);
1590     void speculateCellOrOther(Edge);
1591     void speculateObject(Edge, GPRReg cell);
1592     void speculateObject(Edge);
1593     void speculateArray(Edge, GPRReg cell);
1594     void speculateArray(Edge);
1595     void speculateFunction(Edge, GPRReg cell);
1596     void speculateFunction(Edge);
1597     void speculateFinalObject(Edge, GPRReg cell);
1598     void speculateFinalObject(Edge);
1599     void speculateRegExpObject(Edge, GPRReg cell);
1600     void speculateRegExpObject(Edge);
1601     void speculateProxyObject(Edge, GPRReg cell);
1602     void speculateProxyObject(Edge);
1603     void speculateDerivedArray(Edge, GPRReg cell);
1604     void speculateDerivedArray(Edge);
1605     void speculateMapObject(Edge);
1606     void speculateMapObject(Edge, GPRReg cell);
1607     void speculateSetObject(Edge);
1608     void speculateSetObject(Edge, GPRReg cell);
1609     void speculateWeakMapObject(Edge);
1610     void speculateWeakMapObject(Edge, GPRReg cell);
1611     void speculateWeakSetObject(Edge);
1612     void speculateWeakSetObject(Edge, GPRReg cell);
1613     void speculateDataViewObject(Edge);
1614     void speculateDataViewObject(Edge, GPRReg cell);
1615     void speculateObjectOrOther(Edge);
1616     void speculateString(Edge edge, GPRReg cell);
1617     void speculateStringIdentAndLoadStorage(Edge edge, GPRReg string, GPRReg storage);
1618     void speculateStringIdent(Edge edge, GPRReg string);
1619     void speculateStringIdent(Edge);
1620     void speculateString(Edge);
1621     void speculateStringOrOther(Edge, JSValueRegs, GPRReg scratch);
1622     void speculateStringOrOther(Edge);
1623     void speculateNotStringVar(Edge);
1624     void speculateNotSymbol(Edge);
1625     template<typename StructureLocationType>
1626     void speculateStringObjectForStructure(Edge, StructureLocationType);
1627     void speculateStringObject(Edge, GPRReg);
1628     void speculateStringObject(Edge);
1629     void speculateStringOrStringObject(Edge);
1630     void speculateSymbol(Edge, GPRReg cell);
1631     void speculateSymbol(Edge);
1632     void speculateBigInt(Edge, GPRReg cell);
1633     void speculateBigInt(Edge);
1634     void speculateNotCell(Edge, JSValueRegs);
1635     void speculateNotCell(Edge);
1636     void speculateOther(Edge, JSValueRegs, GPRReg temp);
1637     void speculateOther(Edge, JSValueRegs);
1638     void speculateOther(Edge);
1639     void speculateMisc(Edge, JSValueRegs);
1640     void speculateMisc(Edge);
1641     void speculate(Node*, Edge);
1642     
1643     JITCompiler::JumpList jumpSlowForUnwantedArrayMode(GPRReg tempWithIndexingTypeReg, ArrayMode);
1644     void checkArray(Node*);
1645     void arrayify(Node*, GPRReg baseReg, GPRReg propertyReg);
1646     void arrayify(Node*);
1647     
1648     template<bool strict>
1649     GPRReg fillSpeculateInt32Internal(Edge, DataFormat& returnFormat);
1650     
1651     void cageTypedArrayStorage(GPRReg);
1652     
1653     // It is possible, during speculative generation, to reach a situation in which we
1654     // can statically determine a speculation will fail (for example, when two nodes
1655     // will make conflicting speculations about the same operand). In such cases this
1656     // flag is cleared, indicating no further code generation should take place.
1657     bool m_compileOkay;
1658     
1659     void recordSetLocal(
1660         VirtualRegister bytecodeReg, VirtualRegister machineReg, DataFormat format)
1661     {
1662         m_stream->appendAndLog(VariableEvent::setLocal(bytecodeReg, machineReg, format));
1663     }
1664     
1665     void recordSetLocal(DataFormat format)
1666     {
1667         VariableAccessData* variable = m_currentNode->variableAccessData();
1668         recordSetLocal(variable->local(), variable->machineLocal(), format);
1669     }
1670
1671     GenerationInfo& generationInfoFromVirtualRegister(VirtualRegister virtualRegister)
1672     {
1673         return m_generationInfo[virtualRegister.toLocal()];
1674     }
1675     
1676     GenerationInfo& generationInfo(Node* node)
1677     {
1678         return generationInfoFromVirtualRegister(node->virtualRegister());
1679     }
1680     
1681     GenerationInfo& generationInfo(Edge edge)
1682     {
1683         return generationInfo(edge.node());
1684     }
1685
1686     // The JIT, while also provides MacroAssembler functionality.
1687     JITCompiler& m_jit;
1688     Graph& m_graph;
1689
1690     // The current node being generated.
1691     BasicBlock* m_block;
1692     Node* m_currentNode;
1693     NodeType m_lastGeneratedNode;
1694     unsigned m_indexInBlock;
1695
1696     // Virtual and physical register maps.
1697     Vector<GenerationInfo, 32> m_generationInfo;
1698     RegisterBank<GPRInfo> m_gprs;
1699     RegisterBank<FPRInfo> m_fprs;
1700
1701     Vector<MacroAssembler::Label> m_osrEntryHeads;
1702     
1703     struct BranchRecord {
1704         BranchRecord(MacroAssembler::Jump jump, BasicBlock* destination)
1705             : jump(jump)
1706             , destination(destination)
1707         {
1708         }
1709
1710         MacroAssembler::Jump jump;
1711         BasicBlock* destination;
1712     };
1713     Vector<BranchRecord, 8> m_branches;
1714
1715     NodeOrigin m_origin;
1716     
1717     InPlaceAbstractState m_state;
1718     AbstractInterpreter<InPlaceAbstractState> m_interpreter;
1719     
1720     VariableEventStream* m_stream;
1721     MinifiedGraph* m_minifiedGraph;
1722     
1723     Vector<std::unique_ptr<SlowPathGenerator>, 8> m_slowPathGenerators;
1724     struct SlowPathLambda {
1725         Function<void()> generator;
1726         Node* currentNode;
1727         unsigned streamIndex;
1728     };
1729     Vector<SlowPathLambda> m_slowPathLambdas;
1730     Vector<SilentRegisterSavePlan> m_plans;
1731     std::optional<unsigned> m_outOfLineStreamIndex;
1732 };
1733
1734
1735 // === Operand types ===
1736 //
1737 // These classes are used to lock the operands to a node into machine
1738 // registers. These classes implement of pattern of locking a value
1739 // into register at the point of construction only if it is already in
1740 // registers, and otherwise loading it lazily at the point it is first
1741 // used. We do so in order to attempt to avoid spilling one operand
1742 // in order to make space available for another.
1743
1744 class JSValueOperand {
1745 public:
1746     explicit JSValueOperand(SpeculativeJIT* jit, Edge edge, OperandSpeculationMode mode = AutomaticOperandSpeculation)
1747         : m_jit(jit)
1748         , m_edge(edge)
1749 #if USE(JSVALUE64)
1750         , m_gprOrInvalid(InvalidGPRReg)
1751 #elif USE(JSVALUE32_64)
1752         , m_isDouble(false)
1753 #endif
1754     {
1755         ASSERT(m_jit);
1756         if (!edge)
1757             return;
1758         ASSERT_UNUSED(mode, mode == ManualOperandSpeculation || edge.useKind() == UntypedUse);
1759 #if USE(JSVALUE64)
1760         if (jit->isFilled(node()))
1761             gpr();
1762 #elif USE(JSVALUE32_64)
1763         m_register.pair.tagGPR = InvalidGPRReg;
1764         m_register.pair.payloadGPR = InvalidGPRReg;
1765         if (jit->isFilled(node()))
1766             fill();
1767 #endif
1768     }
1769
1770     explicit JSValueOperand(JSValueOperand&& other)
1771         : m_jit(other.m_jit)
1772         , m_edge(other.m_edge)
1773     {
1774 #if USE(JSVALUE64)
1775         m_gprOrInvalid = other.m_gprOrInvalid;
1776 #elif USE(JSVALUE32_64)
1777         m_register.pair.tagGPR = InvalidGPRReg;
1778         m_register.pair.payloadGPR = InvalidGPRReg;
1779         m_isDouble = other.m_isDouble;
1780
1781         if (m_edge) {
1782             if (m_isDouble)
1783                 m_register.fpr = other.m_register.fpr;
1784             else
1785                 m_register.pair = other.m_register.pair;
1786         }
1787 #endif
1788         other.m_edge = Edge();
1789 #if USE(JSVALUE64)
1790         other.m_gprOrInvalid = InvalidGPRReg;
1791 #elif USE(JSVALUE32_64)
1792         other.m_isDouble = false;
1793 #endif
1794     }
1795
1796     ~JSValueOperand()
1797     {
1798         if (!m_edge)
1799             return;
1800 #if USE(JSVALUE64)
1801         ASSERT(m_gprOrInvalid != InvalidGPRReg);
1802         m_jit->unlock(m_gprOrInvalid);
1803 #elif USE(JSVALUE32_64)
1804         if (m_isDouble) {
1805             ASSERT(m_register.fpr != InvalidFPRReg);
1806             m_jit->unlock(m_register.fpr);
1807         } else {
1808             ASSERT(m_register.pair.tagGPR != InvalidGPRReg && m_register.pair.payloadGPR != InvalidGPRReg);
1809             m_jit->unlock(m_register.pair.tagGPR);
1810             m_jit->unlock(m_register.pair.payloadGPR);
1811         }
1812 #endif
1813     }
1814     
1815     Edge edge() const
1816     {
1817         return m_edge;
1818     }
1819
1820     Node* node() const
1821     {
1822         return edge().node();
1823     }
1824
1825 #if USE(JSVALUE64)
1826     GPRReg gpr()
1827     {
1828         if (m_gprOrInvalid == InvalidGPRReg)
1829             m_gprOrInvalid = m_jit->fillJSValue(m_edge);
1830         return m_gprOrInvalid;
1831     }
1832     JSValueRegs jsValueRegs()
1833     {
1834         return JSValueRegs(gpr());
1835     }
1836 #elif USE(JSVALUE32_64)
1837     bool isDouble() { return m_isDouble; }
1838
1839     void fill()
1840     {
1841         if (m_register.pair.tagGPR == InvalidGPRReg && m_register.pair.payloadGPR == InvalidGPRReg)
1842             m_isDouble = !m_jit->fillJSValue(m_edge, m_register.pair.tagGPR, m_register.pair.payloadGPR, m_register.fpr);
1843     }
1844
1845     GPRReg tagGPR()
1846     {
1847         fill();
1848         ASSERT(!m_isDouble);
1849         return m_register.pair.tagGPR;
1850     } 
1851
1852     GPRReg payloadGPR()
1853     {
1854         fill();
1855         ASSERT(!m_isDouble);
1856         return m_register.pair.payloadGPR;
1857     }
1858     
1859     JSValueRegs jsValueRegs()
1860     {
1861         return JSValueRegs(tagGPR(), payloadGPR());
1862     }
1863
1864     GPRReg gpr(WhichValueWord which)
1865     {
1866         return jsValueRegs().gpr(which);
1867     }
1868
1869     FPRReg fpr()
1870     {
1871         fill();
1872         ASSERT(m_isDouble);
1873         return m_register.fpr;
1874     }
1875 #endif
1876
1877     void use()
1878     {
1879         m_jit->use(node());
1880     }
1881
1882 private:
1883     SpeculativeJIT* m_jit;
1884     Edge m_edge;
1885 #if USE(JSVALUE64)
1886     GPRReg m_gprOrInvalid;
1887 #elif USE(JSVALUE32_64)
1888     union {
1889         struct {
1890             GPRReg tagGPR;
1891             GPRReg payloadGPR;
1892         } pair;
1893         FPRReg fpr;
1894     } m_register;
1895     bool m_isDouble;
1896 #endif
1897 };
1898
1899 class StorageOperand {
1900 public:
1901     explicit StorageOperand(SpeculativeJIT* jit, Edge edge)
1902         : m_jit(jit)
1903         , m_edge(edge)
1904         , m_gprOrInvalid(InvalidGPRReg)
1905     {
1906         ASSERT(m_jit);
1907         ASSERT(edge.useKind() == UntypedUse || edge.useKind() == KnownCellUse);
1908         if (jit->isFilled(node()))
1909             gpr();
1910     }
1911     
1912     ~StorageOperand()
1913     {
1914         ASSERT(m_gprOrInvalid != InvalidGPRReg);
1915         m_jit->unlock(m_gprOrInvalid);
1916     }
1917     
1918     Edge edge() const
1919     {
1920         return m_edge;
1921     }
1922     
1923     Node* node() const
1924     {
1925         return edge().node();
1926     }
1927     
1928     GPRReg gpr()
1929     {
1930         if (m_gprOrInvalid == InvalidGPRReg)
1931             m_gprOrInvalid = m_jit->fillStorage(edge());
1932         return m_gprOrInvalid;
1933     }
1934     
1935     void use()
1936     {
1937         m_jit->use(node());
1938     }
1939     
1940 private:
1941     SpeculativeJIT* m_jit;
1942     Edge m_edge;
1943     GPRReg m_gprOrInvalid;
1944 };
1945
1946
1947 // === Temporaries ===
1948 //
1949 // These classes are used to allocate temporary registers.
1950 // A mechanism is provided to attempt to reuse the registers
1951 // currently allocated to child nodes whose value is consumed
1952 // by, and not live after, this operation.
1953
1954 enum ReuseTag { Reuse };
1955
1956 class GPRTemporary {
1957 public:
1958     GPRTemporary();
1959     GPRTemporary(SpeculativeJIT*);
1960     GPRTemporary(SpeculativeJIT*, GPRReg specific);
1961     template<typename T>
1962     GPRTemporary(SpeculativeJIT* jit, ReuseTag, T& operand)
1963         : m_jit(jit)
1964         , m_gpr(InvalidGPRReg)
1965     {
1966         if (m_jit->canReuse(operand.node()))
1967             m_gpr = m_jit->reuse(operand.gpr());
1968         else
1969             m_gpr = m_jit->allocate();
1970     }
1971     template<typename T1, typename T2>
1972     GPRTemporary(SpeculativeJIT* jit, ReuseTag, T1& op1, T2& op2)
1973         : m_jit(jit)
1974         , m_gpr(InvalidGPRReg)
1975     {
1976         if (m_jit->canReuse(op1.node()))
1977             m_gpr = m_jit->reuse(op1.gpr());
1978         else if (m_jit->canReuse(op2.node()))
1979             m_gpr = m_jit->reuse(op2.gpr());
1980         else if (m_jit->canReuse(op1.node(), op2.node()) && op1.gpr() == op2.gpr())
1981             m_gpr = m_jit->reuse(op1.gpr());
1982         else
1983             m_gpr = m_jit->allocate();
1984     }
1985     GPRTemporary(SpeculativeJIT*, ReuseTag, JSValueOperand&, WhichValueWord);
1986
1987     GPRTemporary(GPRTemporary& other) = delete;
1988
1989     GPRTemporary(GPRTemporary&& other)
1990     {
1991         ASSERT(other.m_jit);
1992         ASSERT(other.m_gpr != InvalidGPRReg);
1993         m_jit = other.m_jit;
1994         m_gpr = other.m_gpr;
1995         other.m_jit = nullptr;
1996         other.m_gpr = InvalidGPRReg;
1997     }
1998
1999     GPRTemporary& operator=(GPRTemporary&& other)
2000     {
2001         ASSERT(!m_jit);
2002         ASSERT(m_gpr == InvalidGPRReg);
2003         std::swap(m_jit, other.m_jit);
2004         std::swap(m_gpr, other.m_gpr);
2005         return *this;
2006     }
2007
2008     void adopt(GPRTemporary&);
2009
2010     ~GPRTemporary()
2011     {
2012         if (m_jit && m_gpr != InvalidGPRReg)
2013             m_jit->unlock(gpr());
2014     }
2015
2016     GPRReg gpr()
2017     {
2018         return m_gpr;
2019     }
2020
2021 private:
2022     SpeculativeJIT* m_jit;
2023     GPRReg m_gpr;
2024 };
2025
2026 class JSValueRegsTemporary {
2027 public:
2028     JSValueRegsTemporary();
2029     JSValueRegsTemporary(SpeculativeJIT*);
2030     template<typename T>
2031     JSValueRegsTemporary(SpeculativeJIT*, ReuseTag, T& operand, WhichValueWord resultRegWord = PayloadWord);
2032     JSValueRegsTemporary(SpeculativeJIT*, ReuseTag, JSValueOperand&);
2033     ~JSValueRegsTemporary();
2034     
2035     JSValueRegs regs();
2036
2037 private:
2038 #if USE(JSVALUE64)
2039     GPRTemporary m_gpr;
2040 #else
2041     GPRTemporary m_payloadGPR;
2042     GPRTemporary m_tagGPR;
2043 #endif
2044 };
2045
2046 class FPRTemporary {
2047     WTF_MAKE_NONCOPYABLE(FPRTemporary);
2048 public:
2049     FPRTemporary(FPRTemporary&&);
2050     FPRTemporary(SpeculativeJIT*);
2051     FPRTemporary(SpeculativeJIT*, SpeculateDoubleOperand&);
2052     FPRTemporary(SpeculativeJIT*, SpeculateDoubleOperand&, SpeculateDoubleOperand&);
2053 #if USE(JSVALUE32_64)
2054     FPRTemporary(SpeculativeJIT*, JSValueOperand&);
2055 #endif
2056
2057     ~FPRTemporary()
2058     {
2059         if (LIKELY(m_jit))
2060             m_jit->unlock(fpr());
2061     }
2062
2063     FPRReg fpr() const
2064     {
2065         ASSERT(m_jit);
2066         ASSERT(m_fpr != InvalidFPRReg);
2067         return m_fpr;
2068     }
2069
2070 protected:
2071     FPRTemporary(SpeculativeJIT* jit, FPRReg lockedFPR)
2072         : m_jit(jit)
2073         , m_fpr(lockedFPR)
2074     {
2075     }
2076
2077 private:
2078     SpeculativeJIT* m_jit;
2079     FPRReg m_fpr;
2080 };
2081
2082
2083 // === Results ===
2084 //
2085 // These classes lock the result of a call to a C++ helper function.
2086
2087 class GPRFlushedCallResult : public GPRTemporary {
2088 public:
2089     GPRFlushedCallResult(SpeculativeJIT* jit)
2090         : GPRTemporary(jit, GPRInfo::returnValueGPR)
2091     {
2092     }
2093 };
2094
2095 #if USE(JSVALUE32_64)
2096 class GPRFlushedCallResult2 : public GPRTemporary {
2097 public:
2098     GPRFlushedCallResult2(SpeculativeJIT* jit)
2099         : GPRTemporary(jit, GPRInfo::returnValueGPR2)
2100     {
2101     }
2102 };
2103 #endif
2104
2105 class FPRResult : public FPRTemporary {
2106 public:
2107     FPRResult(SpeculativeJIT* jit)
2108         : FPRTemporary(jit, lockedResult(jit))
2109     {
2110     }
2111
2112 private:
2113     static FPRReg lockedResult(SpeculativeJIT* jit)
2114     {
2115         jit->lock(FPRInfo::returnValueFPR);
2116         return FPRInfo::returnValueFPR;
2117     }
2118 };
2119
2120 class JSValueRegsFlushedCallResult {
2121 public:
2122     JSValueRegsFlushedCallResult(SpeculativeJIT* jit)
2123 #if USE(JSVALUE64)
2124         : m_gpr(jit)
2125 #else
2126         : m_payloadGPR(jit)
2127         , m_tagGPR(jit)
2128 #endif
2129     {
2130     }
2131
2132     JSValueRegs regs()
2133     {
2134 #if USE(JSVALUE64)
2135         return JSValueRegs { m_gpr.gpr() };
2136 #else
2137         return JSValueRegs { m_tagGPR.gpr(), m_payloadGPR.gpr() };
2138 #endif
2139     }
2140
2141 private:
2142 #if USE(JSVALUE64)
2143     GPRFlushedCallResult m_gpr;
2144 #else
2145     GPRFlushedCallResult m_payloadGPR;
2146     GPRFlushedCallResult2 m_tagGPR;
2147 #endif
2148 };
2149
2150
2151 // === Speculative Operand types ===
2152 //
2153 // SpeculateInt32Operand, SpeculateStrictInt32Operand and SpeculateCellOperand.
2154 //
2155 // These are used to lock the operands to a node into machine registers within the
2156 // SpeculativeJIT. The classes operate like those above, however these will
2157 // perform a speculative check for a more restrictive type than we can statically
2158 // determine the operand to have. If the operand does not have the requested type,
2159 // a bail-out to the non-speculative path will be taken.
2160
2161 class SpeculateInt32Operand {
2162 public:
2163     explicit SpeculateInt32Operand(SpeculativeJIT* jit, Edge edge, OperandSpeculationMode mode = AutomaticOperandSpeculation)
2164         : m_jit(jit)
2165         , m_edge(edge)
2166         , m_gprOrInvalid(InvalidGPRReg)
2167 #ifndef NDEBUG
2168         , m_format(DataFormatNone)
2169 #endif
2170     {
2171         ASSERT(m_jit);
2172         ASSERT_UNUSED(mode, mode == ManualOperandSpeculation || (edge.useKind() == Int32Use || edge.useKind() == KnownInt32Use));
2173         if (jit->isFilled(node()))
2174             gpr();
2175     }
2176
2177     ~SpeculateInt32Operand()
2178     {
2179         ASSERT(m_gprOrInvalid != InvalidGPRReg);
2180         m_jit->unlock(m_gprOrInvalid);
2181     }
2182     
2183     Edge edge() const
2184     {
2185         return m_edge;
2186     }
2187
2188     Node* node() const
2189     {
2190         return edge().node();
2191     }
2192
2193     DataFormat format()
2194     {
2195         gpr(); // m_format is set when m_gpr is locked.
2196         ASSERT(m_format == DataFormatInt32 || m_format == DataFormatJSInt32);
2197         return m_format;
2198     }
2199
2200     GPRReg gpr()
2201     {
2202         if (m_gprOrInvalid == InvalidGPRReg)
2203             m_gprOrInvalid = m_jit->fillSpeculateInt32(edge(), m_format);
2204         return m_gprOrInvalid;
2205     }
2206     
2207     void use()
2208     {
2209         m_jit->use(node());
2210     }
2211
2212 private:
2213     SpeculativeJIT* m_jit;
2214     Edge m_edge;
2215     GPRReg m_gprOrInvalid;
2216     DataFormat m_format;
2217 };
2218
2219 class SpeculateStrictInt32Operand {
2220 public:
2221     explicit SpeculateStrictInt32Operand(SpeculativeJIT* jit, Edge edge, OperandSpeculationMode mode = AutomaticOperandSpeculation)
2222         : m_jit(jit)
2223         , m_edge(edge)
2224         , m_gprOrInvalid(InvalidGPRReg)
2225     {
2226         ASSERT(m_jit);
2227         ASSERT_UNUSED(mode, mode == ManualOperandSpeculation || (edge.useKind() == Int32Use || edge.useKind() == KnownInt32Use));
2228         if (jit->isFilled(node()))
2229             gpr();
2230     }
2231
2232     ~SpeculateStrictInt32Operand()
2233     {
2234         ASSERT(m_gprOrInvalid != InvalidGPRReg);
2235         m_jit->unlock(m_gprOrInvalid);
2236     }
2237     
2238     Edge edge() const
2239     {
2240         return m_edge;
2241     }
2242
2243     Node* node() const
2244     {
2245         return edge().node();
2246     }
2247
2248     GPRReg gpr()
2249     {
2250         if (m_gprOrInvalid == InvalidGPRReg)
2251             m_gprOrInvalid = m_jit->fillSpeculateInt32Strict(edge());
2252         return m_gprOrInvalid;
2253     }
2254     
2255     void use()
2256     {
2257         m_jit->use(node());
2258     }
2259
2260 private:
2261     SpeculativeJIT* m_jit;
2262     Edge m_edge;
2263     GPRReg m_gprOrInvalid;
2264 };
2265
2266 // Gives you a canonical Int52 (i.e. it's left-shifted by 16, low bits zero).
2267 class SpeculateInt52Operand {
2268 public:
2269     explicit SpeculateInt52Operand(SpeculativeJIT* jit, Edge edge)
2270         : m_jit(jit)
2271         , m_edge(edge)
2272         , m_gprOrInvalid(InvalidGPRReg)
2273     {
2274         RELEASE_ASSERT(edge.useKind() == Int52RepUse);
2275         if (jit->isFilled(node()))
2276             gpr();
2277     }
2278     
2279     ~SpeculateInt52Operand()
2280     {
2281         ASSERT(m_gprOrInvalid != InvalidGPRReg);
2282         m_jit->unlock(m_gprOrInvalid);
2283     }
2284     
2285     Edge edge() const
2286     {
2287         return m_edge;
2288     }
2289     
2290     Node* node() const
2291     {
2292         return edge().node();
2293     }
2294     
2295     GPRReg gpr()
2296     {
2297         if (m_gprOrInvalid == InvalidGPRReg)
2298             m_gprOrInvalid = m_jit->fillSpeculateInt52(edge(), DataFormatInt52);
2299         return m_gprOrInvalid;
2300     }
2301     
2302     void use()
2303     {
2304         m_jit->use(node());
2305     }
2306     
2307 private:
2308     SpeculativeJIT* m_jit;
2309     Edge m_edge;
2310     GPRReg m_gprOrInvalid;
2311 };
2312
2313 // Gives you a strict Int52 (i.e. the payload is in the low 48 bits, high 16 bits are sign-extended).
2314 class SpeculateStrictInt52Operand {
2315 public:
2316     explicit SpeculateStrictInt52Operand(SpeculativeJIT* jit, Edge edge)
2317         : m_jit(jit)
2318         , m_edge(edge)
2319         , m_gprOrInvalid(InvalidGPRReg)
2320     {
2321         RELEASE_ASSERT(edge.useKind() == Int52RepUse);
2322         if (jit->isFilled(node()))
2323             gpr();
2324     }
2325     
2326     ~SpeculateStrictInt52Operand()
2327     {
2328         ASSERT(m_gprOrInvalid != InvalidGPRReg);
2329         m_jit->unlock(m_gprOrInvalid);
2330     }
2331     
2332     Edge edge() const
2333     {
2334         return m_edge;
2335     }
2336     
2337     Node* node() const
2338     {
2339         return edge().node();
2340     }
2341     
2342     GPRReg gpr()
2343     {
2344         if (m_gprOrInvalid == InvalidGPRReg)
2345             m_gprOrInvalid = m_jit->fillSpeculateInt52(edge(), DataFormatStrictInt52);
2346         return m_gprOrInvalid;
2347     }
2348     
2349     void use()
2350     {
2351         m_jit->use(node());
2352     }
2353     
2354 private:
2355     SpeculativeJIT* m_jit;
2356     Edge m_edge;
2357     GPRReg m_gprOrInvalid;
2358 };
2359
2360 enum OppositeShiftTag { OppositeShift };
2361
2362 class SpeculateWhicheverInt52Operand {
2363 public:
2364     explicit SpeculateWhicheverInt52Operand(SpeculativeJIT* jit, Edge edge)
2365         : m_jit(jit)
2366         , m_edge(edge)
2367         , m_gprOrInvalid(InvalidGPRReg)
2368         , m_strict(jit->betterUseStrictInt52(edge))
2369     {
2370         RELEASE_ASSERT(edge.useKind() == Int52RepUse);
2371         if (jit->isFilled(node()))
2372             gpr();
2373     }
2374     
2375     explicit SpeculateWhicheverInt52Operand(SpeculativeJIT* jit, Edge edge, const SpeculateWhicheverInt52Operand& other)
2376         : m_jit(jit)
2377         , m_edge(edge)
2378         , m_gprOrInvalid(InvalidGPRReg)
2379         , m_strict(other.m_strict)
2380     {
2381         RELEASE_ASSERT(edge.useKind() == Int52RepUse);
2382         if (jit->isFilled(node()))
2383             gpr();
2384     }
2385     
2386     explicit SpeculateWhicheverInt52Operand(SpeculativeJIT* jit, Edge edge, OppositeShiftTag, const SpeculateWhicheverInt52Operand& other)
2387         : m_jit(jit)
2388         , m_edge(edge)
2389         , m_gprOrInvalid(InvalidGPRReg)
2390         , m_strict(!other.m_strict)
2391     {
2392         RELEASE_ASSERT(edge.useKind() == Int52RepUse);
2393         if (jit->isFilled(node()))
2394             gpr();
2395     }
2396     
2397     ~SpeculateWhicheverInt52Operand()
2398     {
2399         ASSERT(m_gprOrInvalid != InvalidGPRReg);
2400         m_jit->unlock(m_gprOrInvalid);
2401     }
2402     
2403     Edge edge() const
2404     {
2405         return m_edge;
2406     }
2407     
2408     Node* node() const
2409     {
2410         return edge().node();
2411     }
2412     
2413     GPRReg gpr()
2414     {
2415         if (m_gprOrInvalid == InvalidGPRReg) {
2416             m_gprOrInvalid = m_jit->fillSpeculateInt52(
2417                 edge(), m_strict ? DataFormatStrictInt52 : DataFormatInt52);
2418         }
2419         return m_gprOrInvalid;
2420     }
2421     
2422     void use()
2423     {
2424         m_jit->use(node());
2425     }
2426     
2427     DataFormat format() const
2428     {
2429         return m_strict ? DataFormatStrictInt52 : DataFormatInt52;
2430     }
2431
2432 private:
2433     SpeculativeJIT* m_jit;
2434     Edge m_edge;
2435     GPRReg m_gprOrInvalid;
2436     bool m_strict;
2437 };
2438
2439 class SpeculateDoubleOperand {
2440 public:
2441     explicit SpeculateDoubleOperand(SpeculativeJIT* jit, Edge edge)
2442         : m_jit(jit)
2443         , m_edge(edge)
2444         , m_fprOrInvalid(InvalidFPRReg)
2445     {
2446         ASSERT(m_jit);
2447         RELEASE_ASSERT(isDouble(edge.useKind()));
2448         if (jit->isFilled(node()))
2449             fpr();
2450     }
2451
2452     ~SpeculateDoubleOperand()
2453     {
2454         ASSERT(m_fprOrInvalid != InvalidFPRReg);
2455         m_jit->unlock(m_fprOrInvalid);
2456     }
2457     
2458     Edge edge() const
2459     {
2460         return m_edge;
2461     }
2462
2463     Node* node() const
2464     {
2465         return edge().node();
2466     }
2467
2468     FPRReg fpr()
2469     {
2470         if (m_fprOrInvalid == InvalidFPRReg)
2471             m_fprOrInvalid = m_jit->fillSpeculateDouble(edge());
2472         return m_fprOrInvalid;
2473     }
2474     
2475     void use()
2476     {
2477         m_jit->use(node());
2478     }
2479
2480 private:
2481     SpeculativeJIT* m_jit;
2482     Edge m_edge;
2483     FPRReg m_fprOrInvalid;
2484 };
2485
2486 class SpeculateCellOperand {
2487     WTF_MAKE_NONCOPYABLE(SpeculateCellOperand);
2488
2489 public:
2490     explicit SpeculateCellOperand(SpeculativeJIT* jit, Edge edge, OperandSpeculationMode mode = AutomaticOperandSpeculation)
2491         : m_jit(jit)
2492         , m_edge(edge)
2493         , m_gprOrInvalid(InvalidGPRReg)
2494     {
2495         ASSERT(m_jit);
2496         if (!edge)
2497             return;
2498         ASSERT_UNUSED(mode, mode == ManualOperandSpeculation || isCell(edge.useKind()));
2499         if (jit->isFilled(node()))
2500             gpr();
2501     }
2502
2503     explicit SpeculateCellOperand(SpeculateCellOperand&& other)
2504     {
2505         m_jit = other.m_jit;
2506         m_edge = other.m_edge;
2507         m_gprOrInvalid = other.m_gprOrInvalid;
2508
2509         other.m_gprOrInvalid = InvalidGPRReg;
2510         other.m_edge = Edge();
2511     }
2512
2513     ~SpeculateCellOperand()
2514     {
2515         if (!m_edge)
2516             return;
2517         ASSERT(m_gprOrInvalid != InvalidGPRReg);
2518         m_jit->unlock(m_gprOrInvalid);
2519     }
2520     
2521     Edge edge() const
2522     {
2523         return m_edge;
2524     }
2525
2526     Node* node() const
2527     {
2528         return edge().node();
2529     }
2530
2531     GPRReg gpr()
2532     {
2533         ASSERT(m_edge);
2534         if (m_gprOrInvalid == InvalidGPRReg)
2535             m_gprOrInvalid = m_jit->fillSpeculateCell(edge());
2536         return m_gprOrInvalid;
2537     }
2538     
2539     void use()
2540     {
2541         ASSERT(m_edge);
2542         m_jit->use(node());
2543     }
2544
2545 private:
2546     SpeculativeJIT* m_jit;
2547     Edge m_edge;
2548     GPRReg m_gprOrInvalid;
2549 };
2550
2551 class SpeculateBooleanOperand {
2552 public:
2553     explicit SpeculateBooleanOperand(SpeculativeJIT* jit, Edge edge, OperandSpeculationMode mode = AutomaticOperandSpeculation)
2554         : m_jit(jit)
2555         , m_edge(edge)
2556         , m_gprOrInvalid(InvalidGPRReg)
2557     {
2558         ASSERT(m_jit);
2559         ASSERT_UNUSED(mode, mode == ManualOperandSpeculation || edge.useKind() == BooleanUse || edge.useKind() == KnownBooleanUse);
2560         if (jit->isFilled(node()))
2561             gpr();
2562     }
2563     
2564     ~SpeculateBooleanOperand()
2565     {
2566         ASSERT(m_gprOrInvalid != InvalidGPRReg);
2567         m_jit->unlock(m_gprOrInvalid);
2568     }
2569     
2570     Edge edge() const
2571     {
2572         return m_edge;
2573     }
2574     
2575     Node* node() const
2576     {
2577         return edge().node();
2578     }
2579     
2580     GPRReg gpr()
2581     {
2582         if (m_gprOrInvalid == InvalidGPRReg)
2583             m_gprOrInvalid = m_jit->fillSpeculateBoolean(edge());
2584         return m_gprOrInvalid;
2585     }
2586     
2587     void use()
2588     {
2589         m_jit->use(node());
2590     }
2591
2592 private:
2593     SpeculativeJIT* m_jit;
2594     Edge m_edge;
2595     GPRReg m_gprOrInvalid;
2596 };
2597
2598 template<typename StructureLocationType>
2599 void SpeculativeJIT::speculateStringObjectForStructure(Edge edge, StructureLocationType structureLocation)
2600 {
2601     RegisteredStructure stringObjectStructure =
2602         m_jit.graph().registerStructure(m_jit.globalObjectFor(m_currentNode->origin.semantic)->stringObjectStructure());
2603     
2604     if (!m_state.forNode(edge).m_structure.isSubsetOf(RegisteredStructureSet(stringObjectStructure))) {
2605         speculationCheck(
2606             NotStringObject, JSValueRegs(), 0,
2607             m_jit.branchWeakStructure(
2608                 JITCompiler::NotEqual, structureLocation, stringObjectStructure));
2609     }
2610 }
2611
2612 #define DFG_TYPE_CHECK_WITH_EXIT_KIND(exitKind, source, edge, typesPassedThrough, jumpToFail) do { \
2613         JSValueSource _dtc_source = (source);                           \
2614         Edge _dtc_edge = (edge);                                        \
2615         SpeculatedType _dtc_typesPassedThrough = typesPassedThrough;    \
2616         if (!needsTypeCheck(_dtc_edge, _dtc_typesPassedThrough))        \
2617             break;                                                      \
2618         typeCheck(_dtc_source, _dtc_edge, _dtc_typesPassedThrough, (jumpToFail), exitKind); \
2619     } while (0)
2620
2621 #define DFG_TYPE_CHECK(source, edge, typesPassedThrough, jumpToFail) \
2622     DFG_TYPE_CHECK_WITH_EXIT_KIND(BadType, source, edge, typesPassedThrough, jumpToFail)
2623
2624 } } // namespace JSC::DFG
2625
2626 #endif