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