• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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             if (LIKELY(!self_->IsEnableCMCGC())) {
33                 if constexpr (std::is_same_v<DaemonThread, T>) {
34                     oldState_ = self_->GetState();
35                     if (oldState_ != newState) {
36                         ASSERT(hasSwitchState_ == false);
37                         hasSwitchState_ = true;
38                         if constexpr (newState == ThreadState::RUNNING) {
39                             self_->TransferDaemonThreadToRunning();
40                         } else {
41                             self_->UpdateState(newState);
42                         }
43                     }
44                 } else {
45 #if ECMASCRIPT_ENABLE_SCOPE_LOCK_STAT
46                     auto vm = self_->GetEcmaVM();
47                     bool isCollectingStats = vm->IsCollectingScopeLockStats();
48                     if (isCollectingStats) {
49                         vm->IncreaseEnterThreadManagedScopeCount();
50                     }
51 #endif
52                     if constexpr (newState == ThreadState::RUNNING) {
53                         oldState_ = self_->TransferToRunningIfNonRunning();
54                     } else {
55                         oldState_ = self_->TransferToNonRunning(newState);
56                     }
57                     ASSERT(hasSwitchState_ == false);
58                     hasSwitchState_ = oldState_ != newState;
59 #if ECMASCRIPT_ENABLE_SCOPE_LOCK_STAT
60                     if (hasSwitchState_) {
61                         if (isCollectingStats) {
62                             vm->IncreaseUpdateThreadStateTransCount();
63                         }
64                     }
65 #endif
66                 }
67             } else {
68                 isEnbaleCMCGC_ = true;
69                 if constexpr (newState == ThreadState::RUNNING) {
70                     hasSwitchState_ = self_->GetThreadHolder()->TransferToRunningIfInNative();
71                 } else {
72                     hasSwitchState_ = self_->GetThreadHolder()->TransferToNativeIfInRunning();
73                 }
74             }
75         }
76 
~ThreadStateTransitionScope()77     ~ThreadStateTransitionScope()
78     {
79         if (LIKELY(hasSwitchState_)) {
80             if (LIKELY(!isEnbaleCMCGC_)) {
81                 if constexpr (std::is_same_v<DaemonThread, T>) {
82                     if (oldState_ == ThreadState::RUNNING) {
83                         self_->TransferDaemonThreadToRunning();
84                     } else {
85                         self_->UpdateState(oldState_);
86                     }
87                 } else {
88                     if constexpr (newState == ThreadState::RUNNING) {
89                         self_->TransferToNonRunningInRunning(oldState_);
90                     } else {
91                         self_->TransferInNonRunning(oldState_);
92                     }
93                 }
94             } else {
95                 if constexpr (newState == ThreadState::RUNNING) {
96                     self_->GetThreadHolder()->TransferToNative();
97                 } else {
98                     self_->GetThreadHolder()->TransferToRunning();
99                 }
100             }
101         }
102     }
103 
104 private:
105     T* self_;
106     ThreadState oldState_;
107     uint32_t isEnbaleCMCGC_ {0};
108     uint32_t hasSwitchState_ {0};
109     NO_COPY_SEMANTIC(ThreadStateTransitionScope);
110 };
111 
112 class ThreadSuspensionScope final {
113 public:
ThreadSuspensionScope(JSThread * self)114     explicit ThreadSuspensionScope(JSThread* self) : scope_(self)
115     {
116         ASSERT(!g_isEnableCMCGC || !self->IsInRunningState());
117         ASSERT(g_isEnableCMCGC || self->GetState() == ThreadState::IS_SUSPENDED);
118     }
119 
120     ~ThreadSuspensionScope() = default;
121 
122 private:
123     ThreadStateTransitionScope<JSThread, ThreadState::IS_SUSPENDED> scope_;
124     NO_COPY_SEMANTIC(ThreadSuspensionScope);
125 };
126 
127 class ThreadNativeScope final {
128 public:
ThreadNativeScope(JSThread * self)129     explicit ThreadNativeScope(JSThread* self) : scope_(self)
130     {
131         ASSERT(!self->IsInRunningState());
132     }
133 
134     ~ThreadNativeScope() = default;
135 
136 private:
137     ThreadStateTransitionScope<JSThread, ThreadState::NATIVE> scope_;
138     NO_COPY_SEMANTIC(ThreadNativeScope);
139 };
140 
141 template<typename T>
142 class ThreadManagedScope final {
143     static_assert(std::is_base_of_v<JSThread, T>);
144     static_assert(!std::is_same_v<JitThread, T>);
145 public:
ThreadManagedScope(T * self)146     explicit ThreadManagedScope(T* self) : scope_(self) {}
147 
148     ~ThreadManagedScope() = default;
149 
150 private:
151     ThreadStateTransitionScope<T, ThreadState::RUNNING> scope_;
152     NO_COPY_SEMANTIC(ThreadManagedScope);
153 };
154 
155 template<typename T>
156 class SuspendAllScope final {
157     static_assert(std::is_base_of_v<JSThread, T>);
158     static_assert(!std::is_same_v<JitThread, T>);
159 public:
SuspendAllScope(T * self)160     explicit SuspendAllScope(T* self)
161         : self_(self), scope_(self)
162     {
163         TRACE_GC(GCStats::Scope::ScopeId::SuspendAll, SharedHeap::GetInstance()->GetEcmaGCStats());
164         ECMA_BYTRACE_NAME(HITRACE_LEVEL_COMMERCIAL, HITRACE_TAG_ARK, "SuspendAll", "");
165         Runtime::GetInstance()->SuspendAll(self_);
166     }
~SuspendAllScope()167     ~SuspendAllScope()
168     {
169         TRACE_GC(GCStats::Scope::ScopeId::ResumeAll, SharedHeap::GetInstance()->GetEcmaGCStats());
170         ECMA_BYTRACE_NAME(HITRACE_LEVEL_COMMERCIAL, HITRACE_TAG_ARK, "ResumeAll", "");
171         Runtime::GetInstance()->ResumeAll(self_);
172     }
173 private:
174     T* self_;
175     ThreadStateTransitionScope<T, ThreadState::IS_SUSPENDED> scope_;
176     NO_COPY_SEMANTIC(SuspendAllScope);
177 };
178 }  // namespace panda::ecmascript
179 #endif  // ECMASCRIPT_CHECKPOINT_THREAD_STATE_TRANSITION_H
180