| /* |
| * Copyright (c) 2019-2020 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 "TestHarness.h" |
| |
| #if PAS_ENABLE_ISO && PAS_ENABLE_ISO_TEST |
| |
| #include <functional> |
| #include "iso_heap.h" |
| #include "iso_heap_config.h" |
| #include "iso_test_heap.h" |
| #include "iso_test_heap_config.h" |
| #include <mutex> |
| #include "pas_baseline_allocator_table.h" |
| #include "pas_heap.h" |
| #include "pas_random.h" |
| #include "pas_scavenger.h" |
| #include "pas_segregated_heap.h" |
| #include "pas_segregated_shared_page_directory.h" |
| #include "pas_segregated_view.h" |
| #include <set> |
| #include <thread> |
| #include <vector> |
| |
| using namespace std; |
| |
| namespace { |
| |
| class FreeOrder { |
| public: |
| FreeOrder() = default; |
| virtual ~FreeOrder() = default; |
| |
| void setCount(size_t count) const |
| { |
| m_count = count; |
| didSetCount(); |
| } |
| |
| virtual size_t getNext() const = 0; |
| |
| protected: |
| virtual void didSetCount() const { } |
| |
| mutable size_t m_count { 0 }; |
| }; |
| |
| class FreeInOrder : public FreeOrder { |
| public: |
| size_t getNext() const override |
| { |
| return m_index++; |
| } |
| |
| private: |
| mutable size_t m_index { 0 }; |
| }; |
| |
| class FreeBackwards : public FreeOrder { |
| public: |
| size_t getNext() const override |
| { |
| return --m_count; |
| } |
| }; |
| |
| class FreeRandom : public FreeOrder { |
| public: |
| size_t getNext() const override |
| { |
| PAS_ASSERT(!m_indices.empty()); |
| size_t index = pas_get_fast_random(static_cast<unsigned>(m_indices.size())); |
| size_t result = m_indices[index]; |
| m_indices[index] = m_indices.back(); |
| m_indices.pop_back(); |
| return result; |
| } |
| |
| protected: |
| void didSetCount() const override |
| { |
| for (size_t index = 0; index < m_count; ++index) |
| m_indices.push_back(index); |
| } |
| |
| mutable vector<size_t> m_indices; |
| }; |
| |
| static bool forEachSharedPageDirectoryCallbackAdaptor( |
| pas_segregated_shared_page_directory* directory, |
| void* arg) |
| { |
| function<void(pas_segregated_shared_page_directory*)>* callback = |
| static_cast<function<void(pas_segregated_shared_page_directory*)>*>(arg); |
| |
| (*callback)(directory); |
| |
| return true; |
| } |
| |
| template<typename Func> |
| void forEachSharedPageDirectory(const Func& func) |
| { |
| function<void(pas_segregated_shared_page_directory*)> callback = func; |
| pas_shared_page_directory_by_size_for_each( |
| &iso_page_caches.small_shared_page_directories, |
| forEachSharedPageDirectoryCallbackAdaptor, |
| &callback); |
| pas_shared_page_directory_by_size_for_each( |
| &iso_page_caches.medium_shared_page_directories, |
| forEachSharedPageDirectoryCallbackAdaptor, |
| &callback); |
| } |
| |
| size_t numSharedPages() |
| { |
| size_t result = 0; |
| forEachSharedPageDirectory( |
| [&] (pas_segregated_shared_page_directory* directory) { |
| result += pas_segregated_directory_size(&directory->base); |
| }); |
| return result; |
| } |
| |
| size_t numCommittedSharedPages() |
| { |
| size_t result = 0; |
| forEachSharedPageDirectory( |
| [&] (pas_segregated_shared_page_directory* directory) { |
| result += pas_segregated_directory_num_committed_views(&directory->base); |
| }); |
| return result; |
| } |
| |
| void testSimplePartialAllocations(size_t size, |
| size_t alignment, |
| pas_segregated_page_config_variant expectedMode, |
| size_t count, |
| size_t secondCount, |
| size_t numViews, |
| size_t numPages, |
| size_t secondNumViews, |
| size_t secondNumPages, |
| const FreeOrder& freeOrder) |
| { |
| static constexpr bool verbose = false; |
| |
| struct ObjectData { |
| ObjectData() = default; |
| |
| ObjectData(void* ptr, pas_segregated_view view) |
| : ptr(ptr) |
| , view(view) |
| { |
| } |
| |
| void* ptr { nullptr }; |
| pas_segregated_view view { nullptr }; |
| }; |
| |
| freeOrder.setCount(count); |
| |
| vector<ObjectData> objects; |
| set<void*> objectSet; |
| set<pas_segregated_view> viewSet; |
| set<pas_segregated_page*> pageSet; |
| set<pas_segregated_size_directory*> sizeDirectorySet; |
| |
| pas_heap_ref heap = ISO_HEAP_REF_INITIALIZER_WITH_ALIGNMENT(size, alignment); |
| |
| for (size_t index = 0; index < count; ++index) { |
| void* ptr = iso_allocate(&heap); |
| CHECK(ptr); |
| CHECK(pas_is_aligned(reinterpret_cast<uintptr_t>(ptr), alignment)); |
| pas_segregated_view view = |
| pas_segregated_view_for_object(reinterpret_cast<uintptr_t>(ptr), |
| &iso_heap_config); |
| CHECK(view); |
| if (verbose) |
| cout << "View kind: " << pas_segregated_view_kind_get_string(pas_segregated_view_get_kind(view)) << "\n"; |
| CHECK(pas_segregated_view_is_partial(view)); |
| CHECK_EQUAL(pas_segregated_view_get_page_config(view)->variant, |
| expectedMode); |
| if (verbose) |
| cout << "Allocated " << ptr << "\n"; |
| objects.push_back(ObjectData(ptr, view)); |
| CHECK(!objectSet.count(ptr)); |
| objectSet.insert(ptr); |
| viewSet.insert(view); |
| pageSet.insert(pas_segregated_view_get_page(view)); |
| pas_segregated_size_directory* sizeDirectory = pas_segregated_view_get_size_directory(view); |
| CHECK_EQUAL(sizeDirectory->object_size, size); |
| CHECK(pas_is_aligned(pas_segregated_size_directory_alignment(sizeDirectory), alignment)); |
| sizeDirectorySet.insert(sizeDirectory); |
| } |
| |
| verifyMinimumObjectDistance(objectSet, size); |
| |
| pas_heap* impl = iso_heap_ref_get_heap(&heap); |
| |
| CHECK_EQUAL(viewSet.size(), numViews); |
| CHECK_EQUAL(pageSet.size(), numPages); |
| CHECK_EQUAL(sizeDirectorySet.size(), 1); |
| CHECK_EQUAL(pas_segregated_heap_num_views(&impl->segregated_heap), numViews); |
| CHECK_EQUAL(numSharedPages(), numPages); |
| CHECK_EQUAL(numCommittedSharedPages(), numPages); |
| |
| scavenge(); |
| |
| if (verbose) { |
| cout << "After scavenging but before freeing:\n"; |
| printStatusReport(); |
| } |
| |
| CHECK_EQUAL(viewSet.size(), numViews); |
| CHECK_EQUAL(pageSet.size(), numPages); |
| CHECK_EQUAL(pas_segregated_heap_num_views(&impl->segregated_heap), numViews); |
| CHECK_EQUAL(numSharedPages(), numPages); |
| CHECK_EQUAL(numCommittedSharedPages(), numPages); |
| |
| for (size_t index = 0; index < count; ++index) { |
| void* ptr = objects[freeOrder.getNext()].ptr; |
| if (verbose) |
| cout << "Deallocating " << ptr << "\n"; |
| iso_deallocate(ptr); |
| } |
| |
| if (verbose) { |
| cout << "After freeing but before scavenging:\n"; |
| printStatusReport(); |
| } |
| |
| scavenge(); |
| |
| if (verbose) { |
| cout << "After freeing and scavenging:\n"; |
| printStatusReport(); |
| } |
| |
| CHECK_EQUAL(viewSet.size(), numViews); |
| CHECK_EQUAL(pageSet.size(), numPages); |
| CHECK_EQUAL(pas_segregated_heap_num_views(&impl->segregated_heap), numViews); |
| CHECK_EQUAL(numSharedPages(), numPages); |
| CHECK_EQUAL( |
| numCommittedSharedPages(), |
| scavengeKind == pas_scavenger_run_synchronously_now_kind ? 0 : numPages); |
| |
| for (size_t index = 0; index < secondCount; ++index) { |
| void* ptr = iso_allocate(&heap); |
| CHECK(ptr); |
| CHECK(pas_is_aligned(reinterpret_cast<uintptr_t>(ptr), alignment)); |
| if (verbose) |
| cout << "Reallocated " << ptr << "\n"; |
| pas_segregated_view view = |
| pas_segregated_view_for_object(reinterpret_cast<uintptr_t>(ptr), |
| &iso_heap_config); |
| CHECK(view); |
| CHECK(pas_segregated_view_is_partial(view)); |
| CHECK_EQUAL(pas_segregated_view_get_page_config(view)->variant, |
| expectedMode); |
| if (index < count) { |
| CHECK_EQUAL(ptr, objects[index].ptr); |
| CHECK_EQUAL(view, objects[index].view); |
| continue; |
| } |
| objectSet.insert(ptr); |
| viewSet.insert(view); |
| pageSet.insert(pas_segregated_view_get_page(view)); |
| pas_segregated_size_directory* sizeDirectory = pas_segregated_view_get_size_directory(view); |
| CHECK_EQUAL(sizeDirectory->object_size, size); |
| CHECK(pas_is_aligned(pas_segregated_size_directory_alignment(sizeDirectory), alignment)); |
| sizeDirectorySet.insert(sizeDirectory); |
| } |
| |
| verifyMinimumObjectDistance(objectSet, size); |
| |
| CHECK_EQUAL(viewSet.size(), secondNumViews); |
| CHECK_EQUAL(pageSet.size(), secondNumPages); |
| CHECK_EQUAL(sizeDirectorySet.size(), 1); |
| CHECK_EQUAL(pas_segregated_heap_num_views(&impl->segregated_heap), secondNumViews); |
| CHECK_EQUAL(numSharedPages(), secondNumPages); |
| CHECK_EQUAL(numCommittedSharedPages(), secondNumPages); |
| } |
| |
| void testFreeAroundPrimordialStop(size_t size, size_t alignment, size_t numObjectsToAllocate, bool scavengeAfterAllocating, size_t freeObjectStart, size_t freeObjectEnd, size_t repeat, size_t numAdditionalObjects) |
| { |
| static constexpr bool verbose = false; |
| |
| vector<void*> objects; |
| set<void*> objectSet; |
| |
| pas_heap_ref heap = ISO_HEAP_REF_INITIALIZER_WITH_ALIGNMENT(size, alignment); |
| |
| for (size_t index = 0; index < numObjectsToAllocate; ++index) { |
| void* ptr = iso_test_allocate(&heap); |
| if (verbose) |
| cout << "Allocated " << ptr << "\n"; |
| objects.push_back(ptr); |
| CHECK(!objectSet.count(ptr)); |
| objectSet.insert(ptr); |
| } |
| |
| while (repeat--) { |
| if (scavengeAfterAllocating) |
| scavenge(); |
| |
| for (size_t index = freeObjectStart; index < freeObjectEnd; ++index) { |
| if (verbose) |
| cout << "Deallocating " << objects[index] << "\n"; |
| iso_test_deallocate(objects[index]); |
| } |
| |
| scavenge(); |
| |
| for (size_t index = freeObjectStart; index < freeObjectEnd; ++index) { |
| void* ptr = iso_test_allocate(&heap); |
| if (verbose) |
| cout << "Reallocated " << ptr << "\n"; |
| CHECK_EQUAL(ptr, objects[index]); |
| } |
| } |
| |
| for (size_t index = numAdditionalObjects; index--;) { |
| void* ptr = iso_test_allocate(&heap); |
| CHECK(!objectSet.count(ptr)); |
| objectSet.insert(ptr); |
| } |
| |
| verifyExactObjectDistance(objectSet, size); |
| } |
| |
| void testFreeInterleavedAroundPrimordialStop(size_t size, size_t alignment, size_t numObjectsToAllocate, bool scavengeAfterAllocating, size_t freeObjectStart, size_t freeRunLength, size_t freeStrideLength, size_t repeat, size_t numAdditionalObjects) |
| { |
| static constexpr bool verbose = false; |
| |
| vector<void*> objects; |
| set<void*> objectSet; |
| |
| pas_heap_ref heap = ISO_HEAP_REF_INITIALIZER_WITH_ALIGNMENT(size, alignment); |
| |
| for (size_t index = 0; index < numObjectsToAllocate; ++index) { |
| void* ptr = iso_test_allocate(&heap); |
| if (verbose) |
| cout << "Allocated " << ptr << "\n"; |
| objects.push_back(ptr); |
| CHECK(!objectSet.count(ptr)); |
| objectSet.insert(ptr); |
| } |
| |
| while (repeat--) { |
| if (scavengeAfterAllocating) |
| scavenge(); |
| |
| for (size_t index = freeObjectStart; index < numObjectsToAllocate;) { |
| for (size_t count = freeRunLength; count-- && index < numObjectsToAllocate; ++index) { |
| if (verbose) |
| cout << "Deallocating " << objects[index] << "\n"; |
| iso_test_deallocate(objects[index]); |
| } |
| |
| index += freeStrideLength; |
| } |
| |
| scavenge(); |
| |
| for (size_t index = freeObjectStart; index < numObjectsToAllocate;) { |
| for (size_t count = freeRunLength; count-- && index < numObjectsToAllocate; ++index) { |
| void* ptr = iso_test_allocate(&heap); |
| if (verbose) |
| cout << "Reallocated " << ptr << "\n"; |
| CHECK_EQUAL(ptr, objects[index]); |
| } |
| |
| index += freeStrideLength; |
| } |
| } |
| |
| for (size_t index = numAdditionalObjects; index--;) { |
| void* ptr = iso_test_allocate(&heap); |
| CHECK(!objectSet.count(ptr)); |
| objectSet.insert(ptr); |
| } |
| |
| verifyExactObjectDistance(objectSet, size); |
| } |
| |
| struct PartialProgram { |
| PartialProgram() = default; |
| |
| PartialProgram(size_t size, |
| size_t alignment, |
| size_t numObjectsFirst, |
| size_t freeBegin, |
| size_t freeEnd, |
| size_t numObjectsSecond) |
| : size(size) |
| , alignment(alignment) |
| , numObjectsFirst(numObjectsFirst) |
| , freeBegin(freeBegin) |
| , freeEnd(freeEnd) |
| , numObjectsSecond(numObjectsSecond) |
| { |
| } |
| |
| size_t size { 0 }; |
| size_t alignment { 0 }; |
| size_t numObjectsFirst { 0 }; |
| size_t freeBegin { 0 }; |
| size_t freeEnd { 0 }; |
| size_t numObjectsSecond { 0 }; |
| }; |
| |
| void testMultiplePartialsFromDifferentHeapsPerShared(const vector<PartialProgram>& programs, |
| bool collate, |
| bool scavengeAfterAllocating, |
| size_t repeat) |
| { |
| static constexpr bool verbose = false; |
| |
| vector<pas_heap_ref*> heaps; |
| vector<vector<void*>> objects; |
| vector<set<pas_segregated_view>> viewSets; |
| set<void*> objectSet; |
| set<pas_segregated_page*> pageSet; |
| |
| for (size_t index = 0; index < programs.size(); ++index) { |
| heaps.push_back(new pas_heap_ref(ISO_HEAP_REF_INITIALIZER_WITH_ALIGNMENT( |
| programs[index].size, |
| programs[index].alignment))); |
| objects.push_back({ }); |
| viewSets.push_back({ }); |
| } |
| |
| auto allocatePrimordial = |
| [&] (size_t programIndex, size_t objectIndex) { |
| PAS_ASSERT(objectIndex == objects[programIndex].size()); |
| void* ptr = iso_test_allocate(heaps[programIndex]); |
| if (verbose) |
| cout << "Allocated ptr = " << ptr << "\n"; |
| objects[programIndex].push_back(ptr); |
| CHECK(!objectSet.count(ptr)); |
| objectSet.insert(ptr); |
| pas_segregated_view view = pas_segregated_view_for_object( |
| reinterpret_cast<uintptr_t>(ptr), &iso_test_heap_config); |
| CHECK(pas_segregated_view_is_partial(view)); |
| viewSets[programIndex].insert(view); |
| pageSet.insert(pas_segregated_view_get_page(view)); |
| }; |
| |
| auto loopOverObjects = |
| [&] (const auto& callback) { |
| if (collate) { |
| for (size_t objectIndex = 0; ; objectIndex++) { |
| bool didDoAny = false; |
| for (size_t index = 0; index < programs.size(); ++index) { |
| if (objectIndex >= programs[index].numObjectsFirst) |
| continue; |
| didDoAny = true; |
| callback(index, objectIndex); |
| } |
| if (!didDoAny) |
| break; |
| } |
| } else { |
| for (size_t index = 0; index < programs.size(); ++index) { |
| for (size_t objectIndex = 0; |
| objectIndex < programs[index].numObjectsFirst; |
| ++objectIndex) |
| callback(index, objectIndex); |
| } |
| } |
| }; |
| |
| loopOverObjects(allocatePrimordial); |
| |
| for (size_t programIndex = 0; programIndex < programs.size(); ++programIndex) |
| CHECK_EQUAL(viewSets[programIndex].size(), 1); |
| CHECK_EQUAL(pageSet.size(), 1); |
| |
| while (repeat--) { |
| if (scavengeAfterAllocating) |
| scavenge(); |
| |
| auto deallocate = |
| [&] (size_t programIndex, size_t objectIndex) { |
| if (objectIndex < programs[programIndex].freeBegin |
| || objectIndex >= programs[programIndex].freeEnd) |
| return; |
| |
| if (verbose) |
| cout << "Deallocating: " << objects[programIndex][objectIndex] << "\n"; |
| iso_test_deallocate(objects[programIndex][objectIndex]); |
| }; |
| |
| loopOverObjects(deallocate); |
| |
| scavenge(); |
| |
| auto reallocate = |
| [&] (size_t programIndex, size_t objectIndex) { |
| if (objectIndex < programs[programIndex].freeBegin |
| || objectIndex >= programs[programIndex].freeEnd) |
| return; |
| |
| void* ptr = iso_test_allocate(heaps[programIndex]); |
| if (verbose) |
| cout << "Reallocated ptr = " << ptr << "\n"; |
| CHECK_EQUAL(ptr, objects[programIndex][objectIndex]); |
| }; |
| |
| loopOverObjects(reallocate); |
| } |
| |
| for (size_t programIndex = 0; programIndex < programs.size(); ++programIndex) { |
| void* ptr = iso_test_allocate(heaps[programIndex]); |
| CHECK(!objectSet.count(ptr)); |
| objects[programIndex].push_back(ptr); |
| objectSet.insert(ptr); |
| } |
| |
| for (size_t programIndex = 0; programIndex < programs.size(); ++programIndex) { |
| for (void* object : objects[programIndex]) { |
| auto iter = objectSet.find(object); |
| CHECK(iter != objectSet.end()); |
| ++iter; |
| if (iter != objectSet.end()) { |
| CHECK_GREATER_EQUAL( |
| reinterpret_cast<uintptr_t>(*iter), |
| reinterpret_cast<uintptr_t>(object) + programs[programIndex].size); |
| } |
| } |
| } |
| } |
| |
| void addMultiplePartialsFromDifferentHeapsPerSharedTests(bool collate, |
| bool scavengeAfterAllocating) |
| { |
| ADD_TEST(testMultiplePartialsFromDifferentHeapsPerShared( |
| { |
| PartialProgram(32, 8, 17, 5, 13, 100), |
| PartialProgram(64, 64, 11, 3, 9, 100), |
| PartialProgram(48, 16, 43, 21, 34, 100) |
| }, |
| collate, scavengeAfterAllocating, 5)); |
| ADD_TEST(testMultiplePartialsFromDifferentHeapsPerShared( |
| { |
| PartialProgram(32, 8, 17, 0, 17, 100), |
| PartialProgram(64, 64, 11, 0, 11, 100), |
| PartialProgram(48, 16, 43, 0, 43, 100) |
| }, |
| collate, scavengeAfterAllocating, 5)); |
| ADD_TEST(testMultiplePartialsFromDifferentHeapsPerShared( |
| { |
| PartialProgram(32, 8, 17, 0, 1, 100), |
| PartialProgram(64, 64, 11, 0, 1, 100), |
| PartialProgram(48, 16, 43, 0, 1, 100) |
| }, |
| collate, scavengeAfterAllocating, 5)); |
| ADD_TEST(testMultiplePartialsFromDifferentHeapsPerShared( |
| { |
| PartialProgram(32, 8, 17, 16, 17, 100), |
| PartialProgram(64, 64, 11, 10, 11, 100), |
| PartialProgram(48, 16, 43, 42, 43, 100) |
| }, |
| collate, scavengeAfterAllocating, 5)); |
| ADD_TEST(testMultiplePartialsFromDifferentHeapsPerShared( |
| { |
| PartialProgram(3072, 8, 13, 5, 13, 100), |
| PartialProgram(4096, 4096, 7, 3, 6, 100), |
| PartialProgram(10752, 512, 3, 1, 3, 100) |
| }, |
| collate, scavengeAfterAllocating, 5)); |
| } |
| |
| void testMultiplePartialsFromDifferentThreadsPerShared(size_t size, |
| size_t alignment, |
| size_t numObjects, |
| size_t freeBegin, |
| size_t freeEnd, |
| size_t repeat, |
| size_t numThreads) |
| { |
| static constexpr bool verbose = false; |
| |
| pas_heap_ref heap = ISO_HEAP_REF_INITIALIZER_WITH_ALIGNMENT(size, alignment); |
| |
| vector<thread> threads; |
| vector<vector<void*>> objects; |
| set<void*> objectSet; |
| set<pas_segregated_view> viewSet; |
| mutex startLock; |
| mutex lock; |
| mutex logLock; |
| unsigned numThreadsStopped = 0; |
| |
| auto launch = |
| [&] (const auto& func) { |
| { |
| lock_guard<mutex> locker(startLock); |
| for (size_t index = 0; index < numThreads; ++index) |
| threads.push_back(thread([&, index] () { |
| { |
| lock_guard<mutex> locker(startLock); |
| } |
| |
| func(index); |
| |
| { |
| lock_guard<mutex> locker(startLock); |
| numThreadsStopped++; |
| } |
| })); |
| } |
| |
| for (thread& myThread : threads) |
| myThread.join(); |
| |
| threads.clear(); |
| |
| CHECK_EQUAL(numThreadsStopped, numThreads); |
| numThreadsStopped = 0; |
| }; |
| |
| launch( |
| [&] (size_t threadIndex) { |
| vector<void*> localObjects; |
| set<void*> localObjectSet; |
| |
| for (size_t index = 0; index < numObjects; index++) { |
| void* ptr = iso_test_allocate(&heap); |
| pas_segregated_view view = pas_segregated_view_for_object( |
| reinterpret_cast<uintptr_t>(ptr), |
| &iso_test_heap_config); |
| if (verbose) { |
| lock_guard<mutex> locker(logLock); |
| cout << "Thread " << threadIndex << " allocated " << index << ": " << ptr |
| << ", view = " << view << "\n"; |
| } |
| localObjects.push_back(ptr); |
| CHECK(!localObjectSet.count(ptr)); |
| localObjectSet.insert(ptr); |
| } |
| |
| { |
| lock_guard<mutex> locker(lock); |
| objects.push_back(localObjects); |
| for (void* object : localObjectSet) { |
| CHECK(!objectSet.count(object)); |
| objectSet.insert(object); |
| } |
| } |
| }); |
| |
| if (verbose) |
| cout << "Done with the allocation.\n"; |
| |
| verifyMinimumObjectDistance(objectSet, size); |
| |
| for (void* object : objectSet) { |
| viewSet.insert(pas_segregated_view_for_object( |
| reinterpret_cast<uintptr_t>(object), &iso_test_heap_config)); |
| } |
| |
| for (size_t repeatIndex = 0; repeatIndex < repeat; ++repeatIndex) { |
| launch( |
| [&] (size_t threadIndex) { |
| for (size_t index = freeBegin; index < freeEnd; ++index) { |
| if (verbose) { |
| lock_guard<mutex> locker(logLock); |
| cout << "Thread " << threadIndex << " freeing " << objects[threadIndex][index] << "\n"; |
| } |
| iso_test_deallocate(objects[threadIndex][index]); |
| } |
| }); |
| |
| set<void*> freedObjects; |
| for (size_t threadIndex = 0; threadIndex < numThreads; ++threadIndex) { |
| for (size_t index = freeBegin; index < freeEnd; ++index) |
| freedObjects.insert(objects[threadIndex][index]); |
| } |
| |
| // If we launch numThreads and have each allocate numObjects, will that give us what we |
| // want? |
| // |
| // No: we may get a different breakdown. Any view that is a continuation of a run of |
| // allocations by some thread could now get acquired by a different thread. That thread |
| // will use up that whole run and then it will want another run - at which point it might |
| // get an *unbroken* run. |
| // |
| // We avert this by doing the rest of the test from a single thread. |
| |
| while (freedObjects.size()) { |
| void* ptr = iso_test_allocate(&heap); |
| if (verbose) |
| cout << "Allocated " << ptr << "\n"; |
| pas_segregated_view view = pas_segregated_view_for_object( |
| reinterpret_cast<uintptr_t>(ptr), |
| &iso_test_heap_config); |
| if (verbose) |
| cout << " view = " << view << "\n"; |
| if (freedObjects.count(ptr)) |
| freedObjects.erase(ptr); |
| else { |
| // The case where we allocate an object that we hadn't allocated in the primordial |
| // run can _only_ happen on the first iteration. |
| CHECK(!repeatIndex); |
| if (!viewSet.count(view)) { |
| cout << "Still have freed objects: "; |
| bool first = true; |
| for (void* ptr : freedObjects) { |
| if (first) |
| first = false; |
| else |
| cout << ", "; |
| cout << ptr; |
| } |
| cout << "\n"; |
| } |
| CHECK(viewSet.count(view)); |
| } |
| } |
| |
| scavenge(); |
| } |
| } |
| |
| unsigned incrementalRandom() |
| { |
| static unsigned state; |
| return state++; |
| } |
| |
| unsigned zeroRandom() |
| { |
| return 0; |
| } |
| |
| void testTwoBaselinesEvictions(size_t size1, size_t size2, size_t count, |
| unsigned (*random)(), size_t numEvictions) |
| { |
| pas_heap_ref heap1 = ISO_HEAP_REF_INITIALIZER(size1); |
| pas_heap_ref heap2 = ISO_HEAP_REF_INITIALIZER(size2); |
| vector<void*> objects; |
| |
| pas_mock_fast_random = random; |
| |
| for (size_t index = 0; index < count; ++index) { |
| objects.push_back(iso_allocate(&heap1)); |
| objects.push_back(iso_allocate(&heap2)); |
| } |
| |
| CHECK_EQUAL(pas_num_baseline_allocator_evictions, numEvictions); |
| |
| scavenge(); |
| |
| for (void* object : objects) |
| iso_deallocate(object); |
| |
| scavenge(); |
| |
| for (size_t index = 0; index < count; ++index) { |
| CHECK_EQUAL(iso_allocate(&heap1), |
| objects[index * 2 + 0]); |
| CHECK_EQUAL(iso_allocate(&heap2), |
| objects[index * 2 + 1]); |
| } |
| } |
| |
| void addScavengerDependentTests() |
| { |
| DisableBitfit disableBitfit; |
| |
| { |
| ForcePartials forcePartials; |
| VerifyGranules verifyGranules; |
| { |
| ForceBaselines forceBaselines; |
| |
| // Test that we can allocate and reuse objects in partial views. |
| ADD_TEST(testSimplePartialAllocations(32, 8, pas_small_segregated_page_config_variant, 1, 1, 1, 1, 1, 1, FreeInOrder())); |
| ADD_TEST(testSimplePartialAllocations(32, 8, pas_small_segregated_page_config_variant, 100, 100, 1, 1, 1, 1, FreeInOrder())); |
| ADD_TEST(testSimplePartialAllocations(32, 8, pas_small_segregated_page_config_variant, 1000, 1000, 2, 2, 2, 2, FreeInOrder())); |
| ADD_TEST(testSimplePartialAllocations(32, 8, pas_small_segregated_page_config_variant, 100, 100, 1, 1, 1, 1, FreeBackwards())); |
| ADD_TEST(testSimplePartialAllocations(32, 8, pas_small_segregated_page_config_variant, 1000, 1000, 2, 2, 2, 2, FreeBackwards())); |
| ADD_TEST(testSimplePartialAllocations(32, 8, pas_small_segregated_page_config_variant, 100, 100, 1, 1, 1, 1, FreeRandom())); |
| ADD_TEST(testSimplePartialAllocations(32, 8, pas_small_segregated_page_config_variant, 1000, 1000, 2, 2, 2, 2, FreeRandom())); |
| |
| // Test that we can allocate and reuse objects in partial views and then allocate some more |
| // objects in additional partial views. |
| ADD_TEST(testSimplePartialAllocations(32, 8, pas_small_segregated_page_config_variant, 1, 2, 1, 1, 1, 1, FreeInOrder())); |
| ADD_TEST(testSimplePartialAllocations(32, 8, pas_small_segregated_page_config_variant, 1, 4, 1, 1, 1, 1, FreeInOrder())); |
| ADD_TEST(testSimplePartialAllocations(32, 8, pas_small_segregated_page_config_variant, 1, 100, 1, 1, 2, 1, FreeInOrder())); |
| ADD_TEST(testSimplePartialAllocations(32, 8, pas_small_segregated_page_config_variant, 1, 1000, 1, 1, 3, 2, FreeInOrder())); |
| ADD_TEST(testSimplePartialAllocations(32, 8, pas_small_segregated_page_config_variant, 100, 1000, 1, 1, 3, 2, FreeBackwards())); |
| ADD_TEST(testSimplePartialAllocations(32, 8, pas_small_segregated_page_config_variant, 1000, 2000, 2, 2, 4, 4, FreeBackwards())); |
| |
| // Test that we can allocate objects with interesting sizes and that reuse works right. |
| ADD_TEST(testSimplePartialAllocations(96, 8, pas_small_segregated_page_config_variant, 1000, 1000, 6, 6, 6, 6, FreeInOrder())); |
| ADD_TEST(testSimplePartialAllocations(112, 8, pas_small_segregated_page_config_variant, 1, 2, 1, 1, 1, 1, FreeBackwards())); |
| ADD_TEST(testSimplePartialAllocations(208, 8, pas_small_segregated_page_config_variant, 1, 100, 1, 1, 3, 2, FreeInOrder())); |
| ADD_TEST(testSimplePartialAllocations(64, 16, pas_small_segregated_page_config_variant, 100, 1000, 1, 1, 5, 4, FreeBackwards())); |
| ADD_TEST(testSimplePartialAllocations(112, 8, pas_small_segregated_page_config_variant, 1, 1, 1, 1, 1, 1, FreeInOrder())); |
| ADD_TEST(testSimplePartialAllocations(304, 8, pas_small_segregated_page_config_variant, 1, 1, 1, 1, 1, 1, FreeInOrder())); |
| ADD_TEST(testSimplePartialAllocations(944, 8, pas_small_segregated_page_config_variant, 1, 1, 1, 1, 1, 1, FreeInOrder())); |
| ADD_TEST(testSimplePartialAllocations(2688, 8, pas_small_segregated_page_config_variant, 1, 1, 1, 1, 1, 1, FreeInOrder())); |
| ADD_TEST(testSimplePartialAllocations(3072, 8, pas_medium_segregated_page_config_variant, 1, 1, 1, 1, 1, 1, FreeInOrder())); |
| ADD_TEST(testSimplePartialAllocations(3072, 8, pas_medium_segregated_page_config_variant, 10, 10, 1, 1, 1, 1, FreeInOrder())); |
| ADD_TEST(testSimplePartialAllocations(3072, 8, pas_medium_segregated_page_config_variant, 100, 100, 3, 3, 3, 3, FreeInOrder())); |
| ADD_TEST(testSimplePartialAllocations(3072, 8, pas_medium_segregated_page_config_variant, 1, 10, 1, 1, 2, 1, FreeInOrder())); |
| ADD_TEST(testSimplePartialAllocations(3072, 8, pas_medium_segregated_page_config_variant, 1, 100, 1, 1, 4, 3, FreeInOrder())); |
| ADD_TEST(testSimplePartialAllocations(4096, 8, pas_medium_segregated_page_config_variant, 1, 1, 1, 1, 1, 1, FreeInOrder())); |
| ADD_TEST(testSimplePartialAllocations(10752, 8, pas_medium_segregated_page_config_variant, 1, 1, 1, 1, 1, 1, FreeInOrder())); |
| ADD_TEST(testSimplePartialAllocations(21504, 8, pas_medium_segregated_page_config_variant, 1, 1, 1, 1, 1, 1, FreeInOrder())); |
| |
| // Test that we can allocate objects with interesting alignment. |
| ADD_TEST(testSimplePartialAllocations(32, 32, pas_small_segregated_page_config_variant, 1, 1, 1, 1, 1, 1, FreeInOrder())); |
| ADD_TEST(testSimplePartialAllocations(96, 32, pas_small_segregated_page_config_variant, 1000, 1000, 6, 6, 6, 6, FreeRandom())); |
| ADD_TEST(testSimplePartialAllocations(320, 64, pas_small_segregated_page_config_variant, 1000, 1000, 20, 20, 20, 20, FreeRandom())); |
| ADD_TEST(testSimplePartialAllocations(256, 256, pas_small_segregated_page_config_variant, 1, 1, 1, 1, 1, 1, FreeInOrder())); |
| |
| // Test freeing objects before and after we stop the primordial allocator. Note that some of |
| // these end up freeing objects after some primordials are stopped, but that's not the specific |
| // goal of these tests. |
| ADD_TEST(testFreeAroundPrimordialStop(32, 8, 10, false, 0, 5, 1, 100)); |
| ADD_TEST(testFreeAroundPrimordialStop(32, 8, 10, false, 5, 10, 1, 100)); |
| ADD_TEST(testFreeAroundPrimordialStop(32, 8, 10, false, 2, 5, 1, 100)); |
| ADD_TEST(testFreeAroundPrimordialStop(32, 8, 10, false, 2, 8, 1, 100)); |
| ADD_TEST(testFreeAroundPrimordialStop(32, 8, 10, false, 5, 8, 1, 100)); |
| ADD_TEST(testFreeAroundPrimordialStop(32, 8, 10, false, 8, 10, 1, 100)); |
| ADD_TEST(testFreeAroundPrimordialStop(32, 8, 10, false, 5, 9, 1, 100)); |
| ADD_TEST(testFreeAroundPrimordialStop(32, 8, 100, false, 99, 100, 1, 100)); |
| ADD_TEST(testFreeAroundPrimordialStop(64, 64, 10, false, 0, 5, 1, 100)); |
| ADD_TEST(testFreeAroundPrimordialStop(64, 64, 10, false, 5, 10, 1, 100)); |
| ADD_TEST(testFreeAroundPrimordialStop(64, 64, 10, false, 2, 5, 1, 100)); |
| ADD_TEST(testFreeAroundPrimordialStop(64, 64, 10, false, 2, 8, 1, 100)); |
| ADD_TEST(testFreeAroundPrimordialStop(64, 64, 10, false, 8, 10, 1, 100)); |
| ADD_TEST(testFreeAroundPrimordialStop(64, 64, 10, false, 5, 9, 1, 100)); |
| ADD_TEST(testFreeAroundPrimordialStop(4096, 64, 10, false, 0, 10, 1, 10)); |
| ADD_TEST(testFreeAroundPrimordialStop(4096, 64, 10, false, 0, 1, 1, 10)); |
| ADD_TEST(testFreeAroundPrimordialStop(4096, 64, 10, false, 0, 5, 1, 10)); |
| ADD_TEST(testFreeAroundPrimordialStop(4096, 64, 10, false, 5, 10, 1, 10)); |
| ADD_TEST(testFreeAroundPrimordialStop(4096, 64, 10, false, 8, 10, 1, 10)); |
| ADD_TEST(testFreeAroundPrimordialStop(4096, 64, 10, false, 8, 9, 1, 10)); |
| ADD_TEST(testFreeAroundPrimordialStop(4096, 64, 10, false, 9, 10, 1, 10)); |
| ADD_TEST(testFreeAroundPrimordialStop(32, 8, 10, true, 0, 5, 1, 100)); |
| ADD_TEST(testFreeAroundPrimordialStop(32, 8, 10, true, 5, 10, 1, 100)); |
| ADD_TEST(testFreeAroundPrimordialStop(32, 8, 10, true, 2, 5, 1, 100)); |
| ADD_TEST(testFreeAroundPrimordialStop(32, 8, 10, true, 2, 8, 1, 100)); |
| ADD_TEST(testFreeAroundPrimordialStop(32, 8, 10, true, 5, 8, 1, 100)); |
| ADD_TEST(testFreeAroundPrimordialStop(32, 8, 10, true, 8, 10, 1, 100)); |
| ADD_TEST(testFreeAroundPrimordialStop(32, 8, 10, true, 5, 9, 1, 100)); |
| ADD_TEST(testFreeAroundPrimordialStop(64, 64, 10, true, 0, 5, 1, 100)); |
| ADD_TEST(testFreeAroundPrimordialStop(64, 64, 10, true, 5, 10, 1, 100)); |
| ADD_TEST(testFreeAroundPrimordialStop(64, 64, 10, true, 2, 5, 1, 100)); |
| ADD_TEST(testFreeAroundPrimordialStop(64, 64, 10, true, 2, 8, 1, 100)); |
| ADD_TEST(testFreeAroundPrimordialStop(64, 64, 10, true, 8, 10, 1, 100)); |
| ADD_TEST(testFreeAroundPrimordialStop(64, 64, 10, true, 5, 9, 1, 100)); |
| ADD_TEST(testFreeAroundPrimordialStop(4096, 64, 10, true, 0, 10, 1, 10)); |
| ADD_TEST(testFreeAroundPrimordialStop(4096, 64, 10, true, 0, 1, 1, 10)); |
| ADD_TEST(testFreeAroundPrimordialStop(4096, 64, 10, true, 0, 5, 1, 10)); |
| ADD_TEST(testFreeAroundPrimordialStop(4096, 64, 10, true, 5, 10, 1, 10)); |
| ADD_TEST(testFreeAroundPrimordialStop(4096, 64, 10, true, 8, 10, 1, 10)); |
| ADD_TEST(testFreeAroundPrimordialStop(4096, 64, 10, true, 8, 9, 1, 10)); |
| ADD_TEST(testFreeAroundPrimordialStop(4096, 64, 10, true, 9, 10, 1, 10)); |
| ADD_TEST(testFreeAroundPrimordialStop(32, 8, 10, false, 0, 5, 10, 100)); |
| ADD_TEST(testFreeAroundPrimordialStop(32, 8, 10, false, 5, 10, 10, 100)); |
| ADD_TEST(testFreeAroundPrimordialStop(32, 8, 10, false, 2, 5, 10, 100)); |
| ADD_TEST(testFreeAroundPrimordialStop(32, 8, 10, false, 2, 8, 10, 100)); |
| ADD_TEST(testFreeAroundPrimordialStop(32, 8, 10, false, 5, 8, 10, 100)); |
| ADD_TEST(testFreeAroundPrimordialStop(32, 8, 10, false, 8, 10, 10, 100)); |
| ADD_TEST(testFreeAroundPrimordialStop(32, 8, 10, false, 5, 9, 10, 100)); |
| ADD_TEST(testFreeAroundPrimordialStop(32, 8, 100, false, 99, 100, 10, 100)); |
| ADD_TEST(testFreeAroundPrimordialStop(64, 64, 10, false, 0, 5, 10, 100)); |
| ADD_TEST(testFreeAroundPrimordialStop(64, 64, 10, false, 5, 10, 10, 100)); |
| ADD_TEST(testFreeAroundPrimordialStop(64, 64, 10, false, 2, 5, 10, 100)); |
| ADD_TEST(testFreeAroundPrimordialStop(64, 64, 10, false, 2, 8, 10, 100)); |
| ADD_TEST(testFreeAroundPrimordialStop(64, 64, 10, false, 8, 10, 10, 100)); |
| ADD_TEST(testFreeAroundPrimordialStop(64, 64, 10, false, 5, 9, 10, 100)); |
| ADD_TEST(testFreeAroundPrimordialStop(4096, 64, 10, false, 0, 10, 10, 10)); |
| ADD_TEST(testFreeAroundPrimordialStop(4096, 64, 10, false, 0, 1, 10, 10)); |
| ADD_TEST(testFreeAroundPrimordialStop(4096, 64, 10, false, 0, 5, 10, 10)); |
| ADD_TEST(testFreeAroundPrimordialStop(4096, 64, 10, false, 5, 10, 10, 10)); |
| ADD_TEST(testFreeAroundPrimordialStop(4096, 64, 10, false, 8, 10, 10, 10)); |
| ADD_TEST(testFreeAroundPrimordialStop(4096, 64, 10, false, 8, 9, 10, 10)); |
| ADD_TEST(testFreeAroundPrimordialStop(4096, 64, 10, false, 9, 10, 10, 10)); |
| ADD_TEST(testFreeAroundPrimordialStop(32, 8, 10, true, 0, 5, 10, 100)); |
| ADD_TEST(testFreeAroundPrimordialStop(32, 8, 10, true, 5, 10, 10, 100)); |
| ADD_TEST(testFreeAroundPrimordialStop(32, 8, 10, true, 2, 5, 10, 100)); |
| ADD_TEST(testFreeAroundPrimordialStop(32, 8, 10, true, 2, 8, 10, 100)); |
| ADD_TEST(testFreeAroundPrimordialStop(32, 8, 10, true, 5, 8, 10, 100)); |
| ADD_TEST(testFreeAroundPrimordialStop(32, 8, 10, true, 8, 10, 10, 100)); |
| ADD_TEST(testFreeAroundPrimordialStop(32, 8, 10, true, 5, 9, 10, 100)); |
| ADD_TEST(testFreeAroundPrimordialStop(64, 64, 10, true, 0, 5, 10, 100)); |
| ADD_TEST(testFreeAroundPrimordialStop(64, 64, 10, true, 5, 10, 10, 100)); |
| ADD_TEST(testFreeAroundPrimordialStop(64, 64, 10, true, 2, 5, 10, 100)); |
| ADD_TEST(testFreeAroundPrimordialStop(64, 64, 10, true, 2, 8, 10, 100)); |
| ADD_TEST(testFreeAroundPrimordialStop(64, 64, 10, true, 8, 10, 10, 100)); |
| ADD_TEST(testFreeAroundPrimordialStop(64, 64, 10, true, 5, 9, 10, 100)); |
| ADD_TEST(testFreeAroundPrimordialStop(4096, 64, 10, true, 0, 10, 10, 10)); |
| ADD_TEST(testFreeAroundPrimordialStop(4096, 64, 10, true, 0, 1, 10, 10)); |
| ADD_TEST(testFreeAroundPrimordialStop(4096, 64, 10, true, 0, 5, 10, 10)); |
| ADD_TEST(testFreeAroundPrimordialStop(4096, 64, 10, true, 5, 10, 10, 10)); |
| ADD_TEST(testFreeAroundPrimordialStop(4096, 64, 10, true, 8, 10, 10, 10)); |
| ADD_TEST(testFreeAroundPrimordialStop(4096, 64, 10, true, 8, 9, 10, 10)); |
| ADD_TEST(testFreeAroundPrimordialStop(4096, 64, 10, true, 9, 10, 10, 10)); |
| ADD_TEST(testFreeInterleavedAroundPrimordialStop(32, 32, 100, false, 0, 1, 0, 5, 100)); |
| ADD_TEST(testFreeInterleavedAroundPrimordialStop(32, 32, 100, false, 0, 1, 1, 5, 100)); |
| ADD_TEST(testFreeInterleavedAroundPrimordialStop(32, 32, 100, false, 0, 1, 2, 5, 100)); |
| ADD_TEST(testFreeInterleavedAroundPrimordialStop(32, 32, 100, false, 0, 1, 10, 5, 100)); |
| ADD_TEST(testFreeInterleavedAroundPrimordialStop(32, 32, 100, false, 1, 1, 0, 5, 100)); |
| ADD_TEST(testFreeInterleavedAroundPrimordialStop(32, 32, 100, false, 1, 1, 1, 5, 100)); |
| ADD_TEST(testFreeInterleavedAroundPrimordialStop(32, 32, 100, false, 1, 1, 2, 5, 100)); |
| ADD_TEST(testFreeInterleavedAroundPrimordialStop(32, 32, 100, false, 1, 1, 10, 5, 100)); |
| ADD_TEST(testFreeInterleavedAroundPrimordialStop(32, 32, 100, false, 10, 1, 0, 5, 100)); |
| ADD_TEST(testFreeInterleavedAroundPrimordialStop(32, 32, 100, false, 10, 1, 1, 5, 100)); |
| ADD_TEST(testFreeInterleavedAroundPrimordialStop(32, 32, 100, false, 10, 1, 2, 5, 100)); |
| ADD_TEST(testFreeInterleavedAroundPrimordialStop(32, 32, 100, false, 10, 1, 10, 5, 100)); |
| ADD_TEST(testFreeInterleavedAroundPrimordialStop(32, 32, 100, false, 0, 10, 0, 5, 100)); |
| ADD_TEST(testFreeInterleavedAroundPrimordialStop(32, 32, 100, false, 0, 10, 1, 5, 100)); |
| ADD_TEST(testFreeInterleavedAroundPrimordialStop(32, 32, 100, false, 0, 10, 2, 5, 100)); |
| ADD_TEST(testFreeInterleavedAroundPrimordialStop(32, 32, 100, false, 0, 10, 10, 5, 100)); |
| ADD_TEST(testFreeInterleavedAroundPrimordialStop(32, 32, 100, false, 1, 10, 0, 5, 100)); |
| ADD_TEST(testFreeInterleavedAroundPrimordialStop(32, 32, 100, false, 1, 10, 1, 5, 100)); |
| ADD_TEST(testFreeInterleavedAroundPrimordialStop(32, 32, 100, false, 1, 10, 2, 5, 100)); |
| ADD_TEST(testFreeInterleavedAroundPrimordialStop(32, 32, 100, false, 1, 10, 10, 5, 100)); |
| ADD_TEST(testFreeInterleavedAroundPrimordialStop(32, 32, 100, false, 10, 10, 0, 5, 100)); |
| ADD_TEST(testFreeInterleavedAroundPrimordialStop(32, 32, 100, false, 10, 10, 1, 5, 100)); |
| ADD_TEST(testFreeInterleavedAroundPrimordialStop(32, 32, 100, false, 10, 10, 2, 5, 100)); |
| ADD_TEST(testFreeInterleavedAroundPrimordialStop(32, 32, 100, false, 10, 10, 10, 5, 100)); |
| ADD_TEST(testFreeInterleavedAroundPrimordialStop(32, 32, 100, true, 0, 1, 0, 5, 100)); |
| ADD_TEST(testFreeInterleavedAroundPrimordialStop(32, 32, 100, true, 0, 1, 1, 5, 100)); |
| ADD_TEST(testFreeInterleavedAroundPrimordialStop(32, 32, 100, true, 0, 1, 2, 5, 100)); |
| ADD_TEST(testFreeInterleavedAroundPrimordialStop(32, 32, 100, true, 0, 1, 10, 5, 100)); |
| ADD_TEST(testFreeInterleavedAroundPrimordialStop(32, 32, 100, true, 1, 1, 0, 5, 100)); |
| ADD_TEST(testFreeInterleavedAroundPrimordialStop(32, 32, 100, true, 1, 1, 1, 5, 100)); |
| ADD_TEST(testFreeInterleavedAroundPrimordialStop(32, 32, 100, true, 1, 1, 2, 5, 100)); |
| ADD_TEST(testFreeInterleavedAroundPrimordialStop(32, 32, 100, true, 1, 1, 10, 5, 100)); |
| ADD_TEST(testFreeInterleavedAroundPrimordialStop(32, 32, 100, true, 10, 1, 0, 5, 100)); |
| ADD_TEST(testFreeInterleavedAroundPrimordialStop(32, 32, 100, true, 10, 1, 1, 5, 100)); |
| ADD_TEST(testFreeInterleavedAroundPrimordialStop(32, 32, 100, true, 10, 1, 2, 5, 100)); |
| ADD_TEST(testFreeInterleavedAroundPrimordialStop(32, 32, 100, true, 10, 1, 10, 5, 100)); |
| ADD_TEST(testFreeInterleavedAroundPrimordialStop(32, 32, 100, true, 0, 10, 0, 5, 100)); |
| ADD_TEST(testFreeInterleavedAroundPrimordialStop(32, 32, 100, true, 0, 10, 1, 5, 100)); |
| ADD_TEST(testFreeInterleavedAroundPrimordialStop(32, 32, 100, true, 0, 10, 2, 5, 100)); |
| ADD_TEST(testFreeInterleavedAroundPrimordialStop(32, 32, 100, true, 0, 10, 10, 5, 100)); |
| ADD_TEST(testFreeInterleavedAroundPrimordialStop(32, 32, 100, true, 1, 10, 0, 5, 100)); |
| ADD_TEST(testFreeInterleavedAroundPrimordialStop(32, 32, 100, true, 1, 10, 1, 5, 100)); |
| ADD_TEST(testFreeInterleavedAroundPrimordialStop(32, 32, 100, true, 1, 10, 2, 5, 100)); |
| ADD_TEST(testFreeInterleavedAroundPrimordialStop(32, 32, 100, true, 1, 10, 10, 5, 100)); |
| ADD_TEST(testFreeInterleavedAroundPrimordialStop(32, 32, 100, true, 10, 10, 0, 5, 100)); |
| ADD_TEST(testFreeInterleavedAroundPrimordialStop(32, 32, 100, true, 10, 10, 1, 5, 100)); |
| ADD_TEST(testFreeInterleavedAroundPrimordialStop(32, 32, 100, true, 10, 10, 2, 5, 100)); |
| ADD_TEST(testFreeInterleavedAroundPrimordialStop(32, 32, 100, true, 10, 10, 10, 5, 100)); |
| ADD_TEST(testFreeInterleavedAroundPrimordialStop(4096, 4096, 20, false, 0, 1, 0, 5, 20)); |
| ADD_TEST(testFreeInterleavedAroundPrimordialStop(4096, 4096, 20, false, 0, 1, 1, 5, 20)); |
| ADD_TEST(testFreeInterleavedAroundPrimordialStop(4096, 4096, 20, false, 0, 1, 2, 5, 20)); |
| ADD_TEST(testFreeInterleavedAroundPrimordialStop(4096, 4096, 20, false, 0, 1, 5, 5, 20)); |
| ADD_TEST(testFreeInterleavedAroundPrimordialStop(4096, 4096, 20, false, 0, 2, 0, 5, 20)); |
| ADD_TEST(testFreeInterleavedAroundPrimordialStop(4096, 4096, 20, false, 0, 2, 1, 5, 20)); |
| ADD_TEST(testFreeInterleavedAroundPrimordialStop(4096, 4096, 20, false, 0, 2, 2, 5, 20)); |
| ADD_TEST(testFreeInterleavedAroundPrimordialStop(4096, 4096, 20, false, 0, 2, 5, 5, 20)); |
| ADD_TEST(testFreeInterleavedAroundPrimordialStop(4096, 4096, 20, false, 0, 3, 0, 5, 20)); |
| ADD_TEST(testFreeInterleavedAroundPrimordialStop(4096, 4096, 20, false, 0, 3, 1, 5, 20)); |
| ADD_TEST(testFreeInterleavedAroundPrimordialStop(4096, 4096, 20, false, 0, 3, 2, 5, 20)); |
| ADD_TEST(testFreeInterleavedAroundPrimordialStop(4096, 4096, 20, false, 0, 3, 5, 5, 20)); |
| ADD_TEST(testFreeInterleavedAroundPrimordialStop(4096, 4096, 20, false, 0, 4, 0, 5, 20)); |
| ADD_TEST(testFreeInterleavedAroundPrimordialStop(4096, 4096, 20, false, 0, 4, 1, 5, 20)); |
| ADD_TEST(testFreeInterleavedAroundPrimordialStop(4096, 4096, 20, false, 0, 4, 2, 5, 20)); |
| ADD_TEST(testFreeInterleavedAroundPrimordialStop(4096, 4096, 20, false, 0, 4, 5, 5, 20)); |
| ADD_TEST(testFreeInterleavedAroundPrimordialStop(4096, 4096, 20, false, 1, 1, 0, 5, 20)); |
| ADD_TEST(testFreeInterleavedAroundPrimordialStop(4096, 4096, 20, false, 1, 1, 1, 5, 20)); |
| ADD_TEST(testFreeInterleavedAroundPrimordialStop(4096, 4096, 20, false, 1, 1, 2, 5, 20)); |
| ADD_TEST(testFreeInterleavedAroundPrimordialStop(4096, 4096, 20, false, 1, 1, 5, 5, 20)); |
| ADD_TEST(testFreeInterleavedAroundPrimordialStop(4096, 4096, 20, false, 1, 2, 0, 5, 20)); |
| ADD_TEST(testFreeInterleavedAroundPrimordialStop(4096, 4096, 20, false, 1, 2, 1, 5, 20)); |
| ADD_TEST(testFreeInterleavedAroundPrimordialStop(4096, 4096, 20, false, 1, 2, 2, 5, 20)); |
| ADD_TEST(testFreeInterleavedAroundPrimordialStop(4096, 4096, 20, false, 1, 2, 5, 5, 20)); |
| ADD_TEST(testFreeInterleavedAroundPrimordialStop(4096, 4096, 20, false, 1, 3, 0, 5, 20)); |
| ADD_TEST(testFreeInterleavedAroundPrimordialStop(4096, 4096, 20, false, 1, 3, 1, 5, 20)); |
| ADD_TEST(testFreeInterleavedAroundPrimordialStop(4096, 4096, 20, false, 1, 3, 2, 5, 20)); |
| ADD_TEST(testFreeInterleavedAroundPrimordialStop(4096, 4096, 20, false, 1, 3, 5, 5, 20)); |
| ADD_TEST(testFreeInterleavedAroundPrimordialStop(4096, 4096, 20, false, 1, 4, 0, 5, 20)); |
| ADD_TEST(testFreeInterleavedAroundPrimordialStop(4096, 4096, 20, false, 1, 4, 1, 5, 20)); |
| ADD_TEST(testFreeInterleavedAroundPrimordialStop(4096, 4096, 20, false, 1, 4, 2, 5, 20)); |
| ADD_TEST(testFreeInterleavedAroundPrimordialStop(4096, 4096, 20, false, 1, 4, 5, 5, 20)); |
| ADD_TEST(testFreeInterleavedAroundPrimordialStop(4096, 4096, 20, true, 0, 1, 0, 5, 20)); |
| ADD_TEST(testFreeInterleavedAroundPrimordialStop(4096, 4096, 20, true, 0, 1, 1, 5, 20)); |
| ADD_TEST(testFreeInterleavedAroundPrimordialStop(4096, 4096, 20, true, 0, 1, 2, 5, 20)); |
| ADD_TEST(testFreeInterleavedAroundPrimordialStop(4096, 4096, 20, true, 0, 1, 5, 5, 20)); |
| ADD_TEST(testFreeInterleavedAroundPrimordialStop(4096, 4096, 20, true, 0, 2, 0, 5, 20)); |
| ADD_TEST(testFreeInterleavedAroundPrimordialStop(4096, 4096, 20, true, 0, 2, 1, 5, 20)); |
| ADD_TEST(testFreeInterleavedAroundPrimordialStop(4096, 4096, 20, true, 0, 2, 2, 5, 20)); |
| ADD_TEST(testFreeInterleavedAroundPrimordialStop(4096, 4096, 20, true, 0, 2, 5, 5, 20)); |
| ADD_TEST(testFreeInterleavedAroundPrimordialStop(4096, 4096, 20, true, 0, 3, 0, 5, 20)); |
| ADD_TEST(testFreeInterleavedAroundPrimordialStop(4096, 4096, 20, true, 0, 3, 1, 5, 20)); |
| ADD_TEST(testFreeInterleavedAroundPrimordialStop(4096, 4096, 20, true, 0, 3, 2, 5, 20)); |
| ADD_TEST(testFreeInterleavedAroundPrimordialStop(4096, 4096, 20, true, 0, 3, 5, 5, 20)); |
| ADD_TEST(testFreeInterleavedAroundPrimordialStop(4096, 4096, 20, true, 0, 4, 0, 5, 20)); |
| ADD_TEST(testFreeInterleavedAroundPrimordialStop(4096, 4096, 20, true, 0, 4, 1, 5, 20)); |
| ADD_TEST(testFreeInterleavedAroundPrimordialStop(4096, 4096, 20, true, 0, 4, 2, 5, 20)); |
| ADD_TEST(testFreeInterleavedAroundPrimordialStop(4096, 4096, 20, true, 0, 4, 5, 5, 20)); |
| ADD_TEST(testFreeInterleavedAroundPrimordialStop(4096, 4096, 20, true, 1, 1, 0, 5, 20)); |
| ADD_TEST(testFreeInterleavedAroundPrimordialStop(4096, 4096, 20, true, 1, 1, 1, 5, 20)); |
| ADD_TEST(testFreeInterleavedAroundPrimordialStop(4096, 4096, 20, true, 1, 1, 2, 5, 20)); |
| ADD_TEST(testFreeInterleavedAroundPrimordialStop(4096, 4096, 20, true, 1, 1, 5, 5, 20)); |
| ADD_TEST(testFreeInterleavedAroundPrimordialStop(4096, 4096, 20, true, 1, 2, 0, 5, 20)); |
| ADD_TEST(testFreeInterleavedAroundPrimordialStop(4096, 4096, 20, true, 1, 2, 1, 5, 20)); |
| ADD_TEST(testFreeInterleavedAroundPrimordialStop(4096, 4096, 20, true, 1, 2, 2, 5, 20)); |
| ADD_TEST(testFreeInterleavedAroundPrimordialStop(4096, 4096, 20, true, 1, 2, 5, 5, 20)); |
| ADD_TEST(testFreeInterleavedAroundPrimordialStop(4096, 4096, 20, true, 1, 3, 0, 5, 20)); |
| ADD_TEST(testFreeInterleavedAroundPrimordialStop(4096, 4096, 20, true, 1, 3, 1, 5, 20)); |
| ADD_TEST(testFreeInterleavedAroundPrimordialStop(4096, 4096, 20, true, 1, 3, 2, 5, 20)); |
| ADD_TEST(testFreeInterleavedAroundPrimordialStop(4096, 4096, 20, true, 1, 3, 5, 5, 20)); |
| ADD_TEST(testFreeInterleavedAroundPrimordialStop(4096, 4096, 20, true, 1, 4, 0, 5, 20)); |
| ADD_TEST(testFreeInterleavedAroundPrimordialStop(4096, 4096, 20, true, 1, 4, 1, 5, 20)); |
| ADD_TEST(testFreeInterleavedAroundPrimordialStop(4096, 4096, 20, true, 1, 4, 2, 5, 20)); |
| ADD_TEST(testFreeInterleavedAroundPrimordialStop(4096, 4096, 20, true, 1, 4, 5, 5, 20)); |
| } |
| |
| { |
| ForceTLAs forceTLAs; |
| |
| ADD_GROUP(addMultiplePartialsFromDifferentHeapsPerSharedTests(false, false)); |
| ADD_GROUP(addMultiplePartialsFromDifferentHeapsPerSharedTests(false, true)); |
| ADD_GROUP(addMultiplePartialsFromDifferentHeapsPerSharedTests(true, false)); |
| ADD_GROUP(addMultiplePartialsFromDifferentHeapsPerSharedTests(true, true)); |
| |
| for (unsigned count = 10; count--;) { |
| ADD_TEST(testMultiplePartialsFromDifferentThreadsPerShared(32, 8, 50, 0, 20, 10, 10)); |
| ADD_TEST(testMultiplePartialsFromDifferentThreadsPerShared(32, 8, 50, 0, 50, 10, 10)); |
| ADD_TEST(testMultiplePartialsFromDifferentThreadsPerShared(32, 8, 50, 40, 50, 10, 10)); |
| ADD_TEST(testMultiplePartialsFromDifferentThreadsPerShared(32, 8, 50, 0, 20, 10, 50)); |
| ADD_TEST(testMultiplePartialsFromDifferentThreadsPerShared(32, 8, 50, 0, 50, 10, 50)); |
| ADD_TEST(testMultiplePartialsFromDifferentThreadsPerShared(32, 8, 50, 40, 50, 10, 50)); |
| } |
| } |
| } |
| |
| { |
| ForceBaselines forceBaselines; |
| ADD_TEST(testTwoBaselinesEvictions(32, 64, 10000, incrementalRandom, 0)); |
| ADD_TEST(testTwoBaselinesEvictions(32, 64, 1000, zeroRandom, 1999)); |
| } |
| } |
| |
| } // anonymous namespace |
| |
| #endif // PAS_ENABLE_ISO && PAS_ENABLE_ISO_TEST |
| |
| void addIsoHeapPartialAndBaselineTests() |
| { |
| TestScope commonSharedPageDirectories( |
| "common-shared-page-directories", |
| [] { |
| iso_page_caches.small_shared_page_directories.log_shift = 31; |
| iso_page_caches.medium_shared_page_directories.log_shift = 31; |
| iso_test_page_caches.small_shared_page_directories.log_shift = 31; |
| iso_test_page_caches.medium_shared_page_directories.log_shift = 31; |
| }); |
| |
| SuspendScavengerScope suspendScavenger; |
| |
| #if PAS_ENABLE_ISO && PAS_ENABLE_ISO_TEST |
| { |
| RunScavengerFully runScavengerFully; |
| addScavengerDependentTests(); |
| } |
| { |
| RunScavengerOnNonRemoteCaches runScavengerOnNonRemoteCaches; |
| addScavengerDependentTests(); |
| } |
| #endif // PAS_ENABLE_ISO && PAS_ENABLE_ISO_TEST |
| } |