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