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