diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/3rdparty/masm/stubs/ExecutableAllocator.h | 3 | ||||
-rw-r--r-- | src/qml/qml/v4/qv4engine.cpp | 2 | ||||
-rw-r--r-- | src/qml/qml/v4/qv4engine_p.h | 1 | ||||
-rw-r--r-- | src/qml/qml/v4/qv4executableallocator.cpp | 12 | ||||
-rw-r--r-- | src/qml/qml/v4/qv4executableallocator_p.h | 19 | ||||
-rw-r--r-- | src/qml/qml/v4/qv4function_p.h | 1 | ||||
-rw-r--r-- | src/qml/qml/v4/qv4regexp.cpp | 2 | ||||
-rw-r--r-- | src/qml/qml/v4/qv4unwindhelper.cpp | 4 | ||||
-rw-r--r-- | src/qml/qml/v4/qv4unwindhelper_p-arm.h | 4 | ||||
-rw-r--r-- | src/qml/qml/v4/qv4unwindhelper_p-dw2.h | 90 | ||||
-rw-r--r-- | src/qml/qml/v4/qv4unwindhelper_p.h | 4 |
11 files changed, 78 insertions, 64 deletions
diff --git a/src/3rdparty/masm/stubs/ExecutableAllocator.h b/src/3rdparty/masm/stubs/ExecutableAllocator.h index 351851c68d..cd8d3e06f4 100644 --- a/src/3rdparty/masm/stubs/ExecutableAllocator.h +++ b/src/3rdparty/masm/stubs/ExecutableAllocator.h @@ -79,6 +79,9 @@ struct ExecutableMemoryHandle : public RefCounted<ExecutableMemoryHandle> { void* start() { return m_allocation->start(); } int sizeInBytes() { return m_size; } + QV4::ExecutableAllocator::ChunkOfPages *chunk() const + { return m_allocator->chunkForAllocation(m_allocation); } + QV4::ExecutableAllocator *m_allocator; QV4::ExecutableAllocator::Allocation *m_allocation; int m_size; diff --git a/src/qml/qml/v4/qv4engine.cpp b/src/qml/qml/v4/qv4engine.cpp index 9262436fd1..5adb6dac88 100644 --- a/src/qml/qml/v4/qv4engine.cpp +++ b/src/qml/qml/v4/qv4engine.cpp @@ -73,6 +73,7 @@ using namespace QV4; ExecutionEngine::ExecutionEngine(QQmlJS::EvalISelFactory *factory) : memoryManager(new QV4::MemoryManager) , executableAllocator(new QV4::ExecutableAllocator) + , regExpAllocator(new QV4::ExecutableAllocator) , bumperPointerAllocator(new WTF::BumpPointerAllocator) , debugger(0) , globalObject(0) @@ -258,6 +259,7 @@ ExecutionEngine::~ExecutionEngine() UnwindHelper::deregisterFunctions(functions); qDeleteAll(functions); delete memoryManager; + delete regExpAllocator; delete executableAllocator; } diff --git a/src/qml/qml/v4/qv4engine_p.h b/src/qml/qml/v4/qv4engine_p.h index 5c556c9d2d..7be77711cc 100644 --- a/src/qml/qml/v4/qv4engine_p.h +++ b/src/qml/qml/v4/qv4engine_p.h @@ -111,6 +111,7 @@ struct Q_QML_EXPORT ExecutionEngine { MemoryManager *memoryManager; ExecutableAllocator *executableAllocator; + ExecutableAllocator *regExpAllocator; QScopedPointer<QQmlJS::EvalISelFactory> iselFactory; ExecutionContext *current; diff --git a/src/qml/qml/v4/qv4executableallocator.cpp b/src/qml/qml/v4/qv4executableallocator.cpp index e710eba21b..4c5d238c99 100644 --- a/src/qml/qml/v4/qv4executableallocator.cpp +++ b/src/qml/qml/v4/qv4executableallocator.cpp @@ -113,6 +113,7 @@ bool ExecutableAllocator::Allocation::mergePrevious(ExecutableAllocator *allocat ExecutableAllocator::ChunkOfPages::~ChunkOfPages() { + delete unwindInfo; Allocation *alloc = firstAllocation; while (alloc) { Allocation *next = alloc->next; @@ -206,3 +207,14 @@ void ExecutableAllocator::free(Allocation *allocation) return; } } + +ExecutableAllocator::ChunkOfPages *ExecutableAllocator::chunkForAllocation(Allocation *allocation) const +{ + QMap<quintptr, ChunkOfPages*>::ConstIterator it = chunks.lowerBound(allocation->addr); + if (it != chunks.begin()) + --it; + if (it == chunks.end()) + return 0; + return *it; +} + diff --git a/src/qml/qml/v4/qv4executableallocator_p.h b/src/qml/qml/v4/qv4executableallocator_p.h index 0defd984a3..475445cc35 100644 --- a/src/qml/qml/v4/qv4executableallocator_p.h +++ b/src/qml/qml/v4/qv4executableallocator_p.h @@ -47,6 +47,7 @@ #include <QMultiMap> #include <QHash> #include <QVector> +#include <QByteArray> namespace WTF { class PageAllocation; @@ -58,8 +59,8 @@ namespace QV4 { class Q_AUTOTEST_EXPORT ExecutableAllocator { - struct ChunkOfPages; public: + struct ChunkOfPages; struct Allocation; ~ExecutableAllocator(); @@ -97,17 +98,31 @@ public: int freeAllocationCount() const { return freeAllocations.count(); } int chunkCount() const { return chunks.count(); } -private: + // Used to store CIE+FDE on x86/x86-64. + struct PlatformUnwindInfo + { + virtual ~PlatformUnwindInfo() {} + }; + struct ChunkOfPages { + ChunkOfPages() + : pages(0) + , firstAllocation(0) + , unwindInfo(0) + {} ~ChunkOfPages(); WTF::PageAllocation *pages; Allocation *firstAllocation; + PlatformUnwindInfo *unwindInfo; bool contains(Allocation *alloc) const; }; + ChunkOfPages *chunkForAllocation(Allocation *allocation) const; + +private: QMultiMap<size_t, Allocation*> freeAllocations; QMap<quintptr, ChunkOfPages*> chunks; }; diff --git a/src/qml/qml/v4/qv4function_p.h b/src/qml/qml/v4/qv4function_p.h index c7ae954879..d73dc8d28f 100644 --- a/src/qml/qml/v4/qv4function_p.h +++ b/src/qml/qml/v4/qv4function_p.h @@ -86,7 +86,6 @@ struct Function { const uchar *codeData; JSC::MacroAssemblerCodeRef codeRef; quint32 codeSize; - QByteArray unwindInfo; // CIE+FDE on x86/x86-64. Stored directly in code on ARM. QVector<String *> formals; QVector<String *> locals; diff --git a/src/qml/qml/v4/qv4regexp.cpp b/src/qml/qml/v4/qv4regexp.cpp index 053a32d6a1..e7e2187a50 100644 --- a/src/qml/qml/v4/qv4regexp.cpp +++ b/src/qml/qml/v4/qv4regexp.cpp @@ -112,7 +112,7 @@ RegExp::RegExp(ExecutionEngine* engine, const QString &pattern, bool ignoreCase, m_byteCode = JSC::Yarr::byteCompile(yarrPattern, engine->bumperPointerAllocator); #if ENABLE(YARR_JIT) if (!yarrPattern.m_containsBackreferences && engine->iselFactory->jitCompileRegexps()) { - JSC::JSGlobalData dummy(engine->executableAllocator); + JSC::JSGlobalData dummy(engine->regExpAllocator); JSC::Yarr::jitCompile(yarrPattern, JSC::Yarr::Char16, &dummy, m_jitCode); } #endif diff --git a/src/qml/qml/v4/qv4unwindhelper.cpp b/src/qml/qml/v4/qv4unwindhelper.cpp index 90750e9fe3..3d54ea277a 100644 --- a/src/qml/qml/v4/qv4unwindhelper.cpp +++ b/src/qml/qml/v4/qv4unwindhelper.cpp @@ -31,8 +31,8 @@ using namespace QV4; void UnwindHelper::ensureUnwindInfo(Function *function) {Q_UNUSED(function);} void UnwindHelper::registerFunction(Function *function) {Q_UNUSED(function);} -void UnwindHelper::registerFunctions(QVector<Function *> functions) {Q_UNUSED(functions);} +void UnwindHelper::registerFunctions(const QVector<Function *> &functions) {Q_UNUSED(functions);} void UnwindHelper::deregisterFunction(Function *function) {Q_UNUSED(function);} -void UnwindHelper::deregisterFunctions(QVector<Function *> functions) {Q_UNUSED(functions);} +void UnwindHelper::deregisterFunctions(const QVector<Function *> &functions) {Q_UNUSED(functions);} #endif // USE_NULL_HELPER diff --git a/src/qml/qml/v4/qv4unwindhelper_p-arm.h b/src/qml/qml/v4/qv4unwindhelper_p-arm.h index 92e38f7c80..7055c3a152 100644 --- a/src/qml/qml/v4/qv4unwindhelper_p-arm.h +++ b/src/qml/qml/v4/qv4unwindhelper_p-arm.h @@ -96,7 +96,7 @@ void UnwindHelper::deregisterFunction(Function *function) allFunctions.remove(reinterpret_cast<quintptr>(function->code)); } -void UnwindHelper::deregisterFunctions(QVector<Function *> functions) +void UnwindHelper::deregisterFunctions(const QVector<Function *> &functions) { QMutexLocker locker(&functionProtector); foreach (Function *f, functions) @@ -109,7 +109,7 @@ void UnwindHelper::registerFunction(Function *function) allFunctions.insert(reinterpret_cast<quintptr>(function->code), function); } -void UnwindHelper::registerFunctions(QVector<Function *> functions) +void UnwindHelper::registerFunctions(const QVector<Function *> &functions) { QMutexLocker locker(&functionProtector); foreach (Function *f, functions) diff --git a/src/qml/qml/v4/qv4unwindhelper_p-dw2.h b/src/qml/qml/v4/qv4unwindhelper_p-dw2.h index 841636d912..0e4296769c 100644 --- a/src/qml/qml/v4/qv4unwindhelper_p-dw2.h +++ b/src/qml/qml/v4/qv4unwindhelper_p-dw2.h @@ -5,6 +5,8 @@ #include "qv4functionobject_p.h" #include "qv4function_p.h" #include <wtf/Platform.h> +#include <wtf/PageAllocation.h> +#include <ExecutableAllocator.h> #include <QMap> #include <QMutex> @@ -45,27 +47,7 @@ static const int fde_offset = 20; static const int initial_location_offset = 28; static const int address_range_offset = 32; #endif -} // anonymous namespace - -static QMutex functionProtector; -static QMap<quintptr, Function*> allFunctions; -static Function *lookupFunction(void *pc) -{ - quintptr key = reinterpret_cast<quintptr>(pc); - QMap<quintptr, Function*>::ConstIterator it = allFunctions.lowerBound(key); - if (it != allFunctions.begin() && allFunctions.count() > 0) - --it; - if (it == allFunctions.end()) - return 0; - - quintptr codeStart = reinterpret_cast<quintptr>((*it)->code); - if (key < codeStart || key >= codeStart + (*it)->codeSize) - return 0; - return *it; -} - -namespace { void writeIntPtrValue(unsigned char *addr, intptr_t val) { addr[0] = (val >> 0) & 0xff; @@ -84,66 +66,66 @@ void writeIntPtrValue(unsigned char *addr, intptr_t val) extern "C" void __register_frame(void *fde); extern "C" void __deregister_frame(void *fde); +struct UnwindInfo : public ExecutableAllocator::PlatformUnwindInfo +{ + UnwindInfo(const QByteArray &cieFde); + virtual ~UnwindInfo(); + QByteArray data; +}; + +UnwindInfo::UnwindInfo(const QByteArray &cieFde) + : data(cieFde) +{ + __register_frame(data.data() + fde_offset); +} + +UnwindInfo::~UnwindInfo() +{ + __deregister_frame(data.data() + fde_offset); +} + void UnwindHelper::ensureUnwindInfo(Function *f) { if (!f->codeRef) return; // Not a JIT generated function - if (!f->unwindInfo.isEmpty()) + + JSC::ExecutableMemoryHandle *handle = f->codeRef.executableMemory(); + if (!handle) return; + ExecutableAllocator::ChunkOfPages *chunk = handle->chunk(); + + // Already registered? + if (chunk->unwindInfo) + return; + QByteArray info; info.resize(sizeof(cie_fde_data)); unsigned char *cie_and_fde = reinterpret_cast<unsigned char *>(info.data()); memcpy(cie_and_fde, cie_fde_data, sizeof(cie_fde_data)); - intptr_t ptr = static_cast<char *>(f->codeRef.code().executableAddress()) - static_cast<char *>(0); + intptr_t ptr = static_cast<char *>(chunk->pages->base()) - static_cast<char *>(0); writeIntPtrValue(cie_and_fde + initial_location_offset, ptr); - writeIntPtrValue(cie_and_fde + address_range_offset, f->codeSize); + writeIntPtrValue(cie_and_fde + address_range_offset, chunk->pages->size()); - f->unwindInfo = info; - __register_frame(f->unwindInfo.data() + fde_offset); -} - -static void registerFunctionUnlocked(Function *f) -{ - quintptr addr = reinterpret_cast<quintptr>(f->code); - if (allFunctions.contains(addr)) - return; - allFunctions.insert(addr, f); -} - -static void deregisterFunctionUnlocked(Function *f) -{ - allFunctions.remove(reinterpret_cast<quintptr>(f->code)); - if (!f->unwindInfo.isEmpty()) - __deregister_frame(f->unwindInfo.data() + fde_offset); + chunk->unwindInfo = new UnwindInfo(info); } -void UnwindHelper::registerFunction(Function *function) +void UnwindHelper::registerFunction(Function *) { - QMutexLocker locker(&functionProtector); - registerFunctionUnlocked(function); } -void UnwindHelper::registerFunctions(QVector<Function *> functions) +void UnwindHelper::registerFunctions(const QVector<Function *>&) { - QMutexLocker locker(&functionProtector); - foreach (Function *f, functions) - registerFunctionUnlocked(f); } -void UnwindHelper::deregisterFunction(Function *function) +void UnwindHelper::deregisterFunction(Function *) { - QMutexLocker locker(&functionProtector); - deregisterFunctionUnlocked(function); } -void UnwindHelper::deregisterFunctions(QVector<Function *> functions) +void UnwindHelper::deregisterFunctions(const QVector<Function *> &) { - QMutexLocker locker(&functionProtector); - foreach (Function *f, functions) - deregisterFunctionUnlocked(f); } } diff --git a/src/qml/qml/v4/qv4unwindhelper_p.h b/src/qml/qml/v4/qv4unwindhelper_p.h index 72bf56c531..7949278aad 100644 --- a/src/qml/qml/v4/qv4unwindhelper_p.h +++ b/src/qml/qml/v4/qv4unwindhelper_p.h @@ -12,9 +12,9 @@ class UnwindHelper public: static void ensureUnwindInfo(Function *function); static void registerFunction(Function *function); - static void registerFunctions(QVector<Function *> functions); + static void registerFunctions(const QVector<Function *> &functions); static void deregisterFunction(Function *function); - static void deregisterFunctions(QVector<Function *> functions); + static void deregisterFunctions(const QVector<Function *> &functions); #ifdef Q_PROCESSOR_ARM static int unwindInfoSize(); static void writeARMUnwindInfo(void *codeAddr, int codeSize); |