2011-05-19 Oliver Hunt <oliver@apple.com>
authoroliver@apple.com <oliver@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 19 May 2011 23:46:16 +0000 (23:46 +0000)
committeroliver@apple.com <oliver@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 19 May 2011 23:46:16 +0000 (23:46 +0000)
        Reviewed by Gavin Barraclough.

        Add guard pages to each end of the memory region used by the fixedvm allocator
        https://bugs.webkit.org/show_bug.cgi?id=61150

        Add mechanism to notify the OSAllocator that pages at either end of an
        allocation should be considered guard pages.  Update PageReservation,
        PageAllocation, etc to handle this.

        * JavaScriptCore.exp:
        * jit/ExecutableAllocatorFixedVMPool.cpp:
        (JSC::FixedVMPoolAllocator::FixedVMPoolAllocator):
        * wtf/OSAllocator.h:
        * wtf/OSAllocatorPosix.cpp:
        (WTF::OSAllocator::reserveUncommitted):
        (WTF::OSAllocator::reserveAndCommit):
        * wtf/PageAllocation.h:
        (WTF::PageAllocation::PageAllocation):
        * wtf/PageAllocationAligned.h:
        (WTF::PageAllocationAligned::PageAllocationAligned):
        * wtf/PageBlock.h:
        (WTF::PageBlock::PageBlock):
        * wtf/PageReservation.h:
        (WTF::PageReservation::reserve):
        (WTF::PageReservation::reserveWithGuardPages):
            Add a new function to make a reservation that will add guard
            pages to the ends of an allocation.
        (WTF::PageReservation::PageReservation):

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@86906 268f45cc-cd09-0410-ab3c-d52691b4dbfc

Source/JavaScriptCore/ChangeLog
Source/JavaScriptCore/JavaScriptCore.exp
Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def
Source/JavaScriptCore/jit/ExecutableAllocatorFixedVMPool.cpp
Source/JavaScriptCore/wtf/OSAllocator.h
Source/JavaScriptCore/wtf/OSAllocatorPosix.cpp
Source/JavaScriptCore/wtf/OSAllocatorSymbian.cpp
Source/JavaScriptCore/wtf/PageAllocation.h
Source/JavaScriptCore/wtf/PageAllocationAligned.h
Source/JavaScriptCore/wtf/PageBlock.h
Source/JavaScriptCore/wtf/PageReservation.h

index e02bf2f..2d80565 100644 (file)
@@ -1,5 +1,36 @@
 2011-05-19  Oliver Hunt  <oliver@apple.com>
 
+        Reviewed by Gavin Barraclough.
+
+        Add guard pages to each end of the memory region used by the fixedvm allocator
+        https://bugs.webkit.org/show_bug.cgi?id=61150
+
+        Add mechanism to notify the OSAllocator that pages at either end of an
+        allocation should be considered guard pages.  Update PageReservation,
+        PageAllocation, etc to handle this.
+
+        * JavaScriptCore.exp:
+        * jit/ExecutableAllocatorFixedVMPool.cpp:
+        (JSC::FixedVMPoolAllocator::FixedVMPoolAllocator):
+        * wtf/OSAllocator.h:
+        * wtf/OSAllocatorPosix.cpp:
+        (WTF::OSAllocator::reserveUncommitted):
+        (WTF::OSAllocator::reserveAndCommit):
+        * wtf/PageAllocation.h:
+        (WTF::PageAllocation::PageAllocation):
+        * wtf/PageAllocationAligned.h:
+        (WTF::PageAllocationAligned::PageAllocationAligned):
+        * wtf/PageBlock.h:
+        (WTF::PageBlock::PageBlock):
+        * wtf/PageReservation.h:
+        (WTF::PageReservation::reserve):
+        (WTF::PageReservation::reserveWithGuardPages):
+            Add a new function to make a reservation that will add guard
+            pages to the ends of an allocation.
+        (WTF::PageReservation::PageReservation):
+
+2011-05-19  Oliver Hunt  <oliver@apple.com>
+
         Reviewed by Geoffrey Garen.
 
         Make Executables release their JIT code as soon as they become dead
index 9aa3b1f..e2c0bda 100644 (file)
@@ -375,7 +375,7 @@ __ZN3WTF10StringImplD1Ev
 __ZN3WTF10fastCallocEmm
 __ZN3WTF10fastMallocEm
 __ZN3WTF10fastStrDupEPKc
-__ZN3WTF11OSAllocator16reserveAndCommitEmNS0_5UsageEbb
+__ZN3WTF11OSAllocator16reserveAndCommitEmNS0_5UsageEbbb
 __ZN3WTF11OSAllocator18releaseDecommittedEPvm
 __ZN3WTF11commentAtomE
 __ZN3WTF11currentTimeEv
index 1a0c31a..6f2a0bf 100644 (file)
@@ -285,7 +285,7 @@ EXPORTS
     ?releaseDecommitted@OSAllocator@WTF@@SAXPAXI@Z
     ?releaseStack@MarkStack@JSC@@CAXPAXI@Z
     ?reportExtraMemoryCostSlowCase@Heap@JSC@@AAEXI@Z
-    ?reserveAndCommit@OSAllocator@WTF@@SAPAXIW4Usage@12@_N1@Z
+    ?reserveAndCommit@OSAllocator@WTF@@SAPAXIW4Usage@12@_N11@Z
     ?reserveCapacity@StringBuilder@WTF@@QAEXI@Z
     ?reset@ParserArena@JSC@@QAEXXZ
     ?reset@TimeoutChecker@JSC@@QAEXXZ
index 6a945b0..20209ce 100644 (file)
@@ -409,7 +409,7 @@ public:
         ASSERT(PageTables32MB::size() == 32 * 1024 * 1024);
         ASSERT(PageTables1GB::size() == 1024 * 1024 * 1024);
 
-        m_reservation = PageReservation::reserve(FixedVMPoolPageTables::size(), OSAllocator::JSJITCodePages, EXECUTABLE_POOL_WRITABLE, true);
+        m_reservation = PageReservation::reserveWithGuardPages(FixedVMPoolPageTables::size(), OSAllocator::JSJITCodePages, EXECUTABLE_POOL_WRITABLE, true);
 #if !ENABLE(INTERPRETER)
         if (!isValid())
             CRASH();
index 3fd4cef..ca93056 100644 (file)
@@ -45,7 +45,7 @@ public:
     // These methods are symmetric; reserveUncommitted allocates VM in an uncommitted state,
     // releaseDecommitted should be called on a region of VM allocated by a single reservation,
     // the memory must all currently be in a decommitted state.
-    static void* reserveUncommitted(size_t, Usage = UnknownUsage, bool writable = true, bool executable = false);
+    static void* reserveUncommitted(size_t, Usage = UnknownUsage, bool writable = true, bool executable = false, bool includesGuardPages = false);
     static void releaseDecommitted(void*, size_t);
 
     // These methods are symmetric; they commit or decommit a region of VM (uncommitted VM should
@@ -57,7 +57,7 @@ public:
     // These methods are symmetric; reserveAndCommit allocates VM in an committed state,
     // decommitAndRelease should be called on a region of VM allocated by a single reservation,
     // the memory must all currently be in a committed state.
-    static void* reserveAndCommit(size_t, Usage = UnknownUsage, bool writable = true, bool executable = false);
+    static void* reserveAndCommit(size_t, Usage = UnknownUsage, bool writable = true, bool executable = false, bool includesGuardPages = false);
     static void decommitAndRelease(void* base, size_t size);
 
     // These methods are akin to reserveAndCommit/decommitAndRelease, above - however rather than
index 27ebd91..51cb3af 100644 (file)
@@ -26,6 +26,7 @@
 #include "config.h"
 #include "OSAllocator.h"
 
+#include "PageAllocation.h"
 #include <errno.h>
 #include <sys/mman.h>
 #include <wtf/Assertions.h>
@@ -33,9 +34,9 @@
 
 namespace WTF {
 
-void* OSAllocator::reserveUncommitted(size_t bytes, Usage usage, bool writable, bool executable)
+void* OSAllocator::reserveUncommitted(size_t bytes, Usage usage, bool writable, bool executable, bool includesGuardPages)
 {
-    void* result = reserveAndCommit(bytes, usage, writable, executable);
+    void* result = reserveAndCommit(bytes, usage, writable, executable, includesGuardPages);
 #if HAVE(MADV_FREE_REUSE)
     // To support the "reserve then commit" model, we have to initially decommit.
     while (madvise(result, bytes, MADV_FREE_REUSABLE) == -1 && errno == EAGAIN) { }
@@ -43,7 +44,7 @@ void* OSAllocator::reserveUncommitted(size_t bytes, Usage usage, bool writable,
     return result;
 }
 
-void* OSAllocator::reserveAndCommit(size_t bytes, Usage usage, bool writable, bool executable)
+void* OSAllocator::reserveAndCommit(size_t bytes, Usage usage, bool writable, bool executable, bool includesGuardPages)
 {
     // All POSIX reservations start out logically committed.
     int protection = PROT_READ;
@@ -63,6 +64,7 @@ void* OSAllocator::reserveAndCommit(size_t bytes, Usage usage, bool writable, bo
     void* result = 0;
 #if (OS(DARWIN) && CPU(X86_64))
     if (executable) {
+        ASSERT(includesGuardPages);
         // Cook up an address to allocate at, using the following recipe:
         //   17 bits of zero, stay in userspace kids.
         //   26 bits of randomness for ASLR.
@@ -83,6 +85,10 @@ void* OSAllocator::reserveAndCommit(size_t bytes, Usage usage, bool writable, bo
     result = mmap(result, bytes, protection, flags, fd, 0);
     if (result == MAP_FAILED)
         CRASH();
+    if (includesGuardPages) {
+        mprotect(result, pageSize(), PROT_NONE);
+        mprotect(static_cast<char*>(result) + bytes - pageSize(), pageSize(), PROT_NONE);
+    }
     return result;
 }
 
index c63e609..59bcdba 100644 (file)
@@ -74,7 +74,7 @@ static PageAllocatorSymbian* dataAllocatorInstance()
 }
 
 // Reserve memory and return the base address of the region
-void* OSAllocator::reserveUncommitted(size_t reservationSize, Usage usage, bool , bool executable) 
+void* OSAllocator::reserveUncommitted(size_t reservationSize, Usage usage, bool , bool executable, bool
 {
     void* base = 0; 
     if (executable) 
@@ -110,7 +110,7 @@ void OSAllocator::decommit(void* address, size_t bytes)
         deallocateCodeChunk(address); // for code chunk, decommit AND release    
 }
     
-void* OSAllocator::reserveAndCommit(size_t bytes, Usage usage, bool writable, bool executable)
+void* OSAllocator::reserveAndCommit(size_t bytes, Usage usage, bool writable, bool executable, bool)
 { 
     void* base = reserveUncommitted(bytes, usage, writable, executable);
     commit(base, bytes, writable, executable);
index ad3d217..ff6f195 100644 (file)
@@ -117,7 +117,7 @@ public:
 
 private:
     PageAllocation(void* base, size_t size)
-        : PageBlock(base, size)
+        : PageBlock(base, size, false)
     {
     }
 };
index 282c9e3..c018dab 100644 (file)
@@ -48,13 +48,13 @@ public:
 private:
 #if OS(DARWIN)
     PageAllocationAligned(void* base, size_t size)
-        : PageBlock(base, size)
+        : PageBlock(base, size, false)
     {
     }
 #else
     PageAllocationAligned(void* base, size_t size, void* reservationBase, size_t reservationSize)
-        : PageBlock(base, size)
-        , m_reservation(reservationBase, reservationSize)
+        : PageBlock(base, size, false)
+        , m_reservation(reservationBase, reservationSize, false)
     {
     }
 
index 07452b3..a6f1b49 100644 (file)
@@ -37,7 +37,7 @@ class PageBlock {
 public:
     PageBlock();
     PageBlock(const PageBlock&);
-    PageBlock(void*, size_t);
+    PageBlock(void*, size_t, bool hasGuardPages);
     
     void* base() const { return m_base; }
     size_t size() const { return m_size; }
@@ -51,24 +51,28 @@ public:
     }
 
 private:
+    void* m_realBase;
     void* m_base;
     size_t m_size;
 };
 
 inline PageBlock::PageBlock()
-    : m_base(0)
+    : m_realBase(0)
+    , m_base(0)
     , m_size(0)
 {
 }
 
 inline PageBlock::PageBlock(const PageBlock& other)
-    : m_base(other.m_base)
+    : m_realBase(other.m_realBase)
+    , m_base(other.m_base)
     , m_size(other.m_size)
 {
 }
 
-inline PageBlock::PageBlock(void* base, size_t size)
-    : m_base(base)
+inline PageBlock::PageBlock(void* base, size_t size, bool hasGuardPages)
+    : m_realBase(base)
+    , m_base(static_cast<char*>(base) + (hasGuardPages ? pageSize() : 0))
     , m_size(size)
 {
 }
index 6dff700..77783eb 100644 (file)
@@ -104,7 +104,13 @@ public:
     static PageReservation reserve(size_t size, OSAllocator::Usage usage = OSAllocator::UnknownUsage, bool writable = true, bool executable = false)
     {
         ASSERT(isPageAligned(size));
-        return PageReservation(OSAllocator::reserveUncommitted(size, usage, writable, executable), size, writable, executable);
+        return PageReservation(OSAllocator::reserveUncommitted(size, usage, writable, executable), size, writable, executable, false);
+    }
+    
+    static PageReservation reserveWithGuardPages(size_t size, OSAllocator::Usage usage = OSAllocator::UnknownUsage, bool writable = true, bool executable = false)
+    {
+        ASSERT(isPageAligned(size));
+        return PageReservation(OSAllocator::reserveUncommitted(size + pageSize() * 2, usage, writable, executable, true), size, writable, executable, true);
     }
 
     void deallocate()
@@ -123,8 +129,8 @@ public:
     }
 
 private:
-    PageReservation(void* base, size_t size, bool writable, bool executable)
-        : PageBlock(base, size)
+    PageReservation(void* base, size_t size, bool writable, bool executable, bool hasGuardPages)
+        : PageBlock(base, size, hasGuardPages)
         , m_committed(0)
         , m_writable(writable)
         , m_executable(executable)