1/*
2 * Copyright (c) 2023 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 *     http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16#ifndef ECMASCRIPT_MEM_INCREMENTAL_MARKER_H
17#define ECMASCRIPT_MEM_INCREMENTAL_MARKER_H
18
19#include "ecmascript/mem/allocator.h"
20#include "ecmascript/mem/garbage_collector.h"
21#include "ecmascript/mem/heap.h"
22#include "ecmascript/mem/mark_stack.h"
23#include "ecmascript/mem/mark_word.h"
24#include "ecmascript/mem/mem.h"
25#include "ecmascript/mem/slots.h"
26#include "ecmascript/mem/visitor.h"
27#include "ecmascript/mem/work_manager.h"
28
29namespace panda::ecmascript {
30class EcmaVM;
31class Heap;
32
33enum class IncrementalGCStates {
34    ROOT_SCAN,
35    INCREMENTAL_MARK,
36    REMARK,
37};
38
39// Incremental Mark only suport old gc
40class IncrementalMarker {
41public:
42    IncrementalMarker(Heap *heap);
43    ~IncrementalMarker() = default;
44
45    void TriggerIncrementalMark(int64_t idleMicroSec = 0);
46    void Reset();
47    bool IsTriggeredIncrementalMark()
48    {
49        return isIncrementalMarking_;
50    }
51
52    void UpdateMarkingSpeed(uint32_t visitAddrNum, double costTime)
53    {
54        if (costTime > 1) {
55            markingSpeed_ = static_cast<uint32_t>((double)visitAddrNum / costTime + markingSpeed_) >> 1;
56        }
57    }
58
59    uint32_t GetMarkingSpeed()
60    {
61        return markingSpeed_;
62    }
63
64    void SetMarkingFinished(bool value)
65    {
66        markingFinished_ = value;
67    }
68
69    IncrementalGCStates GetIncrementalGCStates()
70    {
71        return states_;
72    }
73
74    uint32_t GetAverageIncrementalMarkingSpeed()
75    {
76        return incrementalMarkingSpeed_;
77    }
78
79    double GetCurrentTimeInMs();
80
81private:
82    void Mark();
83    void Initialize();
84    void Finish();
85    void ProcessIncrementalMark(int64_t idleMicroSec);
86    void RecordIdleTime(int64_t idleMicroSec, double startTime, bool needInitialize = false);
87    void PrintGCIdleUsageStatistic();
88
89    void UpdateIncrementalMarkingSpeed(double duration)
90    {
91        if (duration > 1) {
92            incrementalMarkingSpeed_ = static_cast<uint32_t>(
93                (double)startObjectSize_ / duration + incrementalMarkingSpeed_) >> 1;
94        }
95    }
96
97    class RecursionScope {
98    public:
99        explicit RecursionScope(IncrementalMarker* marker) : marker_(marker)
100        {
101            if (marker_->recursionDepth_++ != 0) {
102                LOG_GC(FATAL) << "Recursion in IncrementalMarker Constructor, depth:" << marker_->recursionDepth_;
103            }
104        }
105        ~RecursionScope()
106        {
107            if (--marker_->recursionDepth_ != 0) {
108                LOG_GC(FATAL) << "Recursion in IncrementalMarker Destructor, depth:" << marker_->recursionDepth_;
109            }
110        }
111    private:
112        IncrementalMarker* marker_ {nullptr};
113    };
114
115    Heap *heap_ {nullptr};
116    EcmaVM *vm_ {nullptr};
117
118    WorkManager *workManager_ {nullptr};
119    double startTime_ {0.0};
120    size_t startObjectSize_ {0};
121
122    bool isIncrementalMarking_ {false};
123    bool markingFinished_ {false};
124
125    uint32_t markingSpeed_ {200_KB};
126    uint32_t incrementalMarkingSpeed_ {100_KB};
127    IncrementalGCStates states_ {IncrementalGCStates::ROOT_SCAN};
128
129    int64_t receiveIdleTime_ {0};
130    double totalUsedIdleTime_ {0.0};
131    double exceedIdleTime_ {0.0};
132    int32_t recursionDepth_ {0};
133
134    friend class Heap;
135};
136}  // namespace panda::ecmascript
137#endif  // ECMASCRIPT_MEM_INCREMENTAL_MARKER_H
138