Bug 910845 - Add a wrapper for mmap() in order to keep the high 17-bits of JS pointers cleared on IA64. r=billm
authorStephan Schreiber <info@fs-driver.org>
Mon, 09 Sep 2013 08:57:37 -0400
changeset 159095 66c4c1a9b69709466f10038b3cd73235c7ad8404
parent 159094 dbe8e0e7c25070c06b16e5383286dede0f06502b
child 159096 c3b01d22caa9c7ddd8472333dbdba3e4f1ffe353
push id2961
push userlsblakk@mozilla.com
push dateMon, 28 Oct 2013 21:59:28 +0000
treeherdermozilla-beta@73ef4f13486f [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbillm
bugs910845
milestone26.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 910845 - Add a wrapper for mmap() in order to keep the high 17-bits of JS pointers cleared on IA64. r=billm
js/src/gc/Memory.cpp
--- a/js/src/gc/Memory.cpp
+++ b/js/src/gc/Memory.cpp
@@ -138,17 +138,17 @@ gc::UnmapPages(JSRuntime *rt, void *addr
 
     uintptr_t base = reinterpret_cast<uintptr_t>(addr) - ((2 * size) - cb);
     DosFreeMem(reinterpret_cast<void*>(base));
 
     return;
 }
 
 static void *
-gc::MapAlignedPagesRecursively(JSRuntime *rt, size_t size, size_t alignment, int& recursions)
+MapAlignedPagesRecursively(JSRuntime *rt, size_t size, size_t alignment, int& recursions)
 {
     if (++recursions >= OS2_MAX_RECURSIONS)
         return NULL;
 
     void *tmp;
     if (DosAllocMem(&tmp, size,
                     OBJ_ANY | PAG_COMMIT | PAG_READ | PAG_WRITE)) {
         JS_ALWAYS_TRUE(DosAllocMem(&tmp, size,
@@ -304,35 +304,72 @@ gc::GetPageFaultCount()
 #include <unistd.h>
 
 void
 gc::InitMemorySubsystem(JSRuntime *rt)
 {
     rt->gcSystemPageSize = rt->gcSystemAllocGranularity = size_t(sysconf(_SC_PAGESIZE));
 }
 
+static inline void *
+MapMemory(size_t length, int prot, int flags, int fd, off_t offset)
+{
+#if defined(__ia64__)
+    /*
+     * The JS engine assumes that all allocated pointers have their high 17 bits clear,
+     * which ia64's mmap doesn't support directly. However, we can emulate it by passing
+     * mmap an "addr" parameter with those bits clear. The mmap will return that address,
+     * or the nearest available memory above that address, providing a near-guarantee
+     * that those bits are clear. If they are not, we return NULL below to indicate
+     * out-of-memory.
+     *
+     * The addr is chosen as 0x0000070000000000, which still allows about 120TB of virtual
+     * address space.
+     *
+     * See Bug 589735 for more information.
+     */
+    void *region = mmap((void*)0x0000070000000000, length, prot, flags, fd, offset);
+    if (region == MAP_FAILED)
+        return MAP_FAILED;
+    /* 
+     * If the allocated memory doesn't have its upper 17 bits clear, consider it
+     * as out of memory.
+     */
+    if ((uintptr_t(region) + (length - 1)) & 0xffff800000000000) {
+        JS_ALWAYS_TRUE(0 == munmap(region, length));
+        return MAP_FAILED;
+    }
+    return region;
+#else
+    return mmap(NULL, length, prot, flags, fd, offset);
+#endif
+}
+
 void *
 gc::MapAlignedPages(JSRuntime *rt, size_t size, size_t alignment)
 {
     JS_ASSERT(size >= alignment);
     JS_ASSERT(size % alignment == 0);
     JS_ASSERT(size % rt->gcSystemPageSize == 0);
     JS_ASSERT(alignment % rt->gcSystemAllocGranularity == 0);
 
     int prot = PROT_READ | PROT_WRITE;
     int flags = MAP_PRIVATE | MAP_ANON;
 
     /* Special case: If we want page alignment, no further work is needed. */
     if (alignment == rt->gcSystemAllocGranularity) {
-        return mmap(NULL, size, prot, flags, -1, 0);
+        void *region = MapMemory(size, prot, flags, -1, 0);
+        if (region == MAP_FAILED)
+            return NULL;
+        return region;
     }
 
     /* Overallocate and unmap the region's edges. */
     size_t reqSize = Min(size + 2 * alignment, 2 * size);
-    void *region = mmap(NULL, reqSize, prot, flags, -1, 0);
+    void *region = MapMemory(reqSize, prot, flags, -1, 0);
     if (region == MAP_FAILED)
         return NULL;
 
     uintptr_t regionEnd = uintptr_t(region) + reqSize;
     uintptr_t offset = uintptr_t(region) % alignment;
     JS_ASSERT(offset < reqSize - size);
 
     void *front = (void *)(uintptr_t(region) + (alignment - offset));