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