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