[ES6] Implement tail calls in the LLInt and Baseline JIT
[WebKit-https.git] / Source / JavaScriptCore / assembler / AbstractMacroAssembler.h
1 /*
2  * Copyright (C) 2008, 2012, 2014, 2015 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 #ifndef AbstractMacroAssembler_h
27 #define AbstractMacroAssembler_h
28
29 #include "AbortReason.h"
30 #include "AssemblerBuffer.h"
31 #include "CodeLocation.h"
32 #include "MacroAssemblerCodeRef.h"
33 #include "Options.h"
34 #include "WeakRandom.h"
35 #include <wtf/CryptographicallyRandomNumber.h>
36 #include <wtf/Noncopyable.h>
37
38 #if ENABLE(ASSEMBLER)
39
40 namespace JSC {
41
42 inline bool isARMv7IDIVSupported()
43 {
44 #if HAVE(ARM_IDIV_INSTRUCTIONS)
45     return true;
46 #else
47     return false;
48 #endif
49 }
50
51 inline bool isARM64()
52 {
53 #if CPU(ARM64)
54     return true;
55 #else
56     return false;
57 #endif
58 }
59
60 inline bool isX86()
61 {
62 #if CPU(X86_64) || CPU(X86)
63     return true;
64 #else
65     return false;
66 #endif
67 }
68
69 inline bool optimizeForARMv7IDIVSupported()
70 {
71     return isARMv7IDIVSupported() && Options::enableArchitectureSpecificOptimizations();
72 }
73
74 inline bool optimizeForARM64()
75 {
76     return isARM64() && Options::enableArchitectureSpecificOptimizations();
77 }
78
79 inline bool optimizeForX86()
80 {
81     return isX86() && Options::enableArchitectureSpecificOptimizations();
82 }
83
84 class LinkBuffer;
85 class RepatchBuffer;
86 class Watchpoint;
87 namespace DFG {
88 struct OSRExit;
89 }
90
91 template <class AssemblerType, class MacroAssemblerType>
92 class AbstractMacroAssembler {
93 public:
94     friend class JITWriteBarrierBase;
95     typedef AbstractMacroAssembler<AssemblerType, MacroAssemblerType> AbstractMacroAssemblerType;
96     typedef AssemblerType AssemblerType_T;
97
98     typedef MacroAssemblerCodePtr CodePtr;
99     typedef MacroAssemblerCodeRef CodeRef;
100
101     class Jump;
102
103     typedef typename AssemblerType::RegisterID RegisterID;
104     typedef typename AssemblerType::FPRegisterID FPRegisterID;
105     
106     static constexpr RegisterID firstRegister() { return AssemblerType::firstRegister(); }
107     static constexpr RegisterID lastRegister() { return AssemblerType::lastRegister(); }
108
109     static constexpr FPRegisterID firstFPRegister() { return AssemblerType::firstFPRegister(); }
110     static constexpr FPRegisterID lastFPRegister() { return AssemblerType::lastFPRegister(); }
111
112     // Section 1: MacroAssembler operand types
113     //
114     // The following types are used as operands to MacroAssembler operations,
115     // describing immediate  and memory operands to the instructions to be planted.
116
117     enum Scale {
118         TimesOne,
119         TimesTwo,
120         TimesFour,
121         TimesEight,
122     };
123     
124     static Scale timesPtr()
125     {
126         if (sizeof(void*) == 4)
127             return TimesFour;
128         return TimesEight;
129     }
130
131     // Address:
132     //
133     // Describes a simple base-offset address.
134     struct Address {
135         explicit Address(RegisterID base, int32_t offset = 0)
136             : base(base)
137             , offset(offset)
138         {
139         }
140         
141         Address withOffset(int32_t additionalOffset)
142         {
143             return Address(base, offset + additionalOffset);
144         }
145         
146         RegisterID base;
147         int32_t offset;
148     };
149
150     struct ExtendedAddress {
151         explicit ExtendedAddress(RegisterID base, intptr_t offset = 0)
152             : base(base)
153             , offset(offset)
154         {
155         }
156         
157         RegisterID base;
158         intptr_t offset;
159     };
160
161     // ImplicitAddress:
162     //
163     // This class is used for explicit 'load' and 'store' operations
164     // (as opposed to situations in which a memory operand is provided
165     // to a generic operation, such as an integer arithmetic instruction).
166     //
167     // In the case of a load (or store) operation we want to permit
168     // addresses to be implicitly constructed, e.g. the two calls:
169     //
170     //     load32(Address(addrReg), destReg);
171     //     load32(addrReg, destReg);
172     //
173     // Are equivalent, and the explicit wrapping of the Address in the former
174     // is unnecessary.
175     struct ImplicitAddress {
176         ImplicitAddress(RegisterID base)
177             : base(base)
178             , offset(0)
179         {
180         }
181
182         ImplicitAddress(Address address)
183             : base(address.base)
184             , offset(address.offset)
185         {
186         }
187
188         RegisterID base;
189         int32_t offset;
190     };
191
192     // BaseIndex:
193     //
194     // Describes a complex addressing mode.
195     struct BaseIndex {
196         BaseIndex(RegisterID base, RegisterID index, Scale scale, int32_t offset = 0)
197             : base(base)
198             , index(index)
199             , scale(scale)
200             , offset(offset)
201         {
202         }
203
204         RegisterID base;
205         RegisterID index;
206         Scale scale;
207         int32_t offset;
208         
209         BaseIndex withOffset(int32_t additionalOffset)
210         {
211             return BaseIndex(base, index, scale, offset + additionalOffset);
212         }
213     };
214
215     // AbsoluteAddress:
216     //
217     // Describes an memory operand given by a pointer.  For regular load & store
218     // operations an unwrapped void* will be used, rather than using this.
219     struct AbsoluteAddress {
220         explicit AbsoluteAddress(const void* ptr)
221             : m_ptr(ptr)
222         {
223         }
224
225         const void* m_ptr;
226     };
227
228     // TrustedImmPtr:
229     //
230     // A pointer sized immediate operand to an instruction - this is wrapped
231     // in a class requiring explicit construction in order to differentiate
232     // from pointers used as absolute addresses to memory operations
233     struct TrustedImmPtr {
234         TrustedImmPtr() { }
235         
236         explicit TrustedImmPtr(const void* value)
237             : m_value(value)
238         {
239         }
240         
241         // This is only here so that TrustedImmPtr(0) does not confuse the C++
242         // overload handling rules.
243         explicit TrustedImmPtr(int value)
244             : m_value(0)
245         {
246             ASSERT_UNUSED(value, !value);
247         }
248
249         explicit TrustedImmPtr(size_t value)
250             : m_value(reinterpret_cast<void*>(value))
251         {
252         }
253
254         intptr_t asIntptr()
255         {
256             return reinterpret_cast<intptr_t>(m_value);
257         }
258
259         const void* m_value;
260     };
261
262     struct ImmPtr : private TrustedImmPtr
263     {
264         explicit ImmPtr(const void* value)
265             : TrustedImmPtr(value)
266         {
267         }
268
269         TrustedImmPtr asTrustedImmPtr() { return *this; }
270     };
271
272     // TrustedImm32:
273     //
274     // A 32bit immediate operand to an instruction - this is wrapped in a
275     // class requiring explicit construction in order to prevent RegisterIDs
276     // (which are implemented as an enum) from accidentally being passed as
277     // immediate values.
278     struct TrustedImm32 {
279         TrustedImm32() { }
280         
281         explicit TrustedImm32(int32_t value)
282             : m_value(value)
283         {
284         }
285
286 #if !CPU(X86_64)
287         explicit TrustedImm32(TrustedImmPtr ptr)
288             : m_value(ptr.asIntptr())
289         {
290         }
291 #endif
292
293         int32_t m_value;
294     };
295
296
297     struct Imm32 : private TrustedImm32 {
298         explicit Imm32(int32_t value)
299             : TrustedImm32(value)
300         {
301         }
302 #if !CPU(X86_64)
303         explicit Imm32(TrustedImmPtr ptr)
304             : TrustedImm32(ptr)
305         {
306         }
307 #endif
308         const TrustedImm32& asTrustedImm32() const { return *this; }
309
310     };
311     
312     // TrustedImm64:
313     //
314     // A 64bit immediate operand to an instruction - this is wrapped in a
315     // class requiring explicit construction in order to prevent RegisterIDs
316     // (which are implemented as an enum) from accidentally being passed as
317     // immediate values.
318     struct TrustedImm64 {
319         TrustedImm64() { }
320         
321         explicit TrustedImm64(int64_t value)
322             : m_value(value)
323         {
324         }
325
326 #if CPU(X86_64) || CPU(ARM64)
327         explicit TrustedImm64(TrustedImmPtr ptr)
328             : m_value(ptr.asIntptr())
329         {
330         }
331 #endif
332
333         int64_t m_value;
334     };
335
336     struct Imm64 : private TrustedImm64
337     {
338         explicit Imm64(int64_t value)
339             : TrustedImm64(value)
340         {
341         }
342 #if CPU(X86_64) || CPU(ARM64)
343         explicit Imm64(TrustedImmPtr ptr)
344             : TrustedImm64(ptr)
345         {
346         }
347 #endif
348         const TrustedImm64& asTrustedImm64() const { return *this; }
349     };
350     
351     // Section 2: MacroAssembler code buffer handles
352     //
353     // The following types are used to reference items in the code buffer
354     // during JIT code generation.  For example, the type Jump is used to
355     // track the location of a jump instruction so that it may later be
356     // linked to a label marking its destination.
357
358
359     // Label:
360     //
361     // A Label records a point in the generated instruction stream, typically such that
362     // it may be used as a destination for a jump.
363     class Label {
364         template<class TemplateAssemblerType, class TemplateMacroAssemblerType>
365         friend class AbstractMacroAssembler;
366         friend struct DFG::OSRExit;
367         friend class Jump;
368         friend class MacroAssemblerCodeRef;
369         friend class LinkBuffer;
370         friend class Watchpoint;
371
372     public:
373         Label()
374         {
375         }
376
377         Label(AbstractMacroAssemblerType* masm)
378             : m_label(masm->m_assembler.label())
379         {
380             masm->invalidateAllTempRegisters();
381         }
382
383         bool isSet() const { return m_label.isSet(); }
384     private:
385         AssemblerLabel m_label;
386     };
387     
388     // ConvertibleLoadLabel:
389     //
390     // A ConvertibleLoadLabel records a loadPtr instruction that can be patched to an addPtr
391     // so that:
392     //
393     // loadPtr(Address(a, i), b)
394     //
395     // becomes:
396     //
397     // addPtr(TrustedImmPtr(i), a, b)
398     class ConvertibleLoadLabel {
399         template<class TemplateAssemblerType, class TemplateMacroAssemblerType>
400         friend class AbstractMacroAssembler;
401         friend class LinkBuffer;
402         
403     public:
404         ConvertibleLoadLabel()
405         {
406         }
407         
408         ConvertibleLoadLabel(AbstractMacroAssemblerType* masm)
409             : m_label(masm->m_assembler.labelIgnoringWatchpoints())
410         {
411         }
412         
413         bool isSet() const { return m_label.isSet(); }
414     private:
415         AssemblerLabel m_label;
416     };
417
418     // DataLabelPtr:
419     //
420     // A DataLabelPtr is used to refer to a location in the code containing a pointer to be
421     // patched after the code has been generated.
422     class DataLabelPtr {
423         template<class TemplateAssemblerType, class TemplateMacroAssemblerType>
424         friend class AbstractMacroAssembler;
425         friend class LinkBuffer;
426     public:
427         DataLabelPtr()
428         {
429         }
430
431         DataLabelPtr(AbstractMacroAssemblerType* masm)
432             : m_label(masm->m_assembler.label())
433         {
434         }
435
436         bool isSet() const { return m_label.isSet(); }
437         
438     private:
439         AssemblerLabel m_label;
440     };
441
442     // DataLabel32:
443     //
444     // A DataLabel32 is used to refer to a location in the code containing a 32-bit constant to be
445     // patched after the code has been generated.
446     class DataLabel32 {
447         template<class TemplateAssemblerType, class TemplateMacroAssemblerType>
448         friend class AbstractMacroAssembler;
449         friend class LinkBuffer;
450     public:
451         DataLabel32()
452         {
453         }
454
455         DataLabel32(AbstractMacroAssemblerType* masm)
456             : m_label(masm->m_assembler.label())
457         {
458         }
459
460         AssemblerLabel label() const { return m_label; }
461
462     private:
463         AssemblerLabel m_label;
464     };
465
466     // DataLabelCompact:
467     //
468     // A DataLabelCompact is used to refer to a location in the code containing a
469     // compact immediate to be patched after the code has been generated.
470     class DataLabelCompact {
471         template<class TemplateAssemblerType, class TemplateMacroAssemblerType>
472         friend class AbstractMacroAssembler;
473         friend class LinkBuffer;
474     public:
475         DataLabelCompact()
476         {
477         }
478         
479         DataLabelCompact(AbstractMacroAssemblerType* masm)
480             : m_label(masm->m_assembler.label())
481         {
482         }
483
484         DataLabelCompact(AssemblerLabel label)
485             : m_label(label)
486         {
487         }
488
489         AssemblerLabel label() const { return m_label; }
490
491     private:
492         AssemblerLabel m_label;
493     };
494
495     // Call:
496     //
497     // A Call object is a reference to a call instruction that has been planted
498     // into the code buffer - it is typically used to link the call, setting the
499     // relative offset such that when executed it will call to the desired
500     // destination.
501     class Call {
502         template<class TemplateAssemblerType, class TemplateMacroAssemblerType>
503         friend class AbstractMacroAssembler;
504
505     public:
506         enum Flags {
507             None = 0x0,
508             Linkable = 0x1,
509             Near = 0x2,
510             Tail = 0x4,
511             LinkableNear = 0x3,
512             LinkableNearTail = 0x7,
513         };
514
515         Call()
516             : m_flags(None)
517         {
518         }
519         
520         Call(AssemblerLabel jmp, Flags flags)
521             : m_label(jmp)
522             , m_flags(flags)
523         {
524         }
525
526         bool isFlagSet(Flags flag)
527         {
528             return m_flags & flag;
529         }
530
531         static Call fromTailJump(Jump jump)
532         {
533             return Call(jump.m_label, Linkable);
534         }
535
536         AssemblerLabel m_label;
537     private:
538         Flags m_flags;
539     };
540
541     // Jump:
542     //
543     // A jump object is a reference to a jump instruction that has been planted
544     // into the code buffer - it is typically used to link the jump, setting the
545     // relative offset such that when executed it will jump to the desired
546     // destination.
547     class Jump {
548         template<class TemplateAssemblerType, class TemplateMacroAssemblerType>
549         friend class AbstractMacroAssembler;
550         friend class Call;
551         friend struct DFG::OSRExit;
552         friend class LinkBuffer;
553     public:
554         Jump()
555         {
556         }
557         
558 #if CPU(ARM_THUMB2)
559         // Fixme: this information should be stored in the instruction stream, not in the Jump object.
560         Jump(AssemblerLabel jmp, ARMv7Assembler::JumpType type = ARMv7Assembler::JumpNoCondition, ARMv7Assembler::Condition condition = ARMv7Assembler::ConditionInvalid)
561             : m_label(jmp)
562             , m_type(type)
563             , m_condition(condition)
564         {
565         }
566 #elif CPU(ARM64)
567         Jump(AssemblerLabel jmp, ARM64Assembler::JumpType type = ARM64Assembler::JumpNoCondition, ARM64Assembler::Condition condition = ARM64Assembler::ConditionInvalid)
568             : m_label(jmp)
569             , m_type(type)
570             , m_condition(condition)
571         {
572         }
573
574         Jump(AssemblerLabel jmp, ARM64Assembler::JumpType type, ARM64Assembler::Condition condition, bool is64Bit, ARM64Assembler::RegisterID compareRegister)
575             : m_label(jmp)
576             , m_type(type)
577             , m_condition(condition)
578             , m_is64Bit(is64Bit)
579             , m_compareRegister(compareRegister)
580         {
581             ASSERT((type == ARM64Assembler::JumpCompareAndBranch) || (type == ARM64Assembler::JumpCompareAndBranchFixedSize));
582         }
583
584         Jump(AssemblerLabel jmp, ARM64Assembler::JumpType type, ARM64Assembler::Condition condition, unsigned bitNumber, ARM64Assembler::RegisterID compareRegister)
585             : m_label(jmp)
586             , m_type(type)
587             , m_condition(condition)
588             , m_bitNumber(bitNumber)
589             , m_compareRegister(compareRegister)
590         {
591             ASSERT((type == ARM64Assembler::JumpTestBit) || (type == ARM64Assembler::JumpTestBitFixedSize));
592         }
593 #elif CPU(SH4)
594         Jump(AssemblerLabel jmp, SH4Assembler::JumpType type = SH4Assembler::JumpFar)
595             : m_label(jmp)
596             , m_type(type)
597         {
598         }
599 #else
600         Jump(AssemblerLabel jmp)    
601             : m_label(jmp)
602         {
603         }
604 #endif
605         
606         Label label() const
607         {
608             Label result;
609             result.m_label = m_label;
610             return result;
611         }
612
613         void link(AbstractMacroAssemblerType* masm) const
614         {
615             masm->invalidateAllTempRegisters();
616
617 #if ENABLE(DFG_REGISTER_ALLOCATION_VALIDATION)
618             masm->checkRegisterAllocationAgainstBranchRange(m_label.m_offset, masm->debugOffset());
619 #endif
620
621 #if CPU(ARM_THUMB2)
622             masm->m_assembler.linkJump(m_label, masm->m_assembler.label(), m_type, m_condition);
623 #elif CPU(ARM64)
624             if ((m_type == ARM64Assembler::JumpCompareAndBranch) || (m_type == ARM64Assembler::JumpCompareAndBranchFixedSize))
625                 masm->m_assembler.linkJump(m_label, masm->m_assembler.label(), m_type, m_condition, m_is64Bit, m_compareRegister);
626             else if ((m_type == ARM64Assembler::JumpTestBit) || (m_type == ARM64Assembler::JumpTestBitFixedSize))
627                 masm->m_assembler.linkJump(m_label, masm->m_assembler.label(), m_type, m_condition, m_bitNumber, m_compareRegister);
628             else
629                 masm->m_assembler.linkJump(m_label, masm->m_assembler.label(), m_type, m_condition);
630 #elif CPU(SH4)
631             masm->m_assembler.linkJump(m_label, masm->m_assembler.label(), m_type);
632 #else
633             masm->m_assembler.linkJump(m_label, masm->m_assembler.label());
634 #endif
635         }
636         
637         void linkTo(Label label, AbstractMacroAssemblerType* masm) const
638         {
639 #if ENABLE(DFG_REGISTER_ALLOCATION_VALIDATION)
640             masm->checkRegisterAllocationAgainstBranchRange(label.m_label.m_offset, m_label.m_offset);
641 #endif
642
643 #if CPU(ARM_THUMB2)
644             masm->m_assembler.linkJump(m_label, label.m_label, m_type, m_condition);
645 #elif CPU(ARM64)
646             if ((m_type == ARM64Assembler::JumpCompareAndBranch) || (m_type == ARM64Assembler::JumpCompareAndBranchFixedSize))
647                 masm->m_assembler.linkJump(m_label, label.m_label, m_type, m_condition, m_is64Bit, m_compareRegister);
648             else if ((m_type == ARM64Assembler::JumpTestBit) || (m_type == ARM64Assembler::JumpTestBitFixedSize))
649                 masm->m_assembler.linkJump(m_label, label.m_label, m_type, m_condition, m_bitNumber, m_compareRegister);
650             else
651                 masm->m_assembler.linkJump(m_label, label.m_label, m_type, m_condition);
652 #else
653             masm->m_assembler.linkJump(m_label, label.m_label);
654 #endif
655         }
656
657         bool isSet() const { return m_label.isSet(); }
658
659     private:
660         AssemblerLabel m_label;
661 #if CPU(ARM_THUMB2)
662         ARMv7Assembler::JumpType m_type;
663         ARMv7Assembler::Condition m_condition;
664 #elif CPU(ARM64)
665         ARM64Assembler::JumpType m_type;
666         ARM64Assembler::Condition m_condition;
667         bool m_is64Bit;
668         unsigned m_bitNumber;
669         ARM64Assembler::RegisterID m_compareRegister;
670 #endif
671 #if CPU(SH4)
672         SH4Assembler::JumpType m_type;
673 #endif
674     };
675
676     struct PatchableJump {
677         PatchableJump()
678         {
679         }
680
681         explicit PatchableJump(Jump jump)
682             : m_jump(jump)
683         {
684         }
685
686         operator Jump&() { return m_jump; }
687
688         Jump m_jump;
689     };
690
691     // JumpList:
692     //
693     // A JumpList is a set of Jump objects.
694     // All jumps in the set will be linked to the same destination.
695     class JumpList {
696         friend class LinkBuffer;
697
698     public:
699         typedef Vector<Jump, 2> JumpVector;
700         
701         JumpList() { }
702         
703         JumpList(Jump jump)
704         {
705             if (jump.isSet())
706                 append(jump);
707         }
708
709         void link(AbstractMacroAssemblerType* masm)
710         {
711             size_t size = m_jumps.size();
712             for (size_t i = 0; i < size; ++i)
713                 m_jumps[i].link(masm);
714             m_jumps.clear();
715         }
716         
717         void linkTo(Label label, AbstractMacroAssemblerType* masm)
718         {
719             size_t size = m_jumps.size();
720             for (size_t i = 0; i < size; ++i)
721                 m_jumps[i].linkTo(label, masm);
722             m_jumps.clear();
723         }
724         
725         void append(Jump jump)
726         {
727             m_jumps.append(jump);
728         }
729         
730         void append(const JumpList& other)
731         {
732             m_jumps.append(other.m_jumps.begin(), other.m_jumps.size());
733         }
734
735         bool empty()
736         {
737             return !m_jumps.size();
738         }
739         
740         void clear()
741         {
742             m_jumps.clear();
743         }
744         
745         const JumpVector& jumps() const { return m_jumps; }
746
747     private:
748         JumpVector m_jumps;
749     };
750
751
752     // Section 3: Misc admin methods
753 #if ENABLE(DFG_JIT)
754     Label labelIgnoringWatchpoints()
755     {
756         Label result;
757         result.m_label = m_assembler.labelIgnoringWatchpoints();
758         return result;
759     }
760 #else
761     Label labelIgnoringWatchpoints()
762     {
763         return label();
764     }
765 #endif
766     
767     Label label()
768     {
769         return Label(this);
770     }
771     
772     void padBeforePatch()
773     {
774         // Rely on the fact that asking for a label already does the padding.
775         (void)label();
776     }
777     
778     Label watchpointLabel()
779     {
780         Label result;
781         result.m_label = m_assembler.labelForWatchpoint();
782         return result;
783     }
784     
785     Label align()
786     {
787         m_assembler.align(16);
788         return Label(this);
789     }
790
791 #if ENABLE(DFG_REGISTER_ALLOCATION_VALIDATION)
792     class RegisterAllocationOffset {
793     public:
794         RegisterAllocationOffset(unsigned offset)
795             : m_offset(offset)
796         {
797         }
798
799         void checkOffsets(unsigned low, unsigned high)
800         {
801             RELEASE_ASSERT_WITH_MESSAGE(!(low <= m_offset && m_offset <= high), "Unsafe branch over register allocation at instruction offset %u in jump offset range %u..%u", m_offset, low, high);
802         }
803
804     private:
805         unsigned m_offset;
806     };
807
808     void addRegisterAllocationAtOffset(unsigned offset)
809     {
810         m_registerAllocationForOffsets.append(RegisterAllocationOffset(offset));
811     }
812
813     void clearRegisterAllocationOffsets()
814     {
815         m_registerAllocationForOffsets.clear();
816     }
817
818     void checkRegisterAllocationAgainstBranchRange(unsigned offset1, unsigned offset2)
819     {
820         if (offset1 > offset2)
821             std::swap(offset1, offset2);
822
823         size_t size = m_registerAllocationForOffsets.size();
824         for (size_t i = 0; i < size; ++i)
825             m_registerAllocationForOffsets[i].checkOffsets(offset1, offset2);
826     }
827 #endif
828
829     template<typename T, typename U>
830     static ptrdiff_t differenceBetween(T from, U to)
831     {
832         return AssemblerType::getDifferenceBetweenLabels(from.m_label, to.m_label);
833     }
834
835     static ptrdiff_t differenceBetweenCodePtr(const MacroAssemblerCodePtr& a, const MacroAssemblerCodePtr& b)
836     {
837         return reinterpret_cast<ptrdiff_t>(b.executableAddress()) - reinterpret_cast<ptrdiff_t>(a.executableAddress());
838     }
839
840     unsigned debugOffset() { return m_assembler.debugOffset(); }
841
842     ALWAYS_INLINE static void cacheFlush(void* code, size_t size)
843     {
844         AssemblerType::cacheFlush(code, size);
845     }
846
847 #if ENABLE(MASM_PROBE)
848
849     struct CPUState {
850         #define DECLARE_REGISTER(_type, _regName) \
851             _type _regName;
852         FOR_EACH_CPU_REGISTER(DECLARE_REGISTER)
853         #undef DECLARE_REGISTER
854
855         static const char* registerName(RegisterID regID)
856         {
857             switch (regID) {
858                 #define DECLARE_REGISTER(_type, _regName) \
859                 case RegisterID::_regName: \
860                     return #_regName;
861                 FOR_EACH_CPU_GPREGISTER(DECLARE_REGISTER)
862                 #undef DECLARE_REGISTER
863             }
864             RELEASE_ASSERT_NOT_REACHED();
865         }
866
867         static const char* registerName(FPRegisterID regID)
868         {
869             switch (regID) {
870                 #define DECLARE_REGISTER(_type, _regName) \
871                 case FPRegisterID::_regName: \
872                     return #_regName;
873                 FOR_EACH_CPU_FPREGISTER(DECLARE_REGISTER)
874                 #undef DECLARE_REGISTER
875             }
876             RELEASE_ASSERT_NOT_REACHED();
877         }
878
879         void* registerValue(RegisterID regID)
880         {
881             switch (regID) {
882                 #define DECLARE_REGISTER(_type, _regName) \
883                 case RegisterID::_regName: \
884                     return _regName;
885                 FOR_EACH_CPU_GPREGISTER(DECLARE_REGISTER)
886                 #undef DECLARE_REGISTER
887             }
888             RELEASE_ASSERT_NOT_REACHED();
889         }
890
891         double registerValue(FPRegisterID regID)
892         {
893             switch (regID) {
894                 #define DECLARE_REGISTER(_type, _regName) \
895                 case FPRegisterID::_regName: \
896                     return _regName;
897                 FOR_EACH_CPU_FPREGISTER(DECLARE_REGISTER)
898                 #undef DECLARE_REGISTER
899             }
900             RELEASE_ASSERT_NOT_REACHED();
901         }
902
903     };
904
905     struct ProbeContext;
906     typedef void (*ProbeFunction)(struct ProbeContext*);
907
908     struct ProbeContext {
909         ProbeFunction probeFunction;
910         void* arg1;
911         void* arg2;
912         CPUState cpu;
913     };
914
915     // This function emits code to preserve the CPUState (e.g. registers),
916     // call a user supplied probe function, and restore the CPUState before
917     // continuing with other JIT generated code.
918     //
919     // The user supplied probe function will be called with a single pointer to
920     // a ProbeContext struct (defined above) which contains, among other things,
921     // the preserved CPUState. This allows the user probe function to inspect
922     // the CPUState at that point in the JIT generated code.
923     //
924     // If the user probe function alters the register values in the ProbeContext,
925     // the altered values will be loaded into the CPU registers when the probe
926     // returns.
927     //
928     // The ProbeContext is stack allocated and is only valid for the duration
929     // of the call to the user probe function.
930     //
931     // Note: probe() should be implemented by the target specific MacroAssembler.
932     // This prototype is only provided here to document the interface.
933
934     void probe(ProbeFunction, void* arg1 = 0, void* arg2 = 0);
935
936 #endif // ENABLE(MASM_PROBE)
937
938     AssemblerType m_assembler;
939     
940     static void linkJump(void* code, Jump jump, CodeLocationLabel target)
941     {
942         AssemblerType::linkJump(code, jump.m_label, target.dataLocation());
943     }
944
945     static void linkPointer(void* code, AssemblerLabel label, void* value)
946     {
947         AssemblerType::linkPointer(code, label, value);
948     }
949
950     static void* getLinkerAddress(void* code, AssemblerLabel label)
951     {
952         return AssemblerType::getRelocatedAddress(code, label);
953     }
954
955     static unsigned getLinkerCallReturnOffset(Call call)
956     {
957         return AssemblerType::getCallReturnOffset(call.m_label);
958     }
959
960     static void repatchJump(CodeLocationJump jump, CodeLocationLabel destination)
961     {
962         AssemblerType::relinkJump(jump.dataLocation(), destination.dataLocation());
963     }
964
965     static void repatchNearCall(CodeLocationNearCall nearCall, CodeLocationLabel destination)
966     {
967         switch (nearCall.callMode()) {
968         case NearCallMode::Tail:
969             AssemblerType::relinkJump(nearCall.dataLocation(), destination.executableAddress());
970             return;
971         case NearCallMode::Regular:
972             AssemblerType::relinkCall(nearCall.dataLocation(), destination.executableAddress());
973             return;
974         }
975         RELEASE_ASSERT_NOT_REACHED();
976     }
977
978     static void repatchCompact(CodeLocationDataLabelCompact dataLabelCompact, int32_t value)
979     {
980         AssemblerType::repatchCompact(dataLabelCompact.dataLocation(), value);
981     }
982     
983     static void repatchInt32(CodeLocationDataLabel32 dataLabel32, int32_t value)
984     {
985         AssemblerType::repatchInt32(dataLabel32.dataLocation(), value);
986     }
987
988     static void repatchPointer(CodeLocationDataLabelPtr dataLabelPtr, void* value)
989     {
990         AssemblerType::repatchPointer(dataLabelPtr.dataLocation(), value);
991     }
992     
993     static void* readPointer(CodeLocationDataLabelPtr dataLabelPtr)
994     {
995         return AssemblerType::readPointer(dataLabelPtr.dataLocation());
996     }
997     
998     static void replaceWithLoad(CodeLocationConvertibleLoad label)
999     {
1000         AssemblerType::replaceWithLoad(label.dataLocation());
1001     }
1002     
1003     static void replaceWithAddressComputation(CodeLocationConvertibleLoad label)
1004     {
1005         AssemblerType::replaceWithAddressComputation(label.dataLocation());
1006     }
1007
1008 protected:
1009     AbstractMacroAssembler()
1010         : m_randomSource(cryptographicallyRandomNumber())
1011     {
1012         invalidateAllTempRegisters();
1013     }
1014
1015     uint32_t random()
1016     {
1017         return m_randomSource.getUint32();
1018     }
1019
1020     WeakRandom m_randomSource;
1021
1022 #if ENABLE(DFG_REGISTER_ALLOCATION_VALIDATION)
1023     Vector<RegisterAllocationOffset, 10> m_registerAllocationForOffsets;
1024 #endif
1025
1026     static bool haveScratchRegisterForBlinding()
1027     {
1028         return false;
1029     }
1030     static RegisterID scratchRegisterForBlinding()
1031     {
1032         UNREACHABLE_FOR_PLATFORM();
1033         return firstRegister();
1034     }
1035     static bool canBlind() { return false; }
1036     static bool shouldBlindForSpecificArch(uint32_t) { return false; }
1037     static bool shouldBlindForSpecificArch(uint64_t) { return false; }
1038
1039     class CachedTempRegister {
1040         friend class DataLabelPtr;
1041         friend class DataLabel32;
1042         friend class DataLabelCompact;
1043         friend class Jump;
1044         friend class Label;
1045
1046     public:
1047         CachedTempRegister(AbstractMacroAssemblerType* masm, RegisterID registerID)
1048             : m_masm(masm)
1049             , m_registerID(registerID)
1050             , m_value(0)
1051             , m_validBit(1 << static_cast<unsigned>(registerID))
1052         {
1053             ASSERT(static_cast<unsigned>(registerID) < (sizeof(unsigned) * 8));
1054         }
1055
1056         ALWAYS_INLINE RegisterID registerIDInvalidate() { invalidate(); return m_registerID; }
1057
1058         ALWAYS_INLINE RegisterID registerIDNoInvalidate() { return m_registerID; }
1059
1060         bool value(intptr_t& value)
1061         {
1062             value = m_value;
1063             return m_masm->isTempRegisterValid(m_validBit);
1064         }
1065
1066         void setValue(intptr_t value)
1067         {
1068             m_value = value;
1069             m_masm->setTempRegisterValid(m_validBit);
1070         }
1071
1072         ALWAYS_INLINE void invalidate() { m_masm->clearTempRegisterValid(m_validBit); }
1073
1074     private:
1075         AbstractMacroAssemblerType* m_masm;
1076         RegisterID m_registerID;
1077         intptr_t m_value;
1078         unsigned m_validBit;
1079     };
1080
1081     ALWAYS_INLINE void invalidateAllTempRegisters()
1082     {
1083         m_tempRegistersValidBits = 0;
1084     }
1085
1086     ALWAYS_INLINE bool isTempRegisterValid(unsigned registerMask)
1087     {
1088         return (m_tempRegistersValidBits & registerMask);
1089     }
1090
1091     ALWAYS_INLINE void clearTempRegisterValid(unsigned registerMask)
1092     {
1093         m_tempRegistersValidBits &=  ~registerMask;
1094     }
1095
1096     ALWAYS_INLINE void setTempRegisterValid(unsigned registerMask)
1097     {
1098         m_tempRegistersValidBits |= registerMask;
1099     }
1100
1101     unsigned m_tempRegistersValidBits;
1102
1103     friend class LinkBuffer;
1104
1105 private:
1106
1107 }; // class AbstractMacroAssembler
1108
1109 } // namespace JSC
1110
1111 #endif // ENABLE(ASSEMBLER)
1112
1113 #endif // AbstractMacroAssembler_h