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_CHECKPOINT_THREAD_STATE_TRANSITION_H 17 #define ECMASCRIPT_CHECKPOINT_THREAD_STATE_TRANSITION_H 18 19 #include "ecmascript/runtime.h" 20 21 namespace panda::ecmascript { 22 23 template<typename T, ThreadState newState> 24 class ThreadStateTransitionScope final { 25 static_assert(std::is_base_of_v<JSThread, T>); 26 static_assert(!std::is_same_v<JitThread, T>); 27 public: ThreadStateTransitionScope(T * self)28 explicit ThreadStateTransitionScope(T* self) 29 : self_(self) 30 { 31 ASSERT(self_ != nullptr); 32 oldState_ = self_->GetState(); 33 if constexpr (std::is_same_v<DaemonThread, T>) { 34 if (oldState_ != newState) { 35 ASSERT(hasSwitchState_ == false); 36 hasSwitchState_ = true; 37 if constexpr (newState == ThreadState::RUNNING) { 38 self_->TransferDaemonThreadToRunning(); 39 } else { 40 self_->UpdateState(newState); 41 } 42 } 43 } else { 44 #if ECMASCRIPT_ENABLE_SCOPE_LOCK_STAT 45 auto vm = self_->GetEcmaVM(); 46 bool isCollectingStats = vm->IsCollectingScopeLockStats(); 47 if (isCollectingStats) { 48 vm->IncreaseEnterThreadManagedScopeCount(); 49 } 50 #endif 51 if (oldState_ != newState) { 52 #if ECMASCRIPT_ENABLE_SCOPE_LOCK_STAT 53 if (isCollectingStats) { 54 vm->IncreaseUpdateThreadStateTransCount(); 55 } 56 #endif 57 ASSERT(hasSwitchState_ == false); 58 hasSwitchState_ = true; 59 self_->UpdateState(newState); 60 } 61 } 62 } 63 ~ThreadStateTransitionScope()64 ~ThreadStateTransitionScope() 65 { 66 if (hasSwitchState_) { 67 if constexpr (std::is_same_v<DaemonThread, T>) { 68 if (oldState_ == ThreadState::RUNNING) { 69 self_->TransferDaemonThreadToRunning(); 70 } else { 71 self_->UpdateState(oldState_); 72 } 73 } else { 74 self_->UpdateState(oldState_); 75 } 76 } 77 } 78 79 private: 80 T* self_; 81 ThreadState oldState_; 82 bool hasSwitchState_ {false}; 83 NO_COPY_SEMANTIC(ThreadStateTransitionScope); 84 }; 85 86 class ThreadSuspensionScope final { 87 public: ThreadSuspensionScope(JSThread * self)88 explicit ThreadSuspensionScope(JSThread* self) : scope_(self) 89 { 90 ASSERT(self->GetState() == ThreadState::IS_SUSPENDED); 91 } 92 93 ~ThreadSuspensionScope() = default; 94 95 private: 96 ThreadStateTransitionScope<JSThread, ThreadState::IS_SUSPENDED> scope_; 97 NO_COPY_SEMANTIC(ThreadSuspensionScope); 98 }; 99 100 class ThreadNativeScope final { 101 public: ThreadNativeScope(JSThread * self)102 explicit ThreadNativeScope(JSThread* self) : scope_(self) 103 { 104 ASSERT(self->GetState() == ThreadState::NATIVE); 105 } 106 107 ~ThreadNativeScope() = default; 108 109 private: 110 ThreadStateTransitionScope<JSThread, ThreadState::NATIVE> scope_; 111 NO_COPY_SEMANTIC(ThreadNativeScope); 112 }; 113 114 template<typename T> 115 class ThreadManagedScope final { 116 static_assert(std::is_base_of_v<JSThread, T>); 117 static_assert(!std::is_same_v<JitThread, T>); 118 public: ThreadManagedScope(T * self)119 explicit ThreadManagedScope(T* self) : scope_(self) {} 120 121 ~ThreadManagedScope() = default; 122 123 private: 124 ThreadStateTransitionScope<T, ThreadState::RUNNING> scope_; 125 NO_COPY_SEMANTIC(ThreadManagedScope); 126 }; 127 128 template<typename T> 129 class SuspendAllScope final { 130 static_assert(std::is_base_of_v<JSThread, T>); 131 static_assert(!std::is_same_v<JitThread, T>); 132 public: SuspendAllScope(T * self)133 explicit SuspendAllScope(T* self) 134 : self_(self), scope_(self) 135 { 136 TRACE_GC(GCStats::Scope::ScopeId::SuspendAll, SharedHeap::GetInstance()->GetEcmaGCStats()); 137 ECMA_BYTRACE_NAME(HITRACE_TAG_ARK, "SuspendAll"); 138 Runtime::GetInstance()->SuspendAll(self_); 139 } ~SuspendAllScope()140 ~SuspendAllScope() 141 { 142 TRACE_GC(GCStats::Scope::ScopeId::ResumeAll, SharedHeap::GetInstance()->GetEcmaGCStats()); 143 ECMA_BYTRACE_NAME(HITRACE_TAG_ARK, "ResumeAll"); 144 Runtime::GetInstance()->ResumeAll(self_); 145 } 146 private: 147 T* self_; 148 ThreadStateTransitionScope<T, ThreadState::IS_SUSPENDED> scope_; 149 NO_COPY_SEMANTIC(SuspendAllScope); 150 }; 151 } // namespace panda::ecmascript 152 #endif // ECMASCRIPT_CHECKPOINT_THREAD_STATE_TRANSITION_H 153