diff --git a/memory/jemalloc/jemalloc.c b/memory/jemalloc/jemalloc.c --- a/memory/jemalloc/jemalloc.c +++ b/memory/jemalloc/jemalloc.c @@ -2198,16 +2198,36 @@ pages_map_align(size_t size, int pfd, si return (ret); } #endif static void * pages_map(void *addr, size_t size, int pfd) { void *ret; +#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. + */ + bool check_placement = true; + if (addr == NULL) { + addr = (void*)0x0000070000000000; + check_placement = false; + } +#endif /* * We don't use MAP_FIXED here, because it can cause the *replacement* * of existing mappings, and we only want to create new mappings. */ #ifdef MALLOC_PAGEFILE if (pfd != -1) { ret = mmap(addr, size, PROT_READ | PROT_WRITE, MAP_PRIVATE | @@ -2217,34 +2237,52 @@ pages_map(void *addr, size_t size, int p { ret = mmap(addr, size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0); } assert(ret != NULL); if (ret == MAP_FAILED) ret = NULL; +#if defined(__ia64__) + /* + * If the allocated memory doesn't have its upper 17 bits clear, consider it + * as out of memory. + */ + else if ((long long)ret & 0xffff800000000000) { + munmap(ret, size); + ret = NULL; + } + /* If the caller requested a specific memory location, verify that's what mmap returned. */ + else if (check_placement && ret != addr) { +#else else if (addr != NULL && ret != addr) { +#endif /* * We succeeded in mapping memory, but not in the right place. */ if (munmap(ret, size) == -1) { char buf[STRERROR_BUF]; strerror_r(errno, buf, sizeof(buf)); _malloc_message(_getprogname(), ": (malloc) Error in munmap(): ", buf, "\n"); if (opt_abort) abort(); } ret = NULL; } +#if defined(__ia64__) + assert(ret == NULL || (!check_placement && ret != NULL) + || (check_placement && ret == addr)); +#else assert(ret == NULL || (addr == NULL && ret != addr) || (addr != NULL && ret == addr)); +#endif return (ret); } static void pages_unmap(void *addr, size_t size) { if (munmap(addr, size) == -1) {