1.1 --- a/src/os/windows/vm/os_windows.cpp Wed Oct 01 15:05:06 2008 -0400 1.2 +++ b/src/os/windows/vm/os_windows.cpp Thu Oct 02 12:01:08 2008 -0700 1.3 @@ -2593,9 +2593,104 @@ 1.4 } 1.5 1.6 char* os::reserve_memory_special(size_t bytes) { 1.7 - DWORD flag = MEM_RESERVE | MEM_COMMIT | MEM_LARGE_PAGES; 1.8 - char * res = (char *)VirtualAlloc(NULL, bytes, flag, PAGE_EXECUTE_READWRITE); 1.9 - return res; 1.10 + 1.11 + if (UseLargePagesIndividualAllocation) { 1.12 + if (TracePageSizes && Verbose) { 1.13 + tty->print_cr("Reserving large pages individually."); 1.14 + } 1.15 + char * p_buf; 1.16 + // first reserve enough address space in advance since we want to be 1.17 + // able to break a single contiguous virtual address range into multiple 1.18 + // large page commits but WS2003 does not allow reserving large page space 1.19 + // so we just use 4K pages for reserve, this gives us a legal contiguous 1.20 + // address space. then we will deallocate that reservation, and re alloc 1.21 + // using large pages 1.22 + const size_t size_of_reserve = bytes + _large_page_size; 1.23 + if (bytes > size_of_reserve) { 1.24 + // Overflowed. 1.25 + warning("Individually allocated large pages failed, " 1.26 + "use -XX:-UseLargePagesIndividualAllocation to turn off"); 1.27 + return NULL; 1.28 + } 1.29 + p_buf = (char *) VirtualAlloc(NULL, 1.30 + size_of_reserve, // size of Reserve 1.31 + MEM_RESERVE, 1.32 + PAGE_EXECUTE_READWRITE); 1.33 + // If reservation failed, return NULL 1.34 + if (p_buf == NULL) return NULL; 1.35 + 1.36 + release_memory(p_buf, bytes + _large_page_size); 1.37 + // round up to page boundary. If the size_of_reserve did not 1.38 + // overflow and the reservation did not fail, this align up 1.39 + // should not overflow. 1.40 + p_buf = (char *) align_size_up((size_t)p_buf, _large_page_size); 1.41 + 1.42 + // now go through and allocate one page at a time until all bytes are 1.43 + // allocated 1.44 + size_t bytes_remaining = align_size_up(bytes, _large_page_size); 1.45 + // An overflow of align_size_up() would have been caught above 1.46 + // in the calculation of size_of_reserve. 1.47 + char * next_alloc_addr = p_buf; 1.48 + 1.49 +#ifdef ASSERT 1.50 + // Variable for the failure injection 1.51 + long ran_num = os::random(); 1.52 + size_t fail_after = ran_num % bytes; 1.53 +#endif 1.54 + 1.55 + while (bytes_remaining) { 1.56 + size_t bytes_to_rq = MIN2(bytes_remaining, _large_page_size); 1.57 + // Note allocate and commit 1.58 + char * p_new; 1.59 + 1.60 +#ifdef ASSERT 1.61 + bool inject_error = LargePagesIndividualAllocationInjectError && 1.62 + (bytes_remaining <= fail_after); 1.63 +#else 1.64 + const bool inject_error = false; 1.65 +#endif 1.66 + 1.67 + if (inject_error) { 1.68 + p_new = NULL; 1.69 + } else { 1.70 + p_new = (char *) VirtualAlloc(next_alloc_addr, 1.71 + bytes_to_rq, 1.72 + MEM_RESERVE | MEM_COMMIT | MEM_LARGE_PAGES, 1.73 + PAGE_EXECUTE_READWRITE); 1.74 + } 1.75 + 1.76 + if (p_new == NULL) { 1.77 + // Free any allocated pages 1.78 + if (next_alloc_addr > p_buf) { 1.79 + // Some memory was committed so release it. 1.80 + size_t bytes_to_release = bytes - bytes_remaining; 1.81 + release_memory(p_buf, bytes_to_release); 1.82 + } 1.83 +#ifdef ASSERT 1.84 + if (UseLargePagesIndividualAllocation && 1.85 + LargePagesIndividualAllocationInjectError) { 1.86 + if (TracePageSizes && Verbose) { 1.87 + tty->print_cr("Reserving large pages individually failed."); 1.88 + } 1.89 + } 1.90 +#endif 1.91 + return NULL; 1.92 + } 1.93 + bytes_remaining -= bytes_to_rq; 1.94 + next_alloc_addr += bytes_to_rq; 1.95 + } 1.96 + 1.97 + return p_buf; 1.98 + 1.99 + } else { 1.100 + // normal policy just allocate it all at once 1.101 + DWORD flag = MEM_RESERVE | MEM_COMMIT | MEM_LARGE_PAGES; 1.102 + char * res = (char *)VirtualAlloc(NULL, 1.103 + bytes, 1.104 + flag, 1.105 + PAGE_EXECUTE_READWRITE); 1.106 + return res; 1.107 + } 1.108 } 1.109 1.110 bool os::release_memory_special(char* base, size_t bytes) { 1.111 @@ -2983,6 +3078,7 @@ 1.112 volatile intx os::win32::_os_thread_count = 0; 1.113 1.114 bool os::win32::_is_nt = false; 1.115 +bool os::win32::_is_windows_2003 = false; 1.116 1.117 1.118 void os::win32::initialize_system_info() { 1.119 @@ -3005,7 +3101,15 @@ 1.120 GetVersionEx(&oi); 1.121 switch(oi.dwPlatformId) { 1.122 case VER_PLATFORM_WIN32_WINDOWS: _is_nt = false; break; 1.123 - case VER_PLATFORM_WIN32_NT: _is_nt = true; break; 1.124 + case VER_PLATFORM_WIN32_NT: 1.125 + _is_nt = true; 1.126 + { 1.127 + int os_vers = oi.dwMajorVersion * 1000 + oi.dwMinorVersion; 1.128 + if (os_vers == 5002) { 1.129 + _is_windows_2003 = true; 1.130 + } 1.131 + } 1.132 + break; 1.133 default: fatal("Unknown platform"); 1.134 } 1.135 1.136 @@ -3103,9 +3207,13 @@ 1.137 NoYieldsInMicrolock = true; 1.138 } 1.139 #endif 1.140 + // This may be overridden later when argument processing is done. 1.141 + FLAG_SET_ERGO(bool, UseLargePagesIndividualAllocation, 1.142 + os::win32::is_windows_2003()); 1.143 + 1.144 // Initialize main_process and main_thread 1.145 main_process = GetCurrentProcess(); // Remember main_process is a pseudo handle 1.146 - if (!DuplicateHandle(main_process, GetCurrentThread(), main_process, 1.147 + if (!DuplicateHandle(main_process, GetCurrentThread(), main_process, 1.148 &main_thread, THREAD_ALL_ACCESS, false, 0)) { 1.149 fatal("DuplicateHandle failed\n"); 1.150 }