aboutsummaryrefslogtreecommitdiffstats
path: root/src/3rdparty/masm/wtf/OSAllocatorWinRT.cpp
diff options
context:
space:
mode:
authorMaurice Kalinowski <maurice.kalinowski@theqtcompany.com>2015-12-21 09:17:29 +0100
committerSimon Hausmann <simon.hausmann@theqtcompany.com>2016-01-16 10:33:06 +0000
commit9e980750c6647ffcf2cb95e95e63fa8335924866 (patch)
tree72f5519a6c871028e0461535a1993996b5eb1422 /src/3rdparty/masm/wtf/OSAllocatorWinRT.cpp
parentf2dc1ef7390c4dd05a54958da1942399e26e3fde (diff)
WinRT: Enable JIT for x86/x64 target platforms
This only works for Windows 10 and later. Setting the "Code Generation" capability in the manifest, WinRT applications can use JIT for Windows 10 Desktop. Update the Allocator in regards to this and also update the VirtualProtectFromApp section. When the engine gets initialized, check for marking an area as executable. If it fails, fallback to interpreter mode. This does not affect ARM platforms, as we do not have calling conventions yet. It is implicitly disabled as V4_ENABLE_JIT is not defined. [ChangeLog][WinRT] Enable JIT for x86/x64 targets on Windows 10 and later. Change-Id: Ie05add5263f71387c5ce98456b9bec86c6c07ceb Reviewed-by: Simon Hausmann <simon.hausmann@theqtcompany.com>
Diffstat (limited to 'src/3rdparty/masm/wtf/OSAllocatorWinRT.cpp')
-rw-r--r--src/3rdparty/masm/wtf/OSAllocatorWinRT.cpp104
1 files changed, 94 insertions, 10 deletions
diff --git a/src/3rdparty/masm/wtf/OSAllocatorWinRT.cpp b/src/3rdparty/masm/wtf/OSAllocatorWinRT.cpp
index d684367ec6..b7ad723f07 100644
--- a/src/3rdparty/masm/wtf/OSAllocatorWinRT.cpp
+++ b/src/3rdparty/masm/wtf/OSAllocatorWinRT.cpp
@@ -25,12 +25,27 @@
#include "config.h"
#include "OSAllocator.h"
+#include "PageBlock.h"
#if OS(WINRT)
#include "windows.h"
#include <wtf/Assertions.h>
+#if _MSC_VER >= 1900
+// Try to use JIT by default and fallback to non-JIT on first error
+static bool qt_winrt_use_jit = true;
+#else // _MSC_VER < 1900
+# define PAGE_EXECUTE 0x10
+# define PAGE_EXECUTE_READ 0x20
+# define PAGE_EXECUTE_READWRITE 0x40
+# define MEM_RELEASE 0x8000
+inline void* VirtualAllocFromApp(void*, size_t, int, int) { return 0; }
+inline bool VirtualProtectFromApp(void *, size_t, int, DWORD*) { return false; }
+inline bool VirtualFree(void *, size_t, DWORD) { return false; }
+static bool qt_winrt_use_jit = false;
+#endif // _MSC_VER < 1900
+
namespace WTF {
inline size_t getPageSize()
@@ -40,19 +55,58 @@ inline size_t getPageSize()
return info.dwPageSize;
}
-void* OSAllocator::reserveUncommitted(size_t bytes, Usage, bool, bool)
+static inline DWORD protection(bool writable, bool executable)
{
- static const size_t pageSize = getPageSize();
- void* result = _aligned_malloc(bytes, pageSize);
- if (!result)
- CRASH();
- memset(result, 0, bytes);
+ if (writable && executable)
+ qFatal("read/write executable areas are not allowed on WinRT");
+ return executable ?
+ (writable ? PAGE_EXECUTE_READWRITE : PAGE_EXECUTE_READ) :
+ (writable ? PAGE_READWRITE : PAGE_READONLY);
+}
+
+void* OSAllocator::reserveUncommitted(size_t bytes, Usage, bool writable, bool executable)
+{
+ void *result;
+ if (qt_winrt_use_jit) {
+ result = VirtualAllocFromApp(0, bytes, MEM_RESERVE, protection(writable, executable));
+ if (!result) {
+ qt_winrt_use_jit = false;
+ return reserveUncommitted(bytes, UnknownUsage, writable, executable);
+ }
+ } else {
+ static const size_t pageSize = getPageSize();
+ result = _aligned_malloc(bytes, pageSize);
+ if (!result)
+ CRASH();
+ memset(result, 0, bytes);
+ }
return result;
}
-void* OSAllocator::reserveAndCommit(size_t bytes, Usage usage, bool writable, bool executable, bool)
+void* OSAllocator::reserveAndCommit(size_t bytes, Usage usage, bool writable, bool executable, bool includesGuardPages)
{
- return reserveUncommitted(bytes, usage, writable, executable);
+ void *result;
+ if (qt_winrt_use_jit) {
+ result = VirtualAllocFromApp(0, bytes, MEM_RESERVE | MEM_COMMIT,
+ protection(writable, executable));
+ if (!result) {
+ qt_winrt_use_jit = false;
+ return reserveAndCommit(bytes, usage, writable, executable, includesGuardPages);
+ }
+
+ if (includesGuardPages) {
+ size_t guardSize = pageSize();
+ DWORD oldProtect;
+ if (!VirtualProtectFromApp(result, guardSize, protection(false, false), &oldProtect) ||
+ !VirtualProtectFromApp(static_cast<char*>(result) + bytes - guardSize, guardSize,
+ protection(false, false), &oldProtect)) {
+ CRASH();
+ }
+ }
+ } else {
+ result = reserveUncommitted(bytes, usage, writable, executable);
+ }
+ return result;
}
void OSAllocator::commit(void*, size_t, bool, bool)
@@ -62,14 +116,44 @@ void OSAllocator::commit(void*, size_t, bool, bool)
void OSAllocator::decommit(void* address, size_t)
{
- _aligned_free(address);
+ if (qt_winrt_use_jit)
+ Q_UNREACHABLE();
+ else
+ _aligned_free(address);
}
void OSAllocator::releaseDecommitted(void* address, size_t bytes)
{
- decommit(address, bytes);
+ if (qt_winrt_use_jit) {
+ bool result = VirtualFree(address, 0, MEM_RELEASE);
+ if (!result)
+ CRASH();
+ } else {
+ decommit(address, bytes);
+ }
}
+bool OSAllocator::canAllocateExecutableMemory()
+{
+ if (qt_winrt_use_jit) {
+ // For WinRT we first check if code generation is enabled. If successful
+ // we allow to use JIT, otherwise fallback to the interpreter
+ const size_t pageSize = getPageSize();
+ void *all = VirtualAllocFromApp(0, pageSize, MEM_RESERVE | MEM_COMMIT,
+ protection(true, false));
+ DWORD oldProtect;
+ bool res = VirtualProtectFromApp(all, pageSize, PAGE_EXECUTE, &oldProtect);
+ VirtualFree(all, 0, MEM_RELEASE);
+ if (!res) {
+ qt_winrt_use_jit = false;
+ qWarning("Could not enable JIT, fallback to interpreter mode. "
+ "Consider setting the code-generation capability");
+ }
+ }
+ return qt_winrt_use_jit;
+}
+
+
} // namespace WTF
#endif // OS(WINRT)