| 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 21 matching lines...) Expand all Loading... |
| 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/MarkingVisitorImpl.h" | 38 #include "platform/heap/MarkingVisitorImpl.h" |
| 39 #include "platform/heap/SafePoint.h" | 39 #include "platform/heap/SafePoint.h" |
| 40 #include "platform/heap/ThreadState.h" | 40 #include "platform/heap/ThreadState.h" |
| 41 #include "public/platform/Platform.h" | 41 #include "public/platform/Platform.h" |
| 42 #include "wtf/AddressSpaceRandomization.h" | |
| 43 #include "wtf/Assertions.h" | 42 #include "wtf/Assertions.h" |
| 44 #include "wtf/ContainerAnnotations.h" | 43 #include "wtf/ContainerAnnotations.h" |
| 45 #include "wtf/LeakAnnotations.h" | 44 #include "wtf/LeakAnnotations.h" |
| 45 #include "wtf/PageAllocator.h" |
| 46 #include "wtf/PassOwnPtr.h" | 46 #include "wtf/PassOwnPtr.h" |
| 47 #if ENABLE(GC_PROFILING) | 47 #if ENABLE(GC_PROFILING) |
| 48 #include "platform/TracedValue.h" | 48 #include "platform/TracedValue.h" |
| 49 #include "wtf/HashMap.h" | 49 #include "wtf/HashMap.h" |
| 50 #include "wtf/HashSet.h" | 50 #include "wtf/HashSet.h" |
| 51 #include "wtf/text/StringBuilder.h" | 51 #include "wtf/text/StringBuilder.h" |
| 52 #include "wtf/text/StringHash.h" | 52 #include "wtf/text/StringHash.h" |
| 53 #include <stdio.h> | 53 #include <stdio.h> |
| 54 #include <utility> | 54 #include <utility> |
| 55 #endif | 55 #endif |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 103 return gcInfo->m_className; | 103 return gcInfo->m_className; |
| 104 return "unknown"; | 104 return "unknown"; |
| 105 } | 105 } |
| 106 #endif | 106 #endif |
| 107 | 107 |
| 108 static bool vTableInitialized(void* objectPointer) | 108 static bool vTableInitialized(void* objectPointer) |
| 109 { | 109 { |
| 110 return !!(*reinterpret_cast<Address*>(objectPointer)); | 110 return !!(*reinterpret_cast<Address*>(objectPointer)); |
| 111 } | 111 } |
| 112 | 112 |
| 113 static Address roundToBlinkPageBoundary(void* base) | |
| 114 { | |
| 115 return reinterpret_cast<Address>((reinterpret_cast<uintptr_t>(base) + blinkP
ageOffsetMask) & blinkPageBaseMask); | |
| 116 } | |
| 117 | |
| 118 static size_t roundToOsPageSize(size_t size) | 113 static size_t roundToOsPageSize(size_t size) |
| 119 { | 114 { |
| 120 return (size + WTF::kSystemPageSize - 1) & ~(WTF::kSystemPageSize - 1); | 115 return (size + WTF::kSystemPageSize - 1) & ~(WTF::kSystemPageSize - 1); |
| 121 } | 116 } |
| 122 | 117 |
| 123 class MemoryRegion { | 118 class MemoryRegion { |
| 124 public: | 119 public: |
| 125 MemoryRegion(Address base, size_t size) | 120 MemoryRegion(Address base, size_t size) |
| 126 : m_base(base) | 121 : m_base(base) |
| 127 , m_size(size) | 122 , m_size(size) |
| 128 { | 123 { |
| 129 ASSERT(size > 0); | 124 ASSERT(size > 0); |
| 130 } | 125 } |
| 131 | 126 |
| 132 bool contains(Address addr) const | 127 bool contains(Address addr) const |
| 133 { | 128 { |
| 134 return m_base <= addr && addr < (m_base + m_size); | 129 return m_base <= addr && addr < (m_base + m_size); |
| 135 } | 130 } |
| 136 | 131 |
| 137 bool contains(const MemoryRegion& other) const | 132 bool contains(const MemoryRegion& other) const |
| 138 { | 133 { |
| 139 return contains(other.m_base) && contains(other.m_base + other.m_size -
1); | 134 return contains(other.m_base) && contains(other.m_base + other.m_size -
1); |
| 140 } | 135 } |
| 141 | 136 |
| 142 void release() | 137 void release() |
| 143 { | 138 { |
| 144 #if OS(POSIX) | 139 WTF::freePages(m_base, m_size); |
| 145 int err = munmap(m_base, m_size); | |
| 146 RELEASE_ASSERT(!err); | |
| 147 #else | |
| 148 bool success = VirtualFree(m_base, 0, MEM_RELEASE); | |
| 149 RELEASE_ASSERT(success); | |
| 150 #endif | |
| 151 } | 140 } |
| 152 | 141 |
| 153 WARN_UNUSED_RETURN bool commit() | 142 WARN_UNUSED_RETURN bool commit() |
| 154 { | 143 { |
| 155 #if OS(POSIX) | 144 #if OS(POSIX) |
| 156 return !mprotect(m_base, m_size, PROT_READ | PROT_WRITE); | 145 return !mprotect(m_base, m_size, PROT_READ | PROT_WRITE); |
| 157 #else | 146 #else |
| 158 void* result = VirtualAlloc(m_base, m_size, MEM_COMMIT, PAGE_READWRITE); | 147 void* result = VirtualAlloc(m_base, m_size, MEM_COMMIT, PAGE_READWRITE); |
| 159 return !!result; | 148 return !!result; |
| 160 #endif | 149 #endif |
| (...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 249 ASSERT(contains(address)); | 238 ASSERT(contains(address)); |
| 250 if (m_isLargePage) | 239 if (m_isLargePage) |
| 251 return 0; | 240 return 0; |
| 252 size_t offset = blinkPageAddress(address) - base(); | 241 size_t offset = blinkPageAddress(address) - base(); |
| 253 ASSERT(offset % blinkPageSize == 0); | 242 ASSERT(offset % blinkPageSize == 0); |
| 254 return offset / blinkPageSize; | 243 return offset / blinkPageSize; |
| 255 } | 244 } |
| 256 | 245 |
| 257 static PageMemoryRegion* allocate(size_t size, unsigned numPages) | 246 static PageMemoryRegion* allocate(size_t size, unsigned numPages) |
| 258 { | 247 { |
| 259 // Compute a random blink page aligned address for the page memory | 248 // Round size up to the allocation granularity. |
| 260 // region and attempt to get the memory there. | 249 size = (size + WTF::kPageAllocationGranularityOffsetMask) & WTF::kPageAl
locationGranularityBaseMask; |
| 261 Address randomAddress = reinterpret_cast<Address>(WTF::getRandomPageBase
()); | 250 Address base = static_cast<Address>(WTF::allocPages(nullptr, size, blink
PageSize)); |
| 262 Address alignedRandomAddress = roundToBlinkPageBoundary(randomAddress); | |
| 263 | |
| 264 #if OS(POSIX) | |
| 265 Address base = static_cast<Address>(mmap(alignedRandomAddress, size, PRO
T_NONE, MAP_ANON | MAP_PRIVATE, -1, 0)); | |
| 266 if (base == roundToBlinkPageBoundary(base)) | |
| 267 return new PageMemoryRegion(base, size, numPages); | |
| 268 | |
| 269 // We failed to get a blink page aligned chunk of memory. | |
| 270 // Unmap the chunk that we got and fall back to overallocating | |
| 271 // and selecting an aligned sub part of what we allocate. | |
| 272 if (base != MAP_FAILED) { | |
| 273 int error = munmap(base, size); | |
| 274 RELEASE_ASSERT(!error); | |
| 275 } | |
| 276 size_t allocationSize = size + blinkPageSize; | |
| 277 for (int attempt = 0; attempt < 10; ++attempt) { | |
| 278 base = static_cast<Address>(mmap(alignedRandomAddress, allocationSiz
e, PROT_NONE, MAP_ANON | MAP_PRIVATE, -1, 0)); | |
| 279 if (base != MAP_FAILED) | |
| 280 break; | |
| 281 randomAddress = reinterpret_cast<Address>(WTF::getRandomPageBase()); | |
| 282 alignedRandomAddress = roundToBlinkPageBoundary(randomAddress); | |
| 283 } | |
| 284 RELEASE_ASSERT(base != MAP_FAILED); | |
| 285 | |
| 286 Address end = base + allocationSize; | |
| 287 Address alignedBase = roundToBlinkPageBoundary(base); | |
| 288 Address regionEnd = alignedBase + size; | |
| 289 | |
| 290 // If the allocated memory was not blink page aligned release | |
| 291 // the memory before the aligned address. | |
| 292 if (alignedBase != base) | |
| 293 MemoryRegion(base, alignedBase - base).release(); | |
| 294 | |
| 295 // Free the additional memory at the end of the page if any. | |
| 296 if (regionEnd < end) | |
| 297 MemoryRegion(regionEnd, end - regionEnd).release(); | |
| 298 | |
| 299 return new PageMemoryRegion(alignedBase, size, numPages); | |
| 300 #else | |
| 301 Address base = static_cast<Address>(VirtualAlloc(alignedRandomAddress, s
ize, MEM_RESERVE, PAGE_NOACCESS)); | |
| 302 if (base) { | |
| 303 ASSERT(base == alignedRandomAddress); | |
| 304 return new PageMemoryRegion(base, size, numPages); | |
| 305 } | |
| 306 | |
| 307 // We failed to get the random aligned address that we asked | |
| 308 // for. Fall back to overallocating. On Windows it is | |
| 309 // impossible to partially release a region of memory | |
| 310 // allocated by VirtualAlloc. To avoid wasting virtual address | |
| 311 // space we attempt to release a large region of memory | |
| 312 // returned as a whole and then allocate an aligned region | |
| 313 // inside this larger region. | |
| 314 size_t allocationSize = size + blinkPageSize; | |
| 315 for (int attempt = 0; attempt < 3; ++attempt) { | |
| 316 base = static_cast<Address>(VirtualAlloc(0, allocationSize, MEM_RESE
RVE, PAGE_NOACCESS)); | |
| 317 RELEASE_ASSERT(base); | |
| 318 VirtualFree(base, 0, MEM_RELEASE); | |
| 319 | |
| 320 Address alignedBase = roundToBlinkPageBoundary(base); | |
| 321 base = static_cast<Address>(VirtualAlloc(alignedBase, size, MEM_RESE
RVE, PAGE_NOACCESS)); | |
| 322 if (base) { | |
| 323 ASSERT(base == alignedBase); | |
| 324 return new PageMemoryRegion(alignedBase, size, numPages); | |
| 325 } | |
| 326 } | |
| 327 | |
| 328 // We failed to avoid wasting virtual address space after | |
| 329 // several attempts. | |
| 330 base = static_cast<Address>(VirtualAlloc(0, allocationSize, MEM_RESERVE,
PAGE_NOACCESS)); | |
| 331 RELEASE_ASSERT(base); | 251 RELEASE_ASSERT(base); |
| 332 | 252 WTF::setSystemPagesInaccessible(base, size); |
| 333 // FIXME: If base is by accident blink page size aligned | 253 return new PageMemoryRegion(base, size, numPages); |
| 334 // here then we can create two pages out of reserved | |
| 335 // space. Do this. | |
| 336 Address alignedBase = roundToBlinkPageBoundary(base); | |
| 337 | |
| 338 return new PageMemoryRegion(alignedBase, size, numPages); | |
| 339 #endif | |
| 340 } | 254 } |
| 341 | 255 |
| 342 bool m_isLargePage; | 256 bool m_isLargePage; |
| 343 bool m_inUse[blinkPagesPerRegion]; | 257 bool m_inUse[blinkPagesPerRegion]; |
| 344 unsigned m_numPages; | 258 unsigned m_numPages; |
| 345 }; | 259 }; |
| 346 | 260 |
| 347 // Representation of the memory used for a Blink heap page. | 261 // Representation of the memory used for a Blink heap page. |
| 348 // | 262 // |
| 349 // The representation keeps track of two memory regions: | 263 // The representation keeps track of two memory regions: |
| (...skipping 2563 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2913 size_t Heap::s_allocatedObjectSize = 0; | 2827 size_t Heap::s_allocatedObjectSize = 0; |
| 2914 size_t Heap::s_allocatedSpace = 0; | 2828 size_t Heap::s_allocatedSpace = 0; |
| 2915 size_t Heap::s_markedObjectSize = 0; | 2829 size_t Heap::s_markedObjectSize = 0; |
| 2916 | 2830 |
| 2917 size_t Heap::s_externallyAllocatedBytes = 0; | 2831 size_t Heap::s_externallyAllocatedBytes = 0; |
| 2918 size_t Heap::s_externallyAllocatedBytesAlive = 0; | 2832 size_t Heap::s_externallyAllocatedBytesAlive = 0; |
| 2919 unsigned Heap::s_requestedUrgentGC = false; | 2833 unsigned Heap::s_requestedUrgentGC = false; |
| 2920 double Heap::s_markingTimeInLastGC = 0.0; | 2834 double Heap::s_markingTimeInLastGC = 0.0; |
| 2921 | 2835 |
| 2922 } // namespace blink | 2836 } // namespace blink |
| OLD | NEW |