1 /*
2  * Copyright (c) 2024 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_MARKER_H
17 #define ECMASCRIPT_MEM_SHARED_HEAP_SHARED_GC_MARKER_H
18 
19 #include "ecmascript/js_hclass.h"
20 #include "ecmascript/mem/rset_worklist_handler-inl.h"
21 #include "ecmascript/mem/slots.h"
22 #include "ecmascript/mem/work_manager.h"
23 
24 namespace panda::ecmascript {
25 class Region;
26 class TaggedObject;
27 class SharedGCMarker;
28 class JSHClass;
29 enum class Root;
30 
31 enum class SharedMarkType : uint8_t {
32     NOT_CONCURRENT_MARK,
33     CONCURRENT_MARK_INITIAL_MARK,
34     CONCURRENT_MARK_REMARK,
35 };
36 
37 class SharedGCMarkerBase {
38 public:
SharedGCMarkerBase(SharedGCWorkManager *workManger)39     explicit SharedGCMarkerBase(SharedGCWorkManager *workManger) : sWorkManager_(workManger) {}
40     virtual ~SharedGCMarkerBase() = default;
41 
42     void ResetWorkManager(SharedGCWorkManager *workManager);
43     void MarkRoots(uint32_t threadId, SharedMarkType markType, VMRootVisitType type = VMRootVisitType::MARK);
44     void MarkLocalVMRoots(uint32_t threadId, EcmaVM *localVm, SharedMarkType markType,
45                           VMRootVisitType type = VMRootVisitType::MARK);
46     void CollectLocalVMRSet(EcmaVM *localVm);
47     void MarkStringCache(uint32_t threadId);
48     void MarkSerializeRoots(uint32_t threadId);
49     void MarkSharedModule(uint32_t threadId);
50     inline void ProcessThenMergeBackRSetFromBoundJSThread(RSetWorkListHandler *handler);
51     template<SharedMarkType markType>
52     inline void DoMark(uint32_t threadId);
53     template <typename Callback>
54     inline bool VisitBodyInObj(TaggedObject *root, ObjectSlot start, ObjectSlot end, Callback callback);
55     inline void HandleRoots(uint32_t threadId, [[maybe_unused]] Root type, ObjectSlot slot);
56     inline void HandleLocalRoots(uint32_t threadId, [[maybe_unused]] Root type, ObjectSlot slot);
57     inline void HandleLocalRangeRoots(uint32_t threadId, [[maybe_unused]] Root type, ObjectSlot start,
58                                       ObjectSlot end);
59     inline void RecordWeakReference(uint32_t threadId, JSTaggedType *ref);
60     void MergeBackAndResetRSetWorkListHandler();
61     template<SharedMarkType markType>
62     inline void ProcessVisitorOfDoMark(uint32_t threadId);
63     inline void ProcessVisitor(RSetWorkListHandler *handler);
64     inline bool MarkObjectOfProcessVisitor(void *mem, WorkNode *&localBuffer);
65 
66     inline void MarkObjectFromJSThread(WorkNode *&localBuffer, TaggedObject *object);
67 
MarkValue([[maybe_unused]] uint32_t threadId, [[maybe_unused]] ObjectSlot &slot)68     virtual inline void MarkValue([[maybe_unused]] uint32_t threadId, [[maybe_unused]] ObjectSlot &slot)
69     {
70         LOG_GC(FATAL) << " can not call this method";
71     }
72 
MarkObject([[maybe_unused]] uint32_t threadId, [[maybe_unused]] TaggedObject *object, [[maybe_unused]] ObjectSlot &slot)73     virtual inline void MarkObject([[maybe_unused]] uint32_t threadId, [[maybe_unused]] TaggedObject *object,
74                                    [[maybe_unused]] ObjectSlot &slot)
75     {
76         LOG_GC(FATAL) << " can not call this method";
77     }
78 
HandleLocalDerivedRoots([[maybe_unused]] Root type, [[maybe_unused]] ObjectSlot base, [[maybe_unused]] ObjectSlot derived, [[maybe_unused]] uintptr_t baseOldObject)79     virtual inline void HandleLocalDerivedRoots([[maybe_unused]] Root type, [[maybe_unused]] ObjectSlot base,
80                                                 [[maybe_unused]] ObjectSlot derived,
81                                                 [[maybe_unused]] uintptr_t baseOldObject)
82     {
83         LOG_GC(FATAL) << " can not call this method";
84     }
ProcessMarkStack([[maybe_unused]] uint32_t threadId)85     virtual void ProcessMarkStack([[maybe_unused]] uint32_t threadId)
86     {
87         LOG_GC(FATAL) << " can not call this method";
88     }
89 
90 protected:
91     SharedGCWorkManager *sWorkManager_ {nullptr};
92 
93 private:
94     template<SharedMarkType markType>
95     inline auto GenerateRSetVisitor(uint32_t threadId);
96     inline void RecordObject(JSTaggedValue value, uint32_t threadId, void *mem);
97     template<SharedMarkType markType>
98     inline bool GetVisitor(JSTaggedValue value, uint32_t threadId, void *mem);
99 
100     std::vector<RSetWorkListHandler*> rSetHandlers_;
101 };
102 
103 class SharedGCMarker : public SharedGCMarkerBase {
104 public:
105     explicit SharedGCMarker(SharedGCWorkManager *workManger);
106     ~SharedGCMarker() override = default;
107     void ProcessMarkStack(uint32_t threadId) override;
108 
109 protected:
110     inline void MarkValue(uint32_t threadId, ObjectSlot &slot) override;
111     inline void MarkObject(uint32_t threadId, TaggedObject *object, ObjectSlot &slot) override;
112     inline void HandleLocalDerivedRoots(Root type, ObjectSlot base, ObjectSlot derived,
113                                         uintptr_t baseOldObject) override;
114 };
115 
116 class SharedGCMovableMarker : public SharedGCMarkerBase {
117 public:
118     explicit SharedGCMovableMarker(SharedGCWorkManager *workManger, SharedHeap *sHeap);
119     ~SharedGCMovableMarker() override = default;
120     inline bool NeedEvacuate(Region *region);
121     void ProcessMarkStack(uint32_t threadId) override;
122 
123 protected:
124     inline void HandleLocalDerivedRoots(Root type, ObjectSlot base, ObjectSlot derived,
125                                         uintptr_t baseOldObject) override;
126     inline void MarkValue(uint32_t threadId, ObjectSlot &slot) override;
127     inline void MarkObject(uint32_t threadId, TaggedObject *object, ObjectSlot &slot) override;
128     inline uintptr_t AllocateForwardAddress(uint32_t threadId, size_t size);
129     inline void EvacuateObject(uint32_t threadId, TaggedObject *object, const MarkWord &markWord, ObjectSlot slot);
130     inline uintptr_t AllocateDstSpace(uint32_t threadId, size_t size);
131     inline void RawCopyObject(uintptr_t fromAddress, uintptr_t toAddress, size_t size, const MarkWord &markWord);
132     inline void UpdateForwardAddressIfSuccess(uint32_t threadId, TaggedObject *object, JSHClass *klass,
133                                               uintptr_t toAddress, size_t size, ObjectSlot slot);
134     inline void UpdateForwardAddressIfFailed(TaggedObject *object, uintptr_t toAddress, size_t size, ObjectSlot slot);
135 
136 private:
137     SharedHeap *sHeap_;
138 };
139 }  // namespace panda::ecmascript
140 #endif  // ECMASCRIPT_MEM_SHARED_HEAP_SHARED_GC_MARKER_H