Changeset 180701 in webkit
- Timestamp:
- Feb 26, 2015, 2:24:37 PM (12 years ago)
- Location:
- trunk/Source/bmalloc
- Files:
-
- 6 edited
-
ChangeLog (modified) (1 diff)
-
bmalloc/BoundaryTag.h (modified) (3 diffs)
-
bmalloc/FreeList.cpp (modified) (1 diff)
-
bmalloc/FreeList.h (modified) (1 diff)
-
bmalloc/LargeObject.h (modified) (3 diffs)
-
bmalloc/Sizes.h (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/bmalloc/ChangeLog
r180695 r180701 1 2015-02-26 Geoffrey Garen <ggaren@apple.com> 2 3 bmalloc: Large object free list can grow infinitely 4 https://bugs.webkit.org/show_bug.cgi?id=142055 5 6 Reviewed by Andreas Kling. 7 8 By design, we don't eagerly remove large objects from the free list. 9 This creates two simple pathologies: 10 11 (1) If you free and then allocate the same object repeatedly, it will 12 duplicate itself in the free list repeatedly. Since it is never 13 invalid at the time of allocation, it will never be removed. 14 15 (2) If you split and then merge the same object repeatedly, it will 16 duplicate its split sibling in the free list repeatedly. If its 17 sibling is in a separate free list size class, it will never be 18 consulted at the time of allocation, so it will never be removed. 19 20 So, a simple "while (1) { free(malloc(x)); }" causes infinite memory 21 use in the free list. 22 23 The solution in this patch is a simple helper to remove garbage from the 24 free list if it grows too large. This pathology is not common, so the 25 cost is OK. 26 27 Long-term, perhaps we should rethink the laziness of these free lists. 28 29 * bmalloc/BoundaryTag.h: 30 (bmalloc::BoundaryTag::isMarked): 31 (bmalloc::BoundaryTag::setMarked): New bit, used by free list GC. 32 33 * bmalloc/FreeList.cpp: 34 (bmalloc::FreeList::removeInvalidAndDuplicateEntries): The GC algorithm. 35 36 * bmalloc/FreeList.h: 37 (bmalloc::FreeList::FreeList): 38 (bmalloc::FreeList::push): Invoke the GC if we're getting huge. 39 40 * bmalloc/LargeObject.h: 41 (bmalloc::LargeObject::isMarked): 42 (bmalloc::LargeObject::setMarked): 43 (bmalloc::LargeObject::validateSelf): Expose the new bit. 44 45 * bmalloc/Sizes.h: New constant to control GC frequency. 46 1 47 2015-02-26 Csaba Osztrogonác <ossy@webkit.org> 2 48 -
trunk/Source/bmalloc/bmalloc/BoundaryTag.h
r180688 r180701 52 52 bool hasPhysicalPages() { return m_hasPhysicalPages; } 53 53 void setHasPhysicalPages(bool hasPhysicalPages) { m_hasPhysicalPages = hasPhysicalPages; } 54 55 bool isMarked() { return m_isMarked; } 56 void setMarked(bool isMarked) { m_isMarked = isMarked; } 54 57 55 58 bool isNull() { return !m_size; } … … 68 71 69 72 private: 70 static const size_t flagBits = 3;73 static const size_t flagBits = 4; 71 74 static const size_t compactBeginBits = 4; 72 75 static const size_t sizeBits = bitCount<unsigned>() - flagBits - compactBeginBits; … … 83 86 bool m_isEnd: 1; 84 87 bool m_hasPhysicalPages: 1; 88 bool m_isMarked: 1; 85 89 unsigned m_compactBegin: compactBeginBits; 86 90 unsigned m_size: sizeBits; -
trunk/Source/bmalloc/bmalloc/FreeList.cpp
r180693 r180701 108 108 } 109 109 110 void FreeList::removeInvalidAndDuplicateEntries() 111 { 112 for (size_t i = m_vector.size(); i-- > 0; ) { 113 LargeObject largeObject(LargeObject::DoNotValidate, m_vector[i].begin()); 114 if (!largeObject.isValidAndFree(m_vector[i].size())) { 115 m_vector.pop(i); 116 continue; 117 } 118 119 largeObject.setMarked(false); 120 } 121 122 for (size_t i = m_vector.size(); i-- > 0; ) { 123 LargeObject largeObject(LargeObject::DoNotValidate, m_vector[i].begin()); 124 if (largeObject.isMarked()) { 125 m_vector.pop(i); 126 continue; 127 } 128 129 largeObject.setMarked(true); 130 } 131 } 132 133 110 134 } // namespace bmalloc -
trunk/Source/bmalloc/bmalloc/FreeList.h
r180693 r180701 36 36 class FreeList { 37 37 public: 38 FreeList(); 39 38 40 void push(const LargeObject&); 39 41 40 42 LargeObject take(size_t); 41 43 LargeObject take(size_t alignment, size_t, size_t unalignedSize); 44 42 45 LargeObject takeGreedy(size_t); 46 47 void removeInvalidAndDuplicateEntries(); 43 48 44 49 private: 45 50 Vector<Range> m_vector; 51 size_t m_limit; 46 52 }; 53 54 inline FreeList::FreeList() 55 : m_vector() 56 , m_limit(freeListSearchDepth) 57 { 58 } 47 59 48 60 inline void FreeList::push(const LargeObject& largeObject) 49 61 { 50 62 BASSERT(largeObject.isFree()); 63 if (m_vector.size() == m_limit) { 64 removeInvalidAndDuplicateEntries(); 65 m_limit = std::max(m_vector.size() * freeListGrowFactor, freeListSearchDepth); 66 } 51 67 m_vector.push(largeObject.range()); 52 68 } -
trunk/Source/bmalloc/bmalloc/LargeObject.h
r180693 r180701 56 56 void setHasPhysicalPages(bool) const; 57 57 58 bool isMarked() const; 59 void setMarked(bool) const; 60 58 61 bool isValidAndFree(size_t) const; 59 62 … … 125 128 m_beginTag->setHasPhysicalPages(hasPhysicalPages); 126 129 m_endTag->setHasPhysicalPages(hasPhysicalPages); 130 } 131 132 inline bool LargeObject::isMarked() const 133 { 134 validate(); 135 return m_beginTag->isMarked(); 136 } 137 138 inline void LargeObject::setMarked(bool isMarked) const 139 { 140 validate(); 141 m_beginTag->setMarked(isMarked); 142 m_endTag->setMarked(isMarked); 127 143 } 128 144 … … 224 240 BASSERT(m_beginTag->isFree() == m_endTag->isFree()); 225 241 BASSERT(m_beginTag->hasPhysicalPages() == m_endTag->hasPhysicalPages()); 242 BASSERT(m_beginTag->isMarked() == m_endTag->isMarked()); 226 243 } 227 244 -
trunk/Source/bmalloc/bmalloc/Sizes.h
r180693 r180701 83 83 84 84 static const size_t freeListSearchDepth = 16; 85 static const size_t freeListGrowFactor = 2; 85 86 86 87 static const uintptr_t typeMask = (superChunkSize - 1) & ~((superChunkSize / 4) - 1); // 4 taggable chunks
Note:
See TracChangeset
for help on using the changeset viewer.