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 |