• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2025 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_SHARED_HEAP_SHARED_GC_EVACUATOR_H
17 #define ECMASCRIPT_MEM_SHARED_HEAP_SHARED_GC_EVACUATOR_H
18 
19 #include "ecmascript/mem/heap-inl.h"
20 
21 namespace panda::ecmascript {
22 class SharedGCEvacuator {
23 public:
SharedGCEvacuator(SharedHeap * heap)24     explicit SharedGCEvacuator(SharedHeap *heap) : sHeap_(heap), objectFieldCSetVisitor_(this) {}
25     ~SharedGCEvacuator() = default;
26     NO_COPY_SEMANTIC(SharedGCEvacuator);
27     NO_MOVE_SEMANTIC(SharedGCEvacuator);
28     void Evacuate();
29 private:
30     void EvacuateRegions();
31     void UpdateReference();
32     bool UpdateObjectSlot(ObjectSlot slot);
33     void UpdateObjectSlotRoot(ObjectSlot slot);
34     void ProcessObjectField(TaggedObject *object, JSHClass *hclass);
35     void UpdateCrossRegionRSet(ObjectSlot slot, Region *objectRegion);
36     void WaitFinished();
37     int CalculateUpdateThreadNum();
38 
39     class UpdateRootVisitor final : public RootVisitor {
40     public:
41         UpdateRootVisitor() = default;
42         ~UpdateRootVisitor() = default;
43 
44         void VisitRoot([[maybe_unused]] Root type, ObjectSlot slot) override;
45         void VisitRangeRoot([[maybe_unused]] Root type, ObjectSlot start, ObjectSlot end) override;
46         void VisitBaseAndDerivedRoot([[maybe_unused]] Root type, ObjectSlot base, ObjectSlot derived,
47                                      uintptr_t baseOldObject) override;
48     private:
49         void UpdateObjectSlotRoot(ObjectSlot slot);
50     };
51 
52     class ObjectFieldCSetVisitor final : public EcmaObjectRangeVisitor<ObjectFieldCSetVisitor> {
53     public:
ObjectFieldCSetVisitor(SharedGCEvacuator * evacuator)54         explicit ObjectFieldCSetVisitor(SharedGCEvacuator *evacuator) : evacuator_(evacuator) {}
55         ~ObjectFieldCSetVisitor() override = default;
56 
57         void VisitObjectRangeImpl(TaggedObject *root, ObjectSlot start, ObjectSlot end, VisitObjectArea area) override;
58     private:
59         SharedGCEvacuator *evacuator_ {nullptr};
60     };
61 
62     class Workload {
63     public:
Workload(SharedGCEvacuator * evacuator,Region * region)64         Workload(SharedGCEvacuator *evacuator, Region *region) : evacuator_(evacuator), region_(region) {}
65         virtual ~Workload() = default;
66         virtual void Process(bool isMain) = 0;
67     protected:
68         SharedGCEvacuator *evacuator_ {nullptr};
69         Region *region_ {nullptr};
70     };
71 
AddWorkload(std::unique_ptr<Workload> workload)72     void AddWorkload(std::unique_ptr<Workload> workload)
73     {
74         workloads_.emplace_back(std::move(workload));
75     }
76 
GetWorkload()77     std::unique_ptr<Workload> GetWorkload()
78     {
79         LockHolder holder(lock_);
80         std::unique_ptr<Workload> workload;
81         if (!workloads_.empty()) {
82             workload = std::move(workloads_.back());
83             workloads_.pop_back();
84         }
85         return workload;
86     }
87 
ProcessWorkloads(bool isMain)88     void ProcessWorkloads(bool isMain)
89     {
90         std::unique_ptr<Workload> workload = GetWorkload();
91         while (workload != nullptr) {
92             workload->Process(isMain);
93             workload = GetWorkload();
94         }
95         if (!isMain) {
96             LockHolder holder(lock_);
97             if (--parallel_ <= 0) {
98                 condition_.SignalAll();
99             }
100         }
101     }
102 
103     class UpdateLocalReferenceWorkload : public Workload {
104     public:
UpdateLocalReferenceWorkload(SharedGCEvacuator * evacuator,Region * region)105         UpdateLocalReferenceWorkload(SharedGCEvacuator *evacuator, Region *region) : Workload(evacuator, region) {}
106         void Process(bool isMain) override;
107     };
108 
109     class UpdateSharedReferenceWorkload : public Workload {
110     public:
UpdateSharedReferenceWorkload(SharedGCEvacuator * evacuator,Region * region)111         UpdateSharedReferenceWorkload(SharedGCEvacuator *evacuator, Region *region) : Workload(evacuator, region) {}
112         void Process(bool isMain) override;
113     };
114 
115     class UpdateReferenceTask : public Task {
116     public:
UpdateReferenceTask(int32_t id,SharedGCEvacuator * evacuator)117         UpdateReferenceTask(int32_t id, SharedGCEvacuator *evacuator) : Task(id), evacuator_(evacuator) {};
118         ~UpdateReferenceTask() override = default;
119         NO_COPY_SEMANTIC(UpdateReferenceTask);
120         NO_MOVE_SEMANTIC(UpdateReferenceTask);
121 
122         bool Run(uint32_t threadIndex) override;
123 
124     private:
125         SharedGCEvacuator *evacuator_ {nullptr};
126     };
127 
128     SharedHeap *sHeap_ {nullptr};
129     Mutex lock_;
130     ConditionVariable condition_;
131     std::vector<std::unique_ptr<Workload>> workloads_;
132     UpdateRootVisitor rootVisitor_;
133     ObjectFieldCSetVisitor objectFieldCSetVisitor_;
134     int parallel_ {0};
135 };
136 }  // namespace panda::ecmascript
137 
138 #endif  // ECMASCRIPT_MEM_SHARED_HEAP_SHARED_GC_EVACUATOR_H
139