| 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 188 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 199 void HeapObjectHeader::zapMagic() | 199 void HeapObjectHeader::zapMagic() |
| 200 { | 200 { |
| 201 checkHeader(); | 201 checkHeader(); |
| 202 m_magic = zappedMagic; | 202 m_magic = zappedMagic; |
| 203 } | 203 } |
| 204 #endif | 204 #endif |
| 205 | 205 |
| 206 void HeapObjectHeader::finalize(Address object, size_t objectSize) | 206 void HeapObjectHeader::finalize(Address object, size_t objectSize) |
| 207 { | 207 { |
| 208 const GCInfo* gcInfo = Heap::gcInfo(gcInfoIndex()); | 208 const GCInfo* gcInfo = Heap::gcInfo(gcInfoIndex()); |
| 209 if (gcInfo->hasFinalizer()) | 209 if (gcInfo->hasFinalizer()) { |
| 210 gcInfo->m_finalize(object); | 210 gcInfo->m_finalize(object); |
| 211 } |
| 211 | 212 |
| 212 ASAN_RETIRE_CONTAINER_ANNOTATION(object, objectSize); | 213 ASAN_RETIRE_CONTAINER_ANNOTATION(object, objectSize); |
| 214 |
| 215 #if ENABLE(ASSERT) || defined(LEAK_SANITIZER) || defined(ADDRESS_SANITIZER) |
| 216 // In Debug builds, memory is zapped when it's freed, and the zapped memory |
| 217 // is zeroed out when the memory is reused. Memory is also zapped when |
| 218 // using Leak Sanitizer because the heap is used as a root region for LSan |
| 219 // and therefore pointers in unreachable memory could hide leaks. |
| 220 for (size_t i = 0; i < objectSize; ++i) |
| 221 object[i] = finalizedZapValue; |
| 222 |
| 223 // Zap the primary vTable entry (secondary vTable entries are not zapped). |
| 224 if (gcInfo->hasVTable()) { |
| 225 *(reinterpret_cast<uintptr_t*>(object)) = zappedVTable; |
| 226 } |
| 227 #endif |
| 228 // In Release builds, the entire object is zeroed out when it is added to |
| 229 // the free list. This happens right after sweeping the page and before the |
| 230 // thread commences execution. |
| 213 } | 231 } |
| 214 | 232 |
| 215 BaseHeap::BaseHeap(ThreadState* state, int index) | 233 BaseHeap::BaseHeap(ThreadState* state, int index) |
| 216 : m_firstPage(nullptr) | 234 : m_firstPage(nullptr) |
| 217 , m_firstUnsweptPage(nullptr) | 235 , m_firstUnsweptPage(nullptr) |
| 218 , m_threadState(state) | 236 , m_threadState(state) |
| 219 , m_index(index) | 237 , m_index(index) |
| 220 { | 238 { |
| 221 } | 239 } |
| 222 | 240 |
| (...skipping 369 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 592 } else { | 610 } else { |
| 593 Heap::freePagePool()->addFreePage(heapIndex(), memory); | 611 Heap::freePagePool()->addFreePage(heapIndex(), memory); |
| 594 } | 612 } |
| 595 offset += blinkPageSize; | 613 offset += blinkPageSize; |
| 596 } | 614 } |
| 597 } | 615 } |
| 598 NormalPage* page = new (pageMemory->writableStart()) NormalPage(pageMemory,
this); | 616 NormalPage* page = new (pageMemory->writableStart()) NormalPage(pageMemory,
this); |
| 599 page->link(&m_firstPage); | 617 page->link(&m_firstPage); |
| 600 | 618 |
| 601 Heap::increaseAllocatedSpace(page->size()); | 619 Heap::increaseAllocatedSpace(page->size()); |
| 602 #if ENABLE(ASSERT) || defined(LEAK_SANITIZER) || defined(ADDRESS_SANITIZER) | |
| 603 // Allow the following addToFreeList() to add the newly allocated memory | |
| 604 // to the free list. | |
| 605 Address address = page->payload(); | |
| 606 for (size_t i = 0; i < page->payloadSize(); i++) | |
| 607 address[i] = reuseAllowedZapValue; | |
| 608 #endif | |
| 609 addToFreeList(page->payload(), page->payloadSize()); | 620 addToFreeList(page->payload(), page->payloadSize()); |
| 610 } | 621 } |
| 611 | 622 |
| 612 void NormalPageHeap::freePage(NormalPage* page) | 623 void NormalPageHeap::freePage(NormalPage* page) |
| 613 { | 624 { |
| 614 Heap::decreaseAllocatedSpace(page->size()); | 625 Heap::decreaseAllocatedSpace(page->size()); |
| 615 | 626 |
| 616 if (page->terminating()) { | 627 if (page->terminating()) { |
| 617 // The thread is shutting down and this page is being removed as a part | 628 // The thread is shutting down and this page is being removed as a part |
| 618 // of the thread local GC. In that case the object could be traced in | 629 // of the thread local GC. In that case the object could be traced in |
| (...skipping 436 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1055 FreeListEntry* entry; | 1066 FreeListEntry* entry; |
| 1056 if (size < sizeof(*entry)) { | 1067 if (size < sizeof(*entry)) { |
| 1057 // Create a dummy header with only a size and freelist bit set. | 1068 // Create a dummy header with only a size and freelist bit set. |
| 1058 ASSERT(size >= sizeof(HeapObjectHeader)); | 1069 ASSERT(size >= sizeof(HeapObjectHeader)); |
| 1059 // Free list encode the size to mark the lost memory as freelist memory. | 1070 // Free list encode the size to mark the lost memory as freelist memory. |
| 1060 new (NotNull, address) HeapObjectHeader(size, gcInfoIndexForFreeListHead
er); | 1071 new (NotNull, address) HeapObjectHeader(size, gcInfoIndexForFreeListHead
er); |
| 1061 // This memory gets lost. Sweeping can reclaim it. | 1072 // This memory gets lost. Sweeping can reclaim it. |
| 1062 return; | 1073 return; |
| 1063 } | 1074 } |
| 1064 entry = new (NotNull, address) FreeListEntry(size); | 1075 entry = new (NotNull, address) FreeListEntry(size); |
| 1065 | 1076 #if defined(ADDRESS_SANITIZER) |
| 1066 #if ENABLE(ASSERT) || defined(LEAK_SANITIZER) || defined(ADDRESS_SANITIZER) | 1077 BasePage* page = pageFromObject(address); |
| 1067 // The following logic delays reusing free lists for (at least) one GC | 1078 ASSERT(!page->isLargeObjectPage()); |
| 1068 // cycle or coalescing. This is helpful to detect use-after-free errors | 1079 // For ASan we don't add the entry to the free lists until the |
| 1069 // that could be caused by lazy sweeping etc. | 1080 // asanDeferMemoryReuseCount reaches zero. However we always add entire |
| 1070 size_t allowedCount = 0; | 1081 // pages to ensure that adding a new page will increase the allocation |
| 1071 size_t forbiddenCount = 0; | 1082 // space. |
| 1072 for (size_t i = sizeof(FreeListEntry); i < size; i++) { | 1083 if (static_cast<NormalPage*>(page)->payloadSize() != size && !entry->shouldA
ddToFreeList()) |
| 1073 if (address[i] == reuseAllowedZapValue) { | |
| 1074 allowedCount++; | |
| 1075 } else if (address[i] == reuseForbiddenZapValue) { | |
| 1076 forbiddenCount++; | |
| 1077 } else { | |
| 1078 ASSERT_NOT_REACHED(); | |
| 1079 } | |
| 1080 } | |
| 1081 size_t entryCount = size - sizeof(FreeListEntry); | |
| 1082 if (forbiddenCount == entryCount) { | |
| 1083 // If all values in the memory region are reuseForbiddenZapValue, | |
| 1084 // we flip them to reuseAllowedZapValue. This allows the next | |
| 1085 // addToFreeList() to add the memory region to the free list | |
| 1086 // (unless someone concatenates the memory region with another memory | |
| 1087 // region that contains reuseForbiddenZapValue.) | |
| 1088 for (size_t i = sizeof(FreeListEntry); i < size; i++) | |
| 1089 address[i] = reuseAllowedZapValue; | |
| 1090 // Don't add the memory region to the free list in this addToFreeList(). | |
| 1091 return; | 1084 return; |
| 1092 } | |
| 1093 if (allowedCount != entryCount) { | |
| 1094 // If the memory region mixes reuseForbiddenZapValue and | |
| 1095 // reuseAllowedZapValue, we (conservatively) flip all the values | |
| 1096 // to reuseForbiddenZapValue. These values will be changed to | |
| 1097 // reuseAllowedZapValue in the next addToFreeList(). | |
| 1098 for (size_t i = sizeof(FreeListEntry); i < size; i++) | |
| 1099 address[i] = reuseForbiddenZapValue; | |
| 1100 // Don't add the memory region to the free list in this addToFreeList(). | |
| 1101 return; | |
| 1102 } | |
| 1103 // We reach here only when all the values in the memory region are | |
| 1104 // reuseAllowedZapValue. In this case, we are allowed to add the memory | |
| 1105 // region to the free list and reuse it for another object. | |
| 1106 #endif | 1085 #endif |
| 1107 | |
| 1108 int index = bucketIndexForSize(size); | 1086 int index = bucketIndexForSize(size); |
| 1109 entry->link(&m_freeLists[index]); | 1087 entry->link(&m_freeLists[index]); |
| 1110 if (index > m_biggestFreeListIndex) | 1088 if (index > m_biggestFreeListIndex) |
| 1111 m_biggestFreeListIndex = index; | 1089 m_biggestFreeListIndex = index; |
| 1112 } | 1090 } |
| 1113 | 1091 |
| 1114 #if ENABLE(ASSERT) || defined(LEAK_SANITIZER) || defined(ADDRESS_SANITIZER) | |
| 1115 void FreeList::zapFreedMemory(Address address, size_t size) | |
| 1116 { | |
| 1117 for (size_t i = 0; i < size; i++) { | |
| 1118 // See the comment in addToFreeList(). | |
| 1119 if (address[i] != reuseAllowedZapValue) | |
| 1120 address[i] = reuseForbiddenZapValue; | |
| 1121 } | |
| 1122 } | |
| 1123 #endif | |
| 1124 | |
| 1125 void FreeList::clear() | 1092 void FreeList::clear() |
| 1126 { | 1093 { |
| 1127 m_biggestFreeListIndex = 0; | 1094 m_biggestFreeListIndex = 0; |
| 1128 for (size_t i = 0; i < blinkPageSizeLog2; ++i) | 1095 for (size_t i = 0; i < blinkPageSizeLog2; ++i) |
| 1129 m_freeLists[i] = nullptr; | 1096 m_freeLists[i] = nullptr; |
| 1130 } | 1097 } |
| 1131 | 1098 |
| 1132 int FreeList::bucketIndexForSize(size_t size) | 1099 int FreeList::bucketIndexForSize(size_t size) |
| 1133 { | 1100 { |
| 1134 ASSERT(size > 0); | 1101 ASSERT(size > 0); |
| (...skipping 1220 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2355 size_t Heap::s_allocatedObjectSize = 0; | 2322 size_t Heap::s_allocatedObjectSize = 0; |
| 2356 size_t Heap::s_allocatedSpace = 0; | 2323 size_t Heap::s_allocatedSpace = 0; |
| 2357 size_t Heap::s_markedObjectSize = 0; | 2324 size_t Heap::s_markedObjectSize = 0; |
| 2358 // We don't want to use 0 KB for the initial value because it may end up | 2325 // We don't want to use 0 KB for the initial value because it may end up |
| 2359 // triggering the first GC of some thread too prematurely. | 2326 // triggering the first GC of some thread too prematurely. |
| 2360 size_t Heap::s_estimatedLiveObjectSize = 512 * 1024; | 2327 size_t Heap::s_estimatedLiveObjectSize = 512 * 1024; |
| 2361 size_t Heap::s_externalObjectSizeAtLastGC = 0; | 2328 size_t Heap::s_externalObjectSizeAtLastGC = 0; |
| 2362 double Heap::s_estimatedMarkingTimePerByte = 0.0; | 2329 double Heap::s_estimatedMarkingTimePerByte = 0.0; |
| 2363 | 2330 |
| 2364 } // namespace blink | 2331 } // namespace blink |
| OLD | NEW |