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