Remove branch compaction #ifdef

Since the #ifdef for ARMv7 and ARM64 makes it impossible to cross
compile, we need to replace it with a template specialization of
LinkBuffer. The "old" LinkBuffer becomes LinkBufferBase, then there's a
generic LinkBuffer that's a sub-class of LinkBufferBase. Then there's a
BranchCompactingLinkBuffer template that implements the compaction and
two ARMv7 and ARM64 specializations of LinkBuffer<T> end up being
sub-classes of BranchCompactingLinkBuffer instead of LinkBufferBase.

Change-Id: Ib62fe24aa6c3570dfa311edc39fde6fb5975f3cc
Reviewed-by: Lars Knoll <lars.knoll@qt.io>
This commit is contained in:
Simon Hausmann 2017-01-20 10:43:55 +01:00
parent 64f21fc782
commit 4eca12e9f5
10 changed files with 156 additions and 69 deletions

View File

@ -47,8 +47,10 @@
namespace JSC {
class JumpReplacementWatchpoint;
template <typename, template <typename> class>
class LinkBufferBase;
template <typename>
class LinkBuffer;
class BranchCompactingLinkBuffer;
class RepatchBuffer;
class Watchpoint;
namespace DFG {
@ -326,7 +328,7 @@ public:
friend class Jump;
friend class JumpReplacementWatchpoint;
friend class MacroAssemblerCodeRef;
template <typename> friend class LinkBuffer;
template <typename, template <typename> class> friend class LinkBufferBase;
friend class Watchpoint;
public:
@ -357,7 +359,7 @@ public:
class ConvertibleLoadLabel {
template<class TemplateAssemblerType>
friend class AbstractMacroAssembler;
template <typename> friend class LinkBuffer;
template <typename, template <typename> class> friend class LinkBufferBase;
public:
ConvertibleLoadLabel()
@ -381,7 +383,7 @@ public:
class DataLabelPtr {
template<class TemplateAssemblerType>
friend class AbstractMacroAssembler;
template <typename> friend class LinkBuffer;
template <typename, template <typename> class> friend class LinkBufferBase;
public:
DataLabelPtr()
{
@ -405,7 +407,7 @@ public:
class DataLabel32 {
template<class TemplateAssemblerType>
friend class AbstractMacroAssembler;
template <typename> friend class LinkBuffer;
template <typename, template <typename> class> friend class LinkBufferBase;
public:
DataLabel32()
{
@ -429,7 +431,7 @@ public:
class DataLabelCompact {
template<class TemplateAssemblerType>
friend class AbstractMacroAssembler;
template <typename> friend class LinkBuffer;
template <typename, template <typename> class> friend class LinkBufferBase;
public:
DataLabelCompact()
{
@ -504,7 +506,7 @@ public:
friend class AbstractMacroAssembler;
friend class Call;
friend struct DFG::OSRExit;
template <typename> friend class LinkBuffer;
template <typename, template <typename> class> friend class LinkBufferBase;
public:
Jump()
{
@ -646,7 +648,7 @@ public:
// A JumpList is a set of Jump objects.
// All jumps in the set will be linked to the same destination.
class JumpList {
template <typename> friend class LinkBuffer;
template <typename, template <typename> class> friend class LinkBufferBase;
public:
typedef Vector<Jump, 2> JumpVector;
@ -820,7 +822,8 @@ protected:
static bool shouldBlindForSpecificArch(uint64_t) { return true; }
#endif
template <typename> friend class LinkBuffer;
template <typename, template <typename> class> friend class LinkBufferBase;
template <typename> friend class BranchCompactingLinkBuffer;
friend class RepatchBuffer;
static void linkJump(void* code, Jump jump, CodeLocationLabel target)

View File

@ -44,6 +44,12 @@ namespace JSC {
class JSGlobalData;
template <typename T>
struct DefaultExecutableOffsetCalculator {
template <typename Assembler>
static T applyOffset(Assembler *, T src) { return src; }
};
// LinkBuffer:
//
// This class assists in linking code generated by the macro assembler, once code generation
@ -58,9 +64,9 @@ class JSGlobalData;
// * The address of a Label pointing into the code may be resolved.
// * The value referenced by a DataLabel may be set.
//
template <typename MacroAssembler>
class LinkBuffer {
WTF_MAKE_NONCOPYABLE(LinkBuffer);
template <typename MacroAssembler, template <typename T> class ExecutableOffsetCalculator>
class LinkBufferBase {
WTF_MAKE_NONCOPYABLE(LinkBufferBase);
typedef MacroAssemblerCodeRef CodeRef;
typedef MacroAssemblerCodePtr CodePtr;
typedef typename MacroAssembler::Label Label;
@ -72,17 +78,10 @@ class LinkBuffer {
typedef typename MacroAssembler::DataLabel32 DataLabel32;
typedef typename MacroAssembler::DataLabelPtr DataLabelPtr;
typedef typename MacroAssembler::ConvertibleLoadLabel ConvertibleLoadLabel;
#if ENABLE(BRANCH_COMPACTION)
typedef typename MacroAssembler::LinkRecord LinkRecord;
typedef typename MacroAssembler::JumpLinkType JumpLinkType;
#endif
public:
LinkBuffer(JSGlobalData& globalData, MacroAssembler* masm, void* ownerUID, JITCompilationEffort effort = JITCompilationMustSucceed)
LinkBufferBase(JSGlobalData& globalData, MacroAssembler* masm, JITCompilationEffort effort = JITCompilationMustSucceed)
: m_size(0)
#if ENABLE(BRANCH_COMPACTION)
, m_initialSize(0)
#endif
, m_code(0)
, m_assembler(masm)
, m_globalData(&globalData)
@ -91,10 +90,13 @@ public:
, m_effort(effort)
#endif
{
linkCode(ownerUID, effort);
#ifdef NDEBUG
UNUSED_PARAM(effort)
#endif
// Simon: Moved this to the sub-classes linkCode(ownerUID, effort);
}
~LinkBuffer()
~LinkBufferBase()
{
ASSERT(m_completed || (!m_executableMemory && m_effort == JITCompilationCanFail));
}
@ -227,12 +229,10 @@ public:
private:
template <typename T> T applyOffset(T src)
{
#if ENABLE(BRANCH_COMPACTION)
src.m_offset -= m_assembler->executableOffsetFor(src.m_offset);
#endif
return src;
return ExecutableOffsetCalculator<T>::applyOffset(m_assembler, src);
}
protected:
// Keep this private! - the underlying code should only be obtained externally via finalizeCode().
void* code()
{
@ -253,12 +253,10 @@ private:
RefPtr<ExecutableMemoryHandle> m_executableMemory;
size_t m_size;
#if ENABLE(BRANCH_COMPACTION)
size_t m_initialSize;
#endif
void* m_code;
MacroAssembler* m_assembler;
JSGlobalData* m_globalData;
protected:
#ifndef NDEBUG
bool m_completed;
JITCompilationEffort m_effort;
@ -293,16 +291,16 @@ private:
FINALIZE_CODE_IF((Options::showDisassembly() || Options::showDFGDisassembly()), linkBufferReference, dataLogFArgumentsForHeading)
template <typename MacroAssembler>
inline typename LinkBuffer<MacroAssembler>::CodeRef LinkBuffer<MacroAssembler>::finalizeCodeWithoutDisassembly()
template <typename MacroAssembler, template <typename T> class ExecutableOffsetCalculator>
inline typename LinkBufferBase<MacroAssembler, ExecutableOffsetCalculator>::CodeRef LinkBufferBase<MacroAssembler, ExecutableOffsetCalculator>::finalizeCodeWithoutDisassembly()
{
performFinalization();
return CodeRef(m_executableMemory);
}
template <typename MacroAssembler>
inline typename LinkBuffer<MacroAssembler>::CodeRef LinkBuffer<MacroAssembler>::finalizeCodeWithDisassembly(const char* format, ...)
template <typename MacroAssembler, template <typename T> class ExecutableOffsetCalculator>
inline typename LinkBufferBase<MacroAssembler, ExecutableOffsetCalculator>::CodeRef LinkBufferBase<MacroAssembler, ExecutableOffsetCalculator>::finalizeCodeWithDisassembly(const char* format, ...)
{
ASSERT(Options::showDisassembly() || Options::showDFGDisassembly());
@ -327,18 +325,109 @@ inline typename LinkBuffer<MacroAssembler>::CodeRef LinkBuffer<MacroAssembler>::
return result;
}
template <typename MacroAssembler>
inline void LinkBuffer<MacroAssembler>::linkCode(void* ownerUID, JITCompilationEffort effort)
template <typename MacroAssembler, template <typename T> class ExecutableOffsetCalculator>
inline void LinkBufferBase<MacroAssembler, ExecutableOffsetCalculator>::linkCode(void* ownerUID, JITCompilationEffort effort)
{
UNUSED_PARAM(ownerUID)
UNUSED_PARAM(effort)
ASSERT(!m_code);
#if !ENABLE(BRANCH_COMPACTION)
m_executableMemory = m_assembler->m_assembler.executableCopy(*m_globalData, ownerUID, effort);
if (!m_executableMemory)
return;
m_code = m_executableMemory->start();
m_size = m_assembler->m_assembler.codeSize();
ASSERT(m_code);
#else
}
template <typename MacroAssembler, template <typename T> class ExecutableOffsetCalculator>
inline void LinkBufferBase<MacroAssembler, ExecutableOffsetCalculator>::performFinalization()
{
// NOTE: This function is specialized in LinkBuffer<MacroAssemblerARMv7>
#ifndef NDEBUG
ASSERT(!m_completed);
ASSERT(isValid());
m_completed = true;
#endif
ASSERT(m_size <= INT_MAX);
ExecutableAllocator::makeExecutable(code(), static_cast<int>(m_size));
MacroAssembler::cacheFlush(code(), m_size);
}
template <typename MacroAssembler>
class LinkBuffer : public LinkBufferBase<MacroAssembler, DefaultExecutableOffsetCalculator>
{
public:
LinkBuffer(JSGlobalData& globalData, MacroAssembler* masm, void* ownerUID, JITCompilationEffort effort = JITCompilationMustSucceed)
: LinkBufferBase<MacroAssembler, DefaultExecutableOffsetCalculator>(globalData, masm, effort)
{
this->linkCode(ownerUID, effort);
}
};
#if CPU(ARM_THUMB2) || CPU(ARM64)
template <typename T>
struct BranchCompactingExecutableOffsetCalculator {
template <typename Assembler>
static T applyOffset(Assembler *as, T src) {
src.m_offset -= as->executableOffsetFor(src.m_offset);
return src;
}
};
template <typename MacroAssembler>
class BranchCompactingLinkBuffer : public LinkBufferBase<MacroAssembler, BranchCompactingExecutableOffsetCalculator>
{
public:
BranchCompactingLinkBuffer(JSGlobalData& globalData, MacroAssembler* masm, void* ownerUID, JITCompilationEffort effort = JITCompilationMustSucceed)
: LinkBufferBase<MacroAssembler, BranchCompactingExecutableOffsetCalculator>(globalData, masm, effort)
{
linkCode(ownerUID, effort);
}
inline void performFinalization();
inline void linkCode(void* ownerUID, JITCompilationEffort);
private:
using Base = LinkBufferBase<MacroAssembler, BranchCompactingExecutableOffsetCalculator>;
#ifndef NDEBUG
using Base::m_completed;
#endif
using Base::isValid;
using Base::code;
using Base::m_code;
using Base::m_size;
using Base::m_assembler;
using Base::m_executableMemory;
using Base::m_globalData;
using LinkRecord = typename MacroAssembler::LinkRecord;
using JumpLinkType = typename MacroAssembler::JumpLinkType;
size_t m_initialSize = 0;
};
template <typename MacroAssembler>
inline void BranchCompactingLinkBuffer<MacroAssembler>::performFinalization()
{
#ifndef NDEBUG
ASSERT(!m_completed);
ASSERT(isValid());
this->m_completed = true;
#endif
ExecutableAllocator::makeExecutable(code(), m_initialSize);
MacroAssembler::cacheFlush(code(), m_size);
}
template <typename MacroAssembler>
inline void BranchCompactingLinkBuffer<MacroAssembler>::linkCode(void* ownerUID, JITCompilationEffort effort)
{
UNUSED_PARAM(ownerUID)
UNUSED_PARAM(effort)
ASSERT(!m_code);
m_initialSize = m_assembler->m_assembler.codeSize();
m_executableMemory = m_globalData->executableAllocator.allocate(*m_globalData, m_initialSize, ownerUID, effort);
if (!m_executableMemory)
@ -403,33 +492,32 @@ inline void LinkBuffer<MacroAssembler>::linkCode(void* ownerUID, JITCompilationE
jumpsToLink.clear();
m_size = writePtr + m_initialSize - readPtr;
m_executableMemory->shrink(m_size);
#if DUMP_LINK_STATISTICS
dumpLinkStatistics(m_code, m_initialSize, m_size);
#endif
#if DUMP_CODE
dumpCode(m_code, m_size);
#endif
#endif
}
template <typename MacroAssembler>
inline void LinkBuffer<MacroAssembler>::performFinalization()
#if CPU(ARM_THUMB2)
template <>
class LinkBuffer<JSC::MacroAssembler<MacroAssemblerARMv7>> : public BranchCompactingLinkBuffer<JSC::MacroAssembler<MacroAssemblerARMv7>>
{
#ifndef NDEBUG
ASSERT(!m_completed);
ASSERT(isValid());
m_completed = true;
public:
LinkBuffer(JSGlobalData& globalData, JSC::MacroAssembler<MacroAssemblerARMv7>* masm, void* ownerUID, JITCompilationEffort effort = JITCompilationMustSucceed)
: BranchCompactingLinkBuffer<JSC::MacroAssembler<MacroAssemblerARMv7>>(globalData, masm, ownerUID, effort)
{}
};
#endif
#if ENABLE(BRANCH_COMPACTION)
ExecutableAllocator::makeExecutable(code(), m_initialSize);
#else
ASSERT(m_size <= INT_MAX);
ExecutableAllocator::makeExecutable(code(), static_cast<int>(m_size));
#if CPU(ARM64)
template <>
class LinkBuffer<JSC::MacroAssembler<MacroAssemblerARM64>> : public BranchCompactingLinkBuffer<JSC::MacroAssembler<MacroAssemblerARM64>>
{
public:
LinkBuffer(JSGlobalData& globalData, JSC::MacroAssembler<MacroAssemblerARM64>* masm, void* ownerUID, JITCompilationEffort effort = JITCompilationMustSucceed)
: BranchCompactingLinkBuffer<JSC::MacroAssembler<JSC::MacroAssemblerARM64>>(globalData, masm, ownerUID, effort)
{}
};
#endif
MacroAssembler::cacheFlush(code(), m_size);
}
#endif
} // namespace JSC
#endif // ENABLE(ASSEMBLER)

View File

@ -1349,7 +1349,7 @@ protected:
}
private:
template <typename> friend class LinkBuffer;
template <typename, template <typename> class> friend class LinkBufferBase;
friend class RepatchBuffer;
void internalCompare32(RegisterID left, TrustedImm32 right)

View File

@ -3353,7 +3353,7 @@ private:
return makeBranch(cond);
}
template <typename> friend class LinkBuffer;
template <typename, template <typename> class> friend class LinkBufferBase;
void recordLinkOffsets(int32_t regionStart, int32_t regionEnd, int32_t offset) {return m_assembler.recordLinkOffsets(regionStart, regionEnd, offset); }
int executableOffsetFor(int location) { return m_assembler.executableOffsetFor(location); }

View File

@ -1930,7 +1930,7 @@ protected:
}
private:
template <typename> friend class LinkBuffer;
template <typename, template <typename> class> friend class LinkBufferBase;
friend class RepatchBuffer;
static void linkCall(void* code, Call call, FunctionPtr function)

View File

@ -2802,7 +2802,7 @@ private:
// Otherwise, we can emit any number of instructions.
bool m_fixedWidth;
template <typename> friend class LinkBuffer;
template <typename, template <typename> class> friend class LinkBufferBase;
friend class RepatchBuffer;
static void linkCall(void* code, Call call, FunctionPtr function)

View File

@ -2278,7 +2278,7 @@ protected:
return static_cast<SH4Assembler::Condition>(cond);
}
private:
template <typename> friend class LinkBuffer;
template <typename, template <typename> class> friend class LinkBufferBase;
friend class RepatchBuffer;
static void linkCall(void*, Call, FunctionPtr);

View File

@ -306,7 +306,7 @@ public:
}
private:
template <typename> friend class LinkBuffer;
template <typename, template <typename> class> friend class LinkBufferBase;
friend class RepatchBuffer;
static void linkCall(void* code, Call call, FunctionPtr function)

View File

@ -634,7 +634,7 @@ public:
}
private:
template <typename> friend class LinkBuffer;
template <typename, template <typename> class> friend class LinkBufferBase;
friend class RepatchBuffer;
static void linkCall(void* code, Call call, FunctionPtr function)

View File

@ -949,10 +949,6 @@
#define WTF_USE_ACCESSIBILITY_CONTEXT_MENUS 1
#endif
#if CPU(ARM_THUMB2) || CPU(ARM64)
#define ENABLE_BRANCH_COMPACTION 1
#endif
#if !defined(ENABLE_THREADING_LIBDISPATCH) && HAVE(DISPATCH_H)
#define ENABLE_THREADING_LIBDISPATCH 1
#elif !defined(ENABLE_THREADING_OPENMP) && defined(_OPENMP)