[K/N] Fix custom allocator ^KT-55364
* Make CustomFinalizerProcessor mirror the existing FinalizerProcessor * Fix Heap::PrepareForGC in custom allocator Merge-request: KOTLIN-MR-616 Merged-by: Alexander Shabalin <alexander.shabalin@jetbrains.com>
This commit is contained in:
committed by
Space
parent
f8f63f4573
commit
dd9b0f9fa5
@@ -30,30 +30,30 @@ void CustomFinalizerProcessor::StartFinalizerThreadIfNone() noexcept {
|
|||||||
initialized_ = true;
|
initialized_ = true;
|
||||||
}
|
}
|
||||||
initializedCondVar_.notify_all();
|
initializedCondVar_.notify_all();
|
||||||
|
int64_t finalizersEpoch = 0;
|
||||||
while (true) {
|
while (true) {
|
||||||
std::unique_lock lock(finalizerQueueMutex_);
|
std::unique_lock lock(finalizerQueueMutex_);
|
||||||
finalizerQueueCondVar_.wait(lock, [this] {
|
finalizerQueueCondVar_.wait(lock, [this, &finalizersEpoch] {
|
||||||
return finalizedEpoch_ != scheduledEpoch_ || shutdownFlag_;
|
return !finalizerQueue_.isEmpty() || finalizerQueueEpoch_ != finalizersEpoch || shutdownFlag_;
|
||||||
});
|
});
|
||||||
if (finalizedEpoch_ == scheduledEpoch_) {
|
if (finalizerQueue_.isEmpty() && finalizerQueueEpoch_ == finalizersEpoch) {
|
||||||
|
newTasksAllowed_ = false;
|
||||||
RuntimeAssert(shutdownFlag_, "Nothing to do, but no shutdownFlag_ is set on wakeup");
|
RuntimeAssert(shutdownFlag_, "Nothing to do, but no shutdownFlag_ is set on wakeup");
|
||||||
RuntimeAssert(finalizerQueue_.isEmpty(), "Finalizer queue should be empty when killing finalizer thread");
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
int64_t queueEpoch = scheduledEpoch_;
|
auto queue = std::move(finalizerQueue_);
|
||||||
Queue finalizerQueue = std::move(finalizerQueue_);
|
finalizersEpoch = finalizerQueueEpoch_;
|
||||||
lock.unlock();
|
lock.unlock();
|
||||||
ThreadStateGuard guard(ThreadState::kRunnable);
|
{
|
||||||
ExtraObjectCell* cell;
|
ThreadStateGuard guard(ThreadState::kRunnable);
|
||||||
while ((cell = finalizerQueue.Pop())) {
|
while (auto* cell = queue.Pop()) {
|
||||||
auto* extraObject = cell->Data();
|
auto* extraObject = cell->Data();
|
||||||
auto* baseObject = extraObject->GetBaseObject();
|
auto* baseObject = extraObject->GetBaseObject();
|
||||||
RunFinalizers(baseObject);
|
RunFinalizers(baseObject);
|
||||||
extraObject->setFlag(mm::ExtraObjectData::FLAGS_FINALIZED);
|
extraObject->setFlag(mm::ExtraObjectData::FLAGS_FINALIZED);
|
||||||
}
|
}
|
||||||
while (finalizedEpoch_ != queueEpoch) {
|
|
||||||
epochDoneCallback_(++finalizedEpoch_);
|
|
||||||
}
|
}
|
||||||
|
epochDoneCallback_(finalizersEpoch);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
std::unique_lock guard(initializedMutex_);
|
std::unique_lock guard(initializedMutex_);
|
||||||
@@ -75,14 +75,20 @@ void CustomFinalizerProcessor::StopFinalizerThread() noexcept {
|
|||||||
shutdownFlag_ = false;
|
shutdownFlag_ = false;
|
||||||
RuntimeAssert(finalizerQueue_.isEmpty(), "Finalizer queue should be empty when killing finalizer thread");
|
RuntimeAssert(finalizerQueue_.isEmpty(), "Finalizer queue should be empty when killing finalizer thread");
|
||||||
std::unique_lock guard(finalizerQueueMutex_);
|
std::unique_lock guard(finalizerQueueMutex_);
|
||||||
|
newTasksAllowed_ = true;
|
||||||
finalizerQueueCondVar_.notify_all();
|
finalizerQueueCondVar_.notify_all();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CustomFinalizerProcessor::ScheduleTasks(Queue&& tasks, int64_t epoch) noexcept {
|
void CustomFinalizerProcessor::ScheduleTasks(Queue&& tasks, int64_t epoch) noexcept {
|
||||||
std::unique_lock guard(finalizerQueueMutex_);
|
std::unique_lock guard(finalizerQueueMutex_);
|
||||||
|
if (tasks.isEmpty() && !IsRunning()) {
|
||||||
|
epochDoneCallback_(epoch);
|
||||||
|
return;
|
||||||
|
}
|
||||||
StartFinalizerThreadIfNone();
|
StartFinalizerThreadIfNone();
|
||||||
|
finalizerQueueCondVar_.wait(guard, [this] { return newTasksAllowed_; });
|
||||||
finalizerQueue_.TransferAllFrom(std::move(tasks));
|
finalizerQueue_.TransferAllFrom(std::move(tasks));
|
||||||
scheduledEpoch_ = epoch;
|
finalizerQueueEpoch_ = epoch;
|
||||||
finalizerQueueCondVar_.notify_all();
|
finalizerQueueCondVar_.notify_all();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -32,9 +32,9 @@ private:
|
|||||||
std::condition_variable finalizerQueueCondVar_;
|
std::condition_variable finalizerQueueCondVar_;
|
||||||
std::mutex finalizerQueueMutex_;
|
std::mutex finalizerQueueMutex_;
|
||||||
std::function<void(int64_t)> epochDoneCallback_;
|
std::function<void(int64_t)> epochDoneCallback_;
|
||||||
int64_t scheduledEpoch_ = 0;
|
int64_t finalizerQueueEpoch_ = 0;
|
||||||
int64_t finalizedEpoch_ = 0;
|
|
||||||
bool shutdownFlag_ = false;
|
bool shutdownFlag_ = false;
|
||||||
|
bool newTasksAllowed_ = true;
|
||||||
|
|
||||||
std::mutex initializedMutex_;
|
std::mutex initializedMutex_;
|
||||||
std::condition_variable initializedCondVar_;
|
std::condition_variable initializedCondVar_;
|
||||||
|
|||||||
@@ -53,6 +53,7 @@ bool SweepExtraObject(ExtraObjectCell* extraObjectCell, AtomicStack<ExtraObjectC
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (IsAlive(baseObject)) {
|
if (IsAlive(baseObject)) {
|
||||||
|
CustomAllocDebug("SweepIsCollectable(%p): base object (%p) is alive", extraObject, baseObject);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
extraObject->ClearWeakReferenceCounter();
|
extraObject->ClearWeakReferenceCounter();
|
||||||
|
|||||||
@@ -37,6 +37,7 @@ void Heap::PrepareForGC() noexcept {
|
|||||||
for (int blockSize = 0; blockSize <= SMALL_PAGE_MAX_BLOCK_SIZE; ++blockSize) {
|
for (int blockSize = 0; blockSize <= SMALL_PAGE_MAX_BLOCK_SIZE; ++blockSize) {
|
||||||
smallPages_[blockSize].PrepareForGC();
|
smallPages_[blockSize].PrepareForGC();
|
||||||
}
|
}
|
||||||
|
usedExtraObjectPages_.TransferAllFrom(std::move(extraObjectPages_));
|
||||||
}
|
}
|
||||||
|
|
||||||
void Heap::Sweep() noexcept {
|
void Heap::Sweep() noexcept {
|
||||||
|
|||||||
Reference in New Issue
Block a user