2 * Copyright (C) 2008-2018 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.
28 #include "AbortReason.h"
29 #include "AssemblerBuffer.h"
30 #include "AssemblerCommon.h"
32 #include "CodeLocation.h"
33 #include "JSCJSValue.h"
34 #include "JSCPtrTag.h"
35 #include "MacroAssemblerCodeRef.h"
36 #include "MacroAssemblerHelpers.h"
38 #include <wtf/CryptographicallyRandomNumber.h>
39 #include <wtf/Noncopyable.h>
40 #include <wtf/SharedTask.h>
41 #include <wtf/Vector.h>
42 #include <wtf/WeakRandom.h>
48 class AllowMacroScratchRegisterUsage;
49 class DisallowMacroScratchRegisterUsage;
56 class AbstractMacroAssemblerBase {
57 WTF_MAKE_FAST_ALLOCATED;
59 enum StatusCondition {
64 static StatusCondition invert(StatusCondition condition)
72 RELEASE_ASSERT_NOT_REACHED();
77 template <class AssemblerType>
78 class AbstractMacroAssembler : public AbstractMacroAssemblerBase {
80 typedef AbstractMacroAssembler<AssemblerType> AbstractMacroAssemblerType;
81 typedef AssemblerType AssemblerType_T;
83 template<PtrTag tag> using CodePtr = MacroAssemblerCodePtr<tag>;
84 template<PtrTag tag> using CodeRef = MacroAssemblerCodeRef<tag>;
86 enum class CPUIDCheckState {
94 typedef typename AssemblerType::RegisterID RegisterID;
95 typedef typename AssemblerType::SPRegisterID SPRegisterID;
96 typedef typename AssemblerType::FPRegisterID FPRegisterID;
98 static constexpr RegisterID firstRegister() { return AssemblerType::firstRegister(); }
99 static constexpr RegisterID lastRegister() { return AssemblerType::lastRegister(); }
100 static constexpr unsigned numberOfRegisters() { return AssemblerType::numberOfRegisters(); }
101 static const char* gprName(RegisterID id) { return AssemblerType::gprName(id); }
103 static constexpr SPRegisterID firstSPRegister() { return AssemblerType::firstSPRegister(); }
104 static constexpr SPRegisterID lastSPRegister() { return AssemblerType::lastSPRegister(); }
105 static constexpr unsigned numberOfSPRegisters() { return AssemblerType::numberOfSPRegisters(); }
106 static const char* sprName(SPRegisterID id) { return AssemblerType::sprName(id); }
108 static constexpr FPRegisterID firstFPRegister() { return AssemblerType::firstFPRegister(); }
109 static constexpr FPRegisterID lastFPRegister() { return AssemblerType::lastFPRegister(); }
110 static constexpr unsigned numberOfFPRegisters() { return AssemblerType::numberOfFPRegisters(); }
111 static const char* fprName(FPRegisterID id) { return AssemblerType::fprName(id); }
113 // Section 1: MacroAssembler operand types
115 // The following types are used as operands to MacroAssembler operations,
116 // describing immediate and memory operands to the instructions to be planted.
125 static Scale timesPtr()
127 if (sizeof(void*) == 4)
134 static RegisterID withSwappedRegister(RegisterID original, RegisterID left, RegisterID right)
136 if (original == left)
138 if (original == right)
145 // Describes a simple base-offset address.
147 explicit Address(RegisterID base, int32_t offset = 0)
153 Address withOffset(int32_t additionalOffset)
155 return Address(base, offset + additionalOffset);
158 Address withSwappedRegister(RegisterID left, RegisterID right)
160 return Address(AbstractMacroAssembler::withSwappedRegister(base, left, right), offset);
163 BaseIndex indexedBy(RegisterID index, Scale) const;
169 struct ExtendedAddress {
170 explicit ExtendedAddress(RegisterID base, intptr_t offset = 0)
182 // This class is used for explicit 'load' and 'store' operations
183 // (as opposed to situations in which a memory operand is provided
184 // to a generic operation, such as an integer arithmetic instruction).
186 // In the case of a load (or store) operation we want to permit
187 // addresses to be implicitly constructed, e.g. the two calls:
189 // load32(Address(addrReg), destReg);
190 // load32(addrReg, destReg);
192 // Are equivalent, and the explicit wrapping of the Address in the former
194 struct ImplicitAddress {
195 ImplicitAddress(RegisterID base)
201 ImplicitAddress(Address address)
203 , offset(address.offset)
213 // Describes a complex addressing mode.
215 BaseIndex(RegisterID base, RegisterID index, Scale scale, int32_t offset = 0)
228 BaseIndex withOffset(int32_t additionalOffset)
230 return BaseIndex(base, index, scale, offset + additionalOffset);
233 BaseIndex withSwappedRegister(RegisterID left, RegisterID right)
235 return BaseIndex(AbstractMacroAssembler::withSwappedRegister(base, left, right), AbstractMacroAssembler::withSwappedRegister(index, left, right), scale, offset);
241 // Describes an memory operand given by a pointer. For regular load & store
242 // operations an unwrapped void* will be used, rather than using this.
243 struct AbsoluteAddress {
244 explicit AbsoluteAddress(const void* ptr)
254 // An empty super class of each of the TrustedImm types. This class is used for template overloads
255 // on a TrustedImm type via std::is_base_of.
256 struct TrustedImm { };
260 // A pointer sized immediate operand to an instruction - this is wrapped
261 // in a class requiring explicit construction in order to differentiate
262 // from pointers used as absolute addresses to memory operations
263 struct TrustedImmPtr : public TrustedImm {
266 explicit TrustedImmPtr(const void* value)
271 template<typename ReturnType, typename... Arguments>
272 explicit TrustedImmPtr(ReturnType(*value)(Arguments...))
273 : m_value(reinterpret_cast<void*>(value))
277 explicit TrustedImmPtr(std::nullptr_t)
281 explicit TrustedImmPtr(size_t value)
282 : m_value(reinterpret_cast<void*>(value))
288 return reinterpret_cast<intptr_t>(m_value);
293 return const_cast<void*>(m_value);
296 const void* m_value { 0 };
299 struct ImmPtr : private TrustedImmPtr
301 explicit ImmPtr(const void* value)
302 : TrustedImmPtr(value)
306 TrustedImmPtr asTrustedImmPtr() { return *this; }
311 // A 32bit immediate operand to an instruction - this is wrapped in a
312 // class requiring explicit construction in order to prevent RegisterIDs
313 // (which are implemented as an enum) from accidentally being passed as
315 struct TrustedImm32 : public TrustedImm {
318 explicit TrustedImm32(int32_t value)
324 explicit TrustedImm32(TrustedImmPtr ptr)
325 : m_value(ptr.asIntptr())
334 struct Imm32 : private TrustedImm32 {
335 explicit Imm32(int32_t value)
336 : TrustedImm32(value)
340 explicit Imm32(TrustedImmPtr ptr)
345 const TrustedImm32& asTrustedImm32() const { return *this; }
351 // A 64bit immediate operand to an instruction - this is wrapped in a
352 // class requiring explicit construction in order to prevent RegisterIDs
353 // (which are implemented as an enum) from accidentally being passed as
355 struct TrustedImm64 : TrustedImm {
358 explicit TrustedImm64(int64_t value)
363 #if CPU(X86_64) || CPU(ARM64)
364 explicit TrustedImm64(TrustedImmPtr ptr)
365 : m_value(ptr.asIntptr())
373 struct Imm64 : private TrustedImm64
375 explicit Imm64(int64_t value)
376 : TrustedImm64(value)
379 #if CPU(X86_64) || CPU(ARM64)
380 explicit Imm64(TrustedImmPtr ptr)
385 const TrustedImm64& asTrustedImm64() const { return *this; }
388 // Section 2: MacroAssembler code buffer handles
390 // The following types are used to reference items in the code buffer
391 // during JIT code generation. For example, the type Jump is used to
392 // track the location of a jump instruction so that it may later be
393 // linked to a label marking its destination.
398 // A Label records a point in the generated instruction stream, typically such that
399 // it may be used as a destination for a jump.
401 friend class AbstractMacroAssembler<AssemblerType>;
402 friend struct DFG::OSRExit;
404 template<PtrTag> friend class MacroAssemblerCodeRef;
405 friend class LinkBuffer;
406 friend class Watchpoint;
413 Label(AbstractMacroAssemblerType* masm)
414 : m_label(masm->m_assembler.label())
416 masm->invalidateAllTempRegisters();
419 bool operator==(const Label& other) const { return m_label == other.m_label; }
421 bool isSet() const { return m_label.isSet(); }
423 AssemblerLabel m_label;
426 // ConvertibleLoadLabel:
428 // A ConvertibleLoadLabel records a loadPtr instruction that can be patched to an addPtr
431 // loadPtr(Address(a, i), b)
435 // addPtr(TrustedImmPtr(i), a, b)
436 class ConvertibleLoadLabel {
437 friend class AbstractMacroAssembler<AssemblerType>;
438 friend class LinkBuffer;
441 ConvertibleLoadLabel()
445 ConvertibleLoadLabel(AbstractMacroAssemblerType* masm)
446 : m_label(masm->m_assembler.labelIgnoringWatchpoints())
450 bool isSet() const { return m_label.isSet(); }
452 AssemblerLabel m_label;
457 // A DataLabelPtr is used to refer to a location in the code containing a pointer to be
458 // patched after the code has been generated.
460 friend class AbstractMacroAssembler<AssemblerType>;
461 friend class LinkBuffer;
467 DataLabelPtr(AbstractMacroAssemblerType* masm)
468 : m_label(masm->m_assembler.label())
472 bool isSet() const { return m_label.isSet(); }
475 AssemblerLabel m_label;
480 // A DataLabel32 is used to refer to a location in the code containing a 32-bit constant to be
481 // patched after the code has been generated.
483 friend class AbstractMacroAssembler<AssemblerType>;
484 friend class LinkBuffer;
490 DataLabel32(AbstractMacroAssemblerType* masm)
491 : m_label(masm->m_assembler.label())
495 AssemblerLabel label() const { return m_label; }
498 AssemblerLabel m_label;
503 // A DataLabelCompact is used to refer to a location in the code containing a
504 // compact immediate to be patched after the code has been generated.
505 class DataLabelCompact {
506 friend class AbstractMacroAssembler<AssemblerType>;
507 friend class LinkBuffer;
513 DataLabelCompact(AbstractMacroAssemblerType* masm)
514 : m_label(masm->m_assembler.label())
518 DataLabelCompact(AssemblerLabel label)
523 AssemblerLabel label() const { return m_label; }
526 AssemblerLabel m_label;
531 // A Call object is a reference to a call instruction that has been planted
532 // into the code buffer - it is typically used to link the call, setting the
533 // relative offset such that when executed it will call to the desired
536 friend class AbstractMacroAssembler<AssemblerType>;
545 LinkableNearTail = 0x7,
553 Call(AssemblerLabel jmp, Flags flags)
559 bool isFlagSet(Flags flag)
561 return m_flags & flag;
564 static Call fromTailJump(Jump jump)
566 return Call(jump.m_label, Linkable);
569 AssemblerLabel m_label;
576 // A jump object is a reference to a jump instruction that has been planted
577 // into the code buffer - it is typically used to link the jump, setting the
578 // relative offset such that when executed it will jump to the desired
581 friend class AbstractMacroAssembler<AssemblerType>;
583 friend struct DFG::OSRExit;
584 friend class LinkBuffer;
591 // Fixme: this information should be stored in the instruction stream, not in the Jump object.
592 Jump(AssemblerLabel jmp, ARMv7Assembler::JumpType type = ARMv7Assembler::JumpNoCondition, ARMv7Assembler::Condition condition = ARMv7Assembler::ConditionInvalid)
595 , m_condition(condition)
599 Jump(AssemblerLabel jmp, ARM64Assembler::JumpType type = ARM64Assembler::JumpNoCondition, ARM64Assembler::Condition condition = ARM64Assembler::ConditionInvalid)
602 , m_condition(condition)
606 Jump(AssemblerLabel jmp, ARM64Assembler::JumpType type, ARM64Assembler::Condition condition, bool is64Bit, ARM64Assembler::RegisterID compareRegister)
609 , m_condition(condition)
611 , m_compareRegister(compareRegister)
613 ASSERT((type == ARM64Assembler::JumpCompareAndBranch) || (type == ARM64Assembler::JumpCompareAndBranchFixedSize));
616 Jump(AssemblerLabel jmp, ARM64Assembler::JumpType type, ARM64Assembler::Condition condition, unsigned bitNumber, ARM64Assembler::RegisterID compareRegister)
619 , m_condition(condition)
620 , m_bitNumber(bitNumber)
621 , m_compareRegister(compareRegister)
623 ASSERT((type == ARM64Assembler::JumpTestBit) || (type == ARM64Assembler::JumpTestBitFixedSize));
626 Jump(AssemblerLabel jmp)
635 result.m_label = m_label;
639 void link(AbstractMacroAssemblerType* masm) const
641 masm->invalidateAllTempRegisters();
643 #if ENABLE(DFG_REGISTER_ALLOCATION_VALIDATION)
644 masm->checkRegisterAllocationAgainstBranchRange(m_label.m_offset, masm->debugOffset());
648 masm->m_assembler.linkJump(m_label, masm->m_assembler.label(), m_type, m_condition);
650 if ((m_type == ARM64Assembler::JumpCompareAndBranch) || (m_type == ARM64Assembler::JumpCompareAndBranchFixedSize))
651 masm->m_assembler.linkJump(m_label, masm->m_assembler.label(), m_type, m_condition, m_is64Bit, m_compareRegister);
652 else if ((m_type == ARM64Assembler::JumpTestBit) || (m_type == ARM64Assembler::JumpTestBitFixedSize))
653 masm->m_assembler.linkJump(m_label, masm->m_assembler.label(), m_type, m_condition, m_bitNumber, m_compareRegister);
655 masm->m_assembler.linkJump(m_label, masm->m_assembler.label(), m_type, m_condition);
657 masm->m_assembler.linkJump(m_label, masm->m_assembler.label());
661 void linkTo(Label label, AbstractMacroAssemblerType* masm) const
663 #if ENABLE(DFG_REGISTER_ALLOCATION_VALIDATION)
664 masm->checkRegisterAllocationAgainstBranchRange(label.m_label.m_offset, m_label.m_offset);
668 masm->m_assembler.linkJump(m_label, label.m_label, m_type, m_condition);
670 if ((m_type == ARM64Assembler::JumpCompareAndBranch) || (m_type == ARM64Assembler::JumpCompareAndBranchFixedSize))
671 masm->m_assembler.linkJump(m_label, label.m_label, m_type, m_condition, m_is64Bit, m_compareRegister);
672 else if ((m_type == ARM64Assembler::JumpTestBit) || (m_type == ARM64Assembler::JumpTestBitFixedSize))
673 masm->m_assembler.linkJump(m_label, label.m_label, m_type, m_condition, m_bitNumber, m_compareRegister);
675 masm->m_assembler.linkJump(m_label, label.m_label, m_type, m_condition);
677 masm->m_assembler.linkJump(m_label, label.m_label);
681 bool isSet() const { return m_label.isSet(); }
684 AssemblerLabel m_label;
686 ARMv7Assembler::JumpType m_type;
687 ARMv7Assembler::Condition m_condition;
689 ARM64Assembler::JumpType m_type;
690 ARM64Assembler::Condition m_condition;
692 unsigned m_bitNumber;
693 ARM64Assembler::RegisterID m_compareRegister;
697 struct PatchableJump {
702 explicit PatchableJump(Jump jump)
707 operator Jump&() { return m_jump; }
714 // A JumpList is a set of Jump objects.
715 // All jumps in the set will be linked to the same destination.
718 typedef Vector<Jump, 2> JumpVector;
728 void link(AbstractMacroAssemblerType* masm) const
730 size_t size = m_jumps.size();
731 for (size_t i = 0; i < size; ++i)
732 m_jumps[i].link(masm);
735 void linkTo(Label label, AbstractMacroAssemblerType* masm) const
737 size_t size = m_jumps.size();
738 for (size_t i = 0; i < size; ++i)
739 m_jumps[i].linkTo(label, masm);
742 void append(Jump jump)
745 m_jumps.append(jump);
748 void append(const JumpList& other)
750 m_jumps.append(other.m_jumps.begin(), other.m_jumps.size());
755 return !m_jumps.size();
763 const JumpVector& jumps() const { return m_jumps; }
770 // Section 3: Misc admin methods
772 Label labelIgnoringWatchpoints()
775 result.m_label = m_assembler.labelIgnoringWatchpoints();
779 Label labelIgnoringWatchpoints()
790 void padBeforePatch()
792 // Rely on the fact that asking for a label already does the padding.
796 Label watchpointLabel()
799 result.m_label = m_assembler.labelForWatchpoint();
805 m_assembler.align(16);
809 #if ENABLE(DFG_REGISTER_ALLOCATION_VALIDATION)
810 class RegisterAllocationOffset {
812 RegisterAllocationOffset(unsigned offset)
817 void checkOffsets(unsigned low, unsigned high)
819 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);
826 void addRegisterAllocationAtOffset(unsigned offset)
828 m_registerAllocationForOffsets.append(RegisterAllocationOffset(offset));
831 void clearRegisterAllocationOffsets()
833 m_registerAllocationForOffsets.clear();
836 void checkRegisterAllocationAgainstBranchRange(unsigned offset1, unsigned offset2)
838 if (offset1 > offset2)
839 std::swap(offset1, offset2);
841 size_t size = m_registerAllocationForOffsets.size();
842 for (size_t i = 0; i < size; ++i)
843 m_registerAllocationForOffsets[i].checkOffsets(offset1, offset2);
847 template<typename T, typename U>
848 static ptrdiff_t differenceBetween(T from, U to)
850 return AssemblerType::getDifferenceBetweenLabels(from.m_label, to.m_label);
853 template<PtrTag aTag, PtrTag bTag>
854 static ptrdiff_t differenceBetweenCodePtr(const MacroAssemblerCodePtr<aTag>& a, const MacroAssemblerCodePtr<bTag>& b)
856 return b.template dataLocation<ptrdiff_t>() - a.template dataLocation<ptrdiff_t>();
859 unsigned debugOffset() { return m_assembler.debugOffset(); }
861 ALWAYS_INLINE static void cacheFlush(void* code, size_t size)
863 AssemblerType::cacheFlush(code, size);
867 static void linkJump(void* code, Jump jump, CodeLocationLabel<tag> target)
869 AssemblerType::linkJump(code, jump.m_label, target.dataLocation());
872 static void linkPointer(void* code, AssemblerLabel label, void* value)
874 AssemblerType::linkPointer(code, label, value);
878 static void linkPointer(void* code, AssemblerLabel label, MacroAssemblerCodePtr<tag> value)
880 AssemblerType::linkPointer(code, label, value.executableAddress());
884 static void* getLinkerAddress(void* code, AssemblerLabel label)
886 return tagCodePtr(AssemblerType::getRelocatedAddress(code, label), tag);
889 static unsigned getLinkerCallReturnOffset(Call call)
891 return AssemblerType::getCallReturnOffset(call.m_label);
894 template<PtrTag jumpTag, PtrTag destTag>
895 static void repatchJump(CodeLocationJump<jumpTag> jump, CodeLocationLabel<destTag> destination)
897 AssemblerType::relinkJump(jump.dataLocation(), destination.dataLocation());
900 template<PtrTag jumpTag>
901 static void repatchJumpToNop(CodeLocationJump<jumpTag> jump)
903 AssemblerType::relinkJumpToNop(jump.dataLocation());
906 template<PtrTag callTag, PtrTag destTag>
907 static void repatchNearCall(CodeLocationNearCall<callTag> nearCall, CodeLocationLabel<destTag> destination)
909 switch (nearCall.callMode()) {
910 case NearCallMode::Tail:
911 AssemblerType::relinkJump(nearCall.dataLocation(), destination.dataLocation());
913 case NearCallMode::Regular:
914 AssemblerType::relinkCall(nearCall.dataLocation(), destination.untaggedExecutableAddress());
917 RELEASE_ASSERT_NOT_REACHED();
921 static void repatchCompact(CodeLocationDataLabelCompact<tag> dataLabelCompact, int32_t value)
923 AssemblerType::repatchCompact(dataLabelCompact.template dataLocation(), value);
927 static void repatchInt32(CodeLocationDataLabel32<tag> dataLabel32, int32_t value)
929 AssemblerType::repatchInt32(dataLabel32.dataLocation(), value);
933 static void repatchPointer(CodeLocationDataLabelPtr<tag> dataLabelPtr, void* value)
935 AssemblerType::repatchPointer(dataLabelPtr.dataLocation(), value);
939 static void* readPointer(CodeLocationDataLabelPtr<tag> dataLabelPtr)
941 return AssemblerType::readPointer(dataLabelPtr.dataLocation());
945 static void replaceWithLoad(CodeLocationConvertibleLoad<tag> label)
947 AssemblerType::replaceWithLoad(label.dataLocation());
951 static void replaceWithAddressComputation(CodeLocationConvertibleLoad<tag> label)
953 AssemblerType::replaceWithAddressComputation(label.dataLocation());
956 template<typename Functor>
957 void addLinkTask(const Functor& functor)
959 m_linkTasks.append(createSharedTask<void(LinkBuffer&)>(functor));
962 void emitNops(size_t memoryToFillWithNopsInBytes)
965 RELEASE_ASSERT(memoryToFillWithNopsInBytes % 4 == 0);
966 for (unsigned i = 0; i < memoryToFillWithNopsInBytes / 4; ++i)
969 AssemblerBuffer& buffer = m_assembler.buffer();
970 size_t startCodeSize = buffer.codeSize();
971 size_t targetCodeSize = startCodeSize + memoryToFillWithNopsInBytes;
972 buffer.ensureSpace(memoryToFillWithNopsInBytes);
973 AssemblerType::fillNops(static_cast<char*>(buffer.data()) + startCodeSize, memoryToFillWithNopsInBytes, memcpy);
974 buffer.setCodeSize(targetCodeSize);
978 ALWAYS_INLINE void tagReturnAddress() { }
979 ALWAYS_INLINE void untagReturnAddress() { }
981 ALWAYS_INLINE void tagPtr(PtrTag, RegisterID) { }
982 ALWAYS_INLINE void tagPtr(RegisterID, RegisterID) { }
983 ALWAYS_INLINE void untagPtr(PtrTag, RegisterID) { }
984 ALWAYS_INLINE void untagPtr(RegisterID, RegisterID) { }
985 ALWAYS_INLINE void removePtrTag(RegisterID) { }
988 AbstractMacroAssembler()
992 invalidateAllTempRegisters();
997 if (!m_randomSourceIsInitialized) {
998 m_randomSourceIsInitialized = true;
999 m_randomSource.setSeed(cryptographicallyRandomNumber());
1001 return m_randomSource.getUint32();
1004 bool m_randomSourceIsInitialized { false };
1005 WeakRandom m_randomSource;
1007 AssemblerType m_assembler;
1010 #if ENABLE(DFG_REGISTER_ALLOCATION_VALIDATION)
1011 Vector<RegisterAllocationOffset, 10> m_registerAllocationForOffsets;
1014 static bool haveScratchRegisterForBlinding()
1018 static RegisterID scratchRegisterForBlinding()
1020 UNREACHABLE_FOR_PLATFORM();
1021 return firstRegister();
1023 static bool canBlind() { return false; }
1024 static bool shouldBlindForSpecificArch(uint32_t) { return false; }
1025 static bool shouldBlindForSpecificArch(uint64_t) { return false; }
1027 class CachedTempRegister {
1028 friend class DataLabelPtr;
1029 friend class DataLabel32;
1030 friend class DataLabelCompact;
1035 CachedTempRegister(AbstractMacroAssemblerType* masm, RegisterID registerID)
1037 , m_registerID(registerID)
1039 , m_validBit(1 << static_cast<unsigned>(registerID))
1041 ASSERT(static_cast<unsigned>(registerID) < (sizeof(unsigned) * 8));
1044 ALWAYS_INLINE RegisterID registerIDInvalidate() { invalidate(); return m_registerID; }
1046 ALWAYS_INLINE RegisterID registerIDNoInvalidate() { return m_registerID; }
1048 bool value(intptr_t& value)
1051 return m_masm->isTempRegisterValid(m_validBit);
1054 void setValue(intptr_t value)
1057 m_masm->setTempRegisterValid(m_validBit);
1060 ALWAYS_INLINE void invalidate() { m_masm->clearTempRegisterValid(m_validBit); }
1063 AbstractMacroAssemblerType* m_masm;
1064 RegisterID m_registerID;
1066 unsigned m_validBit;
1069 ALWAYS_INLINE void invalidateAllTempRegisters()
1071 m_tempRegistersValidBits = 0;
1074 ALWAYS_INLINE bool isTempRegisterValid(unsigned registerMask)
1076 return (m_tempRegistersValidBits & registerMask);
1079 ALWAYS_INLINE void clearTempRegisterValid(unsigned registerMask)
1081 m_tempRegistersValidBits &= ~registerMask;
1084 ALWAYS_INLINE void setTempRegisterValid(unsigned registerMask)
1086 m_tempRegistersValidBits |= registerMask;
1089 friend class AllowMacroScratchRegisterUsage;
1090 friend class AllowMacroScratchRegisterUsageIf;
1091 friend class DisallowMacroScratchRegisterUsage;
1092 unsigned m_tempRegistersValidBits;
1093 bool m_allowScratchRegister { true };
1095 Vector<RefPtr<SharedTask<void(LinkBuffer&)>>> m_linkTasks;
1097 friend class LinkBuffer;
1098 }; // class AbstractMacroAssembler
1100 template <class AssemblerType>
1101 inline typename AbstractMacroAssembler<AssemblerType>::BaseIndex
1102 AbstractMacroAssembler<AssemblerType>::Address::indexedBy(
1103 typename AbstractMacroAssembler<AssemblerType>::RegisterID index,
1104 typename AbstractMacroAssembler<AssemblerType>::Scale scale) const
1106 return BaseIndex(base, index, scale, offset);
1109 #endif // ENABLE(ASSEMBLER)
1113 #if ENABLE(ASSEMBLER)
1119 void printInternal(PrintStream& out, JSC::AbstractMacroAssemblerBase::StatusCondition);
1123 #endif // ENABLE(ASSEMBLER)