diff options
author | Ulf Hermann <ulf.hermann@qt.io> | 2018-11-08 18:09:21 +0100 |
---|---|---|
committer | Ulf Hermann <ulf.hermann@qt.io> | 2018-12-03 08:28:36 +0000 |
commit | 74d23ca548b47c85c4b8cdde5fd5a9026e4eb08c (patch) | |
tree | caf94cffe04b7c6235ccfd5f117b17187733752b /src/3rdparty | |
parent | faf99c36d29bfad629fb6ec541ccc2f61ef93443 (diff) |
V4: Generate function tables on 64bit windows
In order for global exception handlers to be called reliably, the runtime
needs to unwind through JIT-generated code. This can be facilitated by
installing a "function table" for each JITed function that specifies "use
the frame pointer".
Also make sure to generate a function table for JIT'ed regular
expressions. Those were forgotten also in the linux case.
Fixes: QTBUG-50061
Change-Id: Ib0b8ae9356ed80afe1cab017e36efa4ccbe73f90
Reviewed-by: Simon Hausmann <simon.hausmann@qt.io>
Diffstat (limited to 'src/3rdparty')
-rw-r--r-- | src/3rdparty/masm/assembler/LinkBuffer.h | 13 | ||||
-rw-r--r-- | src/3rdparty/masm/stubs/ExecutableAllocator.h | 1 | ||||
-rw-r--r-- | src/3rdparty/masm/yarr/YarrJIT.cpp | 40 | ||||
-rw-r--r-- | src/3rdparty/masm/yarr/YarrJIT.h | 25 |
4 files changed, 63 insertions, 16 deletions
diff --git a/src/3rdparty/masm/assembler/LinkBuffer.h b/src/3rdparty/masm/assembler/LinkBuffer.h index c79b0663c8..4dfd051797 100644 --- a/src/3rdparty/masm/assembler/LinkBuffer.h +++ b/src/3rdparty/masm/assembler/LinkBuffer.h @@ -228,6 +228,8 @@ public: return m_size; } + inline void makeExecutable(); + private: template <typename T> T applyOffset(T src) { @@ -353,6 +355,11 @@ inline void LinkBufferBase<MacroAssembler, ExecutableOffsetCalculator>::performF ASSERT(m_size <= INT_MAX); MacroAssembler::cacheFlush(code(), m_size); +} + +template <typename MacroAssembler, template <typename T> class ExecutableOffsetCalculator> +inline void LinkBufferBase<MacroAssembler, ExecutableOffsetCalculator>::makeExecutable() +{ ExecutableAllocator::makeExecutable(code(), static_cast<int>(m_size)); } @@ -389,6 +396,7 @@ public: } inline void performFinalization(); + inline void makeExecutable(); inline void linkCode(void* ownerUID, JITCompilationEffort); @@ -421,6 +429,11 @@ inline void BranchCompactingLinkBuffer<MacroAssembler>::performFinalization() #endif MacroAssembler::cacheFlush(code(), m_size); +} + +template <typename MacroAssembler> +inline void BranchCompactingLinkBuffer<MacroAssembler>::makeExecutable() +{ ExecutableAllocator::makeExecutable(code(), m_initialSize); } diff --git a/src/3rdparty/masm/stubs/ExecutableAllocator.h b/src/3rdparty/masm/stubs/ExecutableAllocator.h index 156b24b4e8..a439c53827 100644 --- a/src/3rdparty/masm/stubs/ExecutableAllocator.h +++ b/src/3rdparty/masm/stubs/ExecutableAllocator.h @@ -82,6 +82,7 @@ struct ExecutableMemoryHandle : public RefCounted<ExecutableMemoryHandle> { inline bool isManaged() const { return true; } + void *exceptionHandler() { return m_allocation->exceptionHandler(); } void *start() { return m_allocation->start(); } size_t sizeInBytes() { return m_size; } diff --git a/src/3rdparty/masm/yarr/YarrJIT.cpp b/src/3rdparty/masm/yarr/YarrJIT.cpp index 9a9ab581e8..73c919dd90 100644 --- a/src/3rdparty/masm/yarr/YarrJIT.cpp +++ b/src/3rdparty/masm/yarr/YarrJIT.cpp @@ -33,6 +33,8 @@ #include "Yarr.h" #include "YarrCanonicalize.h" +#include <private/qv4functiontable_p.h> + #if ENABLE(YARR_JIT) using namespace WTF; @@ -3529,17 +3531,30 @@ public: m_backtrackingState.linkDataLabels(linkBuffer); + CodeRef codeRef; if (compileMode == MatchOnly) { - if (m_charSize == Char8) - codeBlock.set8BitCodeMatchOnly(FINALIZE_CODE(linkBuffer, "YarJIT", "Match-only 8-bit regular expression")); - else - codeBlock.set16BitCodeMatchOnly(FINALIZE_CODE(linkBuffer, "YarJIT", "Match-only 16-bit regular expression")); + if (m_charSize == Char8) { + codeRef = FINALIZE_CODE(linkBuffer, "YarJIT", + "Match-only 8-bit regular expression"); + codeBlock.set8BitCodeMatchOnly(codeRef); + } else { + codeRef = FINALIZE_CODE(linkBuffer, "YarJIT", + "Match-only 16-bit regular expression"); + codeBlock.set16BitCodeMatchOnly(codeRef); + } } else { - if (m_charSize == Char8) - codeBlock.set8BitCode(FINALIZE_CODE(linkBuffer, "YarJIT", "8-bit regular expression")); - else - codeBlock.set16BitCode(FINALIZE_CODE(linkBuffer, "YarJIT", "16-bit regular expression")); + if (m_charSize == Char8) { + codeRef = FINALIZE_CODE(linkBuffer, "YarJIT", "8-bit regular expression"); + codeBlock.set8BitCode(codeRef); + } else { + codeRef = FINALIZE_CODE(linkBuffer, "YarJIT", "16-bit regular expression"); + codeBlock.set16BitCode(codeRef); + } } + QV4::generateFunctionTable(nullptr, &codeRef); + + linkBuffer.makeExecutable(); + if (m_failureReason) codeBlock.setFallBackWithFailureReason(*m_failureReason); } @@ -3587,6 +3602,15 @@ private: BacktrackingState m_backtrackingState; }; +void YarrCodeBlock::replaceCodeRef(MacroAssemblerCodeRef &target, + const MacroAssemblerCodeRef &source) +{ + if (!!target && target.code().executableAddress() != source.code().executableAddress()) + QV4::destroyFunctionTable(nullptr, &target); + + target = source; +} + static void dumpCompileFailure(JITFailureReason failure) { switch (failure) { diff --git a/src/3rdparty/masm/yarr/YarrJIT.h b/src/3rdparty/masm/yarr/YarrJIT.h index 8b6b3a7577..35a0690f6e 100644 --- a/src/3rdparty/masm/yarr/YarrJIT.h +++ b/src/3rdparty/masm/yarr/YarrJIT.h @@ -82,19 +82,28 @@ class YarrCodeBlock { public: YarrCodeBlock() = default; + ~YarrCodeBlock() { clear(); } + + static void replaceCodeRef(MacroAssemblerCodeRef &target, const MacroAssemblerCodeRef &source); void setFallBackWithFailureReason(JITFailureReason failureReason) { m_failureReason = failureReason; } std::optional<JITFailureReason> failureReason() { return m_failureReason; } bool has8BitCode() { return m_ref8.size(); } bool has16BitCode() { return m_ref16.size(); } - void set8BitCode(MacroAssemblerCodeRef ref) { m_ref8 = ref; } - void set16BitCode(MacroAssemblerCodeRef ref) { m_ref16 = ref; } + void set8BitCode(MacroAssemblerCodeRef ref) { replaceCodeRef(m_ref8, ref); } + void set16BitCode(MacroAssemblerCodeRef ref) { replaceCodeRef(m_ref16, ref); } bool has8BitCodeMatchOnly() { return m_matchOnly8.size(); } bool has16BitCodeMatchOnly() { return m_matchOnly16.size(); } - void set8BitCodeMatchOnly(MacroAssemblerCodeRef matchOnly) { m_matchOnly8 = matchOnly; } - void set16BitCodeMatchOnly(MacroAssemblerCodeRef matchOnly) { m_matchOnly16 = matchOnly; } + void set8BitCodeMatchOnly(MacroAssemblerCodeRef matchOnly) + { + replaceCodeRef(m_matchOnly8, matchOnly); + } + void set16BitCodeMatchOnly(MacroAssemblerCodeRef matchOnly) + { + replaceCodeRef(m_matchOnly16, matchOnly); + } #if ENABLE(YARR_JIT_ALL_PARENS_EXPRESSIONS) bool usesPatternContextBuffer() { return m_usesPatternContextBuffer; } @@ -190,10 +199,10 @@ public: void clear() { - m_ref8 = MacroAssemblerCodeRef(); - m_ref16 = MacroAssemblerCodeRef(); - m_matchOnly8 = MacroAssemblerCodeRef(); - m_matchOnly16 = MacroAssemblerCodeRef(); + replaceCodeRef(m_ref8, MacroAssemblerCodeRef()); + replaceCodeRef(m_ref16, MacroAssemblerCodeRef()); + replaceCodeRef(m_matchOnly8, MacroAssemblerCodeRef()); + replaceCodeRef(m_matchOnly16, MacroAssemblerCodeRef()); m_failureReason = std::nullopt; } |