Add SetCallee as DFG-Operation
[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 addSlowPathGenerator(std::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 compileIn(Node*);
739     
740     void nonSpeculativeNonPeepholeCompareNullOrUndefined(Edge operand);
741     void nonSpeculativePeepholeBranchNullOrUndefined(Edge operand, Node* branchNode);
742     
743     void nonSpeculativePeepholeBranch(Node*, Node* branchNode, MacroAssembler::RelationalCondition, S_JITOperation_EJJ helperFunction);
744     void nonSpeculativeNonPeepholeCompare(Node*, MacroAssembler::RelationalCondition, S_JITOperation_EJJ helperFunction);
745     
746     void nonSpeculativePeepholeStrictEq(Node*, Node* branchNode, bool invert = false);
747     void nonSpeculativeNonPeepholeStrictEq(Node*, bool invert = false);
748     bool nonSpeculativeStrictEq(Node*, bool invert = false);
749     
750     void compileInstanceOfForObject(Node*, GPRReg valueReg, GPRReg prototypeReg, GPRReg scratchAndResultReg, GPRReg scratch2Reg, GPRReg scratch3Reg);
751     void compileInstanceOf(Node*);
752     void compileInstanceOfCustom(Node*);
753     void compileOverridesHasInstance(Node*);
754
755     void compileIsCellWithType(Node*);
756     void compileIsTypedArrayView(Node*);
757
758     void emitCall(Node*);
759
760     void emitAllocateButterfly(GPRReg storageGPR, GPRReg sizeGPR, GPRReg scratch1, GPRReg scratch2, GPRReg scratch3, MacroAssembler::JumpList& slowCases);
761     void emitInitializeButterfly(GPRReg storageGPR, GPRReg sizeGPR, JSValueRegs emptyValueRegs, GPRReg scratchGPR);
762     void compileAllocateNewArrayWithSize(JSGlobalObject*, GPRReg resultGPR, GPRReg sizeGPR, IndexingType, bool shouldConvertLargeSizeToArrayStorage = true);
763     
764     // Called once a node has completed code generation but prior to setting
765     // its result, to free up its children. (This must happen prior to setting
766     // the nodes result, since the node may have the same VirtualRegister as
767     // a child, and as such will use the same GeneratioInfo).
768     void useChildren(Node*);
769
770     // These method called to initialize the GenerationInfo
771     // to describe the result of an operation.
772     void int32Result(GPRReg reg, Node* node, DataFormat format = DataFormatInt32, UseChildrenMode mode = CallUseChildren)
773     {
774         if (mode == CallUseChildren)
775             useChildren(node);
776
777         VirtualRegister virtualRegister = node->virtualRegister();
778         GenerationInfo& info = generationInfoFromVirtualRegister(virtualRegister);
779
780         if (format == DataFormatInt32) {
781             m_jit.jitAssertIsInt32(reg);
782             m_gprs.retain(reg, virtualRegister, SpillOrderInteger);
783             info.initInt32(node, node->refCount(), reg);
784         } else {
785 #if USE(JSVALUE64)
786             RELEASE_ASSERT(format == DataFormatJSInt32);
787             m_jit.jitAssertIsJSInt32(reg);
788             m_gprs.retain(reg, virtualRegister, SpillOrderJS);
789             info.initJSValue(node, node->refCount(), reg, format);
790 #elif USE(JSVALUE32_64)
791             RELEASE_ASSERT_NOT_REACHED();
792 #endif
793         }
794     }
795     void int32Result(GPRReg reg, Node* node, UseChildrenMode mode)
796     {
797         int32Result(reg, node, DataFormatInt32, mode);
798     }
799     void int52Result(GPRReg reg, Node* node, DataFormat format, UseChildrenMode mode = CallUseChildren)
800     {
801         if (mode == CallUseChildren)
802             useChildren(node);
803
804         VirtualRegister virtualRegister = node->virtualRegister();
805         GenerationInfo& info = generationInfoFromVirtualRegister(virtualRegister);
806
807         m_gprs.retain(reg, virtualRegister, SpillOrderJS);
808         info.initInt52(node, node->refCount(), reg, format);
809     }
810     void int52Result(GPRReg reg, Node* node, UseChildrenMode mode = CallUseChildren)
811     {
812         int52Result(reg, node, DataFormatInt52, mode);
813     }
814     void strictInt52Result(GPRReg reg, Node* node, UseChildrenMode mode = CallUseChildren)
815     {
816         int52Result(reg, node, DataFormatStrictInt52, mode);
817     }
818     void noResult(Node* node, UseChildrenMode mode = CallUseChildren)
819     {
820         if (mode == UseChildrenCalledExplicitly)
821             return;
822         useChildren(node);
823     }
824     void cellResult(GPRReg reg, Node* node, UseChildrenMode mode = CallUseChildren)
825     {
826         if (mode == CallUseChildren)
827             useChildren(node);
828
829         VirtualRegister virtualRegister = node->virtualRegister();
830         m_gprs.retain(reg, virtualRegister, SpillOrderCell);
831         GenerationInfo& info = generationInfoFromVirtualRegister(virtualRegister);
832         info.initCell(node, node->refCount(), reg);
833     }
834     void blessedBooleanResult(GPRReg reg, Node* node, UseChildrenMode mode = CallUseChildren)
835     {
836 #if USE(JSVALUE64)
837         jsValueResult(reg, node, DataFormatJSBoolean, mode);
838 #else
839         booleanResult(reg, node, mode);
840 #endif
841     }
842     void unblessedBooleanResult(GPRReg reg, Node* node, UseChildrenMode mode = CallUseChildren)
843     {
844 #if USE(JSVALUE64)
845         blessBoolean(reg);
846 #endif
847         blessedBooleanResult(reg, node, mode);
848     }
849 #if USE(JSVALUE64)
850     void jsValueResult(GPRReg reg, Node* node, DataFormat format = DataFormatJS, UseChildrenMode mode = CallUseChildren)
851     {
852         if (format == DataFormatJSInt32)
853             m_jit.jitAssertIsJSInt32(reg);
854         
855         if (mode == CallUseChildren)
856             useChildren(node);
857
858         VirtualRegister virtualRegister = node->virtualRegister();
859         m_gprs.retain(reg, virtualRegister, SpillOrderJS);
860         GenerationInfo& info = generationInfoFromVirtualRegister(virtualRegister);
861         info.initJSValue(node, node->refCount(), reg, format);
862     }
863     void jsValueResult(GPRReg reg, Node* node, UseChildrenMode mode)
864     {
865         jsValueResult(reg, node, DataFormatJS, mode);
866     }
867 #elif USE(JSVALUE32_64)
868     void booleanResult(GPRReg reg, Node* node, UseChildrenMode mode = CallUseChildren)
869     {
870         if (mode == CallUseChildren)
871             useChildren(node);
872
873         VirtualRegister virtualRegister = node->virtualRegister();
874         m_gprs.retain(reg, virtualRegister, SpillOrderBoolean);
875         GenerationInfo& info = generationInfoFromVirtualRegister(virtualRegister);
876         info.initBoolean(node, node->refCount(), reg);
877     }
878     void jsValueResult(GPRReg tag, GPRReg payload, Node* node, DataFormat format = DataFormatJS, UseChildrenMode mode = CallUseChildren)
879     {
880         if (mode == CallUseChildren)
881             useChildren(node);
882
883         VirtualRegister virtualRegister = node->virtualRegister();
884         m_gprs.retain(tag, virtualRegister, SpillOrderJS);
885         m_gprs.retain(payload, virtualRegister, SpillOrderJS);
886         GenerationInfo& info = generationInfoFromVirtualRegister(virtualRegister);
887         info.initJSValue(node, node->refCount(), tag, payload, format);
888     }
889     void jsValueResult(GPRReg tag, GPRReg payload, Node* node, UseChildrenMode mode)
890     {
891         jsValueResult(tag, payload, node, DataFormatJS, mode);
892     }
893 #endif
894     void jsValueResult(JSValueRegs regs, Node* node, DataFormat format = DataFormatJS, UseChildrenMode mode = CallUseChildren)
895     {
896 #if USE(JSVALUE64)
897         jsValueResult(regs.gpr(), node, format, mode);
898 #else
899         jsValueResult(regs.tagGPR(), regs.payloadGPR(), node, format, mode);
900 #endif
901     }
902     void storageResult(GPRReg reg, Node* node, UseChildrenMode mode = CallUseChildren)
903     {
904         if (mode == CallUseChildren)
905             useChildren(node);
906         
907         VirtualRegister virtualRegister = node->virtualRegister();
908         m_gprs.retain(reg, virtualRegister, SpillOrderStorage);
909         GenerationInfo& info = generationInfoFromVirtualRegister(virtualRegister);
910         info.initStorage(node, node->refCount(), reg);
911     }
912     void doubleResult(FPRReg reg, Node* node, UseChildrenMode mode = CallUseChildren)
913     {
914         if (mode == CallUseChildren)
915             useChildren(node);
916
917         VirtualRegister virtualRegister = node->virtualRegister();
918         m_fprs.retain(reg, virtualRegister, SpillOrderDouble);
919         GenerationInfo& info = generationInfoFromVirtualRegister(virtualRegister);
920         info.initDouble(node, node->refCount(), reg);
921     }
922     void initConstantInfo(Node* node)
923     {
924         ASSERT(node->hasConstant());
925         generationInfo(node).initConstant(node, node->refCount());
926     }
927
928 #define FIRST_ARGUMENT_TYPE typename FunctionTraits<OperationType>::template ArgumentType<0>
929
930     template<typename OperationType, typename ResultRegType, typename... Args>
931     std::enable_if_t<
932         FunctionTraits<OperationType>::hasResult,
933     JITCompiler::Call>
934     callOperation(OperationType operation, ResultRegType result, Args... args)
935     {
936         m_jit.setupArguments<OperationType>(args...);
937         return appendCallSetResult(operation, result);
938     }
939
940     template<typename OperationType, typename Arg, typename... Args>
941     std::enable_if_t<
942         !FunctionTraits<OperationType>::hasResult
943         && !std::is_same<Arg, NoResultTag>::value,
944     JITCompiler::Call>
945     callOperation(OperationType operation, Arg arg, Args... args)
946     {
947         m_jit.setupArguments<OperationType>(arg, args...);
948         return appendCall(operation);
949     }
950
951     template<typename OperationType, typename... Args>
952     std::enable_if_t<
953         !FunctionTraits<OperationType>::hasResult,
954     JITCompiler::Call>
955     callOperation(OperationType operation, NoResultTag, Args... args)
956     {
957         m_jit.setupArguments<OperationType>(args...);
958         return appendCall(operation);
959     }
960
961     template<typename OperationType>
962     std::enable_if_t<
963         !FunctionTraits<OperationType>::hasResult,
964     JITCompiler::Call>
965     callOperation(OperationType operation)
966     {
967         m_jit.setupArguments<OperationType>();
968         return appendCall(operation);
969     }
970
971 #undef FIRST_ARGUMENT_TYPE
972
973     JITCompiler::Call callOperationWithCallFrameRollbackOnException(V_JITOperation_ECb operation, void* pointer)
974     {
975         m_jit.setupArguments<V_JITOperation_ECb>(TrustedImmPtr(pointer));
976         return appendCallWithCallFrameRollbackOnException(operation);
977     }
978
979     JITCompiler::Call callOperationWithCallFrameRollbackOnException(Z_JITOperation_E operation, GPRReg result)
980     {
981         m_jit.setupArguments<Z_JITOperation_E>();
982         return appendCallWithCallFrameRollbackOnExceptionSetResult(operation, result);
983     }
984     
985 #if !defined(NDEBUG) && !CPU(ARM) && !CPU(MIPS)
986     void prepareForExternalCall()
987     {
988         // We're about to call out to a "native" helper function. The helper
989         // function is expected to set topCallFrame itself with the ExecState
990         // that is passed to it.
991         //
992         // We explicitly trash topCallFrame here so that we'll know if some of
993         // the helper functions are not setting topCallFrame when they should
994         // be doing so. Note: the previous value in topcallFrame was not valid
995         // anyway since it was not being updated by JIT'ed code by design.
996
997         for (unsigned i = 0; i < sizeof(void*) / 4; i++)
998             m_jit.store32(TrustedImm32(0xbadbeef), reinterpret_cast<char*>(&m_jit.vm()->topCallFrame) + i * 4);
999     }
1000 #else
1001     void prepareForExternalCall() { }
1002 #endif
1003
1004     // These methods add call instructions, optionally setting results, and optionally rolling back the call frame on an exception.
1005     JITCompiler::Call appendCall(const FunctionPtr<CFunctionPtrTag> function)
1006     {
1007         prepareForExternalCall();
1008         m_jit.emitStoreCodeOrigin(m_currentNode->origin.semantic);
1009         return m_jit.appendCall(function);
1010     }
1011
1012     JITCompiler::Call appendCallWithCallFrameRollbackOnException(const FunctionPtr<CFunctionPtrTag> function)
1013     {
1014         JITCompiler::Call call = appendCall(function);
1015         m_jit.exceptionCheckWithCallFrameRollback();
1016         return call;
1017     }
1018
1019     JITCompiler::Call appendCallWithCallFrameRollbackOnExceptionSetResult(const FunctionPtr<CFunctionPtrTag> function, GPRReg result)
1020     {
1021         JITCompiler::Call call = appendCallWithCallFrameRollbackOnException(function);
1022         if ((result != InvalidGPRReg) && (result != GPRInfo::returnValueGPR))
1023             m_jit.move(GPRInfo::returnValueGPR, result);
1024         return call;
1025     }
1026
1027     JITCompiler::Call appendCallSetResult(const FunctionPtr<CFunctionPtrTag> function, GPRReg result)
1028     {
1029         JITCompiler::Call call = appendCall(function);
1030         if (result != InvalidGPRReg)
1031             m_jit.move(GPRInfo::returnValueGPR, result);
1032         return call;
1033     }
1034
1035     JITCompiler::Call appendCallSetResult(const FunctionPtr<CFunctionPtrTag> function, GPRReg result1, GPRReg result2)
1036     {
1037         JITCompiler::Call call = appendCall(function);
1038         m_jit.setupResults(result1, result2);
1039         return call;
1040     }
1041
1042     JITCompiler::Call appendCallSetResult(const FunctionPtr<CFunctionPtrTag> function, JSValueRegs resultRegs)
1043     {
1044 #if USE(JSVALUE64)
1045         return appendCallSetResult(function, resultRegs.gpr());
1046 #else
1047         return appendCallSetResult(function, resultRegs.payloadGPR(), resultRegs.tagGPR());
1048 #endif
1049     }
1050
1051 #if CPU(X86)
1052     JITCompiler::Call appendCallSetResult(const FunctionPtr<CFunctionPtrTag> function, FPRReg result)
1053     {
1054         JITCompiler::Call call = appendCall(function);
1055         if (result != InvalidFPRReg) {
1056             m_jit.assembler().fstpl(0, JITCompiler::stackPointerRegister);
1057             m_jit.loadDouble(JITCompiler::stackPointerRegister, result);
1058         }
1059         return call;
1060     }
1061 #elif CPU(ARM) && !CPU(ARM_HARDFP)
1062     JITCompiler::Call appendCallSetResult(const FunctionPtr<CFunctionPtrTag> function, FPRReg result)
1063     {
1064         JITCompiler::Call call = appendCall(function);
1065         if (result != InvalidFPRReg)
1066             m_jit.assembler().vmov(result, GPRInfo::returnValueGPR, GPRInfo::returnValueGPR2);
1067         return call;
1068     }
1069 #else // CPU(X86_64) || (CPU(ARM) && CPU(ARM_HARDFP)) || CPU(ARM64) || CPU(MIPS)
1070     JITCompiler::Call appendCallSetResult(const FunctionPtr<CFunctionPtrTag> function, FPRReg result)
1071     {
1072         JITCompiler::Call call = appendCall(function);
1073         if (result != InvalidFPRReg)
1074             m_jit.moveDouble(FPRInfo::returnValueFPR, result);
1075         return call;
1076     }
1077 #endif
1078
1079     void branchDouble(JITCompiler::DoubleCondition cond, FPRReg left, FPRReg right, BasicBlock* destination)
1080     {
1081         return addBranch(m_jit.branchDouble(cond, left, right), destination);
1082     }
1083     
1084     void branchDoubleNonZero(FPRReg value, FPRReg scratch, BasicBlock* destination)
1085     {
1086         return addBranch(m_jit.branchDoubleNonZero(value, scratch), destination);
1087     }
1088     
1089     template<typename T, typename U>
1090     void branch32(JITCompiler::RelationalCondition cond, T left, U right, BasicBlock* destination)
1091     {
1092         return addBranch(m_jit.branch32(cond, left, right), destination);
1093     }
1094     
1095     template<typename T, typename U>
1096     void branchTest32(JITCompiler::ResultCondition cond, T value, U mask, BasicBlock* destination)
1097     {
1098         return addBranch(m_jit.branchTest32(cond, value, mask), destination);
1099     }
1100     
1101     template<typename T>
1102     void branchTest32(JITCompiler::ResultCondition cond, T value, BasicBlock* destination)
1103     {
1104         return addBranch(m_jit.branchTest32(cond, value), destination);
1105     }
1106     
1107 #if USE(JSVALUE64)
1108     template<typename T, typename U>
1109     void branch64(JITCompiler::RelationalCondition cond, T left, U right, BasicBlock* destination)
1110     {
1111         return addBranch(m_jit.branch64(cond, left, right), destination);
1112     }
1113 #endif
1114     
1115     template<typename T, typename U>
1116     void branch8(JITCompiler::RelationalCondition cond, T left, U right, BasicBlock* destination)
1117     {
1118         return addBranch(m_jit.branch8(cond, left, right), destination);
1119     }
1120     
1121     template<typename T, typename U>
1122     void branchPtr(JITCompiler::RelationalCondition cond, T left, U right, BasicBlock* destination)
1123     {
1124         return addBranch(m_jit.branchPtr(cond, left, right), destination);
1125     }
1126     
1127     template<typename T, typename U>
1128     void branchTestPtr(JITCompiler::ResultCondition cond, T value, U mask, BasicBlock* destination)
1129     {
1130         return addBranch(m_jit.branchTestPtr(cond, value, mask), destination);
1131     }
1132     
1133     template<typename T>
1134     void branchTestPtr(JITCompiler::ResultCondition cond, T value, BasicBlock* destination)
1135     {
1136         return addBranch(m_jit.branchTestPtr(cond, value), destination);
1137     }
1138     
1139     template<typename T, typename U>
1140     void branchTest8(JITCompiler::ResultCondition cond, T value, U mask, BasicBlock* destination)
1141     {
1142         return addBranch(m_jit.branchTest8(cond, value, mask), destination);
1143     }
1144     
1145     template<typename T>
1146     void branchTest8(JITCompiler::ResultCondition cond, T value, BasicBlock* destination)
1147     {
1148         return addBranch(m_jit.branchTest8(cond, value), destination);
1149     }
1150     
1151     enum FallThroughMode {
1152         AtFallThroughPoint,
1153         ForceJump
1154     };
1155     void jump(BasicBlock* destination, FallThroughMode fallThroughMode = AtFallThroughPoint)
1156     {
1157         if (destination == nextBlock()
1158             && fallThroughMode == AtFallThroughPoint)
1159             return;
1160         addBranch(m_jit.jump(), destination);
1161     }
1162     
1163     void addBranch(const MacroAssembler::Jump& jump, BasicBlock* destination)
1164     {
1165         m_branches.append(BranchRecord(jump, destination));
1166     }
1167     void addBranch(const MacroAssembler::JumpList& jump, BasicBlock* destination);
1168
1169     void linkBranches();
1170
1171     void dump(const char* label = 0);
1172
1173     bool betterUseStrictInt52(Node* node)
1174     {
1175         return !generationInfo(node).isInt52();
1176     }
1177     bool betterUseStrictInt52(Edge edge)
1178     {
1179         return betterUseStrictInt52(edge.node());
1180     }
1181     
1182     bool compare(Node*, MacroAssembler::RelationalCondition, MacroAssembler::DoubleCondition, S_JITOperation_EJJ);
1183     void compileCompareUnsigned(Node*, MacroAssembler::RelationalCondition);
1184     bool compilePeepHoleBranch(Node*, MacroAssembler::RelationalCondition, MacroAssembler::DoubleCondition, S_JITOperation_EJJ);
1185     void compilePeepHoleInt32Branch(Node*, Node* branchNode, JITCompiler::RelationalCondition);
1186     void compilePeepHoleInt52Branch(Node*, Node* branchNode, JITCompiler::RelationalCondition);
1187     void compilePeepHoleBooleanBranch(Node*, Node* branchNode, JITCompiler::RelationalCondition);
1188     void compilePeepHoleDoubleBranch(Node*, Node* branchNode, JITCompiler::DoubleCondition);
1189     void compilePeepHoleObjectEquality(Node*, Node* branchNode);
1190     void compilePeepHoleObjectStrictEquality(Edge objectChild, Edge otherChild, Node* branchNode);
1191     void compilePeepHoleObjectToObjectOrOtherEquality(Edge leftChild, Edge rightChild, Node* branchNode);
1192     void compileObjectEquality(Node*);
1193     void compileObjectStrictEquality(Edge objectChild, Edge otherChild);
1194     void compileObjectToObjectOrOtherEquality(Edge leftChild, Edge rightChild);
1195     void compileObjectOrOtherLogicalNot(Edge value);
1196     void compileLogicalNot(Node*);
1197     void compileLogicalNotStringOrOther(Node*);
1198     void compileStringEquality(
1199         Node*, GPRReg leftGPR, GPRReg rightGPR, GPRReg lengthGPR,
1200         GPRReg leftTempGPR, GPRReg rightTempGPR, GPRReg leftTemp2GPR,
1201         GPRReg rightTemp2GPR, JITCompiler::JumpList fastTrue,
1202         JITCompiler::JumpList fastSlow);
1203     void compileStringEquality(Node*);
1204     void compileStringIdentEquality(Node*);
1205     void compileStringToUntypedEquality(Node*, Edge stringEdge, Edge untypedEdge);
1206     void compileStringIdentToNotStringVarEquality(Node*, Edge stringEdge, Edge notStringVarEdge);
1207     void compileStringZeroLength(Node*);
1208     void compileMiscStrictEq(Node*);
1209
1210     void compileSymbolEquality(Node*);
1211     void compileBigIntEquality(Node*);
1212     void compilePeepHoleSymbolEquality(Node*, Node* branchNode);
1213     void compileSymbolUntypedEquality(Node*, Edge symbolEdge, Edge untypedEdge);
1214
1215     void emitObjectOrOtherBranch(Edge value, BasicBlock* taken, BasicBlock* notTaken);
1216     void emitStringBranch(Edge value, BasicBlock* taken, BasicBlock* notTaken);
1217     void emitStringOrOtherBranch(Edge value, BasicBlock* taken, BasicBlock* notTaken);
1218     void emitBranch(Node*);
1219     
1220     struct StringSwitchCase {
1221         StringSwitchCase() { }
1222         
1223         StringSwitchCase(StringImpl* string, BasicBlock* target)
1224             : string(string)
1225             , target(target)
1226         {
1227         }
1228         
1229         bool operator<(const StringSwitchCase& other) const
1230         {
1231             return stringLessThan(*string, *other.string);
1232         }
1233         
1234         StringImpl* string;
1235         BasicBlock* target;
1236     };
1237     
1238     void emitSwitchIntJump(SwitchData*, GPRReg value, GPRReg scratch, GPRReg scratch2);
1239     void emitSwitchImm(Node*, SwitchData*);
1240     void emitSwitchCharStringJump(SwitchData*, GPRReg value, GPRReg scratch, GPRReg scratch2);
1241     void emitSwitchChar(Node*, SwitchData*);
1242     void emitBinarySwitchStringRecurse(
1243         SwitchData*, const Vector<StringSwitchCase>&, unsigned numChecked,
1244         unsigned begin, unsigned end, GPRReg buffer, GPRReg length, GPRReg temp,
1245         unsigned alreadyCheckedLength, bool checkedExactLength);
1246     void emitSwitchStringOnString(SwitchData*, GPRReg string);
1247     void emitSwitchString(Node*, SwitchData*);
1248     void emitSwitch(Node*);
1249     
1250     void compileToStringOrCallStringConstructor(Node*);
1251     void compileNumberToStringWithRadix(Node*);
1252     void compileNumberToStringWithValidRadixConstant(Node*);
1253     void compileNumberToStringWithValidRadixConstant(Node*, int32_t radix);
1254     void compileNewStringObject(Node*);
1255     
1256     void compileNewTypedArrayWithSize(Node*);
1257     
1258     void compileInt32Compare(Node*, MacroAssembler::RelationalCondition);
1259     void compileInt52Compare(Node*, MacroAssembler::RelationalCondition);
1260     void compileBooleanCompare(Node*, MacroAssembler::RelationalCondition);
1261     void compileDoubleCompare(Node*, MacroAssembler::DoubleCondition);
1262     void compileStringCompare(Node*, MacroAssembler::RelationalCondition);
1263     void compileStringIdentCompare(Node*, MacroAssembler::RelationalCondition);
1264     
1265     bool compileStrictEq(Node*);
1266     
1267     void compileAllocatePropertyStorage(Node*);
1268     void compileReallocatePropertyStorage(Node*);
1269     void compileNukeStructureAndSetButterfly(Node*);
1270     void compileGetButterfly(Node*);
1271     void compileCallDOMGetter(Node*);
1272     void compileCallDOM(Node*);
1273     void compileCheckSubClass(Node*);
1274     void compileNormalizeMapKey(Node*);
1275     void compileGetMapBucketHead(Node*);
1276     void compileGetMapBucketNext(Node*);
1277     void compileSetAdd(Node*);
1278     void compileMapSet(Node*);
1279     void compileWeakMapGet(Node*);
1280     void compileWeakSetAdd(Node*);
1281     void compileWeakMapSet(Node*);
1282     void compileLoadKeyFromMapBucket(Node*);
1283     void compileLoadValueFromMapBucket(Node*);
1284     void compileExtractValueFromWeakMapGet(Node*);
1285     void compileGetPrototypeOf(Node*);
1286     void compileIdentity(Node*);
1287     
1288 #if USE(JSVALUE32_64)
1289     template<typename BaseOperandType, typename PropertyOperandType, typename ValueOperandType, typename TagType>
1290     void compileContiguousPutByVal(Node*, BaseOperandType&, PropertyOperandType&, ValueOperandType&, GPRReg valuePayloadReg, TagType valueTag);
1291 #endif
1292     void compileDoublePutByVal(Node*, SpeculateCellOperand& base, SpeculateStrictInt32Operand& property);
1293     bool putByValWillNeedExtraRegister(ArrayMode arrayMode)
1294     {
1295         return arrayMode.mayStoreToHole();
1296     }
1297     GPRReg temporaryRegisterForPutByVal(GPRTemporary&, ArrayMode);
1298     GPRReg temporaryRegisterForPutByVal(GPRTemporary& temporary, Node* node)
1299     {
1300         return temporaryRegisterForPutByVal(temporary, node->arrayMode());
1301     }
1302     
1303     void compileGetCharCodeAt(Node*);
1304     void compileGetByValOnString(Node*);
1305     void compileFromCharCode(Node*); 
1306
1307     void compileGetByValOnDirectArguments(Node*);
1308     void compileGetByValOnScopedArguments(Node*);
1309     
1310     void compileGetScope(Node*);
1311     void compileSkipScope(Node*);
1312     void compileGetGlobalObject(Node*);
1313     void compileGetGlobalThis(Node*);
1314
1315     void compileGetArrayLength(Node*);
1316
1317     void compileCheckTypeInfoFlags(Node*);
1318     void compileCheckStringIdent(Node*);
1319
1320     void compileParseInt(Node*);
1321     
1322     void compileValueRep(Node*);
1323     void compileDoubleRep(Node*);
1324     
1325     void compileValueToInt32(Node*);
1326     void compileUInt32ToNumber(Node*);
1327     void compileDoubleAsInt32(Node*);
1328
1329     template<typename SnippetGenerator, J_JITOperation_EJJ slowPathFunction>
1330     void emitUntypedBitOp(Node*);
1331     void compileBitwiseOp(Node*);
1332
1333     void emitUntypedRightShiftBitOp(Node*);
1334     void compileShiftOp(Node*);
1335
1336     template <typename Generator, typename RepatchingFunction, typename NonRepatchingFunction>
1337     void compileMathIC(Node*, JITBinaryMathIC<Generator>*, bool needsScratchGPRReg, bool needsScratchFPRReg, RepatchingFunction, NonRepatchingFunction);
1338     template <typename Generator, typename RepatchingFunction, typename NonRepatchingFunction>
1339     void compileMathIC(Node*, JITUnaryMathIC<Generator>*, bool needsScratchGPRReg, RepatchingFunction, NonRepatchingFunction);
1340
1341     void compileArithDoubleUnaryOp(Node*, double (*doubleFunction)(double), double (*operation)(ExecState*, EncodedJSValue));
1342     void compileValueAdd(Node*);
1343     void compileArithAdd(Node*);
1344     void compileMakeRope(Node*);
1345     void compileArithAbs(Node*);
1346     void compileArithClz32(Node*);
1347     void compileArithSub(Node*);
1348     void compileArithNegate(Node*);
1349     void compileArithMul(Node*);
1350     void compileArithDiv(Node*);
1351     void compileArithFRound(Node*);
1352     void compileArithMod(Node*);
1353     void compileArithPow(Node*);
1354     void compileArithRounding(Node*);
1355     void compileArithRandom(Node*);
1356     void compileArithUnary(Node*);
1357     void compileArithSqrt(Node*);
1358     void compileArithMinMax(Node*);
1359     void compileConstantStoragePointer(Node*);
1360     void compileGetIndexedPropertyStorage(Node*);
1361     JITCompiler::Jump jumpForTypedArrayOutOfBounds(Node*, GPRReg baseGPR, GPRReg indexGPR);
1362     JITCompiler::Jump jumpForTypedArrayIsNeuteredIfOutOfBounds(Node*, GPRReg baseGPR, JITCompiler::Jump outOfBounds);
1363     void emitTypedArrayBoundsCheck(Node*, GPRReg baseGPR, GPRReg indexGPR);
1364     void compileGetTypedArrayByteOffset(Node*);
1365     void compileGetByValOnIntTypedArray(Node*, TypedArrayType);
1366     void compilePutByValForIntTypedArray(GPRReg base, GPRReg property, Node*, TypedArrayType);
1367     void compileGetByValOnFloatTypedArray(Node*, TypedArrayType);
1368     void compilePutByValForFloatTypedArray(GPRReg base, GPRReg property, Node*, TypedArrayType);
1369     void compileGetByValForObjectWithString(Node*);
1370     void compileGetByValForObjectWithSymbol(Node*);
1371     void compilePutByValForCellWithString(Node*, Edge& child1, Edge& child2, Edge& child3);
1372     void compilePutByValForCellWithSymbol(Node*, Edge& child1, Edge& child2, Edge& child3);
1373     void compileGetByValWithThis(Node*);
1374     void compileGetByOffset(Node*);
1375     void compilePutByOffset(Node*);
1376     // If this returns false it means that we terminated speculative execution.
1377     bool getIntTypedArrayStoreOperand(
1378         GPRTemporary& value,
1379         GPRReg property,
1380 #if USE(JSVALUE32_64)
1381         GPRTemporary& propertyTag,
1382         GPRTemporary& valueTag,
1383 #endif
1384         Edge valueUse, JITCompiler::JumpList& slowPathCases, bool isClamped = false);
1385     void loadFromIntTypedArray(GPRReg storageReg, GPRReg propertyReg, GPRReg resultReg, TypedArrayType);
1386     void setIntTypedArrayLoadResult(Node*, GPRReg resultReg, TypedArrayType, bool canSpeculate = false);
1387     template <typename ClassType> void compileNewFunctionCommon(GPRReg, RegisteredStructure, GPRReg, GPRReg, GPRReg, MacroAssembler::JumpList&, size_t, FunctionExecutable*);
1388     void compileNewFunction(Node*);
1389     void compileSetFunctionName(Node*);
1390     void compileNewRegexp(Node*);
1391     void compileForwardVarargs(Node*);
1392     void compileLoadVarargs(Node*);
1393     void compileCreateActivation(Node*);
1394     void compileCreateDirectArguments(Node*);
1395     void compileGetFromArguments(Node*);
1396     void compilePutToArguments(Node*);
1397     void compileGetArgument(Node*);
1398     void compileCreateScopedArguments(Node*);
1399     void compileCreateClonedArguments(Node*);
1400     void compileCreateRest(Node*);
1401     void compileSpread(Node*);
1402     void compileNewArray(Node*);
1403     void compileNewArrayWithSpread(Node*);
1404     void compileGetRestLength(Node*);
1405     void compileArraySlice(Node*);
1406     void compileArrayIndexOf(Node*);
1407     void compileArrayPush(Node*);
1408     void compileNotifyWrite(Node*);
1409     void compileRegExpExec(Node*);
1410     void compileRegExpExecNonGlobalOrSticky(Node*);
1411     void compileRegExpMatchFast(Node*);
1412     void compileRegExpMatchFastGlobal(Node*);
1413     void compileRegExpTest(Node*);
1414     void compileStringReplace(Node*);
1415     void compileIsObject(Node*);
1416     void compileIsObjectOrNull(Node*);
1417     void compileIsFunction(Node*);
1418     void compileTypeOf(Node*);
1419     void compileCheckCell(Node*);
1420     void compileCheckNotEmpty(Node*);
1421     void compileCheckStructure(Node*);
1422     void emitStructureCheck(Node*, GPRReg cellGPR, GPRReg tempGPR);
1423     void compilePutAccessorById(Node*);
1424     void compilePutGetterSetterById(Node*);
1425     void compilePutAccessorByVal(Node*);
1426     void compileGetRegExpObjectLastIndex(Node*);
1427     void compileSetRegExpObjectLastIndex(Node*);
1428     void compileLazyJSConstant(Node*);
1429     void compileMaterializeNewObject(Node*);
1430     void compileRecordRegExpCachedResult(Node*);
1431     void compileToObjectOrCallObjectConstructor(Node*);
1432     void compileResolveScope(Node*);
1433     void compileResolveScopeForHoistingFuncDeclInEval(Node*);
1434     void compileGetGlobalVariable(Node*);
1435     void compilePutGlobalVariable(Node*);
1436     void compileGetDynamicVar(Node*);
1437     void compilePutDynamicVar(Node*);
1438     void compileGetClosureVar(Node*);
1439     void compilePutClosureVar(Node*);
1440     void compileCompareEqPtr(Node*);
1441     void compileDefineDataProperty(Node*);
1442     void compileDefineAccessorProperty(Node*);
1443     void compileStringSlice(Node*);
1444     void compileToLowerCase(Node*);
1445     void compileThrow(Node*);
1446     void compileThrowStaticError(Node*);
1447     void compileGetEnumerableLength(Node*);
1448     void compileHasGenericProperty(Node*);
1449     void compileToIndexString(Node*);
1450     void compilePutByIdFlush(Node*);
1451     void compilePutById(Node*);
1452     void compilePutByIdDirect(Node*);
1453     void compilePutByIdWithThis(Node*);
1454     void compileHasStructureProperty(Node*);
1455     void compileGetDirectPname(Node*);
1456     void compileGetPropertyEnumerator(Node*);
1457     void compileGetEnumeratorPname(Node*);
1458     void compileGetExecutable(Node*);
1459     void compileGetGetter(Node*);
1460     void compileGetSetter(Node*);
1461     void compileGetCallee(Node*);
1462     void compileSetCallee(Node*);
1463     void compileGetArgumentCountIncludingThis(Node*);
1464     void compileSetArgumentCountIncludingThis(Node*);
1465     void compileStrCat(Node*);
1466     void compileNewArrayBuffer(Node*);
1467     void compileNewArrayWithSize(Node*);
1468     void compileNewTypedArray(Node*);
1469     void compileToThis(Node*);
1470     void compileCreateThis(Node*);
1471     void compileNewObject(Node*);
1472     void compileToPrimitive(Node*);
1473     void compileLogShadowChickenPrologue(Node*);
1474     void compileLogShadowChickenTail(Node*);
1475     void compileHasIndexedProperty(Node*);
1476     void compileExtractCatchLocal(Node*);
1477     void compileProfileType(Node*);
1478
1479     void moveTrueTo(GPRReg);
1480     void moveFalseTo(GPRReg);
1481     void blessBoolean(GPRReg);
1482     
1483     // Allocator for a cell of a specific size.
1484     template <typename StructureType> // StructureType can be GPR or ImmPtr.
1485     void emitAllocateJSCell(
1486         GPRReg resultGPR, const JITAllocator& allocator, GPRReg allocatorGPR, StructureType structure,
1487         GPRReg scratchGPR, MacroAssembler::JumpList& slowPath)
1488     {
1489         m_jit.emitAllocateJSCell(resultGPR, allocator, allocatorGPR, structure, scratchGPR, slowPath);
1490     }
1491
1492     // Allocator for an object of a specific size.
1493     template <typename StructureType, typename StorageType> // StructureType and StorageType can be GPR or ImmPtr.
1494     void emitAllocateJSObject(
1495         GPRReg resultGPR, const JITAllocator& allocator, GPRReg allocatorGPR, StructureType structure,
1496         StorageType storage, GPRReg scratchGPR, MacroAssembler::JumpList& slowPath)
1497     {
1498         m_jit.emitAllocateJSObject(
1499             resultGPR, allocator, allocatorGPR, structure, storage, scratchGPR, slowPath);
1500     }
1501
1502     template <typename ClassType, typename StructureType, typename StorageType> // StructureType and StorageType can be GPR or ImmPtr.
1503     void emitAllocateJSObjectWithKnownSize(
1504         GPRReg resultGPR, StructureType structure, StorageType storage, GPRReg scratchGPR1,
1505         GPRReg scratchGPR2, MacroAssembler::JumpList& slowPath, size_t size)
1506     {
1507         m_jit.emitAllocateJSObjectWithKnownSize<ClassType>(*m_jit.vm(), resultGPR, structure, storage, scratchGPR1, scratchGPR2, slowPath, size);
1508     }
1509
1510     // Convenience allocator for a built-in object.
1511     template <typename ClassType, typename StructureType, typename StorageType> // StructureType and StorageType can be GPR or ImmPtr.
1512     void emitAllocateJSObject(GPRReg resultGPR, StructureType structure, StorageType storage,
1513         GPRReg scratchGPR1, GPRReg scratchGPR2, MacroAssembler::JumpList& slowPath)
1514     {
1515         m_jit.emitAllocateJSObject<ClassType>(*m_jit.vm(), resultGPR, structure, storage, scratchGPR1, scratchGPR2, slowPath);
1516     }
1517
1518     template <typename ClassType, typename StructureType> // StructureType and StorageType can be GPR or ImmPtr.
1519     void emitAllocateVariableSizedJSObject(GPRReg resultGPR, StructureType structure, GPRReg allocationSize, GPRReg scratchGPR1, GPRReg scratchGPR2, MacroAssembler::JumpList& slowPath)
1520     {
1521         m_jit.emitAllocateVariableSizedJSObject<ClassType>(*m_jit.vm(), resultGPR, structure, allocationSize, scratchGPR1, scratchGPR2, slowPath);
1522     }
1523
1524     template<typename ClassType>
1525     void emitAllocateDestructibleObject(GPRReg resultGPR, RegisteredStructure structure, 
1526         GPRReg scratchGPR1, GPRReg scratchGPR2, MacroAssembler::JumpList& slowPath)
1527     {
1528         m_jit.emitAllocateDestructibleObject<ClassType>(*m_jit.vm(), resultGPR, structure.get(), scratchGPR1, scratchGPR2, slowPath);
1529     }
1530
1531     void emitAllocateRawObject(GPRReg resultGPR, RegisteredStructure, GPRReg storageGPR, unsigned numElements, unsigned vectorLength);
1532     
1533     void emitGetLength(InlineCallFrame*, GPRReg lengthGPR, bool includeThis = false);
1534     void emitGetLength(CodeOrigin, GPRReg lengthGPR, bool includeThis = false);
1535     void emitGetCallee(CodeOrigin, GPRReg calleeGPR);
1536     void emitGetArgumentStart(CodeOrigin, GPRReg startGPR);
1537     void emitPopulateSliceIndex(Edge&, GPRReg length, GPRReg result);
1538     
1539     // Generate an OSR exit fuzz check. Returns Jump() if OSR exit fuzz is not enabled, or if
1540     // it's in training mode.
1541     MacroAssembler::Jump emitOSRExitFuzzCheck();
1542     
1543     // Add a speculation check.
1544     void speculationCheck(ExitKind, JSValueSource, Node*, MacroAssembler::Jump jumpToFail);
1545     void speculationCheck(ExitKind, JSValueSource, Node*, const MacroAssembler::JumpList& jumpsToFail);
1546
1547     // Add a speculation check without additional recovery, and with a promise to supply a jump later.
1548     OSRExitJumpPlaceholder speculationCheck(ExitKind, JSValueSource, Node*);
1549     OSRExitJumpPlaceholder speculationCheck(ExitKind, JSValueSource, Edge);
1550     void speculationCheck(ExitKind, JSValueSource, Edge, MacroAssembler::Jump jumpToFail);
1551     void speculationCheck(ExitKind, JSValueSource, Edge, const MacroAssembler::JumpList& jumpsToFail);
1552     // Add a speculation check with additional recovery.
1553     void speculationCheck(ExitKind, JSValueSource, Node*, MacroAssembler::Jump jumpToFail, const SpeculationRecovery&);
1554     void speculationCheck(ExitKind, JSValueSource, Edge, MacroAssembler::Jump jumpToFail, const SpeculationRecovery&);
1555     
1556     void emitInvalidationPoint(Node*);
1557     
1558     void unreachable(Node*);
1559     
1560     // Called when we statically determine that a speculation will fail.
1561     void terminateSpeculativeExecution(ExitKind, JSValueRegs, Node*);
1562     void terminateSpeculativeExecution(ExitKind, JSValueRegs, Edge);
1563     
1564     // Helpers for performing type checks on an edge stored in the given registers.
1565     bool needsTypeCheck(Edge edge, SpeculatedType typesPassedThrough) { return m_interpreter.needsTypeCheck(edge, typesPassedThrough); }
1566     void typeCheck(JSValueSource, Edge, SpeculatedType typesPassedThrough, MacroAssembler::Jump jumpToFail, ExitKind = BadType);
1567     
1568     void speculateCellTypeWithoutTypeFiltering(Edge, GPRReg cellGPR, JSType);
1569     void speculateCellType(Edge, GPRReg cellGPR, SpeculatedType, JSType);
1570     
1571     void speculateInt32(Edge);
1572 #if USE(JSVALUE64)
1573     void convertAnyInt(Edge, GPRReg resultGPR);
1574     void speculateAnyInt(Edge);
1575     void speculateInt32(Edge, JSValueRegs);
1576     void speculateDoubleRepAnyInt(Edge);
1577 #endif // USE(JSVALUE64)
1578     void speculateNumber(Edge);
1579     void speculateRealNumber(Edge);
1580     void speculateDoubleRepReal(Edge);
1581     void speculateBoolean(Edge);
1582     void speculateCell(Edge);
1583     void speculateCellOrOther(Edge);
1584     void speculateObject(Edge, GPRReg cell);
1585     void speculateObject(Edge);
1586     void speculateArray(Edge, GPRReg cell);
1587     void speculateArray(Edge);
1588     void speculateFunction(Edge, GPRReg cell);
1589     void speculateFunction(Edge);
1590     void speculateFinalObject(Edge, GPRReg cell);
1591     void speculateFinalObject(Edge);
1592     void speculateRegExpObject(Edge, GPRReg cell);
1593     void speculateRegExpObject(Edge);
1594     void speculateProxyObject(Edge, GPRReg cell);
1595     void speculateProxyObject(Edge);
1596     void speculateDerivedArray(Edge, GPRReg cell);
1597     void speculateDerivedArray(Edge);
1598     void speculateMapObject(Edge);
1599     void speculateMapObject(Edge, GPRReg cell);
1600     void speculateSetObject(Edge);
1601     void speculateSetObject(Edge, GPRReg cell);
1602     void speculateWeakMapObject(Edge);
1603     void speculateWeakMapObject(Edge, GPRReg cell);
1604     void speculateWeakSetObject(Edge);
1605     void speculateWeakSetObject(Edge, GPRReg cell);
1606     void speculateObjectOrOther(Edge);
1607     void speculateString(Edge edge, GPRReg cell);
1608     void speculateStringIdentAndLoadStorage(Edge edge, GPRReg string, GPRReg storage);
1609     void speculateStringIdent(Edge edge, GPRReg string);
1610     void speculateStringIdent(Edge);
1611     void speculateString(Edge);
1612     void speculateStringOrOther(Edge, JSValueRegs, GPRReg scratch);
1613     void speculateStringOrOther(Edge);
1614     void speculateNotStringVar(Edge);
1615     void speculateNotSymbol(Edge);
1616     template<typename StructureLocationType>
1617     void speculateStringObjectForStructure(Edge, StructureLocationType);
1618     void speculateStringObject(Edge, GPRReg);
1619     void speculateStringObject(Edge);
1620     void speculateStringOrStringObject(Edge);
1621     void speculateSymbol(Edge, GPRReg cell);
1622     void speculateSymbol(Edge);
1623     void speculateBigInt(Edge, GPRReg cell);
1624     void speculateBigInt(Edge);
1625     void speculateNotCell(Edge, JSValueRegs);
1626     void speculateNotCell(Edge);
1627     void speculateOther(Edge, JSValueRegs, GPRReg temp);
1628     void speculateOther(Edge, JSValueRegs);
1629     void speculateOther(Edge);
1630     void speculateMisc(Edge, JSValueRegs);
1631     void speculateMisc(Edge);
1632     void speculate(Node*, Edge);
1633     
1634     JITCompiler::JumpList jumpSlowForUnwantedArrayMode(GPRReg tempWithIndexingTypeReg, ArrayMode);
1635     void checkArray(Node*);
1636     void arrayify(Node*, GPRReg baseReg, GPRReg propertyReg);
1637     void arrayify(Node*);
1638     
1639     template<bool strict>
1640     GPRReg fillSpeculateInt32Internal(Edge, DataFormat& returnFormat);
1641     
1642     void cageTypedArrayStorage(GPRReg);
1643     
1644     // It is possible, during speculative generation, to reach a situation in which we
1645     // can statically determine a speculation will fail (for example, when two nodes
1646     // will make conflicting speculations about the same operand). In such cases this
1647     // flag is cleared, indicating no further code generation should take place.
1648     bool m_compileOkay;
1649     
1650     void recordSetLocal(
1651         VirtualRegister bytecodeReg, VirtualRegister machineReg, DataFormat format)
1652     {
1653         m_stream->appendAndLog(VariableEvent::setLocal(bytecodeReg, machineReg, format));
1654     }
1655     
1656     void recordSetLocal(DataFormat format)
1657     {
1658         VariableAccessData* variable = m_currentNode->variableAccessData();
1659         recordSetLocal(variable->local(), variable->machineLocal(), format);
1660     }
1661
1662     GenerationInfo& generationInfoFromVirtualRegister(VirtualRegister virtualRegister)
1663     {
1664         return m_generationInfo[virtualRegister.toLocal()];
1665     }
1666     
1667     GenerationInfo& generationInfo(Node* node)
1668     {
1669         return generationInfoFromVirtualRegister(node->virtualRegister());
1670     }
1671     
1672     GenerationInfo& generationInfo(Edge edge)
1673     {
1674         return generationInfo(edge.node());
1675     }
1676
1677     // The JIT, while also provides MacroAssembler functionality.
1678     JITCompiler& m_jit;
1679     Graph& m_graph;
1680
1681     // The current node being generated.
1682     BasicBlock* m_block;
1683     Node* m_currentNode;
1684     NodeType m_lastGeneratedNode;
1685     unsigned m_indexInBlock;
1686
1687     // Virtual and physical register maps.
1688     Vector<GenerationInfo, 32> m_generationInfo;
1689     RegisterBank<GPRInfo> m_gprs;
1690     RegisterBank<FPRInfo> m_fprs;
1691
1692     Vector<MacroAssembler::Label> m_osrEntryHeads;
1693     
1694     struct BranchRecord {
1695         BranchRecord(MacroAssembler::Jump jump, BasicBlock* destination)
1696             : jump(jump)
1697             , destination(destination)
1698         {
1699         }
1700
1701         MacroAssembler::Jump jump;
1702         BasicBlock* destination;
1703     };
1704     Vector<BranchRecord, 8> m_branches;
1705
1706     NodeOrigin m_origin;
1707     
1708     InPlaceAbstractState m_state;
1709     AbstractInterpreter<InPlaceAbstractState> m_interpreter;
1710     
1711     VariableEventStream* m_stream;
1712     MinifiedGraph* m_minifiedGraph;
1713     
1714     Vector<std::unique_ptr<SlowPathGenerator>, 8> m_slowPathGenerators;
1715     struct SlowPathLambda {
1716         std::function<void()> generator;
1717         Node* currentNode;
1718         unsigned streamIndex;
1719     };
1720     Vector<SlowPathLambda> m_slowPathLambdas;
1721     Vector<SilentRegisterSavePlan> m_plans;
1722     std::optional<unsigned> m_outOfLineStreamIndex;
1723 };
1724
1725
1726 // === Operand types ===
1727 //
1728 // These classes are used to lock the operands to a node into machine
1729 // registers. These classes implement of pattern of locking a value
1730 // into register at the point of construction only if it is already in
1731 // registers, and otherwise loading it lazily at the point it is first
1732 // used. We do so in order to attempt to avoid spilling one operand
1733 // in order to make space available for another.
1734
1735 class JSValueOperand {
1736 public:
1737     explicit JSValueOperand(SpeculativeJIT* jit, Edge edge, OperandSpeculationMode mode = AutomaticOperandSpeculation)
1738         : m_jit(jit)
1739         , m_edge(edge)
1740 #if USE(JSVALUE64)
1741         , m_gprOrInvalid(InvalidGPRReg)
1742 #elif USE(JSVALUE32_64)
1743         , m_isDouble(false)
1744 #endif
1745     {
1746         ASSERT(m_jit);
1747         if (!edge)
1748             return;
1749         ASSERT_UNUSED(mode, mode == ManualOperandSpeculation || edge.useKind() == UntypedUse);
1750 #if USE(JSVALUE64)
1751         if (jit->isFilled(node()))
1752             gpr();
1753 #elif USE(JSVALUE32_64)
1754         m_register.pair.tagGPR = InvalidGPRReg;
1755         m_register.pair.payloadGPR = InvalidGPRReg;
1756         if (jit->isFilled(node()))
1757             fill();
1758 #endif
1759     }
1760
1761     explicit JSValueOperand(JSValueOperand&& other)
1762         : m_jit(other.m_jit)
1763         , m_edge(other.m_edge)
1764     {
1765 #if USE(JSVALUE64)
1766         m_gprOrInvalid = other.m_gprOrInvalid;
1767 #elif USE(JSVALUE32_64)
1768         m_register.pair.tagGPR = InvalidGPRReg;
1769         m_register.pair.payloadGPR = InvalidGPRReg;
1770         m_isDouble = other.m_isDouble;
1771
1772         if (m_edge) {
1773             if (m_isDouble)
1774                 m_register.fpr = other.m_register.fpr;
1775             else
1776                 m_register.pair = other.m_register.pair;
1777         }
1778 #endif
1779         other.m_edge = Edge();
1780 #if USE(JSVALUE64)
1781         other.m_gprOrInvalid = InvalidGPRReg;
1782 #elif USE(JSVALUE32_64)
1783         other.m_isDouble = false;
1784 #endif
1785     }
1786
1787     ~JSValueOperand()
1788     {
1789         if (!m_edge)
1790             return;
1791 #if USE(JSVALUE64)
1792         ASSERT(m_gprOrInvalid != InvalidGPRReg);
1793         m_jit->unlock(m_gprOrInvalid);
1794 #elif USE(JSVALUE32_64)
1795         if (m_isDouble) {
1796             ASSERT(m_register.fpr != InvalidFPRReg);
1797             m_jit->unlock(m_register.fpr);
1798         } else {
1799             ASSERT(m_register.pair.tagGPR != InvalidGPRReg && m_register.pair.payloadGPR != InvalidGPRReg);
1800             m_jit->unlock(m_register.pair.tagGPR);
1801             m_jit->unlock(m_register.pair.payloadGPR);
1802         }
1803 #endif
1804     }
1805     
1806     Edge edge() const
1807     {
1808         return m_edge;
1809     }
1810
1811     Node* node() const
1812     {
1813         return edge().node();
1814     }
1815
1816 #if USE(JSVALUE64)
1817     GPRReg gpr()
1818     {
1819         if (m_gprOrInvalid == InvalidGPRReg)
1820             m_gprOrInvalid = m_jit->fillJSValue(m_edge);
1821         return m_gprOrInvalid;
1822     }
1823     JSValueRegs jsValueRegs()
1824     {
1825         return JSValueRegs(gpr());
1826     }
1827 #elif USE(JSVALUE32_64)
1828     bool isDouble() { return m_isDouble; }
1829
1830     void fill()
1831     {
1832         if (m_register.pair.tagGPR == InvalidGPRReg && m_register.pair.payloadGPR == InvalidGPRReg)
1833             m_isDouble = !m_jit->fillJSValue(m_edge, m_register.pair.tagGPR, m_register.pair.payloadGPR, m_register.fpr);
1834     }
1835
1836     GPRReg tagGPR()
1837     {
1838         fill();
1839         ASSERT(!m_isDouble);
1840         return m_register.pair.tagGPR;
1841     } 
1842
1843     GPRReg payloadGPR()
1844     {
1845         fill();
1846         ASSERT(!m_isDouble);
1847         return m_register.pair.payloadGPR;
1848     }
1849     
1850     JSValueRegs jsValueRegs()
1851     {
1852         return JSValueRegs(tagGPR(), payloadGPR());
1853     }
1854
1855     GPRReg gpr(WhichValueWord which)
1856     {
1857         return jsValueRegs().gpr(which);
1858     }
1859
1860     FPRReg fpr()
1861     {
1862         fill();
1863         ASSERT(m_isDouble);
1864         return m_register.fpr;
1865     }
1866 #endif
1867
1868     void use()
1869     {
1870         m_jit->use(node());
1871     }
1872
1873 private:
1874     SpeculativeJIT* m_jit;
1875     Edge m_edge;
1876 #if USE(JSVALUE64)
1877     GPRReg m_gprOrInvalid;
1878 #elif USE(JSVALUE32_64)
1879     union {
1880         struct {
1881             GPRReg tagGPR;
1882             GPRReg payloadGPR;
1883         } pair;
1884         FPRReg fpr;
1885     } m_register;
1886     bool m_isDouble;
1887 #endif
1888 };
1889
1890 class StorageOperand {
1891 public:
1892     explicit StorageOperand(SpeculativeJIT* jit, Edge edge)
1893         : m_jit(jit)
1894         , m_edge(edge)
1895         , m_gprOrInvalid(InvalidGPRReg)
1896     {
1897         ASSERT(m_jit);
1898         ASSERT(edge.useKind() == UntypedUse || edge.useKind() == KnownCellUse);
1899         if (jit->isFilled(node()))
1900             gpr();
1901     }
1902     
1903     ~StorageOperand()
1904     {
1905         ASSERT(m_gprOrInvalid != InvalidGPRReg);
1906         m_jit->unlock(m_gprOrInvalid);
1907     }
1908     
1909     Edge edge() const
1910     {
1911         return m_edge;
1912     }
1913     
1914     Node* node() const
1915     {
1916         return edge().node();
1917     }
1918     
1919     GPRReg gpr()
1920     {
1921         if (m_gprOrInvalid == InvalidGPRReg)
1922             m_gprOrInvalid = m_jit->fillStorage(edge());
1923         return m_gprOrInvalid;
1924     }
1925     
1926     void use()
1927     {
1928         m_jit->use(node());
1929     }
1930     
1931 private:
1932     SpeculativeJIT* m_jit;
1933     Edge m_edge;
1934     GPRReg m_gprOrInvalid;
1935 };
1936
1937
1938 // === Temporaries ===
1939 //
1940 // These classes are used to allocate temporary registers.
1941 // A mechanism is provided to attempt to reuse the registers
1942 // currently allocated to child nodes whose value is consumed
1943 // by, and not live after, this operation.
1944
1945 enum ReuseTag { Reuse };
1946
1947 class GPRTemporary {
1948 public:
1949     GPRTemporary();
1950     GPRTemporary(SpeculativeJIT*);
1951     GPRTemporary(SpeculativeJIT*, GPRReg specific);
1952     template<typename T>
1953     GPRTemporary(SpeculativeJIT* jit, ReuseTag, T& operand)
1954         : m_jit(jit)
1955         , m_gpr(InvalidGPRReg)
1956     {
1957         if (m_jit->canReuse(operand.node()))
1958             m_gpr = m_jit->reuse(operand.gpr());
1959         else
1960             m_gpr = m_jit->allocate();
1961     }
1962     template<typename T1, typename T2>
1963     GPRTemporary(SpeculativeJIT* jit, ReuseTag, T1& op1, T2& op2)
1964         : m_jit(jit)
1965         , m_gpr(InvalidGPRReg)
1966     {
1967         if (m_jit->canReuse(op1.node()))
1968             m_gpr = m_jit->reuse(op1.gpr());
1969         else if (m_jit->canReuse(op2.node()))
1970             m_gpr = m_jit->reuse(op2.gpr());
1971         else if (m_jit->canReuse(op1.node(), op2.node()) && op1.gpr() == op2.gpr())
1972             m_gpr = m_jit->reuse(op1.gpr());
1973         else
1974             m_gpr = m_jit->allocate();
1975     }
1976     GPRTemporary(SpeculativeJIT*, ReuseTag, JSValueOperand&, WhichValueWord);
1977
1978     GPRTemporary(GPRTemporary& other) = delete;
1979
1980     GPRTemporary(GPRTemporary&& other)
1981     {
1982         ASSERT(other.m_jit);
1983         ASSERT(other.m_gpr != InvalidGPRReg);
1984         m_jit = other.m_jit;
1985         m_gpr = other.m_gpr;
1986         other.m_jit = nullptr;
1987         other.m_gpr = InvalidGPRReg;
1988     }
1989
1990     GPRTemporary& operator=(GPRTemporary&& other)
1991     {
1992         ASSERT(!m_jit);
1993         ASSERT(m_gpr == InvalidGPRReg);
1994         std::swap(m_jit, other.m_jit);
1995         std::swap(m_gpr, other.m_gpr);
1996         return *this;
1997     }
1998
1999     void adopt(GPRTemporary&);
2000
2001     ~GPRTemporary()
2002     {
2003         if (m_jit && m_gpr != InvalidGPRReg)
2004             m_jit->unlock(gpr());
2005     }
2006
2007     GPRReg gpr()
2008     {
2009         return m_gpr;
2010     }
2011
2012 private:
2013     SpeculativeJIT* m_jit;
2014     GPRReg m_gpr;
2015 };
2016
2017 class JSValueRegsTemporary {
2018 public:
2019     JSValueRegsTemporary();
2020     JSValueRegsTemporary(SpeculativeJIT*);
2021     template<typename T>
2022     JSValueRegsTemporary(SpeculativeJIT*, ReuseTag, T& operand, WhichValueWord resultRegWord = PayloadWord);
2023     JSValueRegsTemporary(SpeculativeJIT*, ReuseTag, JSValueOperand&);
2024     ~JSValueRegsTemporary();
2025     
2026     JSValueRegs regs();
2027
2028 private:
2029 #if USE(JSVALUE64)
2030     GPRTemporary m_gpr;
2031 #else
2032     GPRTemporary m_payloadGPR;
2033     GPRTemporary m_tagGPR;
2034 #endif
2035 };
2036
2037 class FPRTemporary {
2038     WTF_MAKE_NONCOPYABLE(FPRTemporary);
2039 public:
2040     FPRTemporary(FPRTemporary&&);
2041     FPRTemporary(SpeculativeJIT*);
2042     FPRTemporary(SpeculativeJIT*, SpeculateDoubleOperand&);
2043     FPRTemporary(SpeculativeJIT*, SpeculateDoubleOperand&, SpeculateDoubleOperand&);
2044 #if USE(JSVALUE32_64)
2045     FPRTemporary(SpeculativeJIT*, JSValueOperand&);
2046 #endif
2047
2048     ~FPRTemporary()
2049     {
2050         if (LIKELY(m_jit))
2051             m_jit->unlock(fpr());
2052     }
2053
2054     FPRReg fpr() const
2055     {
2056         ASSERT(m_jit);
2057         ASSERT(m_fpr != InvalidFPRReg);
2058         return m_fpr;
2059     }
2060
2061 protected:
2062     FPRTemporary(SpeculativeJIT* jit, FPRReg lockedFPR)
2063         : m_jit(jit)
2064         , m_fpr(lockedFPR)
2065     {
2066     }
2067
2068 private:
2069     SpeculativeJIT* m_jit;
2070     FPRReg m_fpr;
2071 };
2072
2073
2074 // === Results ===
2075 //
2076 // These classes lock the result of a call to a C++ helper function.
2077
2078 class GPRFlushedCallResult : public GPRTemporary {
2079 public:
2080     GPRFlushedCallResult(SpeculativeJIT* jit)
2081         : GPRTemporary(jit, GPRInfo::returnValueGPR)
2082     {
2083     }
2084 };
2085
2086 #if USE(JSVALUE32_64)
2087 class GPRFlushedCallResult2 : public GPRTemporary {
2088 public:
2089     GPRFlushedCallResult2(SpeculativeJIT* jit)
2090         : GPRTemporary(jit, GPRInfo::returnValueGPR2)
2091     {
2092     }
2093 };
2094 #endif
2095
2096 class FPRResult : public FPRTemporary {
2097 public:
2098     FPRResult(SpeculativeJIT* jit)
2099         : FPRTemporary(jit, lockedResult(jit))
2100     {
2101     }
2102
2103 private:
2104     static FPRReg lockedResult(SpeculativeJIT* jit)
2105     {
2106         jit->lock(FPRInfo::returnValueFPR);
2107         return FPRInfo::returnValueFPR;
2108     }
2109 };
2110
2111 class JSValueRegsFlushedCallResult {
2112 public:
2113     JSValueRegsFlushedCallResult(SpeculativeJIT* jit)
2114 #if USE(JSVALUE64)
2115         : m_gpr(jit)
2116 #else
2117         : m_payloadGPR(jit)
2118         , m_tagGPR(jit)
2119 #endif
2120     {
2121     }
2122
2123     JSValueRegs regs()
2124     {
2125 #if USE(JSVALUE64)
2126         return JSValueRegs { m_gpr.gpr() };
2127 #else
2128         return JSValueRegs { m_tagGPR.gpr(), m_payloadGPR.gpr() };
2129 #endif
2130     }
2131
2132 private:
2133 #if USE(JSVALUE64)
2134     GPRFlushedCallResult m_gpr;
2135 #else
2136     GPRFlushedCallResult m_payloadGPR;
2137     GPRFlushedCallResult2 m_tagGPR;
2138 #endif
2139 };
2140
2141
2142 // === Speculative Operand types ===
2143 //
2144 // SpeculateInt32Operand, SpeculateStrictInt32Operand and SpeculateCellOperand.
2145 //
2146 // These are used to lock the operands to a node into machine registers within the
2147 // SpeculativeJIT. The classes operate like those above, however these will
2148 // perform a speculative check for a more restrictive type than we can statically
2149 // determine the operand to have. If the operand does not have the requested type,
2150 // a bail-out to the non-speculative path will be taken.
2151
2152 class SpeculateInt32Operand {
2153 public:
2154     explicit SpeculateInt32Operand(SpeculativeJIT* jit, Edge edge, OperandSpeculationMode mode = AutomaticOperandSpeculation)
2155         : m_jit(jit)
2156         , m_edge(edge)
2157         , m_gprOrInvalid(InvalidGPRReg)
2158 #ifndef NDEBUG
2159         , m_format(DataFormatNone)
2160 #endif
2161     {
2162         ASSERT(m_jit);
2163         ASSERT_UNUSED(mode, mode == ManualOperandSpeculation || (edge.useKind() == Int32Use || edge.useKind() == KnownInt32Use));
2164         if (jit->isFilled(node()))
2165             gpr();
2166     }
2167
2168     ~SpeculateInt32Operand()
2169     {
2170         ASSERT(m_gprOrInvalid != InvalidGPRReg);
2171         m_jit->unlock(m_gprOrInvalid);
2172     }
2173     
2174     Edge edge() const
2175     {
2176         return m_edge;
2177     }
2178
2179     Node* node() const
2180     {
2181         return edge().node();
2182     }
2183
2184     DataFormat format()
2185     {
2186         gpr(); // m_format is set when m_gpr is locked.
2187         ASSERT(m_format == DataFormatInt32 || m_format == DataFormatJSInt32);
2188         return m_format;
2189     }
2190
2191     GPRReg gpr()
2192     {
2193         if (m_gprOrInvalid == InvalidGPRReg)
2194             m_gprOrInvalid = m_jit->fillSpeculateInt32(edge(), m_format);
2195         return m_gprOrInvalid;
2196     }
2197     
2198     void use()
2199     {
2200         m_jit->use(node());
2201     }
2202
2203 private:
2204     SpeculativeJIT* m_jit;
2205     Edge m_edge;
2206     GPRReg m_gprOrInvalid;
2207     DataFormat m_format;
2208 };
2209
2210 class SpeculateStrictInt32Operand {
2211 public:
2212     explicit SpeculateStrictInt32Operand(SpeculativeJIT* jit, Edge edge, OperandSpeculationMode mode = AutomaticOperandSpeculation)
2213         : m_jit(jit)
2214         , m_edge(edge)
2215         , m_gprOrInvalid(InvalidGPRReg)
2216     {
2217         ASSERT(m_jit);
2218         ASSERT_UNUSED(mode, mode == ManualOperandSpeculation || (edge.useKind() == Int32Use || edge.useKind() == KnownInt32Use));
2219         if (jit->isFilled(node()))
2220             gpr();
2221     }
2222
2223     ~SpeculateStrictInt32Operand()
2224     {
2225         ASSERT(m_gprOrInvalid != InvalidGPRReg);
2226         m_jit->unlock(m_gprOrInvalid);
2227     }
2228     
2229     Edge edge() const
2230     {
2231         return m_edge;
2232     }
2233
2234     Node* node() const
2235     {
2236         return edge().node();
2237     }
2238
2239     GPRReg gpr()
2240     {
2241         if (m_gprOrInvalid == InvalidGPRReg)
2242             m_gprOrInvalid = m_jit->fillSpeculateInt32Strict(edge());
2243         return m_gprOrInvalid;
2244     }
2245     
2246     void use()
2247     {
2248         m_jit->use(node());
2249     }
2250
2251 private:
2252     SpeculativeJIT* m_jit;
2253     Edge m_edge;
2254     GPRReg m_gprOrInvalid;
2255 };
2256
2257 // Gives you a canonical Int52 (i.e. it's left-shifted by 16, low bits zero).
2258 class SpeculateInt52Operand {
2259 public:
2260     explicit SpeculateInt52Operand(SpeculativeJIT* jit, Edge edge)
2261         : m_jit(jit)
2262         , m_edge(edge)
2263         , m_gprOrInvalid(InvalidGPRReg)
2264     {
2265         RELEASE_ASSERT(edge.useKind() == Int52RepUse);
2266         if (jit->isFilled(node()))
2267             gpr();
2268     }
2269     
2270     ~SpeculateInt52Operand()
2271     {
2272         ASSERT(m_gprOrInvalid != InvalidGPRReg);
2273         m_jit->unlock(m_gprOrInvalid);
2274     }
2275     
2276     Edge edge() const
2277     {
2278         return m_edge;
2279     }
2280     
2281     Node* node() const
2282     {
2283         return edge().node();
2284     }
2285     
2286     GPRReg gpr()
2287     {
2288         if (m_gprOrInvalid == InvalidGPRReg)
2289             m_gprOrInvalid = m_jit->fillSpeculateInt52(edge(), DataFormatInt52);
2290         return m_gprOrInvalid;
2291     }
2292     
2293     void use()
2294     {
2295         m_jit->use(node());
2296     }
2297     
2298 private:
2299     SpeculativeJIT* m_jit;
2300     Edge m_edge;
2301     GPRReg m_gprOrInvalid;
2302 };
2303
2304 // Gives you a strict Int52 (i.e. the payload is in the low 48 bits, high 16 bits are sign-extended).
2305 class SpeculateStrictInt52Operand {
2306 public:
2307     explicit SpeculateStrictInt52Operand(SpeculativeJIT* jit, Edge edge)
2308         : m_jit(jit)
2309         , m_edge(edge)
2310         , m_gprOrInvalid(InvalidGPRReg)
2311     {
2312         RELEASE_ASSERT(edge.useKind() == Int52RepUse);
2313         if (jit->isFilled(node()))
2314             gpr();
2315     }
2316     
2317     ~SpeculateStrictInt52Operand()
2318     {
2319         ASSERT(m_gprOrInvalid != InvalidGPRReg);
2320         m_jit->unlock(m_gprOrInvalid);
2321     }
2322     
2323     Edge edge() const
2324     {
2325         return m_edge;
2326     }
2327     
2328     Node* node() const
2329     {
2330         return edge().node();
2331     }
2332     
2333     GPRReg gpr()
2334     {
2335         if (m_gprOrInvalid == InvalidGPRReg)
2336             m_gprOrInvalid = m_jit->fillSpeculateInt52(edge(), DataFormatStrictInt52);
2337         return m_gprOrInvalid;
2338     }
2339     
2340     void use()
2341     {
2342         m_jit->use(node());
2343     }
2344     
2345 private:
2346     SpeculativeJIT* m_jit;
2347     Edge m_edge;
2348     GPRReg m_gprOrInvalid;
2349 };
2350
2351 enum OppositeShiftTag { OppositeShift };
2352
2353 class SpeculateWhicheverInt52Operand {
2354 public:
2355     explicit SpeculateWhicheverInt52Operand(SpeculativeJIT* jit, Edge edge)
2356         : m_jit(jit)
2357         , m_edge(edge)
2358         , m_gprOrInvalid(InvalidGPRReg)
2359         , m_strict(jit->betterUseStrictInt52(edge))
2360     {
2361         RELEASE_ASSERT(edge.useKind() == Int52RepUse);
2362         if (jit->isFilled(node()))
2363             gpr();
2364     }
2365     
2366     explicit SpeculateWhicheverInt52Operand(SpeculativeJIT* jit, Edge edge, const SpeculateWhicheverInt52Operand& other)
2367         : m_jit(jit)
2368         , m_edge(edge)
2369         , m_gprOrInvalid(InvalidGPRReg)
2370         , m_strict(other.m_strict)
2371     {
2372         RELEASE_ASSERT(edge.useKind() == Int52RepUse);
2373         if (jit->isFilled(node()))
2374             gpr();
2375     }
2376     
2377     explicit SpeculateWhicheverInt52Operand(SpeculativeJIT* jit, Edge edge, OppositeShiftTag, const SpeculateWhicheverInt52Operand& other)
2378         : m_jit(jit)
2379         , m_edge(edge)
2380         , m_gprOrInvalid(InvalidGPRReg)
2381         , m_strict(!other.m_strict)
2382     {
2383         RELEASE_ASSERT(edge.useKind() == Int52RepUse);
2384         if (jit->isFilled(node()))
2385             gpr();
2386     }
2387     
2388     ~SpeculateWhicheverInt52Operand()
2389     {
2390         ASSERT(m_gprOrInvalid != InvalidGPRReg);
2391         m_jit->unlock(m_gprOrInvalid);
2392     }
2393     
2394     Edge edge() const
2395     {
2396         return m_edge;
2397     }
2398     
2399     Node* node() const
2400     {
2401         return edge().node();
2402     }
2403     
2404     GPRReg gpr()
2405     {
2406         if (m_gprOrInvalid == InvalidGPRReg) {
2407             m_gprOrInvalid = m_jit->fillSpeculateInt52(
2408                 edge(), m_strict ? DataFormatStrictInt52 : DataFormatInt52);
2409         }
2410         return m_gprOrInvalid;
2411     }
2412     
2413     void use()
2414     {
2415         m_jit->use(node());
2416     }
2417     
2418     DataFormat format() const
2419     {
2420         return m_strict ? DataFormatStrictInt52 : DataFormatInt52;
2421     }
2422
2423 private:
2424     SpeculativeJIT* m_jit;
2425     Edge m_edge;
2426     GPRReg m_gprOrInvalid;
2427     bool m_strict;
2428 };
2429
2430 class SpeculateDoubleOperand {
2431 public:
2432     explicit SpeculateDoubleOperand(SpeculativeJIT* jit, Edge edge)
2433         : m_jit(jit)
2434         , m_edge(edge)
2435         , m_fprOrInvalid(InvalidFPRReg)
2436     {
2437         ASSERT(m_jit);
2438         RELEASE_ASSERT(isDouble(edge.useKind()));
2439         if (jit->isFilled(node()))
2440             fpr();
2441     }
2442
2443     ~SpeculateDoubleOperand()
2444     {
2445         ASSERT(m_fprOrInvalid != InvalidFPRReg);
2446         m_jit->unlock(m_fprOrInvalid);
2447     }
2448     
2449     Edge edge() const
2450     {
2451         return m_edge;
2452     }
2453
2454     Node* node() const
2455     {
2456         return edge().node();
2457     }
2458
2459     FPRReg fpr()
2460     {
2461         if (m_fprOrInvalid == InvalidFPRReg)
2462             m_fprOrInvalid = m_jit->fillSpeculateDouble(edge());
2463         return m_fprOrInvalid;
2464     }
2465     
2466     void use()
2467     {
2468         m_jit->use(node());
2469     }
2470
2471 private:
2472     SpeculativeJIT* m_jit;
2473     Edge m_edge;
2474     FPRReg m_fprOrInvalid;
2475 };
2476
2477 class SpeculateCellOperand {
2478     WTF_MAKE_NONCOPYABLE(SpeculateCellOperand);
2479
2480 public:
2481     explicit SpeculateCellOperand(SpeculativeJIT* jit, Edge edge, OperandSpeculationMode mode = AutomaticOperandSpeculation)
2482         : m_jit(jit)
2483         , m_edge(edge)
2484         , m_gprOrInvalid(InvalidGPRReg)
2485     {
2486         ASSERT(m_jit);
2487         if (!edge)
2488             return;
2489         ASSERT_UNUSED(mode, mode == ManualOperandSpeculation || isCell(edge.useKind()));
2490         if (jit->isFilled(node()))
2491             gpr();
2492     }
2493
2494     explicit SpeculateCellOperand(SpeculateCellOperand&& other)
2495     {
2496         m_jit = other.m_jit;
2497         m_edge = other.m_edge;
2498         m_gprOrInvalid = other.m_gprOrInvalid;
2499
2500         other.m_gprOrInvalid = InvalidGPRReg;
2501         other.m_edge = Edge();
2502     }
2503
2504     ~SpeculateCellOperand()
2505     {
2506         if (!m_edge)
2507             return;
2508         ASSERT(m_gprOrInvalid != InvalidGPRReg);
2509         m_jit->unlock(m_gprOrInvalid);
2510     }
2511     
2512     Edge edge() const
2513     {
2514         return m_edge;
2515     }
2516
2517     Node* node() const
2518     {
2519         return edge().node();
2520     }
2521
2522     GPRReg gpr()
2523     {
2524         ASSERT(m_edge);
2525         if (m_gprOrInvalid == InvalidGPRReg)
2526             m_gprOrInvalid = m_jit->fillSpeculateCell(edge());
2527         return m_gprOrInvalid;
2528     }
2529     
2530     void use()
2531     {
2532         ASSERT(m_edge);
2533         m_jit->use(node());
2534     }
2535
2536 private:
2537     SpeculativeJIT* m_jit;
2538     Edge m_edge;
2539     GPRReg m_gprOrInvalid;
2540 };
2541
2542 class SpeculateBooleanOperand {
2543 public:
2544     explicit SpeculateBooleanOperand(SpeculativeJIT* jit, Edge edge, OperandSpeculationMode mode = AutomaticOperandSpeculation)
2545         : m_jit(jit)
2546         , m_edge(edge)
2547         , m_gprOrInvalid(InvalidGPRReg)
2548     {
2549         ASSERT(m_jit);
2550         ASSERT_UNUSED(mode, mode == ManualOperandSpeculation || edge.useKind() == BooleanUse || edge.useKind() == KnownBooleanUse);
2551         if (jit->isFilled(node()))
2552             gpr();
2553     }
2554     
2555     ~SpeculateBooleanOperand()
2556     {
2557         ASSERT(m_gprOrInvalid != InvalidGPRReg);
2558         m_jit->unlock(m_gprOrInvalid);
2559     }
2560     
2561     Edge edge() const
2562     {
2563         return m_edge;
2564     }
2565     
2566     Node* node() const
2567     {
2568         return edge().node();
2569     }
2570     
2571     GPRReg gpr()
2572     {
2573         if (m_gprOrInvalid == InvalidGPRReg)
2574             m_gprOrInvalid = m_jit->fillSpeculateBoolean(edge());
2575         return m_gprOrInvalid;
2576     }
2577     
2578     void use()
2579     {
2580         m_jit->use(node());
2581     }
2582
2583 private:
2584     SpeculativeJIT* m_jit;
2585     Edge m_edge;
2586     GPRReg m_gprOrInvalid;
2587 };
2588
2589 template<typename StructureLocationType>
2590 void SpeculativeJIT::speculateStringObjectForStructure(Edge edge, StructureLocationType structureLocation)
2591 {
2592     RegisteredStructure stringObjectStructure =
2593         m_jit.graph().registerStructure(m_jit.globalObjectFor(m_currentNode->origin.semantic)->stringObjectStructure());
2594     
2595     if (!m_state.forNode(edge).m_structure.isSubsetOf(RegisteredStructureSet(stringObjectStructure))) {
2596         speculationCheck(
2597             NotStringObject, JSValueRegs(), 0,
2598             m_jit.branchWeakStructure(
2599                 JITCompiler::NotEqual, structureLocation, stringObjectStructure));
2600     }
2601 }
2602
2603 #define DFG_TYPE_CHECK_WITH_EXIT_KIND(exitKind, source, edge, typesPassedThrough, jumpToFail) do { \
2604         JSValueSource _dtc_source = (source);                           \
2605         Edge _dtc_edge = (edge);                                        \
2606         SpeculatedType _dtc_typesPassedThrough = typesPassedThrough;    \
2607         if (!needsTypeCheck(_dtc_edge, _dtc_typesPassedThrough))        \
2608             break;                                                      \
2609         typeCheck(_dtc_source, _dtc_edge, _dtc_typesPassedThrough, (jumpToFail), exitKind); \
2610     } while (0)
2611
2612 #define DFG_TYPE_CHECK(source, edge, typesPassedThrough, jumpToFail) \
2613     DFG_TYPE_CHECK_WITH_EXIT_KIND(BadType, source, edge, typesPassedThrough, jumpToFail)
2614
2615 } } // namespace JSC::DFG
2616
2617 #endif