• 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             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