Subject: [PATCH] ProcessExecutableMemory.cpp: fix virtual address length on ia64 ia64's usable virtual address space is page dependent. For 16K pages with 3 levels of page tables we can address only 44 bits of virtual memory, not default 47. The change makes page size detection dynamic and adapts to addressable bits. On ia64 it is '4 * log2(page_size/8)'. Signed-off-by: Sergei Trofimovich --- js/src/jit/ProcessExecutableMemory.cpp | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/js/src/jit/ProcessExecutableMemory.cpp b/js/src/jit/ProcessExecutableMemory.cpp index d395ccf..484ff8d 100644 --- a/js/src/jit/ProcessExecutableMemory.cpp +++ b/js/src/jit/ProcessExecutableMemory.cpp @@ -324,7 +324,32 @@ static void* ComputeRandomAllocationAddress() { // x64 CPUs have a 48-bit address space and on some platforms the OS will // give us access to 47 bits, so to be safe we right shift by 18 to leave // 46 bits. +# ifdef __ia64__ + // On ia64 virtual address space looks like one of: + // virt_addr_64 = [ <63..61> | | L3 | L2 | L1 | offset ] + // virt_addr_64 = [ <63..61> | | L4 | L3 | L2 | L1 | offset ] + // where L{1..L4} are page tables. Each page table (except top-level L3 or L4) + // is itself a page-size entry and can store PageSize / 8 entries. Top-level + // entry is 1/8 of of L1/L2 (as 3 upper bits are part of <63..61> address part). + // Note: that makes addressable size directly depend on page size. + // + // We conservatively assume 3 levels of page tables here. This makes the + // following formula: + // L3 = log2(PAGE / 8 / 8) = log2(PAGE / 8) - 3 + // L2 = log2(PAGE / 8) + // L1 = log2(PAGE / 8) + // offset = log2(PAGE) = log2(PAGE / 8) + 3 + // thus + // L3 + L2 + L1 + offset = 4 * log2(PAGE / 8) + // For more details see http://www.ia64-linux.org/doc/IA64linuxkernel.PDF + // (slide 19: "user regions"). + static uint64_t ia64_virt_bits = std::min( + 4 * (mozilla::FloorLog2(gc::SystemPageSize() / 8)), + 46); + rand >>= (64 - ia64_virt_bits); +# else rand >>= 18; +# endif # else // On 32-bit, right shift by 34 to leave 30 bits, range [0, 1GiB). Then add // 512MiB to get range [512MiB, 1.5GiB), or [0x20000000, 0x60000000). This