DFG should be able to set watchpoints on global variables
[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 #include <wtf/UnusedParam.h>
35
36 #if ENABLE(ASSEMBLER)
37
38
39 #if PLATFORM(QT)
40 #define ENABLE_JIT_CONSTANT_BLINDING 0
41 #endif
42
43 #ifndef ENABLE_JIT_CONSTANT_BLINDING
44 #define ENABLE_JIT_CONSTANT_BLINDING 1
45 #endif
46
47 namespace JSC {
48
49 class LinkBuffer;
50 class RepatchBuffer;
51 class Watchpoint;
52 namespace DFG {
53 class CorrectableJumpPoint;
54 }
55
56 template <class AssemblerType>
57 class AbstractMacroAssembler {
58 public:
59     friend class JITWriteBarrierBase;
60     typedef AssemblerType AssemblerType_T;
61
62     typedef MacroAssemblerCodePtr CodePtr;
63     typedef MacroAssemblerCodeRef CodeRef;
64
65     class Jump;
66
67     typedef typename AssemblerType::RegisterID RegisterID;
68
69     // Section 1: MacroAssembler operand types
70     //
71     // The following types are used as operands to MacroAssembler operations,
72     // describing immediate  and memory operands to the instructions to be planted.
73
74     enum Scale {
75         TimesOne,
76         TimesTwo,
77         TimesFour,
78         TimesEight,
79     };
80
81     // Address:
82     //
83     // Describes a simple base-offset address.
84     struct Address {
85         explicit Address(RegisterID base, int32_t offset = 0)
86             : base(base)
87             , offset(offset)
88         {
89         }
90
91         RegisterID base;
92         int32_t offset;
93     };
94
95     struct ExtendedAddress {
96         explicit ExtendedAddress(RegisterID base, intptr_t offset = 0)
97             : base(base)
98             , offset(offset)
99         {
100         }
101         
102         RegisterID base;
103         intptr_t offset;
104     };
105
106     // ImplicitAddress:
107     //
108     // This class is used for explicit 'load' and 'store' operations
109     // (as opposed to situations in which a memory operand is provided
110     // to a generic operation, such as an integer arithmetic instruction).
111     //
112     // In the case of a load (or store) operation we want to permit
113     // addresses to be implicitly constructed, e.g. the two calls:
114     //
115     //     load32(Address(addrReg), destReg);
116     //     load32(addrReg, destReg);
117     //
118     // Are equivalent, and the explicit wrapping of the Address in the former
119     // is unnecessary.
120     struct ImplicitAddress {
121         ImplicitAddress(RegisterID base)
122             : base(base)
123             , offset(0)
124         {
125         }
126
127         ImplicitAddress(Address address)
128             : base(address.base)
129             , offset(address.offset)
130         {
131         }
132
133         RegisterID base;
134         int32_t offset;
135     };
136
137     // BaseIndex:
138     //
139     // Describes a complex addressing mode.
140     struct BaseIndex {
141         BaseIndex(RegisterID base, RegisterID index, Scale scale, int32_t offset = 0)
142             : base(base)
143             , index(index)
144             , scale(scale)
145             , offset(offset)
146         {
147         }
148
149         RegisterID base;
150         RegisterID index;
151         Scale scale;
152         int32_t offset;
153     };
154
155     // AbsoluteAddress:
156     //
157     // Describes an memory operand given by a pointer.  For regular load & store
158     // operations an unwrapped void* will be used, rather than using this.
159     struct AbsoluteAddress {
160         explicit AbsoluteAddress(const void* ptr)
161             : m_ptr(ptr)
162         {
163         }
164
165         const void* m_ptr;
166     };
167
168     // TrustedImmPtr:
169     //
170     // A pointer sized immediate operand to an instruction - this is wrapped
171     // in a class requiring explicit construction in order to differentiate
172     // from pointers used as absolute addresses to memory operations
173     struct TrustedImmPtr {
174         TrustedImmPtr() { }
175         
176         explicit TrustedImmPtr(const void* value)
177             : m_value(value)
178         {
179         }
180         
181         // This is only here so that TrustedImmPtr(0) does not confuse the C++
182         // overload handling rules.
183         explicit TrustedImmPtr(int value)
184             : m_value(0)
185         {
186             ASSERT_UNUSED(value, !value);
187         }
188
189         explicit TrustedImmPtr(size_t value)
190             : m_value(reinterpret_cast<void*>(value))
191         {
192         }
193
194         intptr_t asIntptr()
195         {
196             return reinterpret_cast<intptr_t>(m_value);
197         }
198
199         const void* m_value;
200     };
201
202     struct ImmPtr : 
203 #if ENABLE(JIT_CONSTANT_BLINDING)
204         private TrustedImmPtr 
205 #else
206         public TrustedImmPtr
207 #endif
208     {
209         explicit ImmPtr(const void* value)
210             : TrustedImmPtr(value)
211         {
212         }
213
214         TrustedImmPtr asTrustedImmPtr() { return *this; }
215     };
216
217     // TrustedImm32:
218     //
219     // A 32bit immediate operand to an instruction - this is wrapped in a
220     // class requiring explicit construction in order to prevent RegisterIDs
221     // (which are implemented as an enum) from accidentally being passed as
222     // immediate values.
223     struct TrustedImm32 {
224         TrustedImm32() { }
225         
226         explicit TrustedImm32(int32_t value)
227             : m_value(value)
228         {
229         }
230
231 #if !CPU(X86_64)
232         explicit TrustedImm32(TrustedImmPtr ptr)
233             : m_value(ptr.asIntptr())
234         {
235         }
236 #endif
237
238         int32_t m_value;
239     };
240
241
242     struct Imm32 : 
243 #if ENABLE(JIT_CONSTANT_BLINDING)
244         private TrustedImm32 
245 #else
246         public TrustedImm32
247 #endif
248     {
249         explicit Imm32(int32_t value)
250             : TrustedImm32(value)
251         {
252         }
253 #if !CPU(X86_64)
254         explicit Imm32(TrustedImmPtr ptr)
255             : TrustedImm32(ptr)
256         {
257         }
258 #endif
259         const TrustedImm32& asTrustedImm32() const { return *this; }
260
261     };
262     
263     // Section 2: MacroAssembler code buffer handles
264     //
265     // The following types are used to reference items in the code buffer
266     // during JIT code generation.  For example, the type Jump is used to
267     // track the location of a jump instruction so that it may later be
268     // linked to a label marking its destination.
269
270
271     // Label:
272     //
273     // A Label records a point in the generated instruction stream, typically such that
274     // it may be used as a destination for a jump.
275     class Label {
276         template<class TemplateAssemblerType>
277         friend class AbstractMacroAssembler;
278         friend class DFG::CorrectableJumpPoint;
279         friend class Jump;
280         friend class MacroAssemblerCodeRef;
281         friend class LinkBuffer;
282         friend class Watchpoint;
283
284     public:
285         Label()
286         {
287         }
288
289         Label(AbstractMacroAssembler<AssemblerType>* masm)
290             : m_label(masm->m_assembler.label())
291         {
292         }
293         
294         bool isSet() const { return m_label.isSet(); }
295     private:
296         AssemblerLabel m_label;
297     };
298
299     // DataLabelPtr:
300     //
301     // A DataLabelPtr is used to refer to a location in the code containing a pointer to be
302     // patched after the code has been generated.
303     class DataLabelPtr {
304         template<class TemplateAssemblerType>
305         friend class AbstractMacroAssembler;
306         friend class LinkBuffer;
307     public:
308         DataLabelPtr()
309         {
310         }
311
312         DataLabelPtr(AbstractMacroAssembler<AssemblerType>* masm)
313             : m_label(masm->m_assembler.label())
314         {
315         }
316         
317         bool isSet() const { return m_label.isSet(); }
318         
319     private:
320         AssemblerLabel m_label;
321     };
322
323     // DataLabel32:
324     //
325     // A DataLabelPtr is used to refer to a location in the code containing a pointer to be
326     // patched after the code has been generated.
327     class DataLabel32 {
328         template<class TemplateAssemblerType>
329         friend class AbstractMacroAssembler;
330         friend class LinkBuffer;
331     public:
332         DataLabel32()
333         {
334         }
335
336         DataLabel32(AbstractMacroAssembler<AssemblerType>* masm)
337             : m_label(masm->m_assembler.label())
338         {
339         }
340
341         AssemblerLabel label() const { return m_label; }
342
343     private:
344         AssemblerLabel m_label;
345     };
346
347     // DataLabelCompact:
348     //
349     // A DataLabelCompact is used to refer to a location in the code containing a
350     // compact immediate to be patched after the code has been generated.
351     class DataLabelCompact {
352         template<class TemplateAssemblerType>
353         friend class AbstractMacroAssembler;
354         friend class LinkBuffer;
355     public:
356         DataLabelCompact()
357         {
358         }
359         
360         DataLabelCompact(AbstractMacroAssembler<AssemblerType>* masm)
361             : m_label(masm->m_assembler.label())
362         {
363         }
364     
365         DataLabelCompact(AssemblerLabel label)
366             : m_label(label)
367         {
368         }
369
370     private:
371         AssemblerLabel m_label;
372     };
373
374     // Call:
375     //
376     // A Call object is a reference to a call instruction that has been planted
377     // into the code buffer - it is typically used to link the call, setting the
378     // relative offset such that when executed it will call to the desired
379     // destination.
380     class Call {
381         template<class TemplateAssemblerType>
382         friend class AbstractMacroAssembler;
383
384     public:
385         enum Flags {
386             None = 0x0,
387             Linkable = 0x1,
388             Near = 0x2,
389             LinkableNear = 0x3,
390         };
391
392         Call()
393             : m_flags(None)
394         {
395         }
396         
397         Call(AssemblerLabel jmp, Flags flags)
398             : m_label(jmp)
399             , m_flags(flags)
400         {
401         }
402
403         bool isFlagSet(Flags flag)
404         {
405             return m_flags & flag;
406         }
407
408         static Call fromTailJump(Jump jump)
409         {
410             return Call(jump.m_label, Linkable);
411         }
412
413         AssemblerLabel m_label;
414     private:
415         Flags m_flags;
416     };
417
418     // Jump:
419     //
420     // A jump object is a reference to a jump instruction that has been planted
421     // into the code buffer - it is typically used to link the jump, setting the
422     // relative offset such that when executed it will jump to the desired
423     // destination.
424     class Jump {
425         template<class TemplateAssemblerType>
426         friend class AbstractMacroAssembler;
427         friend class Call;
428         friend class DFG::CorrectableJumpPoint;
429         friend class LinkBuffer;
430     public:
431         Jump()
432         {
433         }
434         
435 #if CPU(ARM_THUMB2)
436         // Fixme: this information should be stored in the instruction stream, not in the Jump object.
437         Jump(AssemblerLabel jmp, ARMv7Assembler::JumpType type, ARMv7Assembler::Condition condition = ARMv7Assembler::ConditionInvalid)
438             : m_label(jmp)
439             , m_type(type)
440             , m_condition(condition)
441         {
442         }
443 #elif CPU(SH4)
444         Jump(AssemblerLabel jmp, SH4Assembler::JumpType type = SH4Assembler::JumpFar)
445             : m_label(jmp)
446             , m_type(type)
447         {
448         }
449 #else
450         Jump(AssemblerLabel jmp)    
451             : m_label(jmp)
452         {
453         }
454 #endif
455
456         void link(AbstractMacroAssembler<AssemblerType>* masm) const
457         {
458 #if CPU(ARM_THUMB2)
459             masm->m_assembler.linkJump(m_label, masm->m_assembler.label(), m_type, m_condition);
460 #elif CPU(SH4)
461             masm->m_assembler.linkJump(m_label, masm->m_assembler.label(), m_type);
462 #else
463             masm->m_assembler.linkJump(m_label, masm->m_assembler.label());
464 #endif
465         }
466         
467         void linkTo(Label label, AbstractMacroAssembler<AssemblerType>* masm) const
468         {
469 #if CPU(ARM_THUMB2)
470             masm->m_assembler.linkJump(m_label, label.m_label, m_type, m_condition);
471 #else
472             masm->m_assembler.linkJump(m_label, label.m_label);
473 #endif
474         }
475
476         bool isSet() const { return m_label.isSet(); }
477
478     private:
479         AssemblerLabel m_label;
480 #if CPU(ARM_THUMB2)
481         ARMv7Assembler::JumpType m_type;
482         ARMv7Assembler::Condition m_condition;
483 #endif
484 #if CPU(SH4)
485         SH4Assembler::JumpType m_type;
486 #endif
487     };
488
489     struct PatchableJump {
490         PatchableJump()
491         {
492         }
493
494         explicit PatchableJump(Jump jump)
495             : m_jump(jump)
496         {
497         }
498
499         operator Jump&() { return m_jump; }
500
501         Jump m_jump;
502     };
503
504     // JumpList:
505     //
506     // A JumpList is a set of Jump objects.
507     // All jumps in the set will be linked to the same destination.
508     class JumpList {
509         friend class LinkBuffer;
510
511     public:
512         typedef Vector<Jump, 16> JumpVector;
513
514         void link(AbstractMacroAssembler<AssemblerType>* masm)
515         {
516             size_t size = m_jumps.size();
517             for (size_t i = 0; i < size; ++i)
518                 m_jumps[i].link(masm);
519             m_jumps.clear();
520         }
521         
522         void linkTo(Label label, AbstractMacroAssembler<AssemblerType>* masm)
523         {
524             size_t size = m_jumps.size();
525             for (size_t i = 0; i < size; ++i)
526                 m_jumps[i].linkTo(label, masm);
527             m_jumps.clear();
528         }
529         
530         void append(Jump jump)
531         {
532             m_jumps.append(jump);
533         }
534         
535         void append(JumpList& other)
536         {
537             m_jumps.append(other.m_jumps.begin(), other.m_jumps.size());
538         }
539
540         bool empty()
541         {
542             return !m_jumps.size();
543         }
544         
545         void clear()
546         {
547             m_jumps.clear();
548         }
549         
550         const JumpVector& jumps() { return m_jumps; }
551
552     private:
553         JumpVector m_jumps;
554     };
555
556
557     // Section 3: Misc admin methods
558     Label label()
559     {
560         return Label(this);
561     }
562     
563     Label watchpointLabel()
564     {
565         Label result;
566         result.m_label = m_assembler.labelForWatchpoint();
567         return result;
568     }
569     
570     Label align()
571     {
572         m_assembler.align(16);
573         return Label(this);
574     }
575
576     template<typename T, typename U>
577     static ptrdiff_t differenceBetween(T from, U to)
578     {
579         return AssemblerType::getDifferenceBetweenLabels(from.m_label, to.m_label);
580     }
581
582     static ptrdiff_t differenceBetweenCodePtr(const MacroAssemblerCodePtr& a, const MacroAssemblerCodePtr& b)
583     {
584         return reinterpret_cast<ptrdiff_t>(b.executableAddress()) - reinterpret_cast<ptrdiff_t>(a.executableAddress());
585     }
586
587     unsigned debugOffset() { return m_assembler.debugOffset(); }
588
589     ALWAYS_INLINE static void cacheFlush(void* code, size_t size)
590     {
591         AssemblerType::cacheFlush(code, size);
592     }
593 protected:
594     AbstractMacroAssembler()
595         : m_randomSource(cryptographicallyRandomNumber())
596     {
597     }
598
599     AssemblerType m_assembler;
600     
601     uint32_t random()
602     {
603         return m_randomSource.getUint32();
604     }
605
606     WeakRandom m_randomSource;
607
608 #if ENABLE(JIT_CONSTANT_BLINDING)
609     static bool scratchRegisterForBlinding() { return false; }
610     static bool shouldBlindForSpecificArch(uint32_t) { return true; }
611     static bool shouldBlindForSpecificArch(uint64_t) { return true; }
612 #endif
613
614     friend class LinkBuffer;
615     friend class RepatchBuffer;
616
617     static void linkJump(void* code, Jump jump, CodeLocationLabel target)
618     {
619         AssemblerType::linkJump(code, jump.m_label, target.dataLocation());
620     }
621
622     static void linkPointer(void* code, AssemblerLabel label, void* value)
623     {
624         AssemblerType::linkPointer(code, label, value);
625     }
626
627     static void* getLinkerAddress(void* code, AssemblerLabel label)
628     {
629         return AssemblerType::getRelocatedAddress(code, label);
630     }
631
632     static unsigned getLinkerCallReturnOffset(Call call)
633     {
634         return AssemblerType::getCallReturnOffset(call.m_label);
635     }
636
637     static void repatchJump(CodeLocationJump jump, CodeLocationLabel destination)
638     {
639         AssemblerType::relinkJump(jump.dataLocation(), destination.dataLocation());
640     }
641
642     static void repatchNearCall(CodeLocationNearCall nearCall, CodeLocationLabel destination)
643     {
644         AssemblerType::relinkCall(nearCall.dataLocation(), destination.executableAddress());
645     }
646
647     static void repatchCompact(CodeLocationDataLabelCompact dataLabelCompact, int32_t value)
648     {
649         AssemblerType::repatchCompact(dataLabelCompact.dataLocation(), value);
650     }
651     
652     static void repatchInt32(CodeLocationDataLabel32 dataLabel32, int32_t value)
653     {
654         AssemblerType::repatchInt32(dataLabel32.dataLocation(), value);
655     }
656
657     static void repatchPointer(CodeLocationDataLabelPtr dataLabelPtr, void* value)
658     {
659         AssemblerType::repatchPointer(dataLabelPtr.dataLocation(), value);
660     }
661     
662     static void* readPointer(CodeLocationDataLabelPtr dataLabelPtr)
663     {
664         return AssemblerType::readPointer(dataLabelPtr.dataLocation());
665     }
666     
667     static void unreachableForPlatform()
668     {
669 #if COMPILER(CLANG)
670 #pragma clang diagnostic push
671 #pragma clang diagnostic ignored "-Wmissing-noreturn"
672         ASSERT_NOT_REACHED();
673 #pragma clang diagnostic pop
674 #else
675         ASSERT_NOT_REACHED();
676 #endif
677     }
678 };
679
680 } // namespace JSC
681
682 #endif // ENABLE(ASSEMBLER)
683
684 #endif // AbstractMacroAssembler_h