diff options
author | Lorry Tar Creator <lorry-tar-importer@lorry> | 2017-06-27 06:07:23 +0000 |
---|---|---|
committer | Lorry Tar Creator <lorry-tar-importer@lorry> | 2017-06-27 06:07:23 +0000 |
commit | 1bf1084f2b10c3b47fd1a588d85d21ed0eb41d0c (patch) | |
tree | 46dcd36c86e7fbc6e5df36deb463b33e9967a6f7 /Source/JavaScriptCore/assembler/AbstractMacroAssembler.h | |
parent | 32761a6cee1d0dee366b885b7b9c777e67885688 (diff) | |
download | WebKitGtk-tarball-master.tar.gz |
webkitgtk-2.16.5HEADwebkitgtk-2.16.5master
Diffstat (limited to 'Source/JavaScriptCore/assembler/AbstractMacroAssembler.h')
-rw-r--r-- | Source/JavaScriptCore/assembler/AbstractMacroAssembler.h | 423 |
1 files changed, 266 insertions, 157 deletions
diff --git a/Source/JavaScriptCore/assembler/AbstractMacroAssembler.h b/Source/JavaScriptCore/assembler/AbstractMacroAssembler.h index 28537201b..b791e5cb1 100644 --- a/Source/JavaScriptCore/assembler/AbstractMacroAssembler.h +++ b/Source/JavaScriptCore/assembler/AbstractMacroAssembler.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2008, 2012 Apple Inc. All rights reserved. + * Copyright (C) 2008, 2012, 2014-2016 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -23,74 +23,37 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef AbstractMacroAssembler_h -#define AbstractMacroAssembler_h +#pragma once +#include "AbortReason.h" #include "AssemblerBuffer.h" +#include "AssemblerCommon.h" +#include "CPU.h" #include "CodeLocation.h" #include "MacroAssemblerCodeRef.h" +#include "MacroAssemblerHelpers.h" #include "Options.h" -#include "WeakRandom.h" #include <wtf/CryptographicallyRandomNumber.h> #include <wtf/Noncopyable.h> - -#if ENABLE(ASSEMBLER) +#include <wtf/SharedTask.h> +#include <wtf/WeakRandom.h> namespace JSC { -inline bool isARMv7s() -{ -#if CPU(APPLE_ARMV7S) - return true; -#else - return false; -#endif -} - -inline bool isARM64() -{ -#if CPU(ARM64) - return true; -#else - return false; -#endif -} - -inline bool isX86() -{ -#if CPU(X86_64) || CPU(X86) - return true; -#else - return false; -#endif -} - -inline bool optimizeForARMv7s() -{ - return isARMv7s() && Options::enableArchitectureSpecificOptimizations(); -} - -inline bool optimizeForARM64() -{ - return isARM64() && Options::enableArchitectureSpecificOptimizations(); -} - -inline bool optimizeForX86() -{ - return isX86() && Options::enableArchitectureSpecificOptimizations(); -} +#if ENABLE(ASSEMBLER) +class AllowMacroScratchRegisterUsage; +class DisallowMacroScratchRegisterUsage; class LinkBuffer; -class RepatchBuffer; class Watchpoint; namespace DFG { struct OSRExit; } -template <class AssemblerType> +template <class AssemblerType, class MacroAssemblerType> class AbstractMacroAssembler { public: - friend class JITWriteBarrierBase; + typedef AbstractMacroAssembler<AssemblerType, MacroAssemblerType> AbstractMacroAssemblerType; typedef AssemblerType AssemblerType_T; typedef MacroAssemblerCodePtr CodePtr; @@ -101,11 +64,11 @@ public: typedef typename AssemblerType::RegisterID RegisterID; typedef typename AssemblerType::FPRegisterID FPRegisterID; - static RegisterID firstRegister() { return AssemblerType::firstRegister(); } - static RegisterID lastRegister() { return AssemblerType::lastRegister(); } + static constexpr RegisterID firstRegister() { return AssemblerType::firstRegister(); } + static constexpr RegisterID lastRegister() { return AssemblerType::lastRegister(); } - static FPRegisterID firstFPRegister() { return AssemblerType::firstFPRegister(); } - static FPRegisterID lastFPRegister() { return AssemblerType::lastFPRegister(); } + static constexpr FPRegisterID firstFPRegister() { return AssemblerType::firstFPRegister(); } + static constexpr FPRegisterID lastFPRegister() { return AssemblerType::lastFPRegister(); } // Section 1: MacroAssembler operand types // @@ -125,7 +88,9 @@ public: return TimesFour; return TimesEight; } - + + struct BaseIndex; + // Address: // // Describes a simple base-offset address. @@ -140,7 +105,9 @@ public: { return Address(base, offset + additionalOffset); } - + + BaseIndex indexedBy(RegisterID index, Scale) const; + RegisterID base; int32_t offset; }; @@ -198,11 +165,16 @@ public: , offset(offset) { } - + RegisterID base; RegisterID index; Scale scale; int32_t offset; + + BaseIndex withOffset(int32_t additionalOffset) + { + return BaseIndex(base, index, scale, offset + additionalOffset); + } }; // AbsoluteAddress: @@ -354,7 +326,7 @@ public: // A Label records a point in the generated instruction stream, typically such that // it may be used as a destination for a jump. class Label { - template<class TemplateAssemblerType> + template<class TemplateAssemblerType, class TemplateMacroAssemblerType> friend class AbstractMacroAssembler; friend struct DFG::OSRExit; friend class Jump; @@ -367,12 +339,14 @@ public: { } - Label(AbstractMacroAssembler<AssemblerType>* masm) + Label(AbstractMacroAssemblerType* masm) : m_label(masm->m_assembler.label()) { masm->invalidateAllTempRegisters(); } + bool operator==(const Label& other) const { return m_label == other.m_label; } + bool isSet() const { return m_label.isSet(); } private: AssemblerLabel m_label; @@ -389,7 +363,7 @@ public: // // addPtr(TrustedImmPtr(i), a, b) class ConvertibleLoadLabel { - template<class TemplateAssemblerType> + template<class TemplateAssemblerType, class TemplateMacroAssemblerType> friend class AbstractMacroAssembler; friend class LinkBuffer; @@ -398,7 +372,7 @@ public: { } - ConvertibleLoadLabel(AbstractMacroAssembler<AssemblerType>* masm) + ConvertibleLoadLabel(AbstractMacroAssemblerType* masm) : m_label(masm->m_assembler.labelIgnoringWatchpoints()) { } @@ -413,7 +387,7 @@ public: // A DataLabelPtr is used to refer to a location in the code containing a pointer to be // patched after the code has been generated. class DataLabelPtr { - template<class TemplateAssemblerType> + template<class TemplateAssemblerType, class TemplateMacroAssemblerType> friend class AbstractMacroAssembler; friend class LinkBuffer; public: @@ -421,7 +395,7 @@ public: { } - DataLabelPtr(AbstractMacroAssembler<AssemblerType>* masm) + DataLabelPtr(AbstractMacroAssemblerType* masm) : m_label(masm->m_assembler.label()) { } @@ -434,10 +408,10 @@ public: // DataLabel32: // - // A DataLabelPtr is used to refer to a location in the code containing a pointer to be + // A DataLabel32 is used to refer to a location in the code containing a 32-bit constant to be // patched after the code has been generated. class DataLabel32 { - template<class TemplateAssemblerType> + template<class TemplateAssemblerType, class TemplateMacroAssemblerType> friend class AbstractMacroAssembler; friend class LinkBuffer; public: @@ -445,7 +419,7 @@ public: { } - DataLabel32(AbstractMacroAssembler<AssemblerType>* masm) + DataLabel32(AbstractMacroAssemblerType* masm) : m_label(masm->m_assembler.label()) { } @@ -461,7 +435,7 @@ public: // A DataLabelCompact is used to refer to a location in the code containing a // compact immediate to be patched after the code has been generated. class DataLabelCompact { - template<class TemplateAssemblerType> + template<class TemplateAssemblerType, class TemplateMacroAssemblerType> friend class AbstractMacroAssembler; friend class LinkBuffer; public: @@ -469,7 +443,7 @@ public: { } - DataLabelCompact(AbstractMacroAssembler<AssemblerType>* masm) + DataLabelCompact(AbstractMacroAssemblerType* masm) : m_label(masm->m_assembler.label()) { } @@ -492,7 +466,7 @@ public: // relative offset such that when executed it will call to the desired // destination. class Call { - template<class TemplateAssemblerType> + template<class TemplateAssemblerType, class TemplateMacroAssemblerType> friend class AbstractMacroAssembler; public: @@ -500,7 +474,9 @@ public: None = 0x0, Linkable = 0x1, Near = 0x2, + Tail = 0x4, LinkableNear = 0x3, + LinkableNearTail = 0x7, }; Call() @@ -536,7 +512,7 @@ public: // relative offset such that when executed it will jump to the desired // destination. class Jump { - template<class TemplateAssemblerType> + template<class TemplateAssemblerType, class TemplateMacroAssemblerType> friend class AbstractMacroAssembler; friend class Call; friend struct DFG::OSRExit; @@ -581,12 +557,6 @@ public: { ASSERT((type == ARM64Assembler::JumpTestBit) || (type == ARM64Assembler::JumpTestBitFixedSize)); } -#elif CPU(SH4) - Jump(AssemblerLabel jmp, SH4Assembler::JumpType type = SH4Assembler::JumpFar) - : m_label(jmp) - , m_type(type) - { - } #else Jump(AssemblerLabel jmp) : m_label(jmp) @@ -601,7 +571,7 @@ public: return result; } - void link(AbstractMacroAssembler<AssemblerType>* masm) const + void link(AbstractMacroAssemblerType* masm) const { masm->invalidateAllTempRegisters(); @@ -618,14 +588,12 @@ public: masm->m_assembler.linkJump(m_label, masm->m_assembler.label(), m_type, m_condition, m_bitNumber, m_compareRegister); else masm->m_assembler.linkJump(m_label, masm->m_assembler.label(), m_type, m_condition); -#elif CPU(SH4) - masm->m_assembler.linkJump(m_label, masm->m_assembler.label(), m_type); #else masm->m_assembler.linkJump(m_label, masm->m_assembler.label()); #endif } - void linkTo(Label label, AbstractMacroAssembler<AssemblerType>* masm) const + void linkTo(Label label, AbstractMacroAssemblerType* masm) const { #if ENABLE(DFG_REGISTER_ALLOCATION_VALIDATION) masm->checkRegisterAllocationAgainstBranchRange(label.m_label.m_offset, m_label.m_offset); @@ -659,9 +627,6 @@ public: unsigned m_bitNumber; ARM64Assembler::RegisterID m_compareRegister; #endif -#if CPU(SH4) - SH4Assembler::JumpType m_type; -#endif }; struct PatchableJump { @@ -684,8 +649,6 @@ public: // A JumpList is a set of Jump objects. // All jumps in the set will be linked to the same destination. class JumpList { - friend class LinkBuffer; - public: typedef Vector<Jump, 2> JumpVector; @@ -693,23 +656,22 @@ public: JumpList(Jump jump) { - append(jump); + if (jump.isSet()) + append(jump); } - void link(AbstractMacroAssembler<AssemblerType>* masm) + void link(AbstractMacroAssemblerType* masm) const { size_t size = m_jumps.size(); for (size_t i = 0; i < size; ++i) m_jumps[i].link(masm); - m_jumps.clear(); } - void linkTo(Label label, AbstractMacroAssembler<AssemblerType>* masm) + void linkTo(Label label, AbstractMacroAssemblerType* masm) const { size_t size = m_jumps.size(); for (size_t i = 0; i < size; ++i) m_jumps[i].linkTo(label, masm); - m_jumps.clear(); } void append(Jump jump) @@ -834,19 +796,215 @@ public: AssemblerType::cacheFlush(code, size); } +#if ENABLE(MASM_PROBE) + + struct CPUState { + #define DECLARE_REGISTER(_type, _regName) \ + _type _regName; + FOR_EACH_CPU_REGISTER(DECLARE_REGISTER) + #undef DECLARE_REGISTER + + static const char* gprName(RegisterID regID) + { + switch (regID) { + #define DECLARE_REGISTER(_type, _regName) \ + case RegisterID::_regName: \ + return #_regName; + FOR_EACH_CPU_GPREGISTER(DECLARE_REGISTER) + #undef DECLARE_REGISTER + default: + RELEASE_ASSERT_NOT_REACHED(); + } + } + + static const char* fprName(FPRegisterID regID) + { + switch (regID) { + #define DECLARE_REGISTER(_type, _regName) \ + case FPRegisterID::_regName: \ + return #_regName; + FOR_EACH_CPU_FPREGISTER(DECLARE_REGISTER) + #undef DECLARE_REGISTER + default: + RELEASE_ASSERT_NOT_REACHED(); + } + } + + void*& gpr(RegisterID regID) + { + switch (regID) { + #define DECLARE_REGISTER(_type, _regName) \ + case RegisterID::_regName: \ + return _regName; + FOR_EACH_CPU_GPREGISTER(DECLARE_REGISTER) + #undef DECLARE_REGISTER + default: + RELEASE_ASSERT_NOT_REACHED(); + } + } + + double& fpr(FPRegisterID regID) + { + switch (regID) { + #define DECLARE_REGISTER(_type, _regName) \ + case FPRegisterID::_regName: \ + return _regName; + FOR_EACH_CPU_FPREGISTER(DECLARE_REGISTER) + #undef DECLARE_REGISTER + default: + RELEASE_ASSERT_NOT_REACHED(); + } + } + }; + + struct ProbeContext; + typedef void (*ProbeFunction)(struct ProbeContext*); + + struct ProbeContext { + ProbeFunction probeFunction; + void* arg1; + void* arg2; + CPUState cpu; + + // Convenience methods: + void*& gpr(RegisterID regID) { return cpu.gpr(regID); } + double& fpr(FPRegisterID regID) { return cpu.fpr(regID); } + const char* gprName(RegisterID regID) { return cpu.gprName(regID); } + const char* fprName(FPRegisterID regID) { return cpu.fprName(regID); } + }; + + // This function emits code to preserve the CPUState (e.g. registers), + // call a user supplied probe function, and restore the CPUState before + // continuing with other JIT generated code. + // + // The user supplied probe function will be called with a single pointer to + // a ProbeContext struct (defined above) which contains, among other things, + // the preserved CPUState. This allows the user probe function to inspect + // the CPUState at that point in the JIT generated code. + // + // If the user probe function alters the register values in the ProbeContext, + // the altered values will be loaded into the CPU registers when the probe + // returns. + // + // The ProbeContext is stack allocated and is only valid for the duration + // of the call to the user probe function. + // + // Note: probe() should be implemented by the target specific MacroAssembler. + // This prototype is only provided here to document the interface. + + void probe(ProbeFunction, void* arg1, void* arg2); + +#endif // ENABLE(MASM_PROBE) + AssemblerType m_assembler; + static void linkJump(void* code, Jump jump, CodeLocationLabel target) + { + AssemblerType::linkJump(code, jump.m_label, target.dataLocation()); + } + + static void linkPointer(void* code, AssemblerLabel label, void* value) + { + AssemblerType::linkPointer(code, label, value); + } + + static void* getLinkerAddress(void* code, AssemblerLabel label) + { + return AssemblerType::getRelocatedAddress(code, label); + } + + static unsigned getLinkerCallReturnOffset(Call call) + { + return AssemblerType::getCallReturnOffset(call.m_label); + } + + static void repatchJump(CodeLocationJump jump, CodeLocationLabel destination) + { + AssemblerType::relinkJump(jump.dataLocation(), destination.dataLocation()); + } + + static void repatchJumpToNop(CodeLocationJump jump) + { + AssemblerType::relinkJumpToNop(jump.dataLocation()); + } + + static void repatchNearCall(CodeLocationNearCall nearCall, CodeLocationLabel destination) + { + switch (nearCall.callMode()) { + case NearCallMode::Tail: + AssemblerType::relinkJump(nearCall.dataLocation(), destination.dataLocation()); + return; + case NearCallMode::Regular: + AssemblerType::relinkCall(nearCall.dataLocation(), destination.executableAddress()); + return; + } + RELEASE_ASSERT_NOT_REACHED(); + } + + static void repatchCompact(CodeLocationDataLabelCompact dataLabelCompact, int32_t value) + { + AssemblerType::repatchCompact(dataLabelCompact.dataLocation(), value); + } + + static void repatchInt32(CodeLocationDataLabel32 dataLabel32, int32_t value) + { + AssemblerType::repatchInt32(dataLabel32.dataLocation(), value); + } + + static void repatchPointer(CodeLocationDataLabelPtr dataLabelPtr, void* value) + { + AssemblerType::repatchPointer(dataLabelPtr.dataLocation(), value); + } + + static void* readPointer(CodeLocationDataLabelPtr dataLabelPtr) + { + return AssemblerType::readPointer(dataLabelPtr.dataLocation()); + } + + static void replaceWithLoad(CodeLocationConvertibleLoad label) + { + AssemblerType::replaceWithLoad(label.dataLocation()); + } + + static void replaceWithAddressComputation(CodeLocationConvertibleLoad label) + { + AssemblerType::replaceWithAddressComputation(label.dataLocation()); + } + + template<typename Functor> + void addLinkTask(const Functor& functor) + { + m_linkTasks.append(createSharedTask<void(LinkBuffer&)>(functor)); + } + + void emitNops(size_t memoryToFillWithNopsInBytes) + { + AssemblerBuffer& buffer = m_assembler.buffer(); + size_t startCodeSize = buffer.codeSize(); + size_t targetCodeSize = startCodeSize + memoryToFillWithNopsInBytes; + buffer.ensureSpace(memoryToFillWithNopsInBytes); + bool isCopyingToExecutableMemory = false; + AssemblerType::fillNops(static_cast<char*>(buffer.data()) + startCodeSize, memoryToFillWithNopsInBytes, isCopyingToExecutableMemory); + buffer.setCodeSize(targetCodeSize); + } + protected: AbstractMacroAssembler() - : m_randomSource(cryptographicallyRandomNumber()) + : m_randomSource(0) { + invalidateAllTempRegisters(); } uint32_t random() { + if (!m_randomSourceIsInitialized) { + m_randomSourceIsInitialized = true; + m_randomSource.setSeed(cryptographicallyRandomNumber()); + } return m_randomSource.getUint32(); } + bool m_randomSourceIsInitialized { false }; WeakRandom m_randomSource; #if ENABLE(DFG_REGISTER_ALLOCATION_VALIDATION) @@ -874,7 +1032,7 @@ protected: friend class Label; public: - CachedTempRegister(AbstractMacroAssembler<AssemblerType>* masm, RegisterID registerID) + CachedTempRegister(AbstractMacroAssemblerType* masm, RegisterID registerID) : m_masm(masm) , m_registerID(registerID) , m_value(0) @@ -902,7 +1060,7 @@ protected: ALWAYS_INLINE void invalidate() { m_masm->clearTempRegisterValid(m_validBit); } private: - AbstractMacroAssembler<AssemblerType>* m_masm; + AbstractMacroAssemblerType* m_masm; RegisterID m_registerID; intptr_t m_value; unsigned m_validBit; @@ -928,74 +1086,25 @@ protected: m_tempRegistersValidBits |= registerMask; } + friend class AllowMacroScratchRegisterUsage; + friend class DisallowMacroScratchRegisterUsage; unsigned m_tempRegistersValidBits; + bool m_allowScratchRegister { true }; - friend class LinkBuffer; - friend class RepatchBuffer; - - static void linkJump(void* code, Jump jump, CodeLocationLabel target) - { - AssemblerType::linkJump(code, jump.m_label, target.dataLocation()); - } - - static void linkPointer(void* code, AssemblerLabel label, void* value) - { - AssemblerType::linkPointer(code, label, value); - } - - static void* getLinkerAddress(void* code, AssemblerLabel label) - { - return AssemblerType::getRelocatedAddress(code, label); - } - - static unsigned getLinkerCallReturnOffset(Call call) - { - return AssemblerType::getCallReturnOffset(call.m_label); - } - - static void repatchJump(CodeLocationJump jump, CodeLocationLabel destination) - { - AssemblerType::relinkJump(jump.dataLocation(), destination.dataLocation()); - } - - static void repatchNearCall(CodeLocationNearCall nearCall, CodeLocationLabel destination) - { - AssemblerType::relinkCall(nearCall.dataLocation(), destination.executableAddress()); - } - - static void repatchCompact(CodeLocationDataLabelCompact dataLabelCompact, int32_t value) - { - AssemblerType::repatchCompact(dataLabelCompact.dataLocation(), value); - } - - static void repatchInt32(CodeLocationDataLabel32 dataLabel32, int32_t value) - { - AssemblerType::repatchInt32(dataLabel32.dataLocation(), value); - } + Vector<RefPtr<SharedTask<void(LinkBuffer&)>>> m_linkTasks; - static void repatchPointer(CodeLocationDataLabelPtr dataLabelPtr, void* value) - { - AssemblerType::repatchPointer(dataLabelPtr.dataLocation(), value); - } - - static void* readPointer(CodeLocationDataLabelPtr dataLabelPtr) - { - return AssemblerType::readPointer(dataLabelPtr.dataLocation()); - } - - static void replaceWithLoad(CodeLocationConvertibleLoad label) - { - AssemblerType::replaceWithLoad(label.dataLocation()); - } - - static void replaceWithAddressComputation(CodeLocationConvertibleLoad label) - { - AssemblerType::replaceWithAddressComputation(label.dataLocation()); - } -}; + friend class LinkBuffer; +}; // class AbstractMacroAssembler -} // namespace JSC +template <class AssemblerType, class MacroAssemblerType> +inline typename AbstractMacroAssembler<AssemblerType, MacroAssemblerType>::BaseIndex +AbstractMacroAssembler<AssemblerType, MacroAssemblerType>::Address::indexedBy( + typename AbstractMacroAssembler<AssemblerType, MacroAssemblerType>::RegisterID index, + typename AbstractMacroAssembler<AssemblerType, MacroAssemblerType>::Scale scale) const +{ + return BaseIndex(base, index, scale, offset); +} #endif // ENABLE(ASSEMBLER) -#endif // AbstractMacroAssembler_h +} // namespace JSC |