| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (C) 2013 Google Inc. All rights reserved. | 2 * Copyright (C) 2013 Google Inc. All rights reserved. |
| 3 * | 3 * |
| 4 * Redistribution and use in source and binary forms, with or without | 4 * Redistribution and use in source and binary forms, with or without |
| 5 * modification, are permitted provided that the following conditions are | 5 * modification, are permitted provided that the following conditions are |
| 6 * met: | 6 * met: |
| 7 * | 7 * |
| 8 * * Redistributions of source code must retain the above copyright | 8 * * Redistributions of source code must retain the above copyright |
| 9 * notice, this list of conditions and the following disclaimer. | 9 * notice, this list of conditions and the following disclaimer. |
| 10 * * Redistributions in binary form must reproduce the above | 10 * * Redistributions in binary form must reproduce the above |
| (...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 102 size_t postSlack = baseLen - preSlack - trimLen; | 102 size_t postSlack = baseLen - preSlack - trimLen; |
| 103 ASSERT(baseLen >= trimLen || preSlack || postSlack); | 103 ASSERT(baseLen >= trimLen || preSlack || postSlack); |
| 104 ASSERT(preSlack < baseLen); | 104 ASSERT(preSlack < baseLen); |
| 105 ASSERT(postSlack < baseLen); | 105 ASSERT(postSlack < baseLen); |
| 106 void* ret = base; | 106 void* ret = base; |
| 107 | 107 |
| 108 #if OS(POSIX) // On POSIX we can resize the allocation run. | 108 #if OS(POSIX) // On POSIX we can resize the allocation run. |
| 109 (void) pageAccessibility; | 109 (void) pageAccessibility; |
| 110 if (preSlack) { | 110 if (preSlack) { |
| 111 int res = munmap(base, preSlack); | 111 int res = munmap(base, preSlack); |
| 112 RELEASE_ASSERT(!res); | 112 CHECK(!res); |
| 113 ret = reinterpret_cast<char*>(base) + preSlack; | 113 ret = reinterpret_cast<char*>(base) + preSlack; |
| 114 } | 114 } |
| 115 if (postSlack) { | 115 if (postSlack) { |
| 116 int res = munmap(reinterpret_cast<char*>(ret) + trimLen, postSlack); | 116 int res = munmap(reinterpret_cast<char*>(ret) + trimLen, postSlack); |
| 117 RELEASE_ASSERT(!res); | 117 CHECK(!res); |
| 118 } | 118 } |
| 119 #else // On Windows we can't resize the allocation run. | 119 #else // On Windows we can't resize the allocation run. |
| 120 if (preSlack || postSlack) { | 120 if (preSlack || postSlack) { |
| 121 ret = reinterpret_cast<char*>(base) + preSlack; | 121 ret = reinterpret_cast<char*>(base) + preSlack; |
| 122 freePages(base, baseLen); | 122 freePages(base, baseLen); |
| 123 ret = systemAllocPages(ret, trimLen, pageAccessibility); | 123 ret = systemAllocPages(ret, trimLen, pageAccessibility); |
| 124 } | 124 } |
| 125 #endif | 125 #endif |
| 126 | 126 |
| 127 return ret; | 127 return ret; |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 165 } | 165 } |
| 166 | 166 |
| 167 #if !CPU(32BIT) // Keep trying random addresses on systems that have a large add
ress space. | 167 #if !CPU(32BIT) // Keep trying random addresses on systems that have a large add
ress space. |
| 168 addr = getRandomPageBase(); | 168 addr = getRandomPageBase(); |
| 169 addr = reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(addr) & align
BaseMask); | 169 addr = reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(addr) & align
BaseMask); |
| 170 #endif | 170 #endif |
| 171 } | 171 } |
| 172 | 172 |
| 173 // Map a larger allocation so we can force alignment, but continue randomizi
ng only on 64-bit POSIX. | 173 // Map a larger allocation so we can force alignment, but continue randomizi
ng only on 64-bit POSIX. |
| 174 size_t tryLen = len + (align - kPageAllocationGranularity); | 174 size_t tryLen = len + (align - kPageAllocationGranularity); |
| 175 RELEASE_ASSERT(tryLen >= len); | 175 CHECK_GE(tryLen, len); |
| 176 void* ret; | 176 void* ret; |
| 177 | 177 |
| 178 do { | 178 do { |
| 179 // Don't continue to burn cycles on mandatory hints (Windows). | 179 // Don't continue to burn cycles on mandatory hints (Windows). |
| 180 addr = kHintIsAdvisory ? getRandomPageBase() : nullptr; | 180 addr = kHintIsAdvisory ? getRandomPageBase() : nullptr; |
| 181 ret = systemAllocPages(addr, tryLen, pageAccessibility); | 181 ret = systemAllocPages(addr, tryLen, pageAccessibility); |
| 182 // The retries are for Windows, where a race can steal our mapping on resize
. | 182 // The retries are for Windows, where a race can steal our mapping on resize
. |
| 183 } while (ret && !(ret = trimMapping(ret, tryLen, len, align, pageAccessibili
ty))); | 183 } while (ret && !(ret = trimMapping(ret, tryLen, len, align, pageAccessibili
ty))); |
| 184 | 184 |
| 185 return ret; | 185 return ret; |
| 186 } | 186 } |
| 187 | 187 |
| 188 void freePages(void* addr, size_t len) | 188 void freePages(void* addr, size_t len) |
| 189 { | 189 { |
| 190 ASSERT(!(reinterpret_cast<uintptr_t>(addr) & kPageAllocationGranularityOffse
tMask)); | 190 ASSERT(!(reinterpret_cast<uintptr_t>(addr) & kPageAllocationGranularityOffse
tMask)); |
| 191 ASSERT(!(len & kPageAllocationGranularityOffsetMask)); | 191 ASSERT(!(len & kPageAllocationGranularityOffsetMask)); |
| 192 #if OS(POSIX) | 192 #if OS(POSIX) |
| 193 int ret = munmap(addr, len); | 193 int ret = munmap(addr, len); |
| 194 RELEASE_ASSERT(!ret); | 194 CHECK(!ret); |
| 195 #else | 195 #else |
| 196 BOOL ret = VirtualFree(addr, 0, MEM_RELEASE); | 196 BOOL ret = VirtualFree(addr, 0, MEM_RELEASE); |
| 197 RELEASE_ASSERT(ret); | 197 CHECK(ret); |
| 198 #endif | 198 #endif |
| 199 } | 199 } |
| 200 | 200 |
| 201 void setSystemPagesInaccessible(void* addr, size_t len) | 201 void setSystemPagesInaccessible(void* addr, size_t len) |
| 202 { | 202 { |
| 203 ASSERT(!(len & kSystemPageOffsetMask)); | 203 ASSERT(!(len & kSystemPageOffsetMask)); |
| 204 #if OS(POSIX) | 204 #if OS(POSIX) |
| 205 int ret = mprotect(addr, len, PROT_NONE); | 205 int ret = mprotect(addr, len, PROT_NONE); |
| 206 RELEASE_ASSERT(!ret); | 206 CHECK(!ret); |
| 207 #else | 207 #else |
| 208 BOOL ret = VirtualFree(addr, len, MEM_DECOMMIT); | 208 BOOL ret = VirtualFree(addr, len, MEM_DECOMMIT); |
| 209 RELEASE_ASSERT(ret); | 209 CHECK(ret); |
| 210 #endif | 210 #endif |
| 211 } | 211 } |
| 212 | 212 |
| 213 bool setSystemPagesAccessible(void* addr, size_t len) | 213 bool setSystemPagesAccessible(void* addr, size_t len) |
| 214 { | 214 { |
| 215 ASSERT(!(len & kSystemPageOffsetMask)); | 215 ASSERT(!(len & kSystemPageOffsetMask)); |
| 216 #if OS(POSIX) | 216 #if OS(POSIX) |
| 217 return !mprotect(addr, len, PROT_READ | PROT_WRITE); | 217 return !mprotect(addr, len, PROT_READ | PROT_WRITE); |
| 218 #else | 218 #else |
| 219 return !!VirtualAlloc(addr, len, MEM_COMMIT, PAGE_READWRITE); | 219 return !!VirtualAlloc(addr, len, MEM_COMMIT, PAGE_READWRITE); |
| 220 #endif | 220 #endif |
| 221 } | 221 } |
| 222 | 222 |
| 223 void decommitSystemPages(void* addr, size_t len) | 223 void decommitSystemPages(void* addr, size_t len) |
| 224 { | 224 { |
| 225 ASSERT(!(len & kSystemPageOffsetMask)); | 225 ASSERT(!(len & kSystemPageOffsetMask)); |
| 226 #if OS(POSIX) | 226 #if OS(POSIX) |
| 227 int ret = madvise(addr, len, MADV_FREE); | 227 int ret = madvise(addr, len, MADV_FREE); |
| 228 RELEASE_ASSERT(!ret); | 228 CHECK(!ret); |
| 229 #else | 229 #else |
| 230 setSystemPagesInaccessible(addr, len); | 230 setSystemPagesInaccessible(addr, len); |
| 231 #endif | 231 #endif |
| 232 } | 232 } |
| 233 | 233 |
| 234 void recommitSystemPages(void* addr, size_t len) | 234 void recommitSystemPages(void* addr, size_t len) |
| 235 { | 235 { |
| 236 ASSERT(!(len & kSystemPageOffsetMask)); | 236 ASSERT(!(len & kSystemPageOffsetMask)); |
| 237 #if OS(POSIX) | 237 #if OS(POSIX) |
| 238 (void) addr; | 238 (void) addr; |
| 239 #else | 239 #else |
| 240 RELEASE_ASSERT(setSystemPagesAccessible(addr, len)); | 240 CHECK(setSystemPagesAccessible(addr, len)); |
| 241 #endif | 241 #endif |
| 242 } | 242 } |
| 243 | 243 |
| 244 void discardSystemPages(void* addr, size_t len) | 244 void discardSystemPages(void* addr, size_t len) |
| 245 { | 245 { |
| 246 ASSERT(!(len & kSystemPageOffsetMask)); | 246 ASSERT(!(len & kSystemPageOffsetMask)); |
| 247 #if OS(POSIX) | 247 #if OS(POSIX) |
| 248 // On POSIX, the implementation detail is that discard and decommit are the | 248 // On POSIX, the implementation detail is that discard and decommit are the |
| 249 // same, and lead to pages that are returned to the system immediately and | 249 // same, and lead to pages that are returned to the system immediately and |
| 250 // get replaced with zeroed pages when touched. So we just call | 250 // get replaced with zeroed pages when touched. So we just call |
| 251 // decommitSystemPages() here to avoid code duplication. | 251 // decommitSystemPages() here to avoid code duplication. |
| 252 decommitSystemPages(addr, len); | 252 decommitSystemPages(addr, len); |
| 253 #else | 253 #else |
| 254 // On Windows discarded pages are not returned to the system immediately and | 254 // On Windows discarded pages are not returned to the system immediately and |
| 255 // not guaranteed to be zeroed when returned to the application. | 255 // not guaranteed to be zeroed when returned to the application. |
| 256 using DiscardVirtualMemoryFunction = DWORD(WINAPI*)(PVOID virtualAddress, SI
ZE_T size); | 256 using DiscardVirtualMemoryFunction = DWORD(WINAPI*)(PVOID virtualAddress, SI
ZE_T size); |
| 257 static DiscardVirtualMemoryFunction discardVirtualMemory = reinterpret_cast<
DiscardVirtualMemoryFunction>(-1); | 257 static DiscardVirtualMemoryFunction discardVirtualMemory = reinterpret_cast<
DiscardVirtualMemoryFunction>(-1); |
| 258 if (discardVirtualMemory == reinterpret_cast<DiscardVirtualMemoryFunction>(-
1)) | 258 if (discardVirtualMemory == reinterpret_cast<DiscardVirtualMemoryFunction>(-
1)) |
| 259 discardVirtualMemory = reinterpret_cast<DiscardVirtualMemoryFunction>(Ge
tProcAddress(GetModuleHandle(L"Kernel32.dll"), "DiscardVirtualMemory")); | 259 discardVirtualMemory = reinterpret_cast<DiscardVirtualMemoryFunction>(Ge
tProcAddress(GetModuleHandle(L"Kernel32.dll"), "DiscardVirtualMemory")); |
| 260 // Use DiscardVirtualMemory when available because it releases faster than M
EM_RESET. | 260 // Use DiscardVirtualMemory when available because it releases faster than M
EM_RESET. |
| 261 DWORD ret = 1; | 261 DWORD ret = 1; |
| 262 if (discardVirtualMemory) | 262 if (discardVirtualMemory) |
| 263 ret = discardVirtualMemory(addr, len); | 263 ret = discardVirtualMemory(addr, len); |
| 264 // DiscardVirtualMemory is buggy in Win10 SP0, so fall back to MEM_RESET on
failure. | 264 // DiscardVirtualMemory is buggy in Win10 SP0, so fall back to MEM_RESET on
failure. |
| 265 if (ret) { | 265 if (ret) { |
| 266 void* ret = VirtualAlloc(addr, len, MEM_RESET, PAGE_READWRITE); | 266 void* ret = VirtualAlloc(addr, len, MEM_RESET, PAGE_READWRITE); |
| 267 RELEASE_ASSERT(ret); | 267 CHECK(ret); |
| 268 } | 268 } |
| 269 #endif | 269 #endif |
| 270 } | 270 } |
| 271 | 271 |
| 272 uint32_t getAllocPageErrorCode() | 272 uint32_t getAllocPageErrorCode() |
| 273 { | 273 { |
| 274 return acquireLoad(&s_allocPageErrorCode); | 274 return acquireLoad(&s_allocPageErrorCode); |
| 275 } | 275 } |
| 276 | 276 |
| 277 } // namespace WTF | 277 } // namespace WTF |
| 278 | 278 |
| OLD | NEW |