2 * Copyright (C) 2008, 2012 Apple Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
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.
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.
26 #ifndef AbstractMacroAssembler_h
27 #define AbstractMacroAssembler_h
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>
39 #if PLATFORM(QT) || OS(TIZEN)
40 #define ENABLE_JIT_CONSTANT_BLINDING 0
43 #ifndef ENABLE_JIT_CONSTANT_BLINDING
44 #define ENABLE_JIT_CONSTANT_BLINDING 1
49 class JumpReplacementWatchpoint;
54 class CorrectableJumpPoint;
57 template <class AssemblerType>
58 class AbstractMacroAssembler {
60 friend class JITWriteBarrierBase;
61 typedef AssemblerType AssemblerType_T;
63 typedef MacroAssemblerCodePtr CodePtr;
64 typedef MacroAssemblerCodeRef CodeRef;
68 typedef typename AssemblerType::RegisterID RegisterID;
70 // Section 1: MacroAssembler operand types
72 // The following types are used as operands to MacroAssembler operations,
73 // describing immediate and memory operands to the instructions to be planted.
84 // Describes a simple base-offset address.
86 explicit Address(RegisterID base, int32_t offset = 0)
96 struct ExtendedAddress {
97 explicit ExtendedAddress(RegisterID base, intptr_t offset = 0)
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).
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:
116 // load32(Address(addrReg), destReg);
117 // load32(addrReg, destReg);
119 // Are equivalent, and the explicit wrapping of the Address in the former
121 struct ImplicitAddress {
122 ImplicitAddress(RegisterID base)
128 ImplicitAddress(Address address)
130 , offset(address.offset)
140 // Describes a complex addressing mode.
142 BaseIndex(RegisterID base, RegisterID index, Scale scale, int32_t offset = 0)
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)
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 {
177 explicit TrustedImmPtr(const void* value)
182 // This is only here so that TrustedImmPtr(0) does not confuse the C++
183 // overload handling rules.
184 explicit TrustedImmPtr(int value)
187 ASSERT_UNUSED(value, !value);
190 explicit TrustedImmPtr(size_t value)
191 : m_value(reinterpret_cast<void*>(value))
197 return reinterpret_cast<intptr_t>(m_value);
204 #if ENABLE(JIT_CONSTANT_BLINDING)
205 private TrustedImmPtr
210 explicit ImmPtr(const void* value)
211 : TrustedImmPtr(value)
215 TrustedImmPtr asTrustedImmPtr() { return *this; }
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
224 struct TrustedImm32 {
227 explicit TrustedImm32(int32_t value)
233 explicit TrustedImm32(TrustedImmPtr ptr)
234 : m_value(ptr.asIntptr())
244 #if ENABLE(JIT_CONSTANT_BLINDING)
250 explicit Imm32(int32_t value)
251 : TrustedImm32(value)
255 explicit Imm32(TrustedImmPtr ptr)
260 const TrustedImm32& asTrustedImm32() const { return *this; }
264 // Section 2: MacroAssembler code buffer handles
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.
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.
277 template<class TemplateAssemblerType>
278 friend class AbstractMacroAssembler;
279 friend class DFG::CorrectableJumpPoint;
281 friend class JumpReplacementWatchpoint;
282 friend class MacroAssemblerCodeRef;
283 friend class LinkBuffer;
284 friend class Watchpoint;
291 Label(AbstractMacroAssembler<AssemblerType>* masm)
292 : m_label(masm->m_assembler.label())
296 bool isSet() const { return m_label.isSet(); }
298 AssemblerLabel m_label;
301 // ConvertibleLoadLabel:
303 // A ConvertibleLoadLabel records a loadPtr instruction that can be patched to an addPtr
306 // loadPtr(Address(a, i), b)
310 // addPtr(TrustedImmPtr(i), a, b)
311 class ConvertibleLoadLabel {
312 template<class TemplateAssemblerType>
313 friend class AbstractMacroAssembler;
314 friend class LinkBuffer;
317 ConvertibleLoadLabel()
321 ConvertibleLoadLabel(AbstractMacroAssembler<AssemblerType>* masm)
322 : m_label(masm->m_assembler.labelIgnoringWatchpoints())
326 bool isSet() const { return m_label.isSet(); }
328 AssemblerLabel m_label;
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.
336 template<class TemplateAssemblerType>
337 friend class AbstractMacroAssembler;
338 friend class LinkBuffer;
344 DataLabelPtr(AbstractMacroAssembler<AssemblerType>* masm)
345 : m_label(masm->m_assembler.label())
349 bool isSet() const { return m_label.isSet(); }
352 AssemblerLabel m_label;
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.
360 template<class TemplateAssemblerType>
361 friend class AbstractMacroAssembler;
362 friend class LinkBuffer;
368 DataLabel32(AbstractMacroAssembler<AssemblerType>* masm)
369 : m_label(masm->m_assembler.label())
373 AssemblerLabel label() const { return m_label; }
376 AssemblerLabel m_label;
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;
392 DataLabelCompact(AbstractMacroAssembler<AssemblerType>* masm)
393 : m_label(masm->m_assembler.label())
397 DataLabelCompact(AssemblerLabel label)
403 AssemblerLabel m_label;
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
413 template<class TemplateAssemblerType>
414 friend class AbstractMacroAssembler;
429 Call(AssemblerLabel jmp, Flags flags)
435 bool isFlagSet(Flags flag)
437 return m_flags & flag;
440 static Call fromTailJump(Jump jump)
442 return Call(jump.m_label, Linkable);
445 AssemblerLabel m_label;
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
457 template<class TemplateAssemblerType>
458 friend class AbstractMacroAssembler;
460 friend class DFG::CorrectableJumpPoint;
461 friend class LinkBuffer;
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)
472 , m_condition(condition)
476 Jump(AssemblerLabel jmp, SH4Assembler::JumpType type = SH4Assembler::JumpFar)
482 Jump(AssemblerLabel jmp)
488 void link(AbstractMacroAssembler<AssemblerType>* masm) const
491 masm->m_assembler.linkJump(m_label, masm->m_assembler.label(), m_type, m_condition);
493 masm->m_assembler.linkJump(m_label, masm->m_assembler.label(), m_type);
495 masm->m_assembler.linkJump(m_label, masm->m_assembler.label());
499 void linkTo(Label label, AbstractMacroAssembler<AssemblerType>* masm) const
502 masm->m_assembler.linkJump(m_label, label.m_label, m_type, m_condition);
504 masm->m_assembler.linkJump(m_label, label.m_label);
508 bool isSet() const { return m_label.isSet(); }
511 AssemblerLabel m_label;
513 ARMv7Assembler::JumpType m_type;
514 ARMv7Assembler::Condition m_condition;
517 SH4Assembler::JumpType m_type;
521 struct PatchableJump {
526 explicit PatchableJump(Jump jump)
531 operator Jump&() { return m_jump; }
538 // A JumpList is a set of Jump objects.
539 // All jumps in the set will be linked to the same destination.
541 friend class LinkBuffer;
544 typedef Vector<Jump, 16> JumpVector;
546 void link(AbstractMacroAssembler<AssemblerType>* masm)
548 size_t size = m_jumps.size();
549 for (size_t i = 0; i < size; ++i)
550 m_jumps[i].link(masm);
554 void linkTo(Label label, AbstractMacroAssembler<AssemblerType>* masm)
556 size_t size = m_jumps.size();
557 for (size_t i = 0; i < size; ++i)
558 m_jumps[i].linkTo(label, masm);
562 void append(Jump jump)
564 m_jumps.append(jump);
567 void append(JumpList& other)
569 m_jumps.append(other.m_jumps.begin(), other.m_jumps.size());
574 return !m_jumps.size();
582 const JumpVector& jumps() { return m_jumps; }
589 // Section 3: Misc admin methods
591 Label labelIgnoringWatchpoints()
594 result.m_label = m_assembler.labelIgnoringWatchpoints();
598 Label labelIgnoringWatchpoints()
609 Label watchpointLabel()
612 result.m_label = m_assembler.labelForWatchpoint();
618 m_assembler.align(16);
622 template<typename T, typename U>
623 static ptrdiff_t differenceBetween(T from, U to)
625 return AssemblerType::getDifferenceBetweenLabels(from.m_label, to.m_label);
628 static ptrdiff_t differenceBetweenCodePtr(const MacroAssemblerCodePtr& a, const MacroAssemblerCodePtr& b)
630 return reinterpret_cast<ptrdiff_t>(b.executableAddress()) - reinterpret_cast<ptrdiff_t>(a.executableAddress());
633 unsigned debugOffset() { return m_assembler.debugOffset(); }
635 ALWAYS_INLINE static void cacheFlush(void* code, size_t size)
637 AssemblerType::cacheFlush(code, size);
640 AbstractMacroAssembler()
641 : m_randomSource(cryptographicallyRandomNumber())
645 AssemblerType m_assembler;
649 return m_randomSource.getUint32();
652 WeakRandom m_randomSource;
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; }
660 friend class LinkBuffer;
661 friend class RepatchBuffer;
663 static void linkJump(void* code, Jump jump, CodeLocationLabel target)
665 AssemblerType::linkJump(code, jump.m_label, target.dataLocation());
668 static void linkPointer(void* code, AssemblerLabel label, void* value)
670 AssemblerType::linkPointer(code, label, value);
673 static void* getLinkerAddress(void* code, AssemblerLabel label)
675 return AssemblerType::getRelocatedAddress(code, label);
678 static unsigned getLinkerCallReturnOffset(Call call)
680 return AssemblerType::getCallReturnOffset(call.m_label);
683 static void repatchJump(CodeLocationJump jump, CodeLocationLabel destination)
685 AssemblerType::relinkJump(jump.dataLocation(), destination.dataLocation());
688 static void repatchNearCall(CodeLocationNearCall nearCall, CodeLocationLabel destination)
690 AssemblerType::relinkCall(nearCall.dataLocation(), destination.executableAddress());
693 static void repatchCompact(CodeLocationDataLabelCompact dataLabelCompact, int32_t value)
695 AssemblerType::repatchCompact(dataLabelCompact.dataLocation(), value);
698 static void repatchInt32(CodeLocationDataLabel32 dataLabel32, int32_t value)
700 AssemblerType::repatchInt32(dataLabel32.dataLocation(), value);
703 static void repatchPointer(CodeLocationDataLabelPtr dataLabelPtr, void* value)
705 AssemblerType::repatchPointer(dataLabelPtr.dataLocation(), value);
708 static void* readPointer(CodeLocationDataLabelPtr dataLabelPtr)
710 return AssemblerType::readPointer(dataLabelPtr.dataLocation());
713 static void replaceWithLoad(CodeLocationConvertibleLoad label)
715 AssemblerType::replaceWithLoad(label.dataLocation());
718 static void replaceWithAddressComputation(CodeLocationConvertibleLoad label)
720 AssemblerType::replaceWithAddressComputation(label.dataLocation());
726 #endif // ENABLE(ASSEMBLER)
728 #endif // AbstractMacroAssembler_h