summaryrefslogtreecommitdiff
path: root/Source/JavaScriptCore/assembler/AbstractMacroAssembler.h
diff options
context:
space:
mode:
authorLorry Tar Creator <lorry-tar-importer@lorry>2017-06-27 06:07:23 +0000
committerLorry Tar Creator <lorry-tar-importer@lorry>2017-06-27 06:07:23 +0000
commit1bf1084f2b10c3b47fd1a588d85d21ed0eb41d0c (patch)
tree46dcd36c86e7fbc6e5df36deb463b33e9967a6f7 /Source/JavaScriptCore/assembler/AbstractMacroAssembler.h
parent32761a6cee1d0dee366b885b7b9c777e67885688 (diff)
downloadWebKitGtk-tarball-master.tar.gz
Diffstat (limited to 'Source/JavaScriptCore/assembler/AbstractMacroAssembler.h')
-rw-r--r--Source/JavaScriptCore/assembler/AbstractMacroAssembler.h423
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