Chromium Code Reviews| 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 19 matching lines...) Expand all Loading... | |
| 30 | 30 |
| 31 #include "config.h" | 31 #include "config.h" |
| 32 #include "platform/heap/Heap.h" | 32 #include "platform/heap/Heap.h" |
| 33 | 33 |
| 34 #include "platform/ScriptForbiddenScope.h" | 34 #include "platform/ScriptForbiddenScope.h" |
| 35 #include "platform/Task.h" | 35 #include "platform/Task.h" |
| 36 #include "platform/TraceEvent.h" | 36 #include "platform/TraceEvent.h" |
| 37 #include "platform/heap/CallbackStack.h" | 37 #include "platform/heap/CallbackStack.h" |
| 38 #include "platform/heap/ThreadState.h" | 38 #include "platform/heap/ThreadState.h" |
| 39 #include "public/platform/Platform.h" | 39 #include "public/platform/Platform.h" |
| 40 #include "wtf/AddressSpaceRandomization.h" | |
| 41 #include "wtf/Assertions.h" | 40 #include "wtf/Assertions.h" |
| 42 #include "wtf/LeakAnnotations.h" | 41 #include "wtf/LeakAnnotations.h" |
| 42 #include "wtf/PageAllocator.h" | |
| 43 #include "wtf/PassOwnPtr.h" | 43 #include "wtf/PassOwnPtr.h" |
| 44 #if ENABLE(GC_PROFILE_MARKING) | 44 #if ENABLE(GC_PROFILE_MARKING) |
| 45 #include "wtf/HashMap.h" | 45 #include "wtf/HashMap.h" |
| 46 #include "wtf/HashSet.h" | 46 #include "wtf/HashSet.h" |
| 47 #include "wtf/text/StringBuilder.h" | 47 #include "wtf/text/StringBuilder.h" |
| 48 #include "wtf/text/StringHash.h" | 48 #include "wtf/text/StringHash.h" |
| 49 #include <stdio.h> | 49 #include <stdio.h> |
| 50 #include <utility> | 50 #include <utility> |
| 51 #endif | 51 #endif |
| 52 #if ENABLE(GC_PROFILE_HEAP) | 52 #if ENABLE(GC_PROFILE_HEAP) |
| (...skipping 25 matching lines...) Expand all Loading... | |
| 78 return !!(*reinterpret_cast<Address*>(objectPointer)); | 78 return !!(*reinterpret_cast<Address*>(objectPointer)); |
| 79 } | 79 } |
| 80 | 80 |
| 81 #if OS(WIN) | 81 #if OS(WIN) |
| 82 static bool IsPowerOf2(size_t power) | 82 static bool IsPowerOf2(size_t power) |
| 83 { | 83 { |
| 84 return !((power - 1) & power); | 84 return !((power - 1) & power); |
| 85 } | 85 } |
| 86 #endif | 86 #endif |
| 87 | 87 |
| 88 static Address roundToBlinkPageBoundary(void* base) | |
| 89 { | |
| 90 return reinterpret_cast<Address>((reinterpret_cast<uintptr_t>(base) + blinkP ageOffsetMask) & blinkPageBaseMask); | |
| 91 } | |
| 92 | |
| 93 static size_t roundToOsPageSize(size_t size) | 88 static size_t roundToOsPageSize(size_t size) |
| 94 { | 89 { |
| 95 return (size + osPageSize() - 1) & ~(osPageSize() - 1); | 90 return (size + osPageSize() - 1) & ~(osPageSize() - 1); |
| 96 } | 91 } |
| 97 | 92 |
| 98 size_t osPageSize() | 93 size_t osPageSize() |
| 99 { | 94 { |
| 100 #if OS(POSIX) | 95 #if OS(POSIX) |
| 101 static const size_t pageSize = getpagesize(); | 96 static const size_t pageSize = getpagesize(); |
| 102 #else | 97 #else |
| (...skipping 22 matching lines...) Expand all Loading... | |
| 125 return m_base <= addr && addr < (m_base + m_size); | 120 return m_base <= addr && addr < (m_base + m_size); |
| 126 } | 121 } |
| 127 | 122 |
| 128 bool contains(const MemoryRegion& other) const | 123 bool contains(const MemoryRegion& other) const |
| 129 { | 124 { |
| 130 return contains(other.m_base) && contains(other.m_base + other.m_size - 1); | 125 return contains(other.m_base) && contains(other.m_base + other.m_size - 1); |
| 131 } | 126 } |
| 132 | 127 |
| 133 void release() | 128 void release() |
| 134 { | 129 { |
| 135 #if OS(POSIX) | 130 WTF::freePages(m_base, m_size); |
| 136 int err = munmap(m_base, m_size); | |
| 137 RELEASE_ASSERT(!err); | |
| 138 #else | |
| 139 bool success = VirtualFree(m_base, 0, MEM_RELEASE); | |
| 140 RELEASE_ASSERT(success); | |
| 141 #endif | |
| 142 } | 131 } |
| 143 | 132 |
| 144 WARN_UNUSED_RETURN bool commit() | 133 WARN_UNUSED_RETURN bool commit() |
| 145 { | 134 { |
| 146 #if OS(POSIX) | 135 #if OS(POSIX) |
| 147 return !mprotect(m_base, m_size, PROT_READ | PROT_WRITE); | 136 return !mprotect(m_base, m_size, PROT_READ | PROT_WRITE); |
| 148 #else | 137 #else |
| 149 void* result = VirtualAlloc(m_base, m_size, MEM_COMMIT, PAGE_READWRITE); | 138 void* result = VirtualAlloc(m_base, m_size, MEM_COMMIT, PAGE_READWRITE); |
| 150 return !!result; | 139 return !!result; |
| 151 #endif | 140 #endif |
| (...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 240 ASSERT(contains(address)); | 229 ASSERT(contains(address)); |
| 241 if (m_isLargePage) | 230 if (m_isLargePage) |
| 242 return 0; | 231 return 0; |
| 243 size_t offset = blinkPageAddress(address) - base(); | 232 size_t offset = blinkPageAddress(address) - base(); |
| 244 ASSERT(offset % blinkPageSize == 0); | 233 ASSERT(offset % blinkPageSize == 0); |
| 245 return offset / blinkPageSize; | 234 return offset / blinkPageSize; |
| 246 } | 235 } |
| 247 | 236 |
| 248 static PageMemoryRegion* allocate(size_t size, unsigned numPages) | 237 static PageMemoryRegion* allocate(size_t size, unsigned numPages) |
| 249 { | 238 { |
| 250 // Compute a random blink page aligned address for the page memory | 239 // Round size up to the allocation granularity. |
| 251 // region and attempt to get the memory there. | 240 size = (size + WTF::kPageAllocationGranularityOffsetMask) & WTF::kPageAl locationGranularityBaseMask; |
| 252 Address randomAddress = reinterpret_cast<Address>(WTF::getRandomPageBase ()); | 241 Address base = static_cast<Address>(WTF::allocPages(nullptr, size, blink PageSize)); |
| 253 Address alignedRandomAddress = roundToBlinkPageBoundary(randomAddress); | |
| 254 | |
| 255 #if OS(POSIX) | |
| 256 Address base = static_cast<Address>(mmap(alignedRandomAddress, size, PRO T_NONE, MAP_ANON | MAP_PRIVATE, -1, 0)); | |
| 257 if (base == roundToBlinkPageBoundary(base)) | |
| 258 return new PageMemoryRegion(base, size, numPages); | |
| 259 | |
| 260 // We failed to get a blink page aligned chunk of memory. | |
| 261 // Unmap the chunk that we got and fall back to overallocating | |
| 262 // and selecting an aligned sub part of what we allocate. | |
| 263 if (base != MAP_FAILED) { | |
| 264 int error = munmap(base, size); | |
| 265 RELEASE_ASSERT(!error); | |
| 266 } | |
| 267 size_t allocationSize = size + blinkPageSize; | |
| 268 for (int attempt = 0; attempt < 10; attempt++) { | |
| 269 base = static_cast<Address>(mmap(alignedRandomAddress, allocationSiz e, PROT_NONE, MAP_ANON | MAP_PRIVATE, -1, 0)); | |
| 270 if (base != MAP_FAILED) | |
| 271 break; | |
| 272 randomAddress = reinterpret_cast<Address>(WTF::getRandomPageBase()); | |
| 273 alignedRandomAddress = roundToBlinkPageBoundary(randomAddress); | |
| 274 } | |
| 275 RELEASE_ASSERT(base != MAP_FAILED); | |
| 276 | |
| 277 Address end = base + allocationSize; | |
| 278 Address alignedBase = roundToBlinkPageBoundary(base); | |
| 279 Address regionEnd = alignedBase + size; | |
| 280 | |
| 281 // If the allocated memory was not blink page aligned release | |
| 282 // the memory before the aligned address. | |
| 283 if (alignedBase != base) | |
| 284 MemoryRegion(base, alignedBase - base).release(); | |
| 285 | |
| 286 // Free the additional memory at the end of the page if any. | |
| 287 if (regionEnd < end) | |
| 288 MemoryRegion(regionEnd, end - regionEnd).release(); | |
| 289 | |
| 290 return new PageMemoryRegion(alignedBase, size, numPages); | |
| 291 #else | |
| 292 Address base = static_cast<Address>(VirtualAlloc(alignedRandomAddress, s ize, MEM_RESERVE, PAGE_NOACCESS)); | |
| 293 if (base) { | |
| 294 ASSERT(base == alignedRandomAddress); | |
| 295 return new PageMemoryRegion(base, size, numPages); | |
| 296 } | |
| 297 | |
| 298 // We failed to get the random aligned address that we asked | |
| 299 // for. Fall back to overallocating. On Windows it is | |
| 300 // impossible to partially release a region of memory | |
| 301 // allocated by VirtualAlloc. To avoid wasting virtual address | |
| 302 // space we attempt to release a large region of memory | |
| 303 // returned as a whole and then allocate an aligned region | |
| 304 // inside this larger region. | |
| 305 size_t allocationSize = size + blinkPageSize; | |
| 306 for (int attempt = 0; attempt < 3; attempt++) { | |
| 307 base = static_cast<Address>(VirtualAlloc(0, allocationSize, MEM_RESE RVE, PAGE_NOACCESS)); | |
| 308 RELEASE_ASSERT(base); | |
| 309 VirtualFree(base, 0, MEM_RELEASE); | |
| 310 | |
| 311 Address alignedBase = roundToBlinkPageBoundary(base); | |
| 312 base = static_cast<Address>(VirtualAlloc(alignedBase, size, MEM_RESE RVE, PAGE_NOACCESS)); | |
| 313 if (base) { | |
| 314 ASSERT(base == alignedBase); | |
| 315 return new PageMemoryRegion(alignedBase, size, numPages); | |
| 316 } | |
| 317 } | |
| 318 | |
| 319 // We failed to avoid wasting virtual address space after | |
| 320 // several attempts. | |
| 321 base = static_cast<Address>(VirtualAlloc(0, allocationSize, MEM_RESERVE, PAGE_NOACCESS)); | |
| 322 RELEASE_ASSERT(base); | 242 RELEASE_ASSERT(base); |
| 323 | 243 WTF::setSystemPagesInaccessible(base, size); |
|
Jens Widell
2014/11/17 10:20:07
I realized the old code here actually allocated in
| |
| 324 // FIXME: If base is by accident blink page size aligned | 244 return new PageMemoryRegion(base, size, numPages); |
| 325 // here then we can create two pages out of reserved | |
| 326 // space. Do this. | |
| 327 Address alignedBase = roundToBlinkPageBoundary(base); | |
| 328 | |
| 329 return new PageMemoryRegion(alignedBase, size, numPages); | |
| 330 #endif | |
| 331 } | 245 } |
| 332 | 246 |
| 333 bool m_isLargePage; | 247 bool m_isLargePage; |
| 334 bool m_inUse[blinkPagesPerRegion]; | 248 bool m_inUse[blinkPagesPerRegion]; |
| 335 unsigned m_numPages; | 249 unsigned m_numPages; |
| 336 }; | 250 }; |
| 337 | 251 |
| 338 // Representation of the memory used for a Blink heap page. | 252 // Representation of the memory used for a Blink heap page. |
| 339 // | 253 // |
| 340 // The representation keeps track of two memory regions: | 254 // The representation keeps track of two memory regions: |
| (...skipping 2627 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2968 CallbackStack* Heap::s_weakCallbackStack; | 2882 CallbackStack* Heap::s_weakCallbackStack; |
| 2969 CallbackStack* Heap::s_ephemeronStack; | 2883 CallbackStack* Heap::s_ephemeronStack; |
| 2970 HeapDoesNotContainCache* Heap::s_heapDoesNotContainCache; | 2884 HeapDoesNotContainCache* Heap::s_heapDoesNotContainCache; |
| 2971 bool Heap::s_shutdownCalled = false; | 2885 bool Heap::s_shutdownCalled = false; |
| 2972 bool Heap::s_lastGCWasConservative = false; | 2886 bool Heap::s_lastGCWasConservative = false; |
| 2973 FreePagePool* Heap::s_freePagePool; | 2887 FreePagePool* Heap::s_freePagePool; |
| 2974 OrphanedPagePool* Heap::s_orphanedPagePool; | 2888 OrphanedPagePool* Heap::s_orphanedPagePool; |
| 2975 Heap::RegionTree* Heap::s_regionTree = 0; | 2889 Heap::RegionTree* Heap::s_regionTree = 0; |
| 2976 | 2890 |
| 2977 } // namespace blink | 2891 } // namespace blink |
| OLD | NEW |