• 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 COMMON_COMPONENTS_MUTATOR_MUTATOR_H
17 #define COMMON_COMPONENTS_MUTATOR_MUTATOR_H
18 
19 #include <climits>
20 
21 #include "common_components/heap/allocator/allocator.h"
22 #include "common_components/heap/collector/gc_infos.h"
23 #include "common_components/mutator/thread_local.h"
24 #include "common_components/mutator/satb_buffer.h"
25 #include "common_interfaces/thread/mutator_base.h"
26 #include "common_interfaces/thread/thread_holder.h"
27 
28 namespace common {
29 class Mutator;
30 using FlipFunction = std::function<void(Mutator&)>;
31 class Mutator {
32 public:
33     using SuspensionType = MutatorBase::SuspensionType;
34     using GCPhaseTransitionState = MutatorBase::GCPhaseTransitionState;
35     using CpuProfileState = MutatorBase::CpuProfileState;
36     using SaferegionState = MutatorBase::SaferegionState;
37 
38     // Called when a mutator starts and finishes, respectively.
Init()39     void Init()
40     {
41         mutatorBase_.Init();
42         mutatorBase_.mutator_ = reinterpret_cast<void*>(this);
43         holder_ = new ThreadHolder(&mutatorBase_);
44     }
45 
~Mutator()46     ~Mutator()
47     {
48         tid_ = 0;
49         if (satbNode_ != nullptr) {
50             SatbBuffer::Instance().RetireNode(satbNode_);
51             satbNode_ = nullptr;
52         }
53         delete holder_;
54     }
55 
NewMutator()56     static Mutator* NewMutator()
57     {
58         Mutator* mutator = new (std::nothrow) Mutator();
59         LOGF_CHECK(mutator != nullptr) << "new Mutator failed";
60         mutator->Init();
61         return mutator;
62     }
63 
ResetMutator()64     void ResetMutator()
65     {
66         rawObject_.object = nullptr;
67         if (satbNode_ != nullptr) {
68             SatbBuffer::Instance().RetireNode(satbNode_);
69             satbNode_ = nullptr;
70         }
71     }
72 
73     static Mutator* GetMutator() noexcept;
74 
InitTid()75     void InitTid()
76     {
77         tid_ = ThreadLocal::GetThreadLocalData()->tid;
78         if (tid_ == 0) {
79             tid_ = static_cast<uint32_t>(GetTid());
80             ThreadLocal::GetThreadLocalData()->tid = tid_;
81         }
82     }
SetArkthreadPtr(void * threadPtr)83     void SetArkthreadPtr(void* threadPtr) { this->thread_ = threadPtr;}
SetEcmaVMPtr(void * ecmaVMPtr)84     void SetEcmaVMPtr(void* ecmaVMPtr) { this->ecmavm_ = ecmaVMPtr;}
GetTid()85     uint32_t GetTid() const { return tid_; }
GetArkthreadPtr()86     void* GetArkthreadPtr() const {return thread_;}
GetEcmaVMPtr()87     void* GetEcmaVMPtr() const {return ecmavm_;}
88 
SetSafepointActive(bool state)89     __attribute__((always_inline)) inline void SetSafepointActive(bool state)
90     {
91         mutatorBase_.SetSafepointActive(state);
92     }
93 
94     // Sets saferegion state of this mutator.
SetInSaferegion(SaferegionState state)95     __attribute__((always_inline)) inline void SetInSaferegion(SaferegionState state)
96     {
97         mutatorBase_.SetInSaferegion(state);
98     }
99 
100     // Returns true if this mutator is in saferegion, otherwise false.
InSaferegion()101     __attribute__((always_inline)) inline bool InSaferegion() const
102     {
103         return mutatorBase_.InSaferegion();
104     }
105 
106     // This interface can only be invoked in current thread environment.
UpdateUnwindContext()107     __attribute__((always_inline)) void UpdateUnwindContext()
108     {
109         // void* ip = __builtin_return_address(0)
110         // void* fa = __builtin_frame_address(0)
111         // uwContext.frameInfo.mFrame.SetIP(static_cast<uint32_t*>(ip))
112         // uwContext.frameInfo.mFrame.SetFA(static_cast<FrameAddress*>(fa)->callerFrameAddress)
113     }
114 
115     // Force current mutator enter saferegion, internal use only.
116     __attribute__((always_inline)) inline void DoEnterSaferegion();
117     // Force current mutator leave saferegion, internal use only.
DoLeaveSaferegion()118     __attribute__((always_inline)) inline void DoLeaveSaferegion()
119     {
120         mutatorBase_.DoLeaveSaferegion();
121     }
122 
123     // If current mutator is not in saferegion, enter and return true
124     // If current mutator has been in saferegion, return false
125     __attribute__((always_inline)) inline bool EnterSaferegion(bool updateUnwindContext) noexcept;
126     // If current mutator is in saferegion, leave and return true
127     // If current mutator has left saferegion, return false
128     __attribute__((always_inline)) inline bool LeaveSaferegion() noexcept;
129 
FinishedTransition()130     __attribute__((always_inline)) inline bool FinishedTransition() const
131     {
132         return mutatorBase_.FinishedTransition();
133     }
134 
FinishedCpuProfile()135     __attribute__((always_inline)) inline bool FinishedCpuProfile() const
136     {
137         return mutatorBase_.FinishedCpuProfile();
138     }
139 
SetCpuProfileState(CpuProfileState state)140     __attribute__((always_inline)) inline void SetCpuProfileState(CpuProfileState state)
141     {
142         mutatorBase_.SetCpuProfileState(state);
143     }
144 
SetSuspensionFlag(SuspensionType flag)145     __attribute__((always_inline)) inline void SetSuspensionFlag(SuspensionType flag)
146     {
147         mutatorBase_.SetSuspensionFlag(flag);
148     }
149 
ClearSuspensionFlag(SuspensionType flag)150     __attribute__((always_inline)) inline void ClearSuspensionFlag(SuspensionType flag)
151     {
152         mutatorBase_.ClearSuspensionFlag(flag);
153     }
154 
GetSuspensionFlag()155     __attribute__((always_inline)) inline uint32_t GetSuspensionFlag() const
156     {
157         return mutatorBase_.GetSuspensionFlag();
158     }
159 
HasSuspensionRequest(SuspensionType flag)160     __attribute__((always_inline)) inline bool HasSuspensionRequest(SuspensionType flag) const
161     {
162         return mutatorBase_.HasSuspensionRequest(flag);
163     }
164 
SetFinalizeRequest()165     void SetFinalizeRequest()
166     {
167         mutatorBase_.SetFinalizeRequest();
168     }
169 
170     // Ensure that mutator phase is changed only once by mutator itself or GC
171     __attribute__((always_inline)) inline bool TransitionGCPhase(bool bySelf);
172 
173     __attribute__((always_inline)) inline bool TransitionToCpuProfile(bool bySelf);
174 
SetMutatorPhase(const GCPhase newPhase)175     __attribute__((always_inline)) inline void SetMutatorPhase(const GCPhase newPhase)
176     {
177         mutatorBase_.SetMutatorPhase(newPhase);
178     }
179 
GetMutatorPhase()180     __attribute__((always_inline)) inline GCPhase GetMutatorPhase() const
181     {
182         return mutatorBase_.GetMutatorPhase();
183     }
184 
VisitMutatorRoots(const RootVisitor & visitor)185     void VisitMutatorRoots(const RootVisitor& visitor)
186     {
187         LOG_COMMON(FATAL) << "Unresolved fatal";
188         UNREACHABLE_CC();
189     }
190 
DumpMutator()191     void DumpMutator() const
192     {
193         LOG_COMMON(ERROR) << "mutator " << this << ": inSaferegion " <<
194             mutatorBase_.inSaferegion_.load(std::memory_order_relaxed) << ", tid " << tid_ <<
195             ", observerCnt " << mutatorBase_.observerCnt_.load() << ", gc phase: " <<
196             mutatorBase_.mutatorPhase_.load() << ", suspension request "<< mutatorBase_.suspensionFlag_.load();
197     }
198 
199     // Init after fork.
InitAfterFork()200     void InitAfterFork()
201     {
202         // tid changed after fork, so we re-initialize it.
203         InitTid();
204     }
205 
SetFlipFunction(FlipFunction * flipFunction)206     void SetFlipFunction(FlipFunction *flipFunction)
207     {
208         flipFunction_ = flipFunction;
209     }
210 
TryRunFlipFunction()211     bool TryRunFlipFunction()
212     {
213         while (true) {
214             uint32_t oldFlag = mutatorBase_.GetSuspensionFlag();
215             if ((oldFlag & SuspensionType::SUSPENSION_FOR_PENDING_CALLBACK) != 0) {
216                 uint32_t newFlag =
217                     MutatorBase::ConstructSuspensionFlag(oldFlag, SuspensionType::SUSPENSION_FOR_PENDING_CALLBACK,
218                                                          SuspensionType::SUSPENSION_FOR_RUNNING_CALLBACK);
219                 if (mutatorBase_.CASSetSuspensionFlag(oldFlag, newFlag)) {
220                     ASSERT(flipFunction_);
221                     (*flipFunction_)(*this);
222                     flipFunction_ = nullptr;
223                     std::unique_lock<std::mutex> lock(flipFunctionMtx_);
224                     mutatorBase_.ClearSuspensionFlag(SuspensionType::SUSPENSION_FOR_RUNNING_CALLBACK);
225                     flipFunctionCV_.notify_all();
226                     return true;
227                 }
228             } else {
229                 return false;
230             }
231         }
232     }
233 
WaitFlipFunctionFinish()234     void WaitFlipFunctionFinish()
235     {
236         while (true) {
237             std::unique_lock<std::mutex> lock(flipFunctionMtx_);
238             if (HasSuspensionRequest(SuspensionType::SUSPENSION_FOR_RUNNING_CALLBACK)) {
239                 flipFunctionCV_.wait(lock);
240             } else {
241                 return;
242             }
243         }
244     }
245 
246 #if defined(GCINFO_DEBUG) && GCINFO_DEBUG
PushFrameInfoForMarking(const GCInfoNode & frameGCInfo)247     void PushFrameInfoForMarking(const GCInfoNode& frameGCInfo) { gcInfos_.PushFrameInfoForMarking(frameGCInfo); }
248 
PushFrameInfoForMarking(const GCInfoNode && frameGCInfo)249     void PushFrameInfoForMarking(const GCInfoNode&& frameGCInfo) { gcInfos_.PushFrameInfoForMarking(frameGCInfo); }
250 
PushFrameInfoForFix(const GCInfoNodeForFix & frameGCInfo)251     void PushFrameInfoForFix(const GCInfoNodeForFix& frameGCInfo) { gcInfos_.PushFrameInfoForFix(frameGCInfo); }
252 
PushFrameInfoForFix(const GCInfoNodeForFix && frameGCInfo)253     void PushFrameInfoForFix(const GCInfoNodeForFix&& frameGCInfo) { gcInfos_.PushFrameInfoForFix(frameGCInfo); }
254 
DumpGCInfos()255     void DumpGCInfos() const
256     {
257         DLOG(ENUM, "dump mutator gc info thread id: %d", tid);
258         gcInfos_.DumpGCInfos();
259     }
260 #endif
261 
RememberObjectInSatbBuffer(const BaseObject * obj)262     NO_INLINE_CC void RememberObjectInSatbBuffer(const BaseObject* obj) { RememberObjectImpl(obj); }
263 
GetSatbBufferNode()264     const SatbBuffer::TreapNode* GetSatbBufferNode() const { return satbNode_; }
265 
ClearSatbBufferNode()266     void ClearSatbBufferNode()
267     {
268         if (satbNode_ == nullptr) {
269             return;
270         }
271         satbNode_->Clear();
272     }
273 
274 #ifdef _WIN64
GetStackGrowFrameSize()275     uint32_t GetStackGrowFrameSize() { return stackGrowFrameSize_; }
SetStackGrowFrameSize(uint32_t sgfs)276     void SetStackGrowFrameSize(uint32_t sgfs) { stackGrowFrameSize_ = sgfs; }
277 #endif
278 
PushRawObject(BaseObject * obj)279     void PushRawObject(BaseObject* obj) { rawObject_.object = obj; }
280 
PopRawObject()281     BaseObject* PopRawObject()
282     {
283         BaseObject* obj = rawObject_.object;
284         rawObject_.object = nullptr;
285         return obj;
286     }
MutatorLock()287     void MutatorLock()
288     {
289         mutatorBase_.MutatorBaseLock();
290     }
291 
MutatorUnlock()292     void MutatorUnlock()
293     {
294         mutatorBase_.MutatorBaseUnlock();
295     }
296 
297     // temporary impl
GetMutatorBasePtr()298     void *GetMutatorBasePtr()
299     {
300         return &mutatorBase_;
301     }
302 
GetThreadHolder()303     ThreadHolder *GetThreadHolder()
304     {
305         return holder_;
306     }
307 
308 protected:
309     // for exception ref
310     void VisitRawObjects(const RootVisitor& func);
311     void CreateCurrentGCInfo();
312 
313 private:
RememberObjectImpl(const BaseObject * obj)314     void RememberObjectImpl(const BaseObject* obj)
315     {
316         if (LIKELY_CC(Heap::IsHeapAddress(obj))) {
317             if (SatbBuffer::Instance().ShouldEnqueue(obj)) {
318                 SatbBuffer::Instance().EnsureGoodNode(satbNode_);
319                 satbNode_->Push(obj);
320             }
321         }
322     }
323     // Indicate the current mutator phase and use which barrier in concurrent gc
324     // ATTENTION: THE LAYOUT FOR GCPHASE MUST NOT BE CHANGED!
325     // currently store struct instead of pointer to keep GCPHASE offset to this is 0
326     MutatorBase mutatorBase_ {};
327     // thread id
328     uint32_t tid_ = 0;
329     // thread ptr
330     void* thread_;
331     // ecmavm
332     void* ecmavm_ = nullptr;
333 #ifndef __WIN64
334     void* unuse_ = nullptr; // reusable placeholder
335 #endif // __WIN64
336 
337 #ifdef _WIN64
338     uint32_t stackGrowFrameSize_ = 0;
339 #endif
340 
341     ObjectRef rawObject_{ nullptr };
342     std::mutex flipFunctionMtx_;
343     std::condition_variable flipFunctionCV_;
344     FlipFunction* flipFunction_ {nullptr};
345     SatbBuffer::TreapNode* satbNode_ = nullptr;
346 #if defined(GCINFO_DEBUG) && GCINFO_DEBUG
347     GCInfos gcInfos_;
348 #endif
349 
350     ThreadHolder *holder_;
351 
352     friend MutatorBase;
353     friend ThreadHolder;
354 };
355 
356 // This function is mainly used to initialize the context of mutator.
357 // Ensured that updated fa is the caller layer of the managed function to be called.
358 void PreRunManagedCode(Mutator* mutator, int layers, ThreadLocalData* threadData);
359 
360 ThreadLocalData *GetThreadLocalData();
361 } // namespace common
362 
363 #endif // COMMON_COMPONENTS_MUTATOR_MUTATOR_H
364