Enable custom allocator with -Xallocator=custom. If the gc is cms (default): * a patched version of the memory manager is used that does not build a list of allocated objects. * a patched version of the cms is used that defers to the allocator for sweeping. Otherwise, a warning is printed, and the allocator is used using the standard api. Design doc: https://docs.google.com/document/d/15xMp-nE-DWL8OrtOc8DoXB80AHUphFICEGjj5K0aNFc Co-authored-by: Troels Lund <troels@google.com> Merge-request: KOTLIN-MR-546 Merged-by: Alexander Shabalin <alexander.shabalin@jetbrains.com>
82 lines
1.9 KiB
C++
82 lines
1.9 KiB
C++
/*
|
|
* Copyright 2022 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
|
* that can be found in the LICENSE file.
|
|
*/
|
|
|
|
#ifndef CUSTOM_ALLOC_CPP_PAGESTORE_HPP_
|
|
#define CUSTOM_ALLOC_CPP_PAGESTORE_HPP_
|
|
|
|
#include <atomic>
|
|
|
|
#include "AtomicStack.hpp"
|
|
|
|
namespace kotlin::alloc {
|
|
|
|
template <class T>
|
|
class PageStore {
|
|
public:
|
|
void PrepareForGC() noexcept {
|
|
unswept_.TransferAllFrom(ready_);
|
|
unswept_.TransferAllFrom(used_);
|
|
T* page;
|
|
while ((page = empty_.Pop())) page->Destroy();
|
|
}
|
|
|
|
T* SweepAndFreeEmpty(AtomicStack<T>& from, AtomicStack<T>& to) noexcept {
|
|
T* page;
|
|
while ((page = from.Pop())) {
|
|
if (!page->Sweep()) {
|
|
empty_.Push(page);
|
|
} else {
|
|
to.Push(page);
|
|
return page;
|
|
}
|
|
}
|
|
return nullptr;
|
|
}
|
|
|
|
void Sweep() noexcept {
|
|
while (SweepAndFreeEmpty(unswept_, ready_)) {}
|
|
}
|
|
|
|
T* GetPage(uint32_t cellCount) noexcept {
|
|
T* page;
|
|
if ((page = SweepAndFreeEmpty(unswept_, used_))) {
|
|
return page;
|
|
}
|
|
if ((page = ready_.Pop())) {
|
|
used_.Push(page);
|
|
return page;
|
|
}
|
|
if ((page = empty_.Pop())) {
|
|
used_.Push(page);
|
|
return page;
|
|
}
|
|
return NewPage(cellCount);
|
|
}
|
|
|
|
T* NewPage(uint64_t cellCount) noexcept {
|
|
T* page = T::Create(cellCount);
|
|
used_.Push(page);
|
|
return page;
|
|
}
|
|
|
|
~PageStore() noexcept {
|
|
T* page;
|
|
while ((page = empty_.Pop())) page->Destroy();
|
|
while ((page = ready_.Pop())) page->Destroy();
|
|
while ((page = used_.Pop())) page->Destroy();
|
|
while ((page = unswept_.Pop())) page->Destroy();
|
|
}
|
|
|
|
private:
|
|
AtomicStack<T> empty_;
|
|
AtomicStack<T> ready_;
|
|
AtomicStack<T> used_;
|
|
AtomicStack<T> unswept_;
|
|
};
|
|
|
|
} // namespace kotlin::alloc
|
|
|
|
#endif
|