support HintGC native api

Issue: https://gitee.com/openharmony/arkcompiler_ets_runtime/issues/IATEO7?from=project-issue

Signed-off-by: xiongluo <xiongluo@huawei.com>
Change-Id: Ib4b0bfef387c161d29fe5a4f3ed25b49cb6ba382
This commit is contained in:
xiongluo 2024-09-24 22:49:59 +08:00
parent 9b56609688
commit d50c327b8a
12 changed files with 284 additions and 55 deletions

View File

@ -226,8 +226,22 @@ JSTaggedValue BuiltinsArkTools::ForceFullGC(EcmaRuntimeCallInfo *info)
JSTaggedValue BuiltinsArkTools::HintGC(EcmaRuntimeCallInfo *info)
{
ASSERT(info);
return JSTaggedValue(const_cast<Heap *>(info->GetThread()->GetEcmaVM()->GetHeap())->
CheckAndTriggerHintGC());
JSThread *thread = info->GetThread();
int value = 0;
if (info->GetArgsNumber() == 1) {
value = JSTaggedValue::ToInt8(thread, GetCallArg(info, 0));
if (value < static_cast<int>(MemoryReduceDegree::LOW)
|| value > static_cast<int>(MemoryReduceDegree::HIGH)) {
CString errorMsg = "ArkTools.hintGC parameter value should be larger than "
+ ToCString(static_cast<int>(MemoryReduceDegree::LOW))
+ "and less than "
+ ToCString(static_cast<int>(MemoryReduceDegree::HIGH));
THROW_NEW_ERROR_WITH_MSG_AND_RETURN_VALUE(thread, ErrorType::ERROR, errorMsg.c_str(),
JSTaggedValue::Exception());
}
}
return JSTaggedValue(const_cast<Heap *>(thread->GetEcmaVM()->GetHeap())->
CheckAndTriggerHintGC(MemoryReduceDegree(value), GCReason::TRIGGER_BY_JS));
}
JSTaggedValue BuiltinsArkTools::RemoveAOTFlag(EcmaRuntimeCallInfo *info)

View File

@ -51,7 +51,7 @@ void GCStats::PrintGCStatistic()
<< sizeToMB(recordData_[(uint8_t)RecordData::END_COMMIT_SIZE]) << ") MB, "
<< scopeDuration_[Scope::ScopeId::TotalGC] << "(+"
<< GetConcurrrentMarkDuration()
<< ")ms, " << GCReasonToString();
<< ")ms, " << GCReasonToString(reason_);
LOG_GC(INFO) << "IsInBackground: " << heap_->IsInBackground() << "; "
<< "SensitiveStatus: " << static_cast<int>(heap_->GetSensitiveStatus()) << "; "
<< "OnStartupEvent: " << heap_->OnStartupEvent() << "; "
@ -64,7 +64,12 @@ void GCStats::PrintGCStatistic()
const char *GCStats::GCReasonToString()
{
switch (reason_) {
return GCReasonToString(reason_);
}
const char *GCStats::GCReasonToString(GCReason reason)
{
switch (reason) {
case GCReason::ALLOCATION_LIMIT:
return "Memory reach limit";
case GCReason::ALLOCATION_FAILED:
@ -711,7 +716,7 @@ void SharedGCStats::PrintGCStatistic()
<< sizeToMB(recordData_[(uint8_t)RecordData::START_COMMIT_SIZE]) << ") -> "
<< sizeToMB(recordData_[(uint8_t)RecordData::END_OBJ_SIZE]) << " ("
<< sizeToMB(recordData_[(uint8_t)RecordData::END_COMMIT_SIZE]) << ") MB, "
<< scopeDuration_[Scope::ScopeId::TotalGC] << "ms, " << GCReasonToString();
<< scopeDuration_[Scope::ScopeId::TotalGC] << "ms, " << GCReasonToString(reason_);
PrintSharedGCDuration();
PrintGCMemoryStatistic();
PrintSharedGCSummaryStatistic();

View File

@ -129,6 +129,7 @@ public:
}
}
static const char *GCReasonToString(GCReason reason);
const char *GCReasonToString();
double GetAvgSurvivalRate()

View File

@ -1666,18 +1666,57 @@ bool Heap::CheckAndTriggerOldGC(size_t size)
return false;
}
bool Heap::CheckAndTriggerHintGC()
bool Heap::CheckAndTriggerHintGC(MemoryReduceDegree degree, GCReason reason)
{
if (IsInBackground()) {
CollectGarbage(TriggerGCType::FULL_GC, GCReason::HINT_GC);
return true;
}
if (InSensitiveStatus()) {
return false;
}
if (memController_->GetPredictedSurvivalRate() < SURVIVAL_RATE_THRESHOLD) {
CollectGarbage(TriggerGCType::FULL_GC, GCReason::HINT_GC);
return true;
LOG_GC(INFO) << "HintGC degree:"<< static_cast<int>(degree) << " reason:" << GCStats::GCReasonToString(reason);
switch (degree) {
case MemoryReduceDegree::LOW: {
if (idleGCTrigger_->HintGCInLowDegree<Heap>(this)) {
if (CheckCanTriggerConcurrentMarking()) {
markType_ = MarkType::MARK_FULL;
TriggerConcurrentMarking();
LOG_GC(INFO) << " MemoryReduceDegree::LOW TriggerConcurrentMark.";
return true;
}
}
if (idleGCTrigger_->HintGCInLowDegree<SharedHeap>(sHeap_)) {
if (sHeap_->CheckCanTriggerConcurrentMarking(thread_)) {
LOG_GC(INFO) << " MemoryReduceDegree::LOW TriggerSharedConcurrentMark.";
sHeap_->TriggerConcurrentMarking<TriggerGCType::SHARED_GC, GCReason::HINT_GC>(thread_);
return true;
}
}
break;
}
case MemoryReduceDegree::MIDDLE: {
if (idleGCTrigger_->HintGCInMiddleDegree<Heap>(this)) {
CollectGarbage(TriggerGCType::FULL_GC, reason);
return true;
}
if (idleGCTrigger_->HintGCInMiddleDegree<SharedHeap>(sHeap_)) {
sHeap_->CollectGarbage<TriggerGCType::SHARED_FULL_GC, GCReason::HINT_GC>(thread_);
return true;
}
break;
}
case MemoryReduceDegree::HIGH: {
bool result = false;
if (idleGCTrigger_->HintGCInHighDegree<Heap>(this)) {
CollectGarbage(TriggerGCType::FULL_GC, reason);
result = true;
}
if (idleGCTrigger_->HintGCInHighDegree<SharedHeap>(sHeap_)) {
sHeap_->CollectGarbage<TriggerGCType::SHARED_FULL_GC, GCReason::HINT_GC>(thread_);
result = true;
}
return result;
}
default:
LOG_GC(INFO) << "HintGC invalid degree value: " << static_cast<int>(degree);
break;
}
return false;
}

View File

@ -50,6 +50,7 @@ class IncrementalMarker;
class JSNativePointer;
class Marker;
class MemController;
class IdleGCTrigger;
class NativeAreaAllocator;
class ParallelEvacuator;
class PartialGC;
@ -75,7 +76,7 @@ using GCListenerId = std::vector<std::pair<FinishGCListener, void *>>::const_ite
using Clock = std::chrono::high_resolution_clock;
using AppFreezeFilterCallback = std::function<bool(const int32_t pid)>;
using BytesAndDuration = std::pair<uint64_t, double>;
using MemoryReduceDegree = panda::JSNApi::MemoryReduceDegree;
enum class IdleTaskType : uint8_t {
NO_TASK,
YOUNG_GC,
@ -1106,7 +1107,7 @@ public:
*/
void CollectGarbage(TriggerGCType gcType, GCReason reason = GCReason::OTHER);
bool CheckAndTriggerOldGC(size_t size = 0);
bool CheckAndTriggerHintGC();
bool CheckAndTriggerHintGC(MemoryReduceDegree degree, GCReason reason = GCReason::OTHER);
TriggerGCType SelectGCType() const;
/*
* Parallel GC related configurations and utilities.

View File

@ -70,7 +70,7 @@ bool IdleGCTrigger::TryTriggerIdleLocalOldGC()
if (!IsPossiblePostGCTask(TRIGGER_IDLE_GC_TYPE::LOCAL_CONCURRENT_MARK)) {
return false;
}
if (ShouldCheckIdleOldGC<Heap>(heap_) && ReachIdleLocalOldGCThresholds() && !heap_->NeedStopCollection()) {
if (CheckIdleOrHintOldGC<Heap>(heap_) && ReachIdleLocalOldGCThresholds() && !heap_->NeedStopCollection()) {
if (heap_->GetConcurrentMarker()->IsEnabled() && heap_->CheckCanTriggerConcurrentMarking()) {
PostIdleGCTask(TRIGGER_IDLE_GC_TYPE::LOCAL_CONCURRENT_MARK);
} else {
@ -83,7 +83,7 @@ bool IdleGCTrigger::TryTriggerIdleLocalOldGC()
bool IdleGCTrigger::TryTriggerIdleSharedOldGC()
{
if (ShouldCheckIdleOldGC<SharedHeap>(sHeap_) && ReachIdleSharedGCThresholds() && !heap_->NeedStopCollection()) {
if (CheckIdleOrHintOldGC<SharedHeap>(sHeap_) && ReachIdleSharedGCThresholds() && !heap_->NeedStopCollection()) {
PostIdleGCTask(TRIGGER_IDLE_GC_TYPE::SHARED_GC);
return true;
}
@ -149,57 +149,36 @@ void IdleGCTrigger::PostIdleGCTask(TRIGGER_IDLE_GC_TYPE gcType)
LOG_GC(DEBUG) << "IdleGCTrigger: failed to post once " << GetGCTypeName(gcType);
}
template<class T>
bool IdleGCTrigger::ShouldCheckIdleOldGC(const T *baseHeap) const
{
size_t heapAliveSizeAfterGC = baseHeap->GetHeapAliveSizeAfterGC();
if (heapAliveSizeAfterGC == 0) {
return false;
}
size_t expectHeapSize = std::max(static_cast<size_t>(heapAliveSizeAfterGC * IDLE_SPACE_SIZE_MIN_INC_RATIO),
heapAliveSizeAfterGC + IDLE_SPACE_SIZE_MIN_INC_STEP);
return baseHeap->GetHeapObjectSize() >= expectHeapSize;
}
template<class T>
bool IdleGCTrigger::ShouldCheckIdleFullGC(const T *baseHeap) const
{
size_t heapAliveSizeAfterGC = baseHeap->GetHeapAliveSizeAfterGC();
size_t expectHeapSize = std::max(static_cast<size_t>(heapAliveSizeAfterGC * IDLE_SPACE_SIZE_MIN_INC_RATIO),
heapAliveSizeAfterGC + IDLE_SPACE_SIZE_MIN_INC_STEP_FULL);
return baseHeap->GetHeapObjectSize() >= expectHeapSize;
}
void IdleGCTrigger::TryTriggerIdleGC(TRIGGER_IDLE_GC_TYPE gcType)
{
LOG_GC(DEBUG) << "IdleGCTrigger: recv once notify of " << GetGCTypeName(gcType);
switch (gcType) {
case TRIGGER_IDLE_GC_TYPE::OLD_GC:
if (ShouldCheckIdleOldGC<Heap>(heap_) && !heap_->NeedStopCollection()) {
if (CheckIdleOrHintOldGC<Heap>(heap_) && !heap_->NeedStopCollection()) {
LOG_GC(INFO) << "IdleGCTrigger: trigger " << GetGCTypeName(gcType);
heap_->CollectGarbage(TriggerGCType::OLD_GC, GCReason::IDLE);
}
break;
case TRIGGER_IDLE_GC_TYPE::FULL_GC:
if (ShouldCheckIdleFullGC<Heap>(heap_) && !heap_->NeedStopCollection()) {
if (CheckIdleOrHintFullGC<Heap>(heap_) && !heap_->NeedStopCollection()) {
LOG_GC(INFO) << "IdleGCTrigger: trigger " << GetGCTypeName(gcType);
heap_->CollectGarbage(TriggerGCType::FULL_GC, GCReason::IDLE);
}
break;
case TRIGGER_IDLE_GC_TYPE::SHARED_GC:
if (ShouldCheckIdleOldGC<SharedHeap>(sHeap_) && !heap_->NeedStopCollection()) {
if (CheckIdleOrHintOldGC<SharedHeap>(sHeap_) && !heap_->NeedStopCollection()) {
LOG_GC(INFO) << "IdleGCTrigger: trigger " << GetGCTypeName(gcType);
sHeap_->CollectGarbage<TriggerGCType::SHARED_GC, GCReason::IDLE>(thread_);
}
break;
case TRIGGER_IDLE_GC_TYPE::SHARED_FULL_GC:
if (ShouldCheckIdleFullGC<SharedHeap>(sHeap_) && !heap_->NeedStopCollection()) {
if (CheckIdleOrHintFullGC<SharedHeap>(sHeap_) && !heap_->NeedStopCollection()) {
LOG_GC(INFO) << "IdleGCTrigger: trigger " << GetGCTypeName(gcType);
sHeap_->CollectGarbage<TriggerGCType::SHARED_FULL_GC, GCReason::IDLE>(thread_);
}
break;
case TRIGGER_IDLE_GC_TYPE::LOCAL_CONCURRENT_MARK:
if (ShouldCheckIdleOldGC<Heap>(heap_) && !heap_->NeedStopCollection()) {
if (CheckIdleOrHintOldGC<Heap>(heap_) && !heap_->NeedStopCollection()) {
LOG_GC(INFO) << "IdleGCTrigger: trigger " << GetGCTypeName(gcType);
TryTriggerLocalConcurrentMark();
}

View File

@ -104,9 +104,43 @@ public:
void TryPostHandleMarkFinished();
void TryTriggerIdleGC(TRIGGER_IDLE_GC_TYPE gcType);
template<class T>
bool ShouldCheckIdleOldGC(const T *baseHeap) const;
bool CheckIdleOrHintOldGC(const T *baseHeap) const
{
size_t heapAliveSizeAfterGC = baseHeap->GetHeapAliveSizeAfterGC();
if (heapAliveSizeAfterGC == 0) {
return false;
}
size_t expectHeapSize = std::max(static_cast<size_t>(heapAliveSizeAfterGC * IDLE_SPACE_SIZE_MIN_INC_RATIO),
heapAliveSizeAfterGC + IDLE_SPACE_SIZE_MIN_INC_STEP);
return baseHeap->GetHeapObjectSize() >= expectHeapSize;
}
template<class T>
bool ShouldCheckIdleFullGC(const T *baseHeap) const;
bool CheckIdleOrHintFullGC(const T *baseHeap) const
{
size_t heapAliveSizeAfterGC = baseHeap->GetHeapAliveSizeAfterGC();
size_t expectHeapSize = std::max(static_cast<size_t>(heapAliveSizeAfterGC * IDLE_SPACE_SIZE_MIN_INC_RATIO),
heapAliveSizeAfterGC + IDLE_SPACE_SIZE_MIN_INC_STEP_FULL);
return baseHeap->GetHeapObjectSize() >= expectHeapSize;
}
template<class T>
bool HintGCInLowDegree(const T *baseHeap) const
{
return CheckIdleOrHintOldGC<T>(baseHeap);
}
template<class T>
bool HintGCInMiddleDegree(const T *baseHeap) const
{
return CheckIdleOrHintOldGC<T>(baseHeap);
}
template<class T>
bool HintGCInHighDegree(const T *baseHeap) const
{
return CheckIdleOrHintFullGC<T>(baseHeap);
}
private:
void PostIdleGCTask(TRIGGER_IDLE_GC_TYPE gcType);

View File

@ -1455,6 +1455,12 @@ public:
LOCAL_REMARK = 1 << 6,
};
enum class ECMA_PUBLIC_API MemoryReduceDegree : uint8_t {
LOW = 0,
MIDDLE,
HIGH,
};
enum class PatchErrorCode : uint8_t {
SUCCESS = 0,
PATCH_HAS_LOADED,
@ -1536,6 +1542,7 @@ public:
static void TriggerGC(const EcmaVM *vm, TRIGGER_GC_TYPE gcType = TRIGGER_GC_TYPE::SEMI_GC);
static void TriggerGC(const EcmaVM *vm, ecmascript::GCReason reason,
TRIGGER_GC_TYPE gcType = TRIGGER_GC_TYPE::SEMI_GC);
static void HintGC(const EcmaVM *vm, MemoryReduceDegree degree, ecmascript::GCReason reason);
static void TriggerIdleGC(const EcmaVM *vm, TRIGGER_IDLE_GC_TYPE gcType);
static void SetStartIdleMonitorCallback(const StartIdleMonitorCallback& callback);
static StartIdleMonitorCallback GetStartIdleMonitorCallback();

View File

@ -4404,6 +4404,15 @@ void JSNApi::TriggerGC(const EcmaVM *vm, ecmascript::GCReason reason, TRIGGER_GC
}
}
void JSNApi::HintGC(const EcmaVM *vm, MemoryReduceDegree degree, ecmascript::GCReason reason)
{
CROSS_THREAD_CHECK(vm);
ecmascript::ThreadManagedScope managedScope(vm->GetJSThread());
if (thread != nullptr && vm->IsInitialized()) {
const_cast<ecmascript::Heap *>(vm->GetHeap())->CheckAndTriggerHintGC(degree, reason);
}
}
void JSNApi::TriggerIdleGC(const EcmaVM *vm, TRIGGER_IDLE_GC_TYPE gcType)
{
CROSS_THREAD_CHECK(vm);

View File

@ -1441,6 +1441,43 @@ HWTEST_F_L0(JSNApiTests, TriggerGC_OLD_GC)
vm_->SetEnableForceGC(true);
}
HWTEST_F_L0(JSNApiTests, Hint_GC)
{
ecmascript::ThreadManagedScope managedScope(thread_);
vm_->SetEnableForceGC(false);
[[maybe_unused]] auto heap = const_cast<Heap *>(thread_->GetEcmaVM()->GetHeap());
#ifdef NDEBUG
heap->CollectGarbage(TriggerGCType::OLD_GC);
{
[[maybe_unused]] ecmascript::EcmaHandleScope baseScope(thread_);
for (int i = 0; i < 2049; i++) {
[[maybe_unused]] JSHandle<TaggedArray> array = thread_->GetEcmaVM()->GetFactory()->NewTaggedArray(
1024, JSTaggedValue::Hole(), MemSpaceType::SEMI_SPACE);
}
}
size_t beforeSize = heap->GetHeapObjectSize();
#endif
Local<StringRef> origin = StringRef::NewFromUtf8(vm_, "1");
ASSERT_EQ("1", origin->ToString(vm_));
// trigger gc
JSNApi::MemoryReduceDegree degree = JSNApi::MemoryReduceDegree::LOW;
JSNApi::HintGC(vm_, degree, GCReason::HINT_GC);
degree = JSNApi::MemoryReduceDegree::MIDDLE;
JSNApi::HintGC(vm_, degree, GCReason::HINT_GC);
degree = JSNApi::MemoryReduceDegree::HIGH;
JSNApi::HintGC(vm_, degree, GCReason::HINT_GC);
ASSERT_EQ("1", origin->ToString(vm_));
#ifdef NDEBUG
size_t afterSize = heap->GetHeapObjectSize();
EXPECT_TRUE(afterSize < beforeSize);
#endif
vm_->SetEnableForceGC(true);
}
/* @tc.number: ffi_interface_api_028
* @tc.name: addWorker_DeleteWorker
* @tc.desc:

View File

@ -51,14 +51,15 @@ HWTEST_F_L0(GCTest, ArkToolsHintGC)
auto getSizeAfterCreateAndCallHintGC = [this, heap] (size_t &newSize, size_t &finalSize) -> bool {
{
[[maybe_unused]] ecmascript::EcmaHandleScope baseScope(thread);
for (int i = 0; i < 500; i++) {
for (int i = 0; i < 2048; i++) {
[[maybe_unused]] JSHandle<TaggedArray> obj = thread->GetEcmaVM()->GetFactory()->
NewTaggedArray(10 * 1024, JSTaggedValue::Hole(), MemSpaceType::SEMI_SPACE);
NewTaggedArray(10 * 1024, JSTaggedValue::Hole(), MemSpaceType::OLD_SPACE);
}
newSize = heap->GetCommittedSize();
}
auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 0);
std::vector<JSTaggedValue> vals{JSTaggedValue(static_cast<double>(2))};
auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, vals,
6);
[[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
JSTaggedValue result = builtins::BuiltinsArkTools::HintGC(ecmaRuntimeCallInfo);
finalSize = heap->GetCommittedSize();
@ -80,9 +81,7 @@ HWTEST_F_L0(GCTest, ArkToolsHintGC)
heap->NotifyHighSensitive(false);
}
{
// Test HintGC() when in background.
heap->CollectGarbage(TriggerGCType::FULL_GC);
heap->ChangeGCParams(true);
#ifdef NDEBUG
size_t originSize = heap->GetCommittedSize();
size_t newSize = 0;
size_t finalSize = 0;
@ -90,7 +89,7 @@ HWTEST_F_L0(GCTest, ArkToolsHintGC)
EXPECT_TRUE(res);
EXPECT_TRUE(newSize > originSize);
EXPECT_TRUE(finalSize < newSize);
heap->ChangeGCParams(false);
#endif
}
}
@ -160,8 +159,107 @@ HWTEST_F_L0(GCTest, ObjectExceedMaxHeapSizeTest001)
HWTEST_F_L0(GCTest, CheckAndTriggerHintGCTest001)
{
#ifdef NDEBUG
auto heap = const_cast<Heap *>(thread->GetEcmaVM()->GetHeap());
ASSERT_EQ(heap->CheckAndTriggerHintGC(), true);
heap->CollectGarbage(TriggerGCType::OLD_GC);
ASSERT_EQ(heap->CheckAndTriggerHintGC(MemoryReduceDegree::LOW, GCReason::HINT_GC), false);
{
[[maybe_unused]] ecmascript::EcmaHandleScope baseScope(thread);
for (int i = 0; i < 4048; i++) {
[[maybe_unused]] JSHandle<TaggedArray> array = thread->GetEcmaVM()->GetFactory()->NewTaggedArray(
1024, JSTaggedValue::Hole(), MemSpaceType::OLD_SPACE);
}
}
ASSERT_EQ(heap->CheckAndTriggerHintGC(MemoryReduceDegree::LOW, GCReason::HINT_GC), true);
#endif
}
HWTEST_F_L0(GCTest, CheckAndTriggerHintGCTest002)
{
#ifdef NDEBUG
auto heap = const_cast<Heap *>(thread->GetEcmaVM()->GetHeap());
heap->CollectGarbage(TriggerGCType::FULL_GC);
ASSERT_EQ(heap->CheckAndTriggerHintGC(MemoryReduceDegree::MIDDLE, GCReason::HINT_GC), false);
{
[[maybe_unused]] ecmascript::EcmaHandleScope baseScope(thread);
for (int i = 0; i < 4048; i++) {
[[maybe_unused]] JSHandle<TaggedArray> array = thread->GetEcmaVM()->GetFactory()->NewTaggedArray(
1024, JSTaggedValue::Hole(), MemSpaceType::OLD_SPACE);
}
}
ASSERT_EQ(heap->CheckAndTriggerHintGC(MemoryReduceDegree::MIDDLE, GCReason::HINT_GC), true);
#endif
}
HWTEST_F_L0(GCTest, CheckAndTriggerHintGCTest003)
{
#ifdef NDEBUG
auto heap = const_cast<Heap *>(thread->GetEcmaVM()->GetHeap());
heap->CollectGarbage(TriggerGCType::FULL_GC);
ASSERT_EQ(heap->CheckAndTriggerHintGC(MemoryReduceDegree::HIGH, GCReason::HINT_GC), false);
{
[[maybe_unused]] ecmascript::EcmaHandleScope baseScope(thread);
for (int i = 0; i < 1049; i++) {
[[maybe_unused]] JSHandle<TaggedArray> array = thread->GetEcmaVM()->GetFactory()->NewTaggedArray(
1024, JSTaggedValue::Hole(), MemSpaceType::OLD_SPACE);
}
}
ASSERT_EQ(heap->CheckAndTriggerHintGC(MemoryReduceDegree::HIGH, GCReason::HINT_GC), true);
#endif
}
HWTEST_F_L0(GCTest, CheckAndTriggerHintGCTest004)
{
#ifdef NDEBUG
auto sHeap = SharedHeap::GetInstance();
sHeap->CollectGarbage<TriggerGCType::SHARED_GC, GCReason::OTHER>(thread);
auto heap = const_cast<Heap *>(thread->GetEcmaVM()->GetHeap());
ASSERT_EQ(heap->CheckAndTriggerHintGC(MemoryReduceDegree::LOW, GCReason::HINT_GC), false);
{
[[maybe_unused]] ecmascript::EcmaHandleScope baseScope(thread);
for (int i = 0; i < 4048; i++) {
[[maybe_unused]] JSHandle<TaggedArray> array = thread->GetEcmaVM()->GetFactory()->
NewSOldSpaceTaggedArray(1024, JSTaggedValue::Undefined());
}
}
ASSERT_EQ(heap->CheckAndTriggerHintGC(MemoryReduceDegree::LOW, GCReason::HINT_GC), true);
#endif
}
HWTEST_F_L0(GCTest, CheckAndTriggerHintGCTest005)
{
#ifdef NDEBUG
auto sHeap = SharedHeap::GetInstance();
sHeap->CollectGarbage<TriggerGCType::SHARED_FULL_GC, GCReason::OTHER>(thread);
auto heap = const_cast<Heap *>(thread->GetEcmaVM()->GetHeap());
ASSERT_EQ(heap->CheckAndTriggerHintGC(MemoryReduceDegree::MIDDLE, GCReason::HINT_GC), false);
{
[[maybe_unused]] ecmascript::EcmaHandleScope baseScope(thread);
for (int i = 0; i < 4048; i++) {
[[maybe_unused]] JSHandle<TaggedArray> array = thread->GetEcmaVM()->GetFactory()->
NewSOldSpaceTaggedArray(1024, JSTaggedValue::Undefined());
}
}
ASSERT_EQ(heap->CheckAndTriggerHintGC(MemoryReduceDegree::MIDDLE, GCReason::HINT_GC), true);
#endif
}
HWTEST_F_L0(GCTest, CheckAndTriggerHintGCTest006)
{
#ifdef NDEBUG
auto sHeap = SharedHeap::GetInstance();
sHeap->CollectGarbage<TriggerGCType::SHARED_FULL_GC, GCReason::OTHER>(thread);
auto heap = const_cast<Heap *>(thread->GetEcmaVM()->GetHeap());
ASSERT_EQ(heap->CheckAndTriggerHintGC(MemoryReduceDegree::HIGH, GCReason::HINT_GC), false);
{
[[maybe_unused]] ecmascript::EcmaHandleScope baseScope(thread);
for (int i = 0; i < 2049; i++) {
[[maybe_unused]] JSHandle<TaggedArray> array = thread->GetEcmaVM()->GetFactory()->
NewSOldSpaceTaggedArray(1024, JSTaggedValue::Undefined());
}
}
ASSERT_EQ(heap->CheckAndTriggerHintGC(MemoryReduceDegree::HIGH, GCReason::HINT_GC), true);
#endif
}
HWTEST_F_L0(GCTest, CalculateIdleDurationTest001)

View File

@ -33,5 +33,10 @@ print(res);
print(ArkTools.forceFullGC());
ArkTools.hintGC();
// MemoryReduceDegree::LOW
ArkTools.hintGC(0);
// MemoryReduceDegree::MIDDLE
ArkTools.hintGC(1);
// MemoryReduceDegree::HIGH
ArkTools.hintGC(2);
print("call hintGC to make vm decide to trigger GC or do noting");