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