Bug 589735 - JS engine is completely broken on ia64 - jemalloc part; r=pbiggar
authorJan Horak <jhorak@redhat.com>
Mon, 29 Aug 2011 17:26:22 +0100
changeset 76184 9c15d0fb3e255648d8050634a073033732ca705e
parent 76183 363c40e0666704df081098a50d2c1c01feff7e98
child 76185 7658f61d9e2bfe17529654c2f65ff1234caaa3bf
push id3
push userfelipc@gmail.com
push dateFri, 30 Sep 2011 20:09:13 +0000
reviewerspbiggar
bugs589735
milestone9.0a1
Bug 589735 - JS engine is completely broken on ia64 - jemalloc part; r=pbiggar
memory/jemalloc/jemalloc.c
--- a/memory/jemalloc/jemalloc.c
+++ b/memory/jemalloc/jemalloc.c
@@ -2190,16 +2190,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 |
@@ -2209,34 +2229,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) {