* Copyright (c) 2025 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "ecmascript/cross_vm/unified_gc/unified_gc.h"
#include "ecmascript/cross_vm/unified_gc/unified_gc_marker.h"
#include "ecmascript/mem/concurrent_marker.h"
#include "ecmascript/mem/verification.h"
#include "ecmascript/mem/heap.h"
namespace panda::ecmascript {
#ifdef PANDA_JS_ETS_HYBRID_MODE
std::atomic<bool> UnifiedGC::isInterruptUnifiedGC_ {false};
#endif
void UnifiedGC::RunPhases()
{
Runtime::GetInstance()->GCIterateThreadList([](JSThread *thread) {
Heap *heap = const_cast<Heap *>(thread->GetEcmaVM()->GetHeap());
if (heap->DaemonCheckOngoingConcurrentMarking()) {
LOG_GC(DEBUG) << "UnifiedGC after ConcurrentMarking";
heap->GetConcurrentMarker()->Reset();
}
});
Initialize();
Mark();
Finish();
}
void UnifiedGC::Initialize()
{
ECMA_BYTRACE_NAME(HITRACE_LEVEL_COMMERCIAL, HITRACE_TAG_ARK, "UnifiedGC::Initialize", "");
Runtime::GetInstance()->GCIterateThreadList([](JSThread *thread) {
Heap *heap = const_cast<Heap *>(thread->GetEcmaVM()->GetHeap());
TRACE_GC(GCStats::Scope::ScopeId::Initialize, heap->GetEcmaGCStats());
heap->GetUnifiedGCMarker()->Initialize();
});
}
void UnifiedGC::Mark()
{
ECMA_BYTRACE_NAME(HITRACE_LEVEL_COMMERCIAL, HITRACE_TAG_ARK, "UnifiedGC::Mark", "");
Runtime::GetInstance()->GCIterateThreadList([](JSThread *thread) {
Heap *heap = const_cast<Heap *>(thread->GetEcmaVM()->GetHeap());
TRACE_GC(GCStats::Scope::ScopeId::Mark, heap->GetEcmaGCStats());
heap->GetUnifiedGCMarker()->InitialMark(DAEMON_THREAD_INDEX);
});
Runtime::GetInstance()->GCIterateThreadList([](JSThread *thread) {
Heap *heap = const_cast<Heap *>(thread->GetEcmaVM()->GetHeap());
heap->GetUnifiedGCMarker()->ProcessMarkStack(DAEMON_THREAD_INDEX);
});
#ifdef PANDA_JS_ETS_HYBRID_MODE
static const auto noMarkTaskCheck = []() -> bool {
bool noMarkTask = true;
Runtime::GetInstance()->GCIterateThreadList([&noMarkTask](JSThread *thread) {
Heap *heap = const_cast<Heap *>(thread->GetEcmaVM()->GetHeap());
if (heap->GetTotalMarkTaskCount() != 0) {
noMarkTask = false;
return;
}
});
return noMarkTask;
};
while (!stsVMInterface_->WaitForConcurrentMark(noMarkTaskCheck)) {
Runtime::GetInstance()->GCIterateThreadList([](JSThread *thread) {
Heap *heap = const_cast<Heap *>(thread->GetEcmaVM()->GetHeap());
heap->WaitAllMarkTaskFinished();
});
}
stsVMInterface_->RemarkStartBarrier();
while (!stsVMInterface_->WaitForRemark(noMarkTaskCheck)) {
Runtime::GetInstance()->GCIterateThreadList([](JSThread *thread) {
Heap *heap = const_cast<Heap *>(thread->GetEcmaVM()->GetHeap());
heap->WaitAllMarkTaskFinished();
});
}
#endif
}
void UnifiedGC::Finish()
{
ECMA_BYTRACE_NAME(HITRACE_LEVEL_COMMERCIAL, HITRACE_TAG_ARK, "UnifiedGC::Finish", "");
DaemonThread::GetInstance()->FinishRunningTask();
Runtime::GetInstance()->GCIterateThreadList([](JSThread *thread) {
Heap *heap = const_cast<Heap *>(thread->GetEcmaVM()->GetHeap());
TRACE_GC(GCStats::Scope::ScopeId::Finish, heap->GetEcmaGCStats());
heap->GetUnifiedGCMarker()->Finish();
});
}
}