Bug 910845 - Add a wrapper for mmap() in order to keep the high 17-bits of JS pointers cleared on IA64. r=billm
☠☠ backed out by 97f0b4398600 ☠ ☠
authorStephan Schreiber <info@fs-driver.org>
Fri, 06 Sep 2013 16:41:55 -0400
changeset 158933 45c33630713688d19d83f52b600c3488b7123b9c
parent 158932 f98b323128d97321cd1896a25aa5a12710c434fe
child 158934 fc3a3227fc829020bffb883985f2e6a6bfb20df5
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
@@ -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 *
+gc::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));