bmalloc: large aligned allocations will put 1 or 2 free object on free list without...
authormsaboff@apple.com <msaboff@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 11 Feb 2016 16:01:55 +0000 (16:01 +0000)
committermsaboff@apple.com <msaboff@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 11 Feb 2016 16:01:55 +0000 (16:01 +0000)
https://bugs.webkit.org/show_bug.cgi?id=154091

Reviewed by Geoffrey Garen.

If we split off any unused free object in the aligned version of Heap::allocateLarge(), we merge them with
free neighbors before putting them back on the free list.  Added helpers to verify that when we
add LargeObjects to the free list their neighbors are allocated.

* bmalloc/Heap.cpp:
(bmalloc::Heap::allocateLarge): Deleted private helper version and rolled it into the two the
two public versions of allocateLarge().
* bmalloc/Heap.h:
* bmalloc/LargeObject.h:
(bmalloc::LargeObject::prevIsAllocated): New helper.
(bmalloc::LargeObject::nextIsAllocated): New helper.
(bmalloc::LargeObject::merge): Check that the merge object has allocated neighbors.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@196421 268f45cc-cd09-0410-ab3c-d52691b4dbfc

Source/bmalloc/ChangeLog
Source/bmalloc/bmalloc/Heap.cpp
Source/bmalloc/bmalloc/Heap.h
Source/bmalloc/bmalloc/LargeObject.h

index 266cf64..8e22100 100644 (file)
@@ -1,3 +1,23 @@
+2016-02-11  Michael Saboff  <msaboff@apple.com>
+
+        bmalloc: large aligned allocations will put 1 or 2 free object on free list without merging with free neighbors
+        https://bugs.webkit.org/show_bug.cgi?id=154091
+
+        Reviewed by Geoffrey Garen.
+
+        If we split off any unused free object in the aligned version of Heap::allocateLarge(), we merge them with
+        free neighbors before putting them back on the free list.  Added helpers to verify that when we
+        add LargeObjects to the free list their neighbors are allocated.
+
+        * bmalloc/Heap.cpp:
+        (bmalloc::Heap::allocateLarge): Deleted private helper version and rolled it into the two the
+        two public versions of allocateLarge().
+        * bmalloc/Heap.h:
+        * bmalloc/LargeObject.h:
+        (bmalloc::LargeObject::prevIsAllocated): New helper.
+        (bmalloc::LargeObject::nextIsAllocated): New helper.
+        (bmalloc::LargeObject::merge): Check that the merge object has allocated neighbors.
+
 2016-02-05  Saam barati  <sbarati@apple.com>
 
         bmalloc: largeMax calculation is wrong on iOS
index e136140..d9e66f6 100644 (file)
@@ -346,21 +346,7 @@ void Heap::deallocateXLarge(std::unique_lock<StaticMutex>& lock, void* object)
     lock.lock();
 }
 
-void* Heap::allocateLarge(std::lock_guard<StaticMutex>&, LargeObject& largeObject, size_t size)
-{
-    BASSERT(largeObject.isFree());
-
-    if (largeObject.size() - size > largeMin) {
-        std::pair<LargeObject, LargeObject> split = largeObject.split(size);
-        largeObject = split.first;
-        m_largeObjects.insert(split.second);
-    }
-
-    largeObject.setFree(false);
-    return largeObject.begin();
-}
-
-void* Heap::allocateLarge(std::lock_guard<StaticMutex>& lock, size_t size)
+void* Heap::allocateLarge(std::lock_guard<StaticMutex>&, size_t size)
 {
     BASSERT(size <= largeMax);
     BASSERT(size >= largeMin);
@@ -372,10 +358,27 @@ void* Heap::allocateLarge(std::lock_guard<StaticMutex>& lock, size_t size)
         largeObject = m_vmHeap.allocateLargeObject(size);
     }
 
-    return allocateLarge(lock, largeObject, size);
+    BASSERT(largeObject.isFree());
+
+    LargeObject nextLargeObject;
+
+    if (largeObject.size() - size > largeMin) {
+        std::pair<LargeObject, LargeObject> split = largeObject.split(size);
+        largeObject = split.first;
+        nextLargeObject = split.second;
+    }
+    
+    largeObject.setFree(false);
+    
+    if (nextLargeObject) {
+        BASSERT(nextLargeObject.nextIsAllocated());
+        m_largeObjects.insert(nextLargeObject);
+    }
+    
+    return largeObject.begin();
 }
 
-void* Heap::allocateLarge(std::lock_guard<StaticMutex>& lock, size_t alignment, size_t size, size_t unalignedSize)
+void* Heap::allocateLarge(std::lock_guard<StaticMutex>&, size_t alignment, size_t size, size_t unalignedSize)
 {
     BASSERT(size <= largeMax);
     BASSERT(size >= largeMin);
@@ -393,15 +396,38 @@ void* Heap::allocateLarge(std::lock_guard<StaticMutex>& lock, size_t alignment,
         largeObject = m_vmHeap.allocateLargeObject(alignment, size, unalignedSize);
     }
 
+    LargeObject prevLargeObject;
+    LargeObject nextLargeObject;
+
     size_t alignmentMask = alignment - 1;
     if (test(largeObject.begin(), alignmentMask)) {
         size_t prefixSize = roundUpToMultipleOf(alignment, largeObject.begin() + largeMin) - largeObject.begin();
         std::pair<LargeObject, LargeObject> pair = largeObject.split(prefixSize);
-        m_largeObjects.insert(pair.first);
+        prevLargeObject = pair.first;
         largeObject = pair.second;
     }
 
-    return allocateLarge(lock, largeObject, size);
+    BASSERT(largeObject.isFree());
+    
+    if (largeObject.size() - size > largeMin) {
+        std::pair<LargeObject, LargeObject> split = largeObject.split(size);
+        largeObject = split.first;
+        nextLargeObject = split.second;
+    }
+    
+    largeObject.setFree(false);
+
+    if (prevLargeObject) {
+        LargeObject merged = prevLargeObject.merge();
+        m_largeObjects.insert(merged);
+    }
+
+    if (nextLargeObject) {
+        LargeObject merged = nextLargeObject.merge();
+        m_largeObjects.insert(merged);
+    }
+
+    return largeObject.begin();
 }
 
 void Heap::deallocateLarge(std::lock_guard<StaticMutex>&, const LargeObject& largeObject)
index 5d57d01..698e738 100644 (file)
@@ -83,7 +83,6 @@ private:
     void deallocateSmallLine(std::lock_guard<StaticMutex>&, SmallLine*);
     void deallocateMediumLine(std::lock_guard<StaticMutex>&, MediumLine*);
 
-    void* allocateLarge(std::lock_guard<StaticMutex>&, LargeObject&, size_t);
     void deallocateLarge(std::lock_guard<StaticMutex>&, const LargeObject&);
 
     void splitLarge(BeginTag*, size_t, EndTag*&, Range&);
index e3400a0..7d9e548 100644 (file)
@@ -53,6 +53,9 @@ public:
 
     void setFree(bool) const;
     bool isFree() const;
+
+    bool prevIsAllocated() const;
+    bool nextIsAllocated() const;
     
     Owner owner() const;
     void setOwner(Owner) const;
@@ -118,6 +121,21 @@ inline bool LargeObject::isFree() const
     return m_beginTag->isFree();
 }
 
+inline bool LargeObject::prevIsAllocated() const
+{
+    EndTag* prev = m_beginTag->prev();
+
+    return !prev->isFree() || prev->owner() != this->owner();
+}
+
+inline bool LargeObject::nextIsAllocated() const
+{
+    BeginTag* next = m_endTag->next();
+
+    return !next->isFree() || next->owner() != this->owner();
+}
+
+
 inline Owner LargeObject::owner() const
 {
     validate();
@@ -201,7 +219,11 @@ inline LargeObject LargeObject::merge() const
     beginTag->setOwner(owner);
     endTag->init(beginTag);
 
-    return LargeObject(beginTag, endTag, range.begin());
+    LargeObject result(beginTag, endTag, range.begin());
+    BASSERT(result.prevIsAllocated());
+    BASSERT(result.nextIsAllocated());
+
+    return result;
 }
 
 inline std::pair<LargeObject, LargeObject> LargeObject::split(size_t size) const