From 74d23ca548b47c85c4b8cdde5fd5a9026e4eb08c Mon Sep 17 00:00:00 2001 From: Ulf Hermann Date: Thu, 8 Nov 2018 18:09:21 +0100 Subject: 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 --- src/3rdparty/masm/assembler/LinkBuffer.h | 13 +++++++++ src/3rdparty/masm/stubs/ExecutableAllocator.h | 1 + src/3rdparty/masm/yarr/YarrJIT.cpp | 40 +++++++++++++++++++++------ src/3rdparty/masm/yarr/YarrJIT.h | 25 +++++++++++------ 4 files changed, 63 insertions(+), 16 deletions(-) (limited to 'src/3rdparty') 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 T applyOffset(T src) { @@ -353,6 +355,11 @@ inline void LinkBufferBase::performF ASSERT(m_size <= INT_MAX); MacroAssembler::cacheFlush(code(), m_size); +} + +template class ExecutableOffsetCalculator> +inline void LinkBufferBase::makeExecutable() +{ ExecutableAllocator::makeExecutable(code(), static_cast(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::performFinalization() #endif MacroAssembler::cacheFlush(code(), m_size); +} + +template +inline void BranchCompactingLinkBuffer::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 { 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 + #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 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; } -- cgit v1.2.3