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_PARALLEL_MARKER_H
17#define ECMASCRIPT_MEM_PARALLEL_MARKER_H
18
19#include "ecmascript/js_hclass.h"
20#include "ecmascript/mem/gc_bitset.h"
21#include "ecmascript/mem/object_xray.h"
22#include "ecmascript/mem/slots.h"
23#include "ecmascript/mem/work_manager.h"
24
25namespace panda::ecmascript {
26class Heap;
27class Region;
28class TaggedObject;
29
30class Marker {
31public:
32    explicit Marker(Heap *heap);
33    virtual ~Marker() = default;
34
35    virtual void Initialize()
36    {
37        LOG_GC(DEBUG) << "Marker::Initialize do nothing";
38    }
39
40    void MarkRoots(uint32_t threadId, VMRootVisitType type = VMRootVisitType::MARK);
41    void ProcessNewToEden(uint32_t threadId);                  // for HPPGC only sticky mode
42    void ProcessNewToEdenNoMarkStack(uint32_t threadId);
43    void ProcessOldToNew(uint32_t threadId);                  // for HPPGC only semi mode
44    void ProcessOldToNewNoMarkStack(uint32_t threadId);
45    void ProcessOldToNew(uint32_t threadId, Region *region);  // for SemiGC
46    void ProcessSnapshotRSet(uint32_t threadId);              // for SemiGC
47    void ProcessSnapshotRSetNoMarkStack(uint32_t threadId);
48    virtual void MarkJitCodeMap([[maybe_unused]] uint32_t threadId)
49    {
50        LOG_GC(FATAL) << "can not call this method";
51    }
52
53    virtual void ProcessMarkStack([[maybe_unused]] uint32_t threadId)
54    {
55        LOG_GC(FATAL) << "can not call this method";
56    }
57
58    virtual void ProcessIncrementalMarkStack([[maybe_unused]] uint32_t threadId,
59                                             [[maybe_unused]] uint32_t markStepSize)
60    {
61        LOG_GC(FATAL) << "can not call this method";
62    }
63
64protected:
65    // non move
66    virtual inline void MarkObject([[maybe_unused]] uint32_t threadId, [[maybe_unused]] TaggedObject *object)
67    {
68        LOG_GC(FATAL) << "can not call this method";
69    }
70
71    virtual inline SlotStatus MarkObject([[maybe_unused]] uint32_t threadId, [[maybe_unused]] TaggedObject *object,
72                                         [[maybe_unused]] ObjectSlot slot)  // move
73    {
74        LOG_GC(FATAL) << "can not call this method";
75        return SlotStatus::KEEP_SLOT;
76    }
77
78    virtual inline void HandleNewToEdenRSet(uint32_t threadId, Region *region) = 0;
79    virtual inline void HandleOldToNewRSet(uint32_t threadId, Region *region) = 0;
80    virtual inline void HandleRoots(uint32_t threadId, [[maybe_unused]] Root type, ObjectSlot slot) = 0;
81    virtual inline void HandleRangeRoots(uint32_t threadId, [[maybe_unused]] Root type, ObjectSlot start,
82                                         ObjectSlot end) = 0;
83    virtual inline void HandleDerivedRoots(Root type, ObjectSlot base, ObjectSlot derived,
84                                           uintptr_t baseOldObject) = 0;
85    virtual inline void RecordWeakReference([[maybe_unused]] uint32_t threadId, [[maybe_unused]] JSTaggedType *ref,
86                                            [[maybe_unused]] Region *objectRegion)
87    {
88        LOG_GC(FATAL) << "can not call this method";
89    }
90
91    Heap *heap_ {nullptr};
92    WorkManager *workManager_ {nullptr};
93
94    friend class Heap;
95};
96
97class NonMovableMarker : public Marker {
98public:
99    explicit NonMovableMarker(Heap *heap) : Marker(heap) {}
100    ~NonMovableMarker() override = default;
101
102protected:
103    void ProcessMarkStack(uint32_t threadId) override;
104    void MarkJitCodeMap(uint32_t threadId) override;
105    template <typename Callback>
106    inline bool VisitBodyInObj(TaggedObject *root, ObjectSlot start, ObjectSlot end,
107                               bool needBarrier, Callback callback);
108    inline void MarkValue(uint32_t threadId, ObjectSlot &slot, Region *rootRegion, bool needBarrier);
109    inline void MarkObject(uint32_t threadId, TaggedObject *object) override;
110    inline void HandleRoots(uint32_t threadId, [[maybe_unused]] Root type, ObjectSlot slot) override;
111    inline void HandleRangeRoots(uint32_t threadId, [[maybe_unused]] Root type, ObjectSlot start,
112                                 ObjectSlot end) override;
113    inline void HandleDerivedRoots(Root type, ObjectSlot base, ObjectSlot derived,
114                                   uintptr_t baseOldObject) override;
115
116    inline void HandleNewToEdenRSet(uint32_t threadId, Region *region) override;
117    inline void HandleOldToNewRSet(uint32_t threadId, Region *region) override;
118    inline void RecordWeakReference(uint32_t threadId, JSTaggedType *ref, Region *objectRegion) override;
119    void ProcessIncrementalMarkStack(uint32_t threadId, uint32_t markStepSize) override;
120};
121
122class MovableMarker : public Marker {
123public:
124    explicit MovableMarker(Heap *heap) : Marker(heap) {}
125    ~MovableMarker() override = default;
126
127protected:
128    template <typename Callback>
129    inline bool VisitBodyInObj(TaggedObject *root, ObjectSlot start, ObjectSlot end, Callback callback);
130    inline void HandleRoots(uint32_t threadId, [[maybe_unused]] Root type, ObjectSlot slot) override;
131    inline void HandleRangeRoots(uint32_t threadId, [[maybe_unused]] Root type, ObjectSlot start,
132                                 ObjectSlot end) override;
133    inline void HandleDerivedRoots(Root type, ObjectSlot base, ObjectSlot derived,
134                                   uintptr_t baseOldObject) override;
135    virtual inline SlotStatus EvacuateObject(uint32_t threadId, TaggedObject *object, const MarkWord &markWord,
136                                             ObjectSlot slot) = 0;
137
138    inline void HandleNewToEdenRSet(uint32_t threadId, Region *region) override;
139    inline void HandleOldToNewRSet(uint32_t threadId, Region *region) override;
140
141    inline uintptr_t AllocateDstSpace(uint32_t threadId, size_t size, bool &shouldPromote);
142    inline void UpdateForwardAddressIfSuccess(uint32_t threadId, TaggedObject *object, JSHClass *klass,
143                                              uintptr_t toAddress, size_t size, ObjectSlot slot,
144                                              bool isPromoted = false);
145    inline bool UpdateForwardAddressIfFailed(TaggedObject *object, uintptr_t toAddress, size_t size, ObjectSlot slot);
146    inline void RawCopyObject(uintptr_t fromAddress, uintptr_t toAddress, size_t size, const MarkWord &markWord);
147    inline void UpdateLocalToShareRSet(TaggedObject *object, JSHClass *cls);
148
149    inline void SetLocalToShareRSet(ObjectSlot slot, Region *region);
150};
151
152class SemiGCMarker : public MovableMarker {
153public:
154    explicit SemiGCMarker(Heap *heap) : MovableMarker(heap) {}
155    ~SemiGCMarker() override = default;
156
157    void Initialize() override;
158
159protected:
160    void ProcessMarkStack(uint32_t threadId) override;
161    inline void MarkValue(uint32_t threadId, TaggedObject *root, ObjectSlot slot);
162    inline SlotStatus MarkObject(uint32_t threadId, TaggedObject *object, ObjectSlot slot) override;
163    inline SlotStatus EvacuateObject(uint32_t threadId, TaggedObject *object, const MarkWord &markWord,
164                                     ObjectSlot slot) override;
165    inline void RecordWeakReference(uint32_t threadId, JSTaggedType *ref, Region *objectRegion = nullptr) override;
166
167private:
168    inline bool ShouldBePromoted(TaggedObject *object);
169
170    uintptr_t waterLine_ {0};
171};
172
173class CompressGCMarker : public MovableMarker {
174public:
175    explicit CompressGCMarker(Heap *heap) : MovableMarker(heap) {}
176    ~CompressGCMarker() override = default;
177
178    inline bool NeedEvacuate(Region *region);
179    void SetAppSpawn(bool flag)
180    {
181        isAppSpawn_ = flag;
182    }
183
184protected:
185    void MarkJitCodeMap(uint32_t threadId) override;
186    void ProcessMarkStack(uint32_t threadId) override;
187    void HandleVisitJitCodeMap(uint32_t threadId, std::map<JSTaggedType, JitCodeVector *> &jitCodeMaps);
188    inline void MarkValue(uint32_t threadId, ObjectSlot slot);
189    inline SlotStatus MarkObject(uint32_t threadId, TaggedObject *object, ObjectSlot slot) override;
190
191    inline SlotStatus EvacuateObject(uint32_t threadId, TaggedObject *object, const MarkWord &markWord,
192                                     ObjectSlot slot) override;
193    uintptr_t AllocateForwardAddress(uint32_t threadId, size_t size, JSHClass *hclass, TaggedObject *object);
194    inline uintptr_t AllocateAppSpawnSpace(size_t size);
195    inline uintptr_t AllocateReadOnlySpace(size_t size);
196    inline void RecordWeakReference(uint32_t threadId, JSTaggedType *ref, Region *objectRegion = nullptr) override;
197
198private:
199    bool isAppSpawn_ {false};
200    Mutex mutex_;
201};
202}  // namespace panda::ecmascript
203#endif  // ECMASCRIPT_MEM_PARALLEL_MARKER_H
204