Title: [248231] releases/WebKitGTK/webkit-2.24
Revision
248231
Author
[email protected]
Date
2019-08-03 20:23:10 -0700 (Sat, 03 Aug 2019)

Log Message

Merge r245908 - IsoHeaps don't notice uncommitted VA becoming the first eligible.
https://bugs.webkit.org/show_bug.cgi?id=198301

Reviewed by Yusuke Suzuki.

Source/bmalloc:

IsoDirectory has a firstEligible member that is used as an
optimization to help find the first fit. However if the scavenger
decommitted a page before firstEligible then we wouldn't move
firstEligible. Thus, if no space is ever freed below firstEligible
we will never reused the decommitted memory (e.g. if the VA page
is decommitted). The fix is to make IsoDirectory::didDecommit move
the firstEligible page back if the decommitted page is smaller
than the current firstEligible. As such, this patch renames
firstEligible to firstEligibleOrDecommitted.

Also, this patch changes gigacageEnabledForProcess to check if the
process starts with Test rather than just test as TestWTF does.

Lastly, unbeknownst to me IsoHeaps are dependent on gigacage, so
by removing gigacage from arm64 I accidentally disabled
IsoHeaps...

* bmalloc.xcodeproj/project.pbxproj:
* bmalloc/IsoDirectory.h:
* bmalloc/IsoDirectoryInlines.h:
(bmalloc::passedNumPages>::takeFirstEligible):
(bmalloc::passedNumPages>::didBecome):
(bmalloc::passedNumPages>::didDecommit):
* bmalloc/IsoHeapImpl.h:
* bmalloc/IsoHeapImplInlines.h:
(bmalloc::IsoHeapImpl<Config>::takeFirstEligible):
(bmalloc::IsoHeapImpl<Config>::didBecomeEligibleOrDecommited):
(bmalloc::IsoHeapImpl<Config>::didCommit):
(bmalloc::IsoHeapImpl<Config>::didBecomeEligible): Deleted.
* bmalloc/IsoTLS.cpp:
(bmalloc::IsoTLS::determineMallocFallbackState):
* bmalloc/ProcessCheck.mm:
(bmalloc::gigacageEnabledForProcess):

Tools:

Move testbmalloc.cpp to TestWTF so it runs in automation.

* TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj:
* TestWebKitAPI/Tests/WTF/bmalloc/IsoHeap.cpp: Renamed from Source/bmalloc/test/testbmalloc.cpp.
(TEST):

Modified Paths

Added Paths

Removed Paths

Diff

Modified: releases/WebKitGTK/webkit-2.24/Source/bmalloc/ChangeLog (248230 => 248231)


--- releases/WebKitGTK/webkit-2.24/Source/bmalloc/ChangeLog	2019-08-04 03:23:06 UTC (rev 248230)
+++ releases/WebKitGTK/webkit-2.24/Source/bmalloc/ChangeLog	2019-08-04 03:23:10 UTC (rev 248231)
@@ -1,3 +1,44 @@
+2019-05-30  Keith Miller  <[email protected]>
+
+        IsoHeaps don't notice uncommitted VA becoming the first eligible.
+        https://bugs.webkit.org/show_bug.cgi?id=198301
+
+        Reviewed by Yusuke Suzuki.
+
+        IsoDirectory has a firstEligible member that is used as an
+        optimization to help find the first fit. However if the scavenger
+        decommitted a page before firstEligible then we wouldn't move
+        firstEligible. Thus, if no space is ever freed below firstEligible
+        we will never reused the decommitted memory (e.g. if the VA page
+        is decommitted). The fix is to make IsoDirectory::didDecommit move
+        the firstEligible page back if the decommitted page is smaller
+        than the current firstEligible. As such, this patch renames
+        firstEligible to firstEligibleOrDecommitted.
+
+        Also, this patch changes gigacageEnabledForProcess to check if the
+        process starts with Test rather than just test as TestWTF does.
+
+        Lastly, unbeknownst to me IsoHeaps are dependent on gigacage, so
+        by removing gigacage from arm64 I accidentally disabled
+        IsoHeaps...
+
+        * bmalloc.xcodeproj/project.pbxproj:
+        * bmalloc/IsoDirectory.h:
+        * bmalloc/IsoDirectoryInlines.h:
+        (bmalloc::passedNumPages>::takeFirstEligible):
+        (bmalloc::passedNumPages>::didBecome):
+        (bmalloc::passedNumPages>::didDecommit):
+        * bmalloc/IsoHeapImpl.h:
+        * bmalloc/IsoHeapImplInlines.h:
+        (bmalloc::IsoHeapImpl<Config>::takeFirstEligible):
+        (bmalloc::IsoHeapImpl<Config>::didBecomeEligibleOrDecommited):
+        (bmalloc::IsoHeapImpl<Config>::didCommit):
+        (bmalloc::IsoHeapImpl<Config>::didBecomeEligible): Deleted.
+        * bmalloc/IsoTLS.cpp:
+        (bmalloc::IsoTLS::determineMallocFallbackState):
+        * bmalloc/ProcessCheck.mm:
+        (bmalloc::gigacageEnabledForProcess):
+
 2019-04-18  Yusuke Suzuki  <[email protected]>
 
         Unreviewed, fix build failure

Modified: releases/WebKitGTK/webkit-2.24/Source/bmalloc/bmalloc/IsoDirectory.h (248230 => 248231)


--- releases/WebKitGTK/webkit-2.24/Source/bmalloc/bmalloc/IsoDirectory.h	2019-08-04 03:23:06 UTC (rev 248230)
+++ releases/WebKitGTK/webkit-2.24/Source/bmalloc/bmalloc/IsoDirectory.h	2019-08-04 03:23:10 UTC (rev 248231)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2017-2018 Apple Inc. All rights reserved.
+ * Copyright (C) 2017-2019 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -89,7 +89,7 @@
     Bits<numPages> m_empty;
     Bits<numPages> m_committed;
     std::array<IsoPage<Config>*, numPages> m_pages;
-    unsigned m_firstEligible { 0 };
+    unsigned m_firstEligibleOrDecommitted { 0 };
     unsigned m_highWatermark { 0 };
 };
 

Modified: releases/WebKitGTK/webkit-2.24/Source/bmalloc/bmalloc/IsoDirectoryInlines.h (248230 => 248231)


--- releases/WebKitGTK/webkit-2.24/Source/bmalloc/bmalloc/IsoDirectoryInlines.h	2019-08-04 03:23:06 UTC (rev 248230)
+++ releases/WebKitGTK/webkit-2.24/Source/bmalloc/bmalloc/IsoDirectoryInlines.h	2019-08-04 03:23:10 UTC (rev 248231)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2017-2018 Apple Inc. All rights reserved.
+ * Copyright (C) 2017-2019 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -46,8 +46,9 @@
 template<typename Config, unsigned passedNumPages>
 EligibilityResult<Config> IsoDirectory<Config, passedNumPages>::takeFirstEligible()
 {
-    unsigned pageIndex = (m_eligible | ~m_committed).findBit(m_firstEligible, true);
-    m_firstEligible = pageIndex;
+    unsigned pageIndex = (m_eligible | ~m_committed).findBit(m_firstEligibleOrDecommitted, true);
+    m_firstEligibleOrDecommitted = pageIndex;
+    BASSERT((m_eligible | ~m_committed).findBit(0, true) == pageIndex);
     if (pageIndex >= numPages)
         return EligibilityKind::Full;
 
@@ -99,8 +100,8 @@
         if (verbose)
             fprintf(stderr, "%p: %p did become eligible.\n", this, page);
         m_eligible[pageIndex] = true;
-        m_firstEligible = std::min(m_firstEligible, pageIndex);
-        this->m_heap.didBecomeEligible(this);
+        m_firstEligibleOrDecommitted = std::min(m_firstEligibleOrDecommitted, pageIndex);
+        this->m_heap.didBecomeEligibleOrDecommited(this);
         return;
     case IsoPageTrigger::Empty:
         if (verbose)
@@ -124,6 +125,8 @@
     BASSERT(!!m_committed[index]);
     this->m_heap.isNoLongerFreeable(m_pages[index], IsoPageBase::pageSize);
     m_committed[index] = false;
+    m_firstEligibleOrDecommitted = std::min(m_firstEligibleOrDecommitted, index);
+    this->m_heap.didBecomeEligibleOrDecommited(this);
     this->m_heap.didDecommit(m_pages[index], IsoPageBase::pageSize);
 }
 

Modified: releases/WebKitGTK/webkit-2.24/Source/bmalloc/bmalloc/IsoHeapImpl.h (248230 => 248231)


--- releases/WebKitGTK/webkit-2.24/Source/bmalloc/bmalloc/IsoHeapImpl.h	2019-08-04 03:23:06 UTC (rev 248230)
+++ releases/WebKitGTK/webkit-2.24/Source/bmalloc/bmalloc/IsoHeapImpl.h	2019-08-04 03:23:10 UTC (rev 248231)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2017-2018 Apple Inc. All rights reserved.
+ * Copyright (C) 2017-2019 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -68,8 +68,8 @@
     EligibilityResult<Config> takeFirstEligible();
     
     // Callbacks from directory.
-    void didBecomeEligible(IsoDirectory<Config, numPagesInInlineDirectory>*);
-    void didBecomeEligible(IsoDirectory<Config, IsoDirectoryPage<Config>::numPages>*);
+    void didBecomeEligibleOrDecommited(IsoDirectory<Config, numPagesInInlineDirectory>*);
+    void didBecomeEligibleOrDecommited(IsoDirectory<Config, IsoDirectoryPage<Config>::numPages>*);
     
     void scavenge(Vector<DeferredDecommit>&) override;
     void scavengeToHighWatermark(Vector<DeferredDecommit>&) override;
@@ -120,8 +120,8 @@
     unsigned m_nextDirectoryPageIndex { 1 }; // We start at 1 so that the high water mark being zero means we've only allocated in the inline directory since the last scavenge.
     unsigned m_directoryHighWatermark { 0 };
     
-    bool m_isInlineDirectoryEligible { true };
-    IsoDirectoryPage<Config>* m_firstEligibleDirectory { nullptr };
+    bool m_isInlineDirectoryEligibleOrDecommitted { true };
+    IsoDirectoryPage<Config>* m_firstEligibleOrDecommitedDirectory { nullptr };
     
     IsoTLSAllocatorEntry<Config> m_allocator;
 };

Modified: releases/WebKitGTK/webkit-2.24/Source/bmalloc/bmalloc/IsoHeapImplInlines.h (248230 => 248231)


--- releases/WebKitGTK/webkit-2.24/Source/bmalloc/bmalloc/IsoHeapImplInlines.h	2019-08-04 03:23:06 UTC (rev 248230)
+++ releases/WebKitGTK/webkit-2.24/Source/bmalloc/bmalloc/IsoHeapImplInlines.h	2019-08-04 03:23:10 UTC (rev 248231)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2017-2018 Apple Inc. All rights reserved.
+ * Copyright (C) 2017-2019 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -42,26 +42,26 @@
 template<typename Config>
 EligibilityResult<Config> IsoHeapImpl<Config>::takeFirstEligible()
 {
-    if (m_isInlineDirectoryEligible) {
+    if (m_isInlineDirectoryEligibleOrDecommitted) {
         EligibilityResult<Config> result = m_inlineDirectory.takeFirstEligible();
         if (result.kind == EligibilityKind::Full)
-            m_isInlineDirectoryEligible = false;
+            m_isInlineDirectoryEligibleOrDecommitted = false;
         else
             return result;
     }
     
-    if (!m_firstEligibleDirectory) {
+    if (!m_firstEligibleOrDecommitedDirectory) {
         // If nothing is eligible, it can only be because we have no directories. It wouldn't be the end
-        // of the world if we broke this invariant. It would only mean that didBecomeEligible() would need
+        // of the world if we broke this invariant. It would only mean that didBecomeEligibleOrDecommited() would need
         // a null check.
         RELEASE_BASSERT(!m_headDirectory);
         RELEASE_BASSERT(!m_tailDirectory);
     }
     
-    for (; m_firstEligibleDirectory; m_firstEligibleDirectory = m_firstEligibleDirectory->next) {
-        EligibilityResult<Config> result = m_firstEligibleDirectory->payload.takeFirstEligible();
+    for (; m_firstEligibleOrDecommitedDirectory; m_firstEligibleOrDecommitedDirectory = m_firstEligibleOrDecommitedDirectory->next) {
+        EligibilityResult<Config> result = m_firstEligibleOrDecommitedDirectory->payload.takeFirstEligible();
         if (result.kind != EligibilityKind::Full) {
-            m_directoryHighWatermark = std::max(m_directoryHighWatermark, m_firstEligibleDirectory->index());
+            m_directoryHighWatermark = std::max(m_directoryHighWatermark, m_firstEligibleOrDecommitedDirectory->index());
             return result;
         }
     }
@@ -76,7 +76,7 @@
         m_tailDirectory = newDirectory;
     }
     m_directoryHighWatermark = newDirectory->index();
-    m_firstEligibleDirectory = newDirectory;
+    m_firstEligibleOrDecommitedDirectory = newDirectory;
     EligibilityResult<Config> result = newDirectory->payload.takeFirstEligible();
     RELEASE_BASSERT(result.kind != EligibilityKind::Full);
     return result;
@@ -83,19 +83,19 @@
 }
 
 template<typename Config>
-void IsoHeapImpl<Config>::didBecomeEligible(IsoDirectory<Config, numPagesInInlineDirectory>* directory)
+void IsoHeapImpl<Config>::didBecomeEligibleOrDecommited(IsoDirectory<Config, numPagesInInlineDirectory>* directory)
 {
     RELEASE_BASSERT(directory == &m_inlineDirectory);
-    m_isInlineDirectoryEligible = true;
+    m_isInlineDirectoryEligibleOrDecommitted = true;
 }
 
 template<typename Config>
-void IsoHeapImpl<Config>::didBecomeEligible(IsoDirectory<Config, IsoDirectoryPage<Config>::numPages>* directory)
+void IsoHeapImpl<Config>::didBecomeEligibleOrDecommited(IsoDirectory<Config, IsoDirectoryPage<Config>::numPages>* directory)
 {
-    RELEASE_BASSERT(m_firstEligibleDirectory);
+    RELEASE_BASSERT(m_firstEligibleOrDecommitedDirectory);
     auto* directoryPage = IsoDirectoryPage<Config>::pageFor(directory);
-    if (directoryPage->index() < m_firstEligibleDirectory->index())
-        m_firstEligibleDirectory = directoryPage;
+    if (directoryPage->index() < m_firstEligibleOrDecommitedDirectory->index())
+        m_firstEligibleOrDecommitedDirectory = directoryPage;
 }
 
 template<typename Config>

Modified: releases/WebKitGTK/webkit-2.24/Source/bmalloc/bmalloc/IsoTLS.cpp (248230 => 248231)


--- releases/WebKitGTK/webkit-2.24/Source/bmalloc/bmalloc/IsoTLS.cpp	2019-08-04 03:23:06 UTC (rev 248230)
+++ releases/WebKitGTK/webkit-2.24/Source/bmalloc/bmalloc/IsoTLS.cpp	2019-08-04 03:23:10 UTC (rev 248231)
@@ -183,11 +183,13 @@
             if (s_mallocFallbackState != MallocFallbackState::Undecided)
                 return;
 
-#if GIGACAGE_ENABLED
+#if GIGACAGE_ENABLED || BCPU(ARM64)
+#if !BCPU(ARM64)
             if (!Gigacage::shouldBeEnabled()) {
                 s_mallocFallbackState = MallocFallbackState::FallBackToMalloc;
                 return;
             }
+#endif
             const char* env = getenv("bmalloc_IsoHeap");
             if (env && (!strcasecmp(env, "false") || !strcasecmp(env, "no") || !strcmp(env, "0")))
                 s_mallocFallbackState = MallocFallbackState::FallBackToMalloc;

Modified: releases/WebKitGTK/webkit-2.24/Source/bmalloc/bmalloc/ProcessCheck.mm (248230 => 248231)


--- releases/WebKitGTK/webkit-2.24/Source/bmalloc/bmalloc/ProcessCheck.mm	2019-08-04 03:23:06 UTC (rev 248230)
+++ releases/WebKitGTK/webkit-2.24/Source/bmalloc/bmalloc/ProcessCheck.mm	2019-08-04 03:23:10 UTC (rev 248231)
@@ -46,7 +46,8 @@
     bool isOptInBinary = [processName isEqualToString:@"jsc"]
         || [processName isEqualToString:@"DumpRenderTree"]
         || [processName isEqualToString:@"wasm"]
-        || [processName hasPrefix:@"test"];
+        || [processName hasPrefix:@"test"]
+        || [processName hasPrefix:@"Test"];
 
     return isOptInBinary;
 }

Deleted: releases/WebKitGTK/webkit-2.24/Source/bmalloc/test/testbmalloc.cpp (248230 => 248231)


--- releases/WebKitGTK/webkit-2.24/Source/bmalloc/test/testbmalloc.cpp	2019-08-04 03:23:06 UTC (rev 248230)
+++ releases/WebKitGTK/webkit-2.24/Source/bmalloc/test/testbmalloc.cpp	2019-08-04 03:23:10 UTC (rev 248231)
@@ -1,336 +0,0 @@
-/*
- * Copyright (C) 2017 Apple Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
- */
-
-#include <bmalloc/bmalloc.h>
-#include <bmalloc/Environment.h>
-#include <bmalloc/IsoHeapInlines.h>
-#include <cmath>
-#include <cstdlib>
-#include <set>
-#include <vector>
-
-using namespace bmalloc;
-using namespace bmalloc::api;
-
-// We don't have a NO_RETURN_DUE_TO_EXIT, nor should we. That's ridiculous.
-static bool hiddenTruthBecauseNoReturnIsStupid() { return true; }
-
-static void usage()
-{
-    puts("Usage: testb3 [<filter>]");
-    if (hiddenTruthBecauseNoReturnIsStupid())
-        exit(1);
-}
-
-#define RUN(test) do {                          \
-        if (!shouldRun(#test))                  \
-            break;                              \
-        puts(#test "...");                      \
-        test;                                   \
-        puts(#test ": OK!");                    \
-    } while (false)
-
-// Nothing fancy for now; we just use the existing WTF assertion machinery.
-#define CHECK(x) do {                                                   \
-        if (!!(x))                                                      \
-            break;                                                      \
-        fprintf(stderr, "%s:%d: in %s: assertion %s failed.\n",         \
-            __FILE__, __LINE__, __PRETTY_FUNCTION__, #x);               \
-        abort();                                                        \
-    } while (false)
-
-static std::set<void*> toptrset(const std::vector<void*>& ptrs)
-{
-    std::set<void*> result;
-    for (void* ptr : ptrs) {
-        if (ptr)
-            result.insert(ptr);
-    }
-    return result;
-}
-
-static void assertEmptyPointerSet(const std::set<void*>& pointers)
-{
-    if (PerProcess<Environment>::get()->isDebugHeapEnabled()) {
-        printf("    skipping checks because DebugHeap.\n");
-        return;
-    }
-    if (pointers.empty())
-        return;
-    printf("Pointer set not empty!\n");
-    printf("Pointers:");
-    for (void* ptr : pointers)
-        printf(" %p", ptr);
-    printf("\n");
-    CHECK(pointers.empty());
-}
-
-template<typename heapType>
-static void assertHasObjects(IsoHeap<heapType>& heap, std::set<void*> pointers)
-{
-    if (PerProcess<Environment>::get()->isDebugHeapEnabled()) {
-        printf("    skipping checks because DebugHeap.\n");
-        return;
-    }
-    auto& impl = heap.impl();
-    std::lock_guard<Mutex> locker(impl.lock);
-    impl.forEachLiveObject(
-        [&] (void* object) {
-            pointers.erase(object);
-        });
-    assertEmptyPointerSet(pointers);
-}
-
-template<typename heapType>
-static void assertHasOnlyObjects(IsoHeap<heapType>& heap, std::set<void*> pointers)
-{
-    if (PerProcess<Environment>::get()->isDebugHeapEnabled()) {
-        printf("    skipping checks because DebugHeap.\n");
-        return;
-    }
-    auto& impl = heap.impl();
-    std::lock_guard<Mutex> locker(impl.lock);
-    impl.forEachLiveObject(
-        [&] (void* object) {
-            CHECK(pointers.erase(object) == 1);
-        });
-    assertEmptyPointerSet(pointers);
-}
-
-template<typename heapType>
-static void assertClean(IsoHeap<heapType>& heap)
-{
-    scavengeThisThread();
-    if (!PerProcess<Environment>::get()->isDebugHeapEnabled()) {
-        auto& impl = heap.impl();
-        {
-            std::lock_guard<Mutex> locker(impl.lock);
-            CHECK(!impl.numLiveObjects());
-        }
-    }
-    heap.scavenge();
-    if (!PerProcess<Environment>::get()->isDebugHeapEnabled()) {
-        auto& impl = heap.impl();
-        std::lock_guard<Mutex> locker(impl.lock);
-        CHECK(!impl.numCommittedPages());
-    }
-}
-
-static void testIsoSimple()
-{
-    static IsoHeap<double> heap;
-    void* ptr1 = heap.allocate();
-    CHECK(ptr1);
-    void* ptr2 = heap.allocate();
-    CHECK(ptr2);
-    CHECK(ptr1 != ptr2);
-    CHECK(std::abs(static_cast<char*>(ptr1) - static_cast<char*>(ptr2)) >= 8);
-    assertHasObjects(heap, {ptr1, ptr2});
-    heap.deallocate(ptr1);
-    heap.deallocate(ptr2);
-    assertClean(heap);
-}
-
-static void testIsoSimpleScavengeBeforeDealloc()
-{
-    static IsoHeap<double> heap;
-    void* ptr1 = heap.allocate();
-    CHECK(ptr1);
-    void* ptr2 = heap.allocate();
-    CHECK(ptr2);
-    CHECK(ptr1 != ptr2);
-    CHECK(std::abs(static_cast<char*>(ptr1) - static_cast<char*>(ptr2)) >= 8);
-    scavengeThisThread();
-    assertHasOnlyObjects(heap, {ptr1, ptr2});
-    heap.deallocate(ptr1);
-    heap.deallocate(ptr2);
-    assertClean(heap);
-}
-
-static void testIsoFlipFlopFragmentedPages()
-{
-    static IsoHeap<double> heap;
-    std::vector<void*> ptrs;
-    for (unsigned i = 100000; i--;) {
-        void* ptr = heap.allocate();
-        CHECK(ptr);
-        ptrs.push_back(ptr);
-    }
-    for (unsigned i = 0; i < ptrs.size(); i += 2) {
-        heap.deallocate(ptrs[i]);
-        ptrs[i] = nullptr;
-    }
-    for (unsigned i = ptrs.size() / 2; i--;)
-        ptrs.push_back(heap.allocate());
-    for (void* ptr : ptrs)
-        heap.deallocate(ptr);
-    assertClean(heap);
-}
-
-static void testIsoFlipFlopFragmentedPagesScavengeInMiddle()
-{
-    static IsoHeap<double> heap;
-    std::vector<void*> ptrs;
-    for (unsigned i = 100000; i--;) {
-        void* ptr = heap.allocate();
-        CHECK(ptr);
-        ptrs.push_back(ptr);
-    }
-    CHECK(toptrset(ptrs).size() == ptrs.size());
-    for (unsigned i = 0; i < ptrs.size(); i += 2) {
-        heap.deallocate(ptrs[i]);
-        ptrs[i] = nullptr;
-    }
-    heap.scavenge();
-    unsigned numCommittedPagesBefore;
-    auto& impl = heap.impl();
-    {
-        std::lock_guard<Mutex> locker(impl.lock);
-        numCommittedPagesBefore = impl.numCommittedPages();
-    }
-    assertHasOnlyObjects(heap, toptrset(ptrs));
-    for (unsigned i = ptrs.size() / 2; i--;)
-        ptrs.push_back(heap.allocate());
-    {
-        std::lock_guard<Mutex> locker(impl.lock);
-        CHECK(numCommittedPagesBefore == impl.numCommittedPages());
-    }
-    for (void* ptr : ptrs)
-        heap.deallocate(ptr);
-    assertClean(heap);
-}
-
-static void testIsoFlipFlopFragmentedPagesScavengeInMiddle288()
-{
-    static IsoHeap<char[288]> heap;
-    std::vector<void*> ptrs;
-    for (unsigned i = 100000; i--;) {
-        void* ptr = heap.allocate();
-        CHECK(ptr);
-        ptrs.push_back(ptr);
-    }
-    CHECK(toptrset(ptrs).size() == ptrs.size());
-    for (unsigned i = 0; i < ptrs.size(); i += 2) {
-        heap.deallocate(ptrs[i]);
-        ptrs[i] = nullptr;
-    }
-    heap.scavenge();
-    unsigned numCommittedPagesBefore;
-    auto& impl = heap.impl();
-    {
-        std::lock_guard<Mutex> locker(impl.lock);
-        numCommittedPagesBefore = impl.numCommittedPages();
-    }
-    assertHasOnlyObjects(heap, toptrset(ptrs));
-    for (unsigned i = ptrs.size() / 2; i--;)
-        ptrs.push_back(heap.allocate());
-    {
-        std::lock_guard<Mutex> locker(impl.lock);
-        CHECK(numCommittedPagesBefore == impl.numCommittedPages());
-    }
-    for (void* ptr : ptrs)
-        heap.deallocate(ptr);
-    assertClean(heap);
-}
-
-class BisoMalloced {
-    MAKE_BISO_MALLOCED(BisoMalloced);
-public:
-    BisoMalloced(int x, float y)
-        : x(x)
-        , y(y)
-    {
-    }
-    
-    int x;
-    float y;
-};
-
-MAKE_BISO_MALLOCED_IMPL(BisoMalloced);
-
-static void testBisoMalloced()
-{
-    BisoMalloced* ptr = new BisoMalloced(4, 5);
-    assertHasObjects(BisoMalloced::bisoHeap(), { ptr });
-    delete ptr;
-    assertClean(BisoMalloced::bisoHeap());
-}
-
-class BisoMallocedInline {
-    MAKE_BISO_MALLOCED_INLINE(BisoMalloced);
-public:
-    BisoMallocedInline(int x, float y)
-        : x(x)
-        , y(y)
-    {
-    }
-    
-    int x;
-    float y;
-};
-
-static void testBisoMallocedInline()
-{
-    BisoMallocedInline* ptr = new BisoMallocedInline(4, 5);
-    assertHasObjects(BisoMallocedInline::bisoHeap(), { ptr });
-    delete ptr;
-    assertClean(BisoMallocedInline::bisoHeap());
-}
-
-static void run(const char* filter)
-{
-    auto shouldRun = [&] (const char* testName) -> bool {
-        return !filter || !!strcasestr(testName, filter);
-    };
-    
-    RUN(testIsoSimple());
-    RUN(testIsoSimpleScavengeBeforeDealloc());
-    RUN(testIsoFlipFlopFragmentedPages());
-    RUN(testIsoFlipFlopFragmentedPagesScavengeInMiddle());
-    RUN(testIsoFlipFlopFragmentedPagesScavengeInMiddle288());
-    RUN(testBisoMalloced());
-    RUN(testBisoMallocedInline());
-    
-    puts("Success!");
-}
-
-int main(int argc, char** argv)
-{
-    const char* filter = nullptr;
-    switch (argc) {
-    case 1:
-        break;
-    case 2:
-        filter = argv[1];
-        break;
-    default:
-        usage();
-        break;
-    }
-    
-    run(filter);
-    return 0;
-}
-

Modified: releases/WebKitGTK/webkit-2.24/Tools/ChangeLog (248230 => 248231)


--- releases/WebKitGTK/webkit-2.24/Tools/ChangeLog	2019-08-04 03:23:06 UTC (rev 248230)
+++ releases/WebKitGTK/webkit-2.24/Tools/ChangeLog	2019-08-04 03:23:10 UTC (rev 248231)
@@ -1,3 +1,16 @@
+2019-05-30  Keith Miller  <[email protected]>
+
+        IsoHeaps don't notice uncommitted VA becoming the first eligible.
+        https://bugs.webkit.org/show_bug.cgi?id=198301
+
+        Reviewed by Yusuke Suzuki.
+
+        Move testbmalloc.cpp to TestWTF so it runs in automation.
+
+        * TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj:
+        * TestWebKitAPI/Tests/WTF/bmalloc/IsoHeap.cpp: Renamed from Source/bmalloc/test/testbmalloc.cpp.
+        (TEST):
+
 2019-05-30  Andres Gonzalez  <[email protected]>
 
         Inserting a newline in contenteditable causes two characters to be added instead of one

Copied: releases/WebKitGTK/webkit-2.24/Tools/TestWebKitAPI/Tests/WTF/bmalloc/IsoHeap.cpp (from rev 248230, releases/WebKitGTK/webkit-2.24/Source/bmalloc/test/testbmalloc.cpp) (0 => 248231)


--- releases/WebKitGTK/webkit-2.24/Tools/TestWebKitAPI/Tests/WTF/bmalloc/IsoHeap.cpp	                        (rev 0)
+++ releases/WebKitGTK/webkit-2.24/Tools/TestWebKitAPI/Tests/WTF/bmalloc/IsoHeap.cpp	2019-08-04 03:23:10 UTC (rev 248231)
@@ -0,0 +1,346 @@
+/*
+ * Copyright (C) 2017-2019 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#if !USE(SYSTEM_MALLOC)
+
+#include <bmalloc/bmalloc.h>
+#include <bmalloc/Environment.h>
+#include <bmalloc/IsoHeapInlines.h>
+
+#include <cmath>
+#include <cstdlib>
+#include <set>
+#include <vector>
+
+using namespace bmalloc;
+using namespace bmalloc::api;
+
+#define RUN(test) do {                          \
+if (!shouldRun(#test))                  \
+break;                              \
+puts(#test "...");                      \
+test;                                   \
+puts(#test ": OK!");                    \
+} while (false)
+
+// Nothing fancy for now; we just use the existing WTF assertion machinery.
+#define CHECK(x) do {                                                   \
+if (!!(x))                                                      \
+break;                                                      \
+fprintf(stderr, "%s:%d: in %s: assertion %s failed.\n",         \
+__FILE__, __LINE__, __PRETTY_FUNCTION__, #x);               \
+abort();                                                        \
+} while (false)
+
+static std::set<void*> toptrset(const std::vector<void*>& ptrs)
+{
+    std::set<void*> result;
+    for (void* ptr : ptrs) {
+        if (ptr)
+            result.insert(ptr);
+    }
+    return result;
+}
+
+static void assertEmptyPointerSet(const std::set<void*>& pointers)
+{
+    if (PerProcess<Environment>::get()->isDebugHeapEnabled()) {
+        printf("    skipping checks because DebugHeap.\n");
+        return;
+    }
+    if (pointers.empty())
+        return;
+    printf("Pointer set not empty!\n");
+    printf("Pointers:");
+    for (void* ptr : pointers)
+        printf(" %p", ptr);
+    printf("\n");
+    CHECK(pointers.empty());
+}
+
+template<typename heapType>
+static void assertHasObjects(IsoHeap<heapType>& heap, std::set<void*> pointers)
+{
+    if (PerProcess<Environment>::get()->isDebugHeapEnabled()) {
+        printf("    skipping checks because DebugHeap.\n");
+        return;
+    }
+    auto& impl = heap.impl();
+    std::lock_guard<Mutex> locker(impl.lock);
+    impl.forEachLiveObject(
+        [&] (void* object) {
+            pointers.erase(object);
+        });
+    assertEmptyPointerSet(pointers);
+}
+
+template<typename heapType>
+static void assertHasOnlyObjects(IsoHeap<heapType>& heap, std::set<void*> pointers)
+{
+    if (PerProcess<Environment>::get()->isDebugHeapEnabled()) {
+        printf("    skipping checks because DebugHeap.\n");
+        return;
+    }
+    auto& impl = heap.impl();
+    std::lock_guard<Mutex> locker(impl.lock);
+    impl.forEachLiveObject(
+        [&] (void* object) {
+            CHECK(pointers.erase(object) == 1);
+        });
+    assertEmptyPointerSet(pointers);
+}
+
+template<typename heapType>
+static void assertClean(IsoHeap<heapType>& heap)
+{
+    scavengeThisThread();
+    if (!PerProcess<Environment>::get()->isDebugHeapEnabled()) {
+        auto& impl = heap.impl();
+        {
+            std::lock_guard<Mutex> locker(impl.lock);
+            CHECK(!impl.numLiveObjects());
+        }
+    }
+    heap.scavenge();
+    if (!PerProcess<Environment>::get()->isDebugHeapEnabled()) {
+        auto& impl = heap.impl();
+        std::lock_guard<Mutex> locker(impl.lock);
+        CHECK(!impl.numCommittedPages());
+    }
+}
+
+TEST(bmalloc, IsoSimple)
+{
+    static IsoHeap<double> heap;
+    void* ptr1 = heap.allocate();
+    CHECK(ptr1);
+    void* ptr2 = heap.allocate();
+    CHECK(ptr2);
+    CHECK(ptr1 != ptr2);
+    CHECK(std::abs(static_cast<char*>(ptr1) - static_cast<char*>(ptr2)) >= 8);
+    assertHasObjects(heap, {ptr1, ptr2});
+    heap.deallocate(ptr1);
+    heap.deallocate(ptr2);
+    assertClean(heap);
+}
+
+TEST(bmalloc, IsoSimpleScavengeBeforeDealloc)
+{
+    static IsoHeap<double> heap;
+    void* ptr1 = heap.allocate();
+    CHECK(ptr1);
+    void* ptr2 = heap.allocate();
+    CHECK(ptr2);
+    CHECK(ptr1 != ptr2);
+    CHECK(std::abs(static_cast<char*>(ptr1) - static_cast<char*>(ptr2)) >= 8);
+    scavengeThisThread();
+    assertHasOnlyObjects(heap, {ptr1, ptr2});
+    heap.deallocate(ptr1);
+    heap.deallocate(ptr2);
+    assertClean(heap);
+}
+
+TEST(bmalloc, IsoFlipFlopFragmentedPages)
+{
+    static IsoHeap<double> heap;
+    std::vector<void*> ptrs;
+    for (unsigned i = 100000; i--;) {
+        void* ptr = heap.allocate();
+        CHECK(ptr);
+        ptrs.push_back(ptr);
+    }
+    for (unsigned i = 0; i < ptrs.size(); i += 2) {
+        heap.deallocate(ptrs[i]);
+        ptrs[i] = nullptr;
+    }
+    for (unsigned i = ptrs.size() / 2; i--;)
+        ptrs.push_back(heap.allocate());
+    for (void* ptr : ptrs)
+        heap.deallocate(ptr);
+    assertClean(heap);
+}
+
+TEST(bmalloc, IsoFlipFlopFragmentedPagesScavengeInMiddle)
+{
+    static IsoHeap<double> heap;
+    std::vector<void*> ptrs;
+    for (unsigned i = 100000; i--;) {
+        void* ptr = heap.allocate();
+        CHECK(ptr);
+        ptrs.push_back(ptr);
+    }
+    CHECK(toptrset(ptrs).size() == ptrs.size());
+    for (unsigned i = 0; i < ptrs.size(); i += 2) {
+        heap.deallocate(ptrs[i]);
+        ptrs[i] = nullptr;
+    }
+    heap.scavenge();
+    unsigned numCommittedPagesBefore;
+    auto& impl = heap.impl();
+    {
+        std::lock_guard<Mutex> locker(impl.lock);
+        numCommittedPagesBefore = impl.numCommittedPages();
+    }
+    assertHasOnlyObjects(heap, toptrset(ptrs));
+    for (unsigned i = ptrs.size() / 2; i--;)
+        ptrs.push_back(heap.allocate());
+    {
+        std::lock_guard<Mutex> locker(impl.lock);
+        CHECK(numCommittedPagesBefore == impl.numCommittedPages());
+    }
+    for (void* ptr : ptrs)
+        heap.deallocate(ptr);
+    assertClean(heap);
+}
+
+TEST(bmalloc, IsoFlipFlopFragmentedPagesScavengeInMiddle288)
+{
+    static IsoHeap<char[288]> heap;
+    std::vector<void*> ptrs;
+    for (unsigned i = 100000; i--;) {
+        void* ptr = heap.allocate();
+        CHECK(ptr);
+        ptrs.push_back(ptr);
+    }
+    CHECK(toptrset(ptrs).size() == ptrs.size());
+    for (unsigned i = 0; i < ptrs.size(); i += 2) {
+        heap.deallocate(ptrs[i]);
+        ptrs[i] = nullptr;
+    }
+    heap.scavenge();
+    unsigned numCommittedPagesBefore;
+    auto& impl = heap.impl();
+    {
+        std::lock_guard<Mutex> locker(impl.lock);
+        numCommittedPagesBefore = impl.numCommittedPages();
+    }
+    assertHasOnlyObjects(heap, toptrset(ptrs));
+    for (unsigned i = ptrs.size() / 2; i--;)
+        ptrs.push_back(heap.allocate());
+    {
+        std::lock_guard<Mutex> locker(impl.lock);
+        CHECK(numCommittedPagesBefore == impl.numCommittedPages());
+    }
+    for (void* ptr : ptrs)
+        heap.deallocate(ptr);
+    assertClean(heap);
+}
+
+TEST(bmalloc, IsoMallocAndFreeFast)
+{
+    static IsoHeap<char[256]> heap;
+    void* ptr = nullptr;
+    for (int i = 0; i < 1e6; ++i) {
+        ptr = heap.allocate();
+        heap.deallocate(ptr);
+    }
+    CHECK(!IsoPageBase::pageFor(ptr)->isShared());
+}
+
+class BisoMalloced {
+    MAKE_BISO_MALLOCED(BisoMalloced);
+public:
+    BisoMalloced(int x, float y)
+        : x(x)
+        , y(y)
+    {
+    }
+
+    int x;
+    float y;
+};
+
+MAKE_BISO_MALLOCED_IMPL(BisoMalloced);
+
+TEST(bmalloc, BisoMalloced)
+{
+    BisoMalloced* ptr = new BisoMalloced(4, 5);
+    assertHasObjects(BisoMalloced::bisoHeap(), { ptr });
+    delete ptr;
+    assertClean(BisoMalloced::bisoHeap());
+}
+
+class BisoMallocedInline {
+    MAKE_BISO_MALLOCED_INLINE(BisoMalloced);
+public:
+    BisoMallocedInline(int x, float y)
+        : x(x)
+        , y(y)
+    {
+    }
+
+    int x;
+    float y;
+};
+
+TEST(bmalloc, BisoMallocedInline)
+{
+    BisoMallocedInline* ptr = new BisoMallocedInline(4, 5);
+    assertHasObjects(BisoMallocedInline::bisoHeap(), { ptr });
+    delete ptr;
+    assertClean(BisoMallocedInline::bisoHeap());
+}
+
+
+TEST(bmalloc, ScavengedMemoryShouldBeReused)
+{
+    static IsoHeap<double> heap;
+
+    auto run = [] (unsigned numPagesToCommit) {
+        auto* ptr1 = heap.allocate();
+
+        std::vector<void*> ptrs;
+
+        for (unsigned i = 0; ;i++) {
+            void* ptr = heap.allocate();
+            CHECK(ptr);
+            ptrs.push_back(ptr);
+            if (heap.impl().numCommittedPages() == numPagesToCommit)
+                break;
+        }
+
+        std::set<void*> uniquedPtrs = toptrset(ptrs);
+
+        heap.deallocate(ptr1);
+        for (unsigned i = 0; i < IsoPage<decltype(heap)::Config>::numObjects - 1; i++) {
+            heap.deallocate(ptrs[i]);
+            uniquedPtrs.erase(ptrs[i]);
+        }
+
+        scavenge();
+        assertHasOnlyObjects(heap, uniquedPtrs);
+
+        // FIXME: This only seems to pass when lldb is attached but the scavenger thread isn't running...
+        // see: https://bugs.webkit.org/show_bug.cgi?id=198384
+        // auto* ptr2 = heap.allocate();
+        // CHECK(ptr1 == ptr2);
+    };
+
+    run(2);
+}
+
+#endif
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to