Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(108)

Side by Side Diff: Source/platform/heap/Heap.cpp

Issue 618353004: Revert "Oilpan: Replace the positive heap-contains cache with a binary search tree of memory region… (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: Created 6 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « Source/platform/heap/Heap.h ('k') | Source/platform/heap/HeapTest.cpp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 107 matching lines...) Expand 10 before | Expand all | Expand 10 after
118 , m_size(size) 118 , m_size(size)
119 { 119 {
120 ASSERT(size > 0); 120 ASSERT(size > 0);
121 } 121 }
122 122
123 bool contains(Address addr) const 123 bool contains(Address addr) const
124 { 124 {
125 return m_base <= addr && addr < (m_base + m_size); 125 return m_base <= addr && addr < (m_base + m_size);
126 } 126 }
127 127
128
128 bool contains(const MemoryRegion& other) const 129 bool contains(const MemoryRegion& other) const
129 { 130 {
130 return contains(other.m_base) && contains(other.m_base + other.m_size - 1); 131 return contains(other.m_base) && contains(other.m_base + other.m_size - 1);
131 } 132 }
132 133
133 void release() 134 void release()
134 { 135 {
135 #if OS(POSIX) 136 #if OS(POSIX)
136 int err = munmap(m_base, m_size); 137 int err = munmap(m_base, m_size);
137 RELEASE_ASSERT(!err); 138 RELEASE_ASSERT(!err);
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
179 // whole. The PageMemoryRegion allows us to do that by keeping track 180 // whole. The PageMemoryRegion allows us to do that by keeping track
180 // of the number of pages using it in order to be able to release all 181 // of the number of pages using it in order to be able to release all
181 // of the virtual address space when there are no more pages using it. 182 // of the virtual address space when there are no more pages using it.
182 class PageMemoryRegion : public MemoryRegion { 183 class PageMemoryRegion : public MemoryRegion {
183 public: 184 public:
184 ~PageMemoryRegion() 185 ~PageMemoryRegion()
185 { 186 {
186 release(); 187 release();
187 } 188 }
188 189
189 void pageDeleted(Address page) 190 void pageRemoved()
190 { 191 {
191 markPageUnused(page); 192 if (!--m_numPages)
192 if (!--m_numPages) {
193 Heap::removePageMemoryRegion(this);
194 delete this; 193 delete this;
195 }
196 }
197
198 void markPageUsed(Address page)
199 {
200 ASSERT(!m_inUse[index(page)]);
201 m_inUse[index(page)] = true;
202 }
203
204 void markPageUnused(Address page)
205 {
206 m_inUse[index(page)] = false;
207 }
208
209 static PageMemoryRegion* allocateLargePage(size_t size)
210 {
211 return allocate(size, 1);
212 }
213
214 static PageMemoryRegion* allocateNormalPages()
215 {
216 return allocate(blinkPageSize * blinkPagesPerRegion, blinkPagesPerRegion );
217 }
218
219 BaseHeapPage* pageFromAddress(Address address)
220 {
221 ASSERT(contains(address));
222 if (!m_inUse[index(address)])
223 return 0;
224 if (m_isLargePage)
225 return pageHeaderFromObject(base());
226 return pageHeaderFromObject(address);
227 }
228
229 private:
230 PageMemoryRegion(Address base, size_t size, unsigned numPages)
231 : MemoryRegion(base, size)
232 , m_isLargePage(numPages == 1)
233 , m_numPages(numPages)
234 {
235 for (size_t i = 0; i < blinkPagesPerRegion; ++i)
236 m_inUse[i] = false;
237 }
238
239 unsigned index(Address address)
240 {
241 ASSERT(contains(address));
242 if (m_isLargePage)
243 return 0;
244 size_t offset = blinkPageAddress(address) - base();
245 ASSERT(offset % blinkPageSize == 0);
246 return offset / blinkPageSize;
247 } 194 }
248 195
249 static PageMemoryRegion* allocate(size_t size, unsigned numPages) 196 static PageMemoryRegion* allocate(size_t size, unsigned numPages)
250 { 197 {
251 ASSERT(Heap::heapDoesNotContainCacheIsEmpty()); 198 ASSERT(Heap::heapDoesNotContainCacheIsEmpty());
252 199
253 // Compute a random blink page aligned address for the page memory 200 // Compute a random blink page aligned address for the page memory
254 // region and attempt to get the memory there. 201 // region and attempt to get the memory there.
255 Address randomAddress = reinterpret_cast<Address>(WTF::getRandomPageBase ()); 202 Address randomAddress = reinterpret_cast<Address>(WTF::getRandomPageBase ());
256 Address alignedRandomAddress = roundToBlinkPageBoundary(randomAddress); 203 Address alignedRandomAddress = roundToBlinkPageBoundary(randomAddress);
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
320 267
321 // FIXME: If base is by accident blink page size aligned 268 // FIXME: If base is by accident blink page size aligned
322 // here then we can create two pages out of reserved 269 // here then we can create two pages out of reserved
323 // space. Do this. 270 // space. Do this.
324 Address alignedBase = roundToBlinkPageBoundary(base); 271 Address alignedBase = roundToBlinkPageBoundary(base);
325 272
326 return new PageMemoryRegion(alignedBase, size, numPages); 273 return new PageMemoryRegion(alignedBase, size, numPages);
327 #endif 274 #endif
328 } 275 }
329 276
330 bool m_isLargePage; 277 private:
331 bool m_inUse[blinkPagesPerRegion]; 278 PageMemoryRegion(Address base, size_t size, unsigned numPages)
279 : MemoryRegion(base, size)
280 , m_numPages(numPages)
281 {
282 }
283
332 unsigned m_numPages; 284 unsigned m_numPages;
333 }; 285 };
334 286
335 // Representation of the memory used for a Blink heap page. 287 // Representation of the memory used for a Blink heap page.
336 // 288 //
337 // The representation keeps track of two memory regions: 289 // The representation keeps track of two memory regions:
338 // 290 //
339 // 1. The virtual memory reserved from the system in order to be able 291 // 1. The virtual memory reserved from the system in order to be able
340 // to free all the virtual memory reserved. Multiple PageMemory 292 // to free all the virtual memory reserved. Multiple PageMemory
341 // instances can share the same reserved memory region and 293 // instances can share the same reserved memory region and
342 // therefore notify the reserved memory region on destruction so 294 // therefore notify the reserved memory region on destruction so
343 // that the system memory can be given back when all PageMemory 295 // that the system memory can be given back when all PageMemory
344 // instances for that memory are gone. 296 // instances for that memory are gone.
345 // 297 //
346 // 2. The writable memory (a sub-region of the reserved virtual 298 // 2. The writable memory (a sub-region of the reserved virtual
347 // memory region) that is used for the actual heap page payload. 299 // memory region) that is used for the actual heap page payload.
348 // 300 //
349 // Guard pages are created before and after the writable memory. 301 // Guard pages are created before and after the writable memory.
350 class PageMemory { 302 class PageMemory {
351 public: 303 public:
352 ~PageMemory() 304 ~PageMemory()
353 { 305 {
354 __lsan_unregister_root_region(m_writable.base(), m_writable.size()); 306 __lsan_unregister_root_region(m_writable.base(), m_writable.size());
355 m_reserved->pageDeleted(writableStart()); 307 m_reserved->pageRemoved();
356 } 308 }
357 309
358 WARN_UNUSED_RETURN bool commit() 310 bool commit() WARN_UNUSED_RETURN { return m_writable.commit(); }
359 { 311 void decommit() { m_writable.decommit(); }
360 m_reserved->markPageUsed(writableStart());
361 return m_writable.commit();
362 }
363
364 void decommit()
365 {
366 m_reserved->markPageUnused(writableStart());
367 m_writable.decommit();
368 }
369
370 void markUnused() { m_reserved->markPageUnused(writableStart()); }
371
372 PageMemoryRegion* region() { return m_reserved; }
373 312
374 Address writableStart() { return m_writable.base(); } 313 Address writableStart() { return m_writable.base(); }
375 314
376 static PageMemory* setupPageMemoryInRegion(PageMemoryRegion* region, size_t pageOffset, size_t payloadSize) 315 static PageMemory* setupPageMemoryInRegion(PageMemoryRegion* region, size_t pageOffset, size_t payloadSize)
377 { 316 {
378 // Setup the payload one OS page into the page memory. The 317 // Setup the payload one OS page into the page memory. The
379 // first os page is the guard page. 318 // first os page is the guard page.
380 Address payloadAddress = region->base() + pageOffset + osPageSize(); 319 Address payloadAddress = region->base() + pageOffset + osPageSize();
381 return new PageMemory(region, MemoryRegion(payloadAddress, payloadSize)) ; 320 return new PageMemory(region, MemoryRegion(payloadAddress, payloadSize)) ;
382 } 321 }
383 322
384 // Allocate a virtual address space for one blink page with the 323 // Allocate a virtual address space for one blink page with the
385 // following layout: 324 // following layout:
386 // 325 //
387 // [ guard os page | ... payload ... | guard os page ] 326 // [ guard os page | ... payload ... | guard os page ]
388 // ^---{ aligned to blink page size } 327 // ^---{ aligned to blink page size }
389 // 328 //
390 static PageMemory* allocate(size_t payloadSize) 329 static PageMemory* allocate(size_t payloadSize)
391 { 330 {
392 ASSERT(payloadSize > 0); 331 ASSERT(payloadSize > 0);
393 332
394 // Virtual memory allocation routines operate in OS page sizes. 333 // Virtual memory allocation routines operate in OS page sizes.
395 // Round up the requested size to nearest os page size. 334 // Round up the requested size to nearest os page size.
396 payloadSize = roundToOsPageSize(payloadSize); 335 payloadSize = roundToOsPageSize(payloadSize);
397 336
398 // Overallocate by 2 times OS page size to have space for a 337 // Overallocate by 2 times OS page size to have space for a
399 // guard page at the beginning and end of blink heap page. 338 // guard page at the beginning and end of blink heap page.
400 size_t allocationSize = payloadSize + 2 * osPageSize(); 339 size_t allocationSize = payloadSize + 2 * osPageSize();
401 PageMemoryRegion* pageMemoryRegion = PageMemoryRegion::allocateLargePage (allocationSize); 340 PageMemoryRegion* pageMemoryRegion = PageMemoryRegion::allocate(allocati onSize, 1);
402 PageMemory* storage = setupPageMemoryInRegion(pageMemoryRegion, 0, paylo adSize); 341 PageMemory* storage = setupPageMemoryInRegion(pageMemoryRegion, 0, paylo adSize);
403 RELEASE_ASSERT(storage->commit()); 342 RELEASE_ASSERT(storage->commit());
404 return storage; 343 return storage;
405 } 344 }
406 345
407 private: 346 private:
408 PageMemory(PageMemoryRegion* reserved, const MemoryRegion& writable) 347 PageMemory(PageMemoryRegion* reserved, const MemoryRegion& writable)
409 : m_reserved(reserved) 348 : m_reserved(reserved)
410 , m_writable(writable) 349 , m_writable(writable)
411 { 350 {
(...skipping 251 matching lines...) Expand 10 before | Expand all | Expand 10 after
663 ThreadHeap<Header>::~ThreadHeap() 602 ThreadHeap<Header>::~ThreadHeap()
664 { 603 {
665 ASSERT(!m_firstPage); 604 ASSERT(!m_firstPage);
666 ASSERT(!m_firstLargeHeapObject); 605 ASSERT(!m_firstLargeHeapObject);
667 } 606 }
668 607
669 template<typename Header> 608 template<typename Header>
670 void ThreadHeap<Header>::cleanupPages() 609 void ThreadHeap<Header>::cleanupPages()
671 { 610 {
672 clearFreeLists(); 611 clearFreeLists();
612 flushHeapContainsCache();
673 613
674 // Add the ThreadHeap's pages to the orphanedPagePool. 614 // Add the ThreadHeap's pages to the orphanedPagePool.
675 for (HeapPage<Header>* page = m_firstPage; page; page = page->m_next) 615 for (HeapPage<Header>* page = m_firstPage; page; page = page->m_next)
676 Heap::orphanedPagePool()->addOrphanedPage(m_index, page); 616 Heap::orphanedPagePool()->addOrphanedPage(m_index, page);
677 m_firstPage = 0; 617 m_firstPage = 0;
678 618
679 for (LargeHeapObject<Header>* largeObject = m_firstLargeHeapObject; largeObj ect; largeObject = largeObject->m_next) 619 for (LargeHeapObject<Header>* largeObject = m_firstLargeHeapObject; largeObj ect; largeObject = largeObject->m_next)
680 Heap::orphanedPagePool()->addOrphanedPage(m_index, largeObject); 620 Heap::orphanedPagePool()->addOrphanedPage(m_index, largeObject);
681 m_firstLargeHeapObject = 0; 621 m_firstLargeHeapObject = 0;
682 } 622 }
(...skipping 295 matching lines...) Expand 10 before | Expand all | Expand 10 after
978 918
979 // If ASan is supported we add allocationGranularity bytes to the allocated space and 919 // If ASan is supported we add allocationGranularity bytes to the allocated space and
980 // poison that to detect overflows 920 // poison that to detect overflows
981 #if defined(ADDRESS_SANITIZER) 921 #if defined(ADDRESS_SANITIZER)
982 allocationSize += allocationGranularity; 922 allocationSize += allocationGranularity;
983 #endif 923 #endif
984 if (threadState()->shouldGC()) 924 if (threadState()->shouldGC())
985 threadState()->setGCRequested(); 925 threadState()->setGCRequested();
986 Heap::flushHeapDoesNotContainCache(); 926 Heap::flushHeapDoesNotContainCache();
987 PageMemory* pageMemory = PageMemory::allocate(allocationSize); 927 PageMemory* pageMemory = PageMemory::allocate(allocationSize);
988 m_threadState->allocatedRegionsSinceLastGC().append(pageMemory->region());
989 Address largeObjectAddress = pageMemory->writableStart(); 928 Address largeObjectAddress = pageMemory->writableStart();
990 Address headerAddress = largeObjectAddress + sizeof(LargeHeapObject<Header>) + headerPadding<Header>(); 929 Address headerAddress = largeObjectAddress + sizeof(LargeHeapObject<Header>) + headerPadding<Header>();
991 memset(headerAddress, 0, size); 930 memset(headerAddress, 0, size);
992 Header* header = new (NotNull, headerAddress) Header(size, gcInfo); 931 Header* header = new (NotNull, headerAddress) Header(size, gcInfo);
993 Address result = headerAddress + sizeof(*header); 932 Address result = headerAddress + sizeof(*header);
994 ASSERT(!(reinterpret_cast<uintptr_t>(result) & allocationMask)); 933 ASSERT(!(reinterpret_cast<uintptr_t>(result) & allocationMask));
995 LargeHeapObject<Header>* largeObject = new (largeObjectAddress) LargeHeapObj ect<Header>(pageMemory, gcInfo, threadState()); 934 LargeHeapObject<Header>* largeObject = new (largeObjectAddress) LargeHeapObj ect<Header>(pageMemory, gcInfo, threadState());
996 935
997 // Poison the object header and allocationGranularity bytes after the object 936 // Poison the object header and allocationGranularity bytes after the object
998 ASAN_POISON_MEMORY_REGION(header, sizeof(*header)); 937 ASAN_POISON_MEMORY_REGION(header, sizeof(*header));
999 ASAN_POISON_MEMORY_REGION(largeObject->address() + largeObject->size(), allo cationGranularity); 938 ASAN_POISON_MEMORY_REGION(largeObject->address() + largeObject->size(), allo cationGranularity);
1000 largeObject->link(&m_firstLargeHeapObject); 939 largeObject->link(&m_firstLargeHeapObject);
1001 stats().increaseAllocatedSpace(largeObject->size()); 940 stats().increaseAllocatedSpace(largeObject->size());
1002 stats().increaseObjectSpace(largeObject->payloadSize()); 941 stats().increaseObjectSpace(largeObject->payloadSize());
1003 return result; 942 return result;
1004 } 943 }
1005 944
1006 template<typename Header> 945 template<typename Header>
1007 void ThreadHeap<Header>::freeLargeObject(LargeHeapObject<Header>* object, LargeH eapObject<Header>** previousNext) 946 void ThreadHeap<Header>::freeLargeObject(LargeHeapObject<Header>* object, LargeH eapObject<Header>** previousNext)
1008 { 947 {
948 flushHeapContainsCache();
1009 object->unlink(previousNext); 949 object->unlink(previousNext);
1010 object->finalize(); 950 object->finalize();
1011 951
1012 // Unpoison the object header and allocationGranularity bytes after the 952 // Unpoison the object header and allocationGranularity bytes after the
1013 // object before freeing. 953 // object before freeing.
1014 ASAN_UNPOISON_MEMORY_REGION(object->heapObjectHeader(), sizeof(Header)); 954 ASAN_UNPOISON_MEMORY_REGION(object->heapObjectHeader(), sizeof(Header));
1015 ASAN_UNPOISON_MEMORY_REGION(object->address() + object->size(), allocationGr anularity); 955 ASAN_UNPOISON_MEMORY_REGION(object->address() + object->size(), allocationGr anularity);
1016 956
1017 if (object->terminating()) { 957 if (object->terminating()) {
1018 ASSERT(ThreadState::current()->isTerminating()); 958 ASSERT(ThreadState::current()->isTerminating());
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
1078 delete entry; 1018 delete entry;
1079 if (memory->commit()) 1019 if (memory->commit())
1080 return memory; 1020 return memory;
1081 1021
1082 // We got some memory, but failed to commit it, try again. 1022 // We got some memory, but failed to commit it, try again.
1083 delete memory; 1023 delete memory;
1084 } 1024 }
1085 return 0; 1025 return 0;
1086 } 1026 }
1087 1027
1088 BaseHeapPage::BaseHeapPage(PageMemory* storage, const GCInfo* gcInfo, ThreadStat e* state)
1089 : m_storage(storage)
1090 , m_gcInfo(gcInfo)
1091 , m_threadState(state)
1092 , m_terminating(false)
1093 , m_tracedAfterOrphaned(false)
1094 {
1095 ASSERT(isPageHeaderAddress(reinterpret_cast<Address>(this)));
1096 }
1097
1098 void BaseHeapPage::markOrphaned()
1099 {
1100 m_threadState = 0;
1101 m_gcInfo = 0;
1102 m_terminating = false;
1103 m_tracedAfterOrphaned = false;
1104 // Since we zap the page payload for orphaned pages we need to mark it as
1105 // unused so a conservative pointer won't interpret the object headers.
1106 storage()->markUnused();
1107 }
1108
1109 OrphanedPagePool::~OrphanedPagePool() 1028 OrphanedPagePool::~OrphanedPagePool()
1110 { 1029 {
1111 for (int index = 0; index < NumberOfHeaps; ++index) { 1030 for (int index = 0; index < NumberOfHeaps; ++index) {
1112 while (PoolEntry* entry = m_pool[index]) { 1031 while (PoolEntry* entry = m_pool[index]) {
1113 m_pool[index] = entry->next; 1032 m_pool[index] = entry->next;
1114 BaseHeapPage* page = entry->data; 1033 BaseHeapPage* page = entry->data;
1115 delete entry; 1034 delete entry;
1116 PageMemory* memory = page->storage(); 1035 PageMemory* memory = page->storage();
1117 ASSERT(memory); 1036 ASSERT(memory);
1118 page->~BaseHeapPage(); 1037 page->~BaseHeapPage();
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after
1223 // When adding a page to the ThreadHeap using HeapObjectHeaders store the GC Info on the heap 1142 // When adding a page to the ThreadHeap using HeapObjectHeaders store the GC Info on the heap
1224 // since it is the same for all objects 1143 // since it is the same for all objects
1225 ASSERT(gcInfo); 1144 ASSERT(gcInfo);
1226 allocatePage(gcInfo); 1145 allocatePage(gcInfo);
1227 } 1146 }
1228 1147
1229 template <typename Header> 1148 template <typename Header>
1230 void ThreadHeap<Header>::removePageFromHeap(HeapPage<Header>* page) 1149 void ThreadHeap<Header>::removePageFromHeap(HeapPage<Header>* page)
1231 { 1150 {
1232 MutexLocker locker(m_threadState->sweepMutex()); 1151 MutexLocker locker(m_threadState->sweepMutex());
1152 flushHeapContainsCache();
1233 if (page->terminating()) { 1153 if (page->terminating()) {
1234 // The thread is shutting down so this page is being removed as part 1154 // The thread is shutting down so this page is being removed as part
1235 // of a thread local GC. In that case the page could be accessed in the 1155 // of a thread local GC. In that case the page could be accessed in the
1236 // next global GC either due to a dead object being traced via a 1156 // next global GC either due to a dead object being traced via a
1237 // conservative pointer or due to a programming error where an object 1157 // conservative pointer or due to a programming error where an object
1238 // in another thread heap keeps a dangling pointer to this object. 1158 // in another thread heap keeps a dangling pointer to this object.
1239 // To guard against this we put the page in the orphanedPagePool to 1159 // To guard against this we put the page in the orphanedPagePool to
1240 // ensure it is still reachable. After the next global GC it can be 1160 // ensure it is still reachable. After the next global GC it can be
1241 // decommitted and moved to the page pool assuming no rogue/dangling 1161 // decommitted and moved to the page pool assuming no rogue/dangling
1242 // pointers refer to it. 1162 // pointers refer to it.
1243 Heap::orphanedPagePool()->addOrphanedPage(m_index, page); 1163 Heap::orphanedPagePool()->addOrphanedPage(m_index, page);
1244 } else { 1164 } else {
1245 PageMemory* memory = page->storage(); 1165 PageMemory* memory = page->storage();
1246 page->~HeapPage<Header>(); 1166 page->~HeapPage<Header>();
1247 Heap::freePagePool()->addFreePage(m_index, memory); 1167 Heap::freePagePool()->addFreePage(m_index, memory);
1248 } 1168 }
1249 } 1169 }
1250 1170
1251 template<typename Header> 1171 template<typename Header>
1252 void ThreadHeap<Header>::allocatePage(const GCInfo* gcInfo) 1172 void ThreadHeap<Header>::allocatePage(const GCInfo* gcInfo)
1253 { 1173 {
1254 Heap::flushHeapDoesNotContainCache(); 1174 Heap::flushHeapDoesNotContainCache();
1255 PageMemory* pageMemory = Heap::freePagePool()->takeFreePage(m_index); 1175 PageMemory* pageMemory = Heap::freePagePool()->takeFreePage(m_index);
1256 // We continue allocating page memory until we succeed in committing one. 1176 // We continue allocating page memory until we succeed in getting one.
1177 // Since the FreePagePool is global other threads could use all the
1178 // newly allocated page memory before this thread calls takeFreePage.
1257 while (!pageMemory) { 1179 while (!pageMemory) {
1258 // Allocate a memory region for blinkPagesPerRegion pages that 1180 // Allocate a memory region for blinkPagesPerRegion pages that
1259 // will each have the following layout. 1181 // will each have the following layout.
1260 // 1182 //
1261 // [ guard os page | ... payload ... | guard os page ] 1183 // [ guard os page | ... payload ... | guard os page ]
1262 // ^---{ aligned to blink page size } 1184 // ^---{ aligned to blink page size }
1263 PageMemoryRegion* region = PageMemoryRegion::allocateNormalPages(); 1185 PageMemoryRegion* region = PageMemoryRegion::allocate(blinkPageSize * bl inkPagesPerRegion, blinkPagesPerRegion);
1264 m_threadState->allocatedRegionsSinceLastGC().append(region);
1265
1266 // Setup the PageMemory object for each of the pages in the 1186 // Setup the PageMemory object for each of the pages in the
1267 // region. 1187 // region.
1268 size_t offset = 0; 1188 size_t offset = 0;
1269 for (size_t i = 0; i < blinkPagesPerRegion; i++) { 1189 for (size_t i = 0; i < blinkPagesPerRegion; i++) {
1270 PageMemory* memory = PageMemory::setupPageMemoryInRegion(region, off set, blinkPagePayloadSize()); 1190 Heap::freePagePool()->addFreePage(m_index, PageMemory::setupPageMemo ryInRegion(region, offset, blinkPagePayloadSize()));
1271 // Take the first possible page ensuring that this thread actually
1272 // gets a page and add the rest to the page pool.
1273 if (!pageMemory) {
1274 if (memory->commit())
1275 pageMemory = memory;
1276 else
1277 delete memory;
1278 } else {
1279 Heap::freePagePool()->addFreePage(m_index, memory);
1280 }
1281 offset += blinkPageSize; 1191 offset += blinkPageSize;
1282 } 1192 }
1193 pageMemory = Heap::freePagePool()->takeFreePage(m_index);
1283 } 1194 }
1284 HeapPage<Header>* page = new (pageMemory->writableStart()) HeapPage<Header>( pageMemory, this, gcInfo); 1195 HeapPage<Header>* page = new (pageMemory->writableStart()) HeapPage<Header>( pageMemory, this, gcInfo);
1285 // Use a separate list for pages allocated during sweeping to make 1196 // Use a separate list for pages allocated during sweeping to make
1286 // sure that we do not accidentally sweep objects that have been 1197 // sure that we do not accidentally sweep objects that have been
1287 // allocated during sweeping. 1198 // allocated during sweeping.
1288 if (m_threadState->isSweepInProgress()) { 1199 if (m_threadState->isSweepInProgress()) {
1289 if (!m_lastPageAllocatedDuringSweeping) 1200 if (!m_lastPageAllocatedDuringSweeping)
1290 m_lastPageAllocatedDuringSweeping = page; 1201 m_lastPageAllocatedDuringSweeping = page;
1291 page->link(&m_firstPageAllocatedDuringSweeping); 1202 page->link(&m_firstPageAllocatedDuringSweeping);
1292 } else { 1203 } else {
(...skipping 538 matching lines...) Expand 10 before | Expand all | Expand 10 after
1831 } 1742 }
1832 1743
1833 if (json) { 1744 if (json) {
1834 json->setInteger("class", tag); 1745 json->setInteger("class", tag);
1835 json->setInteger("size", header->size()); 1746 json->setInteger("size", header->size());
1836 json->setInteger("isMarked", isMarked()); 1747 json->setInteger("isMarked", isMarked());
1837 } 1748 }
1838 } 1749 }
1839 #endif 1750 #endif
1840 1751
1841 void HeapDoesNotContainCache::flush() 1752 template<typename Entry>
1753 void HeapExtentCache<Entry>::flush()
1842 { 1754 {
1843 if (m_hasEntries) { 1755 if (m_hasEntries) {
1844 for (int i = 0; i < numberOfEntries; i++) 1756 for (int i = 0; i < numberOfEntries; i++)
1845 m_entries[i] = 0; 1757 m_entries[i] = Entry();
1846 m_hasEntries = false; 1758 m_hasEntries = false;
1847 } 1759 }
1848 } 1760 }
1849 1761
1850 size_t HeapDoesNotContainCache::hash(Address address) 1762 template<typename Entry>
1763 size_t HeapExtentCache<Entry>::hash(Address address)
1851 { 1764 {
1852 size_t value = (reinterpret_cast<size_t>(address) >> blinkPageSizeLog2); 1765 size_t value = (reinterpret_cast<size_t>(address) >> blinkPageSizeLog2);
1853 value ^= value >> numberOfEntriesLog2; 1766 value ^= value >> numberOfEntriesLog2;
1854 value ^= value >> (numberOfEntriesLog2 * 2); 1767 value ^= value >> (numberOfEntriesLog2 * 2);
1855 value &= numberOfEntries - 1; 1768 value &= numberOfEntries - 1;
1856 return value & ~1; // Returns only even number. 1769 return value & ~1; // Returns only even number.
1857 } 1770 }
1858 1771
1859 bool HeapDoesNotContainCache::lookup(Address address) 1772 template<typename Entry>
1773 typename Entry::LookupResult HeapExtentCache<Entry>::lookup(Address address)
1860 { 1774 {
1861 size_t index = hash(address); 1775 size_t index = hash(address);
1862 ASSERT(!(index & 1)); 1776 ASSERT(!(index & 1));
1863 Address cachePage = roundToBlinkPageStart(address); 1777 Address cachePage = roundToBlinkPageStart(address);
1864 if (m_entries[index] == cachePage) 1778 if (m_entries[index].address() == cachePage)
1865 return m_entries[index]; 1779 return m_entries[index].result();
1866 if (m_entries[index + 1] == cachePage) 1780 if (m_entries[index + 1].address() == cachePage)
1867 return m_entries[index + 1]; 1781 return m_entries[index + 1].result();
1868 return 0; 1782 return 0;
1869 } 1783 }
1870 1784
1871 void HeapDoesNotContainCache::addEntry(Address address) 1785 template<typename Entry>
1786 void HeapExtentCache<Entry>::addEntry(Address address, typename Entry::LookupRes ult entry)
1872 { 1787 {
1873 m_hasEntries = true; 1788 m_hasEntries = true;
1874 size_t index = hash(address); 1789 size_t index = hash(address);
1875 ASSERT(!(index & 1)); 1790 ASSERT(!(index & 1));
1876 Address cachePage = roundToBlinkPageStart(address); 1791 Address cachePage = roundToBlinkPageStart(address);
1877 m_entries[index + 1] = m_entries[index]; 1792 m_entries[index + 1] = m_entries[index];
1878 m_entries[index] = cachePage; 1793 m_entries[index] = Entry(cachePage, entry);
1794 }
1795
1796 // These should not be needed, but it seems impossible to persuade clang to
1797 // instantiate the template functions and export them from a shared library, so
1798 // we add these in the non-templated subclass, which does not have that issue.
1799 void HeapContainsCache::addEntry(Address address, BaseHeapPage* page)
1800 {
1801 HeapExtentCache<PositiveEntry>::addEntry(address, page);
1802 }
1803
1804 BaseHeapPage* HeapContainsCache::lookup(Address address)
1805 {
1806 return HeapExtentCache<PositiveEntry>::lookup(address);
1879 } 1807 }
1880 1808
1881 void Heap::flushHeapDoesNotContainCache() 1809 void Heap::flushHeapDoesNotContainCache()
1882 { 1810 {
1883 s_heapDoesNotContainCache->flush(); 1811 s_heapDoesNotContainCache->flush();
1884 } 1812 }
1885 1813
1886 // The marking mutex is used to ensure sequential access to data 1814 // The marking mutex is used to ensure sequential access to data
1887 // structures during marking. The marking mutex needs to be acquired 1815 // structures during marking. The marking mutex needs to be acquired
1888 // during marking when elements are taken from the global marking 1816 // during marking when elements are taken from the global marking
(...skipping 282 matching lines...) Expand 10 before | Expand all | Expand 10 after
2171 delete s_orphanedPagePool; 2099 delete s_orphanedPagePool;
2172 s_orphanedPagePool = 0; 2100 s_orphanedPagePool = 0;
2173 delete s_weakCallbackStack; 2101 delete s_weakCallbackStack;
2174 s_weakCallbackStack = 0; 2102 s_weakCallbackStack = 0;
2175 delete s_postMarkingCallbackStack; 2103 delete s_postMarkingCallbackStack;
2176 s_postMarkingCallbackStack = 0; 2104 s_postMarkingCallbackStack = 0;
2177 delete s_markingStack; 2105 delete s_markingStack;
2178 s_markingStack = 0; 2106 s_markingStack = 0;
2179 delete s_ephemeronStack; 2107 delete s_ephemeronStack;
2180 s_ephemeronStack = 0; 2108 s_ephemeronStack = 0;
2181 delete s_regionTree;
2182 s_regionTree = 0;
2183 ThreadState::shutdown(); 2109 ThreadState::shutdown();
2184 } 2110 }
2185 2111
2186 BaseHeapPage* Heap::contains(Address address) 2112 BaseHeapPage* Heap::contains(Address address)
2187 { 2113 {
2188 ASSERT(ThreadState::isAnyThreadInGC()); 2114 ASSERT(ThreadState::isAnyThreadInGC());
2189 ThreadState::AttachedThreadStateSet& threads = ThreadState::attachedThreads( ); 2115 ThreadState::AttachedThreadStateSet& threads = ThreadState::attachedThreads( );
2190 for (ThreadState::AttachedThreadStateSet::iterator it = threads.begin(), end = threads.end(); it != end; ++it) { 2116 for (ThreadState::AttachedThreadStateSet::iterator it = threads.begin(), end = threads.end(); it != end; ++it) {
2191 BaseHeapPage* page = (*it)->contains(address); 2117 BaseHeapPage* page = (*it)->contains(address);
2192 if (page) 2118 if (page)
(...skipping 11 matching lines...) Expand all
2204 2130
2205 Address Heap::checkAndMarkPointer(Visitor* visitor, Address address) 2131 Address Heap::checkAndMarkPointer(Visitor* visitor, Address address)
2206 { 2132 {
2207 ASSERT(ThreadState::isAnyThreadInGC()); 2133 ASSERT(ThreadState::isAnyThreadInGC());
2208 2134
2209 #if !ENABLE(ASSERT) 2135 #if !ENABLE(ASSERT)
2210 if (s_heapDoesNotContainCache->lookup(address)) 2136 if (s_heapDoesNotContainCache->lookup(address))
2211 return 0; 2137 return 0;
2212 #endif 2138 #endif
2213 2139
2214 if (BaseHeapPage* page = lookup(address)) { 2140 ThreadState::AttachedThreadStateSet& threads = ThreadState::attachedThreads( );
2215 ASSERT(page->contains(address)); 2141 for (ThreadState::AttachedThreadStateSet::iterator it = threads.begin(), end = threads.end(); it != end; ++it) {
2216 ASSERT(!s_heapDoesNotContainCache->lookup(address)); 2142 if ((*it)->checkAndMarkPointer(visitor, address)) {
2217 page->checkAndMarkPointer(visitor, address); 2143 // Pointer was in a page of that thread. If it actually pointed
2218 // FIXME: We only need to set the conservative flag if checkAndMarkPoint er actually marked the pointer. 2144 // into an object then that object was found and marked.
2219 s_lastGCWasConservative = true; 2145 ASSERT(!s_heapDoesNotContainCache->lookup(address));
2220 return address; 2146 s_lastGCWasConservative = true;
2147 return address;
2148 }
2221 } 2149 }
2222 2150
2223 #if !ENABLE(ASSERT) 2151 #if !ENABLE(ASSERT)
2224 s_heapDoesNotContainCache->addEntry(address); 2152 s_heapDoesNotContainCache->addEntry(address, true);
2225 #else 2153 #else
2226 if (!s_heapDoesNotContainCache->lookup(address)) 2154 if (!s_heapDoesNotContainCache->lookup(address))
2227 s_heapDoesNotContainCache->addEntry(address); 2155 s_heapDoesNotContainCache->addEntry(address, true);
2228 #endif 2156 #endif
2229 return 0; 2157 return 0;
2230 } 2158 }
2231 2159
2232 #if ENABLE(GC_PROFILE_MARKING) 2160 #if ENABLE(GC_PROFILE_MARKING)
2233 const GCInfo* Heap::findGCInfo(Address address) 2161 const GCInfo* Heap::findGCInfo(Address address)
2234 { 2162 {
2235 return ThreadState::findGCInfoFromAllThreads(address); 2163 return ThreadState::findGCInfoFromAllThreads(address);
2236 } 2164 }
2237 #endif 2165 #endif
(...skipping 537 matching lines...) Expand 10 before | Expand all | Expand 10 after
2775 2703
2776 HeaderType* header = HeaderType::fromPayload(address); 2704 HeaderType* header = HeaderType::fromPayload(address);
2777 header->checkHeader(); 2705 header->checkHeader();
2778 2706
2779 const GCInfo* gcInfo = header->gcInfo(); 2707 const GCInfo* gcInfo = header->gcInfo();
2780 int heapIndex = HeapTraits::index(gcInfo->hasFinalizer()); 2708 int heapIndex = HeapTraits::index(gcInfo->hasFinalizer());
2781 HeapType* heap = static_cast<HeapType*>(state->heap(heapIndex)); 2709 HeapType* heap = static_cast<HeapType*>(state->heap(heapIndex));
2782 heap->promptlyFreeObject(header); 2710 heap->promptlyFreeObject(header);
2783 } 2711 }
2784 2712
2785 BaseHeapPage* Heap::lookup(Address address)
2786 {
2787 if (!s_regionTree)
2788 return 0;
2789 if (PageMemoryRegion* region = s_regionTree->lookup(address))
2790 return region->pageFromAddress(address);
2791 return 0;
2792 }
2793
2794 static Mutex& regionTreeMutex()
2795 {
2796 AtomicallyInitializedStatic(Mutex&, mutex = *new Mutex);
2797 return mutex;
2798 }
2799
2800 void Heap::removePageMemoryRegion(PageMemoryRegion* region)
2801 {
2802 // Deletion of large objects (and thus their regions) can happen concurrentl y
2803 // on sweeper threads. Removal can also happen during thread shutdown, but
2804 // that case is safe. Regardless, we make all removals mutually exclusive.
2805 MutexLocker locker(regionTreeMutex());
2806 RegionTree::remove(region, &s_regionTree);
2807 }
2808
2809 void Heap::addPageMemoryRegion(PageMemoryRegion* region)
2810 {
2811 ASSERT(ThreadState::isAnyThreadInGC());
2812 RegionTree::add(new RegionTree(region), &s_regionTree);
2813 }
2814
2815 PageMemoryRegion* Heap::RegionTree::lookup(Address address)
2816 {
2817 RegionTree* current = s_regionTree;
2818 while (current) {
2819 Address base = current->m_region->base();
2820 if (address < base) {
2821 current = current->m_left;
2822 continue;
2823 }
2824 if (address >= base + current->m_region->size()) {
2825 current = current->m_right;
2826 continue;
2827 }
2828 ASSERT(current->m_region->contains(address));
2829 return current->m_region;
2830 }
2831 return 0;
2832 }
2833
2834 void Heap::RegionTree::add(RegionTree* newTree, RegionTree** context)
2835 {
2836 ASSERT(newTree);
2837 Address base = newTree->m_region->base();
2838 for (RegionTree* current = *context; current; current = *context) {
2839 ASSERT(!current->m_region->contains(base));
2840 context = (base < current->m_region->base()) ? &current->m_left : &curre nt->m_right;
2841 }
2842 *context = newTree;
2843 }
2844
2845 void Heap::RegionTree::remove(PageMemoryRegion* region, RegionTree** context)
2846 {
2847 ASSERT(region);
2848 ASSERT(context);
2849 ASSERT(*context);
2850 Address base = region->base();
2851 RegionTree* current = *context;
2852 for ( ; region != current->m_region; current = *context) {
2853 context = (base < current->m_region->base()) ? &current->m_left : &curre nt->m_right;
2854 ASSERT(*context);
2855 }
2856 *context = 0;
2857 if (current->m_left) {
2858 add(current->m_left, context);
2859 current->m_left = 0;
2860 }
2861 if (current->m_right) {
2862 add(current->m_right, context);
2863 current->m_right = 0;
2864 }
2865 delete current;
2866 }
2867
2868 // Force template instantiations for the types that we need. 2713 // Force template instantiations for the types that we need.
2869 template class HeapPage<FinalizedHeapObjectHeader>; 2714 template class HeapPage<FinalizedHeapObjectHeader>;
2870 template class HeapPage<HeapObjectHeader>; 2715 template class HeapPage<HeapObjectHeader>;
2871 template class ThreadHeap<FinalizedHeapObjectHeader>; 2716 template class ThreadHeap<FinalizedHeapObjectHeader>;
2872 template class ThreadHeap<HeapObjectHeader>; 2717 template class ThreadHeap<HeapObjectHeader>;
2873 2718
2874 Visitor* Heap::s_markingVisitor; 2719 Visitor* Heap::s_markingVisitor;
2875 Vector<OwnPtr<blink::WebThread> >* Heap::s_markingThreads; 2720 Vector<OwnPtr<blink::WebThread> >* Heap::s_markingThreads;
2876 CallbackStack* Heap::s_markingStack; 2721 CallbackStack* Heap::s_markingStack;
2877 CallbackStack* Heap::s_postMarkingCallbackStack; 2722 CallbackStack* Heap::s_postMarkingCallbackStack;
2878 CallbackStack* Heap::s_weakCallbackStack; 2723 CallbackStack* Heap::s_weakCallbackStack;
2879 CallbackStack* Heap::s_ephemeronStack; 2724 CallbackStack* Heap::s_ephemeronStack;
2880 HeapDoesNotContainCache* Heap::s_heapDoesNotContainCache; 2725 HeapDoesNotContainCache* Heap::s_heapDoesNotContainCache;
2881 bool Heap::s_shutdownCalled = false; 2726 bool Heap::s_shutdownCalled = false;
2882 bool Heap::s_lastGCWasConservative = false; 2727 bool Heap::s_lastGCWasConservative = false;
2883 FreePagePool* Heap::s_freePagePool; 2728 FreePagePool* Heap::s_freePagePool;
2884 OrphanedPagePool* Heap::s_orphanedPagePool; 2729 OrphanedPagePool* Heap::s_orphanedPagePool;
2885 Heap::RegionTree* Heap::s_regionTree = 0;
2886
2887 } 2730 }
OLDNEW
« no previous file with comments | « Source/platform/heap/Heap.h ('k') | Source/platform/heap/HeapTest.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698