Fix JIT crash on x86-64 (avoid 32-bit branch offset overflow)
authorKent Hansen <kent.hansen@nokia.com>
Thu, 8 Jul 2010 17:26:50 +0000 (17:26 +0000)
committerLisandro Damián Nicanor Pérez Meyer <lisandro@debian.org>
Tue, 5 Feb 2013 21:52:29 +0000 (21:52 +0000)
Cherry-picked from webkit commit
a5b3261a8c4386b4e14ce40a34c7fc933a5f7001

Task-number: QTBUG-23871
Change-Id: Ia028fe072b349e3a7883ae0f6f7298941cc1bc9e
Reviewed-by: Simon Hausmann <simon.hausmann@nokia.com>
(cherry picked from commit 79ebd39d0d4846cb911ae122d2059e5add568d7e in qtscript)

Gbp-Pq: Name fix_jit_crash_on_x86_64.patch

src/3rdparty/javascriptcore/JavaScriptCore/ChangeLog
src/3rdparty/javascriptcore/JavaScriptCore/JavaScriptCore.pri
src/3rdparty/javascriptcore/JavaScriptCore/jit/ExecutableAllocator.cpp
src/3rdparty/javascriptcore/JavaScriptCore/jit/ExecutableAllocatorFixedVMPool.cpp
src/3rdparty/javascriptcore/JavaScriptCore/jit/ExecutableAllocatorPosix.cpp
src/3rdparty/javascriptcore/JavaScriptCore/jit/ExecutableAllocatorSymbian.cpp
src/3rdparty/javascriptcore/JavaScriptCore/jit/ExecutableAllocatorWin.cpp
src/3rdparty/javascriptcore/JavaScriptCore/wtf/Platform.h

index 9cbf0c146c1440d61d7e62d8202b7f6c194972ab..5ab23e67df8c28419f1de6a37f65d744f6b77b5b 100644 (file)
@@ -1,3 +1,30 @@
+2010-07-08  Gavin Barraclough  <barraclough@apple.com>
+
+        Reviewed by Sam Weinig.
+
+        https://bugs.webkit.org/show_bug.cgi?id=41641
+
+        Update compile flags to allow use of ExecutableAllocatorFixedVMPool on platforms
+        other than x86-64 (this may be useful on 32-bit platforms, too).
+
+        Simplify ifdefs by dividing into thwo broad allocation strategies
+        (ENABLE_EXECUTABLE_ALLOCATOR_FIXED & ENABLE_EXECUTABLE_ALLOCATOR_DEMAND).
+
+        Rename constant used in the code to have names descriptive of their purpose,
+        rather than their specific value on a given platform.
+
+        * jit/ExecutableAllocator.cpp:
+        (JSC::ExecutableAllocator::reprotectRegion):
+        (JSC::ExecutableAllocator::cacheFlush):
+        * jit/ExecutableAllocatorFixedVMPool.cpp:
+        (JSC::FixedVMPoolAllocator::FixedVMPoolAllocator):
+        (JSC::FixedVMPoolAllocator::free):
+        (JSC::ExecutablePool::systemAlloc):
+        * jit/ExecutableAllocatorPosix.cpp:
+        * jit/ExecutableAllocatorSymbian.cpp:
+        * jit/ExecutableAllocatorWin.cpp:
+        * wtf/Platform.h:
+
 2010-08-24  Oliver Hunt  <oliver@apple.com>
 
         Reviewed by Geoff Garen.
index b061321465ccd7c3e52b67ca647b36b9c43884ca..847f69c3584b559d3181e0aa207628fa661e649c 100644 (file)
@@ -100,6 +100,7 @@ SOURCES += \
     interpreter/CallFrame.cpp \
     interpreter/Interpreter.cpp \
     interpreter/RegisterFile.cpp \
+    jit/ExecutableAllocatorFixedVMPool.cpp \
     jit/ExecutableAllocatorPosix.cpp \
     jit/ExecutableAllocatorSymbian.cpp \
     jit/ExecutableAllocatorWin.cpp \
index f6b27ec2ab4ef2e3466b90ede62babde16b73116..f0ebbabfb6d5597120f0d56b65be1add4204a2c3 100644 (file)
@@ -33,6 +33,27 @@ namespace JSC {
 
 size_t ExecutableAllocator::pageSize = 0;
 
+#if ENABLE(ASSEMBLER_WX_EXCLUSIVE)
+void ExecutableAllocator::reprotectRegion(void* start, size_t size, ProtectionSeting setting)
+{
+    if (!pageSize)
+        intializePageSize();
+
+    // Calculate the start of the page containing this region,
+    // and account for this extra memory within size.
+    intptr_t startPtr = reinterpret_cast<intptr_t>(start);
+    intptr_t pageStartPtr = startPtr & ~(pageSize - 1);
+    void* pageStart = reinterpret_cast<void*>(pageStartPtr);
+    size += (startPtr - pageStartPtr);
+
+    // Round size up
+    size += (pageSize - 1);
+    size &= ~(pageSize - 1);
+
+    mprotect(pageStart, size, (setting == Writable) ? PROTECTION_FLAGS_RW : PROTECTION_FLAGS_RX);
+}
+#endif
+
 }
 
 #endif // HAVE(ASSEMBLER)
index dd1db4e24ab85df7d8ff8e7c22d89489af8b4918..16d0fb1e8c70f3d26560d915806d2d2220384e3c 100644 (file)
 
 #include "ExecutableAllocator.h"
 
-#include <errno.h>
+#if ENABLE(EXECUTABLE_ALLOCATOR_FIXED)
 
-#if ENABLE(ASSEMBLER) && OS(DARWIN) && CPU(X86_64)
+#include <errno.h>
 
 #include "TCSpinLock.h"
-#include <mach/mach_init.h>
-#include <mach/vm_map.h>
 #include <sys/mman.h>
 #include <unistd.h>
 #include <wtf/AVLTree.h>
 #include <wtf/VMTags.h>
 
+#if CPU(X86_64)
+    // These limits suitable on 64-bit platforms (particularly x86-64, where we require all jumps to have a 2Gb max range).
+    #define VM_POOL_SIZE (2u * 1024u * 1024u * 1024u) // 2Gb
+    #define COALESCE_LIMIT (16u * 1024u * 1024u) // 16Mb
+#else
+    // These limits are hopefully sensible on embedded platforms.
+    #define VM_POOL_SIZE (32u * 1024u * 1024u) // 32Mb
+    #define COALESCE_LIMIT (4u * 1024u * 1024u) // 4Mb
+#endif
+
+// ASLR currently only works on darwin (due to arc4random) & 64-bit (due to address space size).
+#define VM_POOL_ASLR (OS(DARWIN) && CPU(X86_64))
+
 using namespace WTF;
 
 namespace JSC {
 
-#define TWO_GB (2u * 1024u * 1024u * 1024u)
-#define SIXTEEN_MB (16u * 1024u * 1024u)
-
 // FreeListEntry describes a free chunk of memory, stored in the freeList.
 struct FreeListEntry {
     FreeListEntry(void* pointer, size_t size)
@@ -291,9 +299,12 @@ public:
         // for now instead of 2^26 bits of ASLR lets stick with 25 bits of randomization plus
         // 2^24, which should put up somewhere in the middle of usespace (in the address range
         // 0x200000000000 .. 0x5fffffffffff).
-        intptr_t randomLocation = arc4random() & ((1 << 25) - 1);
+        intptr_t randomLocation = 0;
+#if VM_POOL_ASLR
+        randomLocation = arc4random() & ((1 << 25) - 1);
         randomLocation += (1 << 24);
         randomLocation <<= 21;
+#endif
         m_base = mmap(reinterpret_cast<void*>(randomLocation), m_totalHeapSize, INITIAL_PROTECTION_FLAGS, MAP_PRIVATE | MAP_ANON, VM_TAG_FOR_EXECUTABLEALLOCATOR_MEMORY, 0);
         if (!m_base)
             CRASH();
@@ -387,7 +398,7 @@ public:
         // 16MB of allocations have been freed, sweep m_freeList
         // coalescing any neighboring fragments.
         m_countFreedSinceLastCoalesce += size;
-        if (m_countFreedSinceLastCoalesce >= SIXTEEN_MB) {
+        if (m_countFreedSinceLastCoalesce >= COALESCE_LIMIT) {
             m_countFreedSinceLastCoalesce = 0;
             coalesceFreeSpace();
         }
@@ -429,7 +440,7 @@ ExecutablePool::Allocation ExecutablePool::systemAlloc(size_t size)
   SpinLockHolder lock_holder(&spinlock);
 
     if (!allocator)
-        allocator = new FixedVMPoolAllocator(JIT_ALLOCATOR_LARGE_ALLOC_SIZE, TWO_GB);
+        allocator = new FixedVMPoolAllocator(JIT_ALLOCATOR_LARGE_ALLOC_SIZE, VM_POOL_SIZE);
     ExecutablePool::Allocation alloc = {reinterpret_cast<char*>(allocator->alloc(size)), size};
     return alloc;
 }
index 2eb0c87b05363e184aff9ff96455c86f089bad06..b04049c718e4615b2aa16ed55548db6b7be83cfd 100644 (file)
@@ -27,7 +27,7 @@
 
 #include "ExecutableAllocator.h"
 
-#if ENABLE(ASSEMBLER) && OS(UNIX) && !OS(SYMBIAN)
+#if ENABLE(EXECUTABLE_ALLOCATOR_DEMAND) && !OS(WINDOWS) && !OS(SYMBIAN)
 
 #include <sys/mman.h>
 #include <unistd.h>
@@ -35,8 +35,6 @@
 
 namespace JSC {
 
-#if !(OS(DARWIN) && !PLATFORM(QT) && CPU(X86_64))
-
 void ExecutableAllocator::intializePageSize()
 {
     ExecutableAllocator::pageSize = getpagesize();
@@ -57,29 +55,6 @@ void ExecutablePool::systemRelease(const ExecutablePool::Allocation& alloc)
     ASSERT_UNUSED(result, !result);
 }
 
-#endif // !(OS(DARWIN) && !PLATFORM(QT) && CPU(X86_64))
-
-#if ENABLE(ASSEMBLER_WX_EXCLUSIVE)
-void ExecutableAllocator::reprotectRegion(void* start, size_t size, ProtectionSeting setting)
-{
-    if (!pageSize)
-        intializePageSize();
-
-    // Calculate the start of the page containing this region,
-    // and account for this extra memory within size.
-    intptr_t startPtr = reinterpret_cast<intptr_t>(start);
-    intptr_t pageStartPtr = startPtr & ~(pageSize - 1);
-    void* pageStart = reinterpret_cast<void*>(pageStartPtr);
-    size += (startPtr - pageStartPtr);
-
-    // Round size up
-    size += (pageSize - 1);
-    size &= ~(pageSize - 1);
-
-    mprotect(pageStart, size, (setting == Writable) ? PROTECTION_FLAGS_RW : PROTECTION_FLAGS_RX);
-}
-#endif
-
 }
 
-#endif // HAVE(ASSEMBLER)
+#endif
index e82975c9c25fabf50d00005a6677e47d1ba7249a..9028f506ef7c003847f16bd5313397fc204714ac 100644 (file)
@@ -22,7 +22,7 @@
 
 #include "ExecutableAllocator.h"
 
-#if ENABLE(ASSEMBLER) && OS(SYMBIAN)
+#if ENABLE(EXECUTABLE_ALLOCATOR_DEMAND) && OS(SYMBIAN)
 
 #include <e32hal.h>
 #include <e32std.h>
index e38323c5fddd394628cd0d8fe6842a6c53c479c5..72a1d5ffc92088c8ad52983b4ac7d5d708252d7d 100644 (file)
@@ -27,7 +27,7 @@
 
 #include "ExecutableAllocator.h"
 
-#if ENABLE(ASSEMBLER) && OS(WINDOWS)
+#if ENABLE(EXECUTABLE_ALLOCATOR_DEMAND) && OS(WINDOWS)
 
 #include "windows.h"
 
index 700977e1e3e970db3abda8933c553dc9f279ff17..d930ed77be9dd707e07cf52d3e9f1690a44a037c 100644 (file)
@@ -1016,6 +1016,16 @@ on MinGW. See https://bugs.webkit.org/show_bug.cgi?id=29268 */
 #define ENABLE_ASSEMBLER_WX_EXCLUSIVE 0
 #endif
 
+/* Pick which allocator to use; we only need an executable allocator if the assembler is compiled in.
+   On x86-64 we use a single fixed mmap, on other platforms we mmap on demand. */
+#if ENABLE(ASSEMBLER)
+#if CPU(X86_64)
+#define ENABLE_EXECUTABLE_ALLOCATOR_FIXED 1
+#else
+#define ENABLE_EXECUTABLE_ALLOCATOR_DEMAND 1
+#endif
+#endif
+
 #if !defined(ENABLE_PAN_SCROLLING) && OS(WINDOWS)
 #define ENABLE_PAN_SCROLLING 1
 #endif