1 /*
2  * Copyright (c) 2021 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_CONCURRENT_SWEEPER_H
17 #define ECMASCRIPT_MEM_CONCURRENT_SWEEPER_H
18 
19 #include <array>
20 #include <atomic>
21 
22 #include "ecmascript/mem/space.h"
23 #include "ecmascript/taskpool/task.h"
24 
25 #include "ecmascript/platform/mutex.h"
26 
27 namespace panda::ecmascript {
28 // CONFIG_DISABLE means concurrent sweeper is disabled by options or macros and cannot be changed.
29 // REQUEST_DISABLE means we want to disable concurrent sweeper while it is sweeping.
30 // REQUEST_DISABLE can be ragarded as enable and will be changed into disable after finishing sweeping.
31 enum class EnableConcurrentSweepType : uint8_t {
32     ENABLE,
33     CONFIG_DISABLE,
34     DISABLE,
35     REQUEST_DISABLE
36 };
37 
38 class ConcurrentSweeper {
39 public:
40     ConcurrentSweeper(Heap *heap, EnableConcurrentSweepType type);
41     ~ConcurrentSweeper() = default;
42 
43     NO_COPY_SEMANTIC(ConcurrentSweeper);
44     NO_MOVE_SEMANTIC(ConcurrentSweeper);
45 
46     void PostTask(bool fullGC = false);
47     void Sweep(bool fullGC = false);
48 
49     void WaitAllTaskFinished();
50     // Help to finish sweeping task. It can be called through js thread
51     void EnsureAllTaskFinished();
52     // Ensure task finish. It can be called through js thread
53     void EnsureTaskFinished(MemSpaceType type);
54     void EnsureTaskFinishedNoCheck(MemSpaceType type);
55 
56     void TryFillSweptRegion();
57     void ClearRSetInRange(Region *current, uintptr_t freeStart, uintptr_t freeEnd);
58 
59     void EnableConcurrentSweep(EnableConcurrentSweepType type);
60 
IsSweeping()61     bool IsSweeping()
62     {
63         return isSweeping_;
64     }
65 
ConcurrentSweepEnabled()66     bool ConcurrentSweepEnabled()
67     {
68         return !IsDisabled();
69     }
70 
ConfigConcurrentSweep(bool enabled)71     void ConfigConcurrentSweep(bool enabled)
72     {
73         enableType_ = enabled ? EnableConcurrentSweepType::ENABLE :
74                       EnableConcurrentSweepType::CONFIG_DISABLE;
75     }
76 
IsDisabled() const77     bool IsDisabled() const
78     {
79         return enableType_ == EnableConcurrentSweepType::DISABLE ||
80             enableType_ == EnableConcurrentSweepType::CONFIG_DISABLE;
81     }
82 
IsRequestDisabled() const83     bool IsRequestDisabled() const
84     {
85         return enableType_ == EnableConcurrentSweepType::REQUEST_DISABLE;
86     }
87 
IsConfigDisabled() const88     bool IsConfigDisabled() const
89     {
90         return enableType_ == EnableConcurrentSweepType::CONFIG_DISABLE;
91     }
92 private:
93     class SweeperTask : public Task {
94     public:
SweeperTask(int32_t id, ConcurrentSweeper *sweeper, MemSpaceType type)95         SweeperTask(int32_t id, ConcurrentSweeper *sweeper, MemSpaceType type)
96             : Task(id), sweeper_(sweeper), type_(type) {};
97         ~SweeperTask() override = default;
98         bool Run(uint32_t threadIndex) override;
99 
100         NO_COPY_SEMANTIC(SweeperTask);
101         NO_MOVE_SEMANTIC(SweeperTask);
102 
103     private:
104         ConcurrentSweeper *sweeper_;
105         MemSpaceType type_;
106     };
107 
108     void AsyncSweepSpace(MemSpaceType type, bool isMain);
109 
110     void WaitingTaskFinish(MemSpaceType type);
111 
112     std::array<Mutex, FREE_LIST_NUM> mutexs_;
113     std::array<ConditionVariable, FREE_LIST_NUM> cvs_;
114     std::array<std::atomic_int, FREE_LIST_NUM> remainingTaskNum_ = {0, 0, 0};
115 
116     Heap *heap_;
117     EnableConcurrentSweepType enableType_ {EnableConcurrentSweepType::CONFIG_DISABLE};
118     bool isSweeping_ {false};
119     MemSpaceType startSpaceType_ = MemSpaceType::OLD_SPACE;
120 };
121 }  // namespace panda::ecmascript
122 #endif  // ECMASCRIPT_MEM_CONCURRENT_SWEEPER_H
123