• 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 #include "ecmascript/pgo_profiler/pgo_state.h"
17 
18 #include "ecmascript/checkpoint/thread_state_transition.h"
19 #include "ecmascript/js_thread.h"
20 #include "ecmascript/pgo_profiler/pgo_profiler.h"
21 #include "ecmascript/pgo_profiler/pgo_profiler_manager.h"
22 
23 namespace panda::ecmascript::pgo {
24 using State = PGOState::State;
25 using GCState = PGOState::GCState;
PGOState()26 PGOState::PGOState()
27 {
28     manager_ = PGOProfilerManager::GetInstance();
29 }
30 
ToString(State state)31 std::string PGOState::ToString(State state)
32 {
33     switch (state) {
34         case State::STOP:
35             return "STOP";
36         case State::SAVE:
37             return "SAVE";
38         case State::START:
39             return "START";
40         default:
41             return "UNKNOWN";
42     }
43 }
44 
ToString(GCState state)45 std::string PGOState::ToString(GCState state)
46 {
47     switch (state) {
48         case GCState::STOP:
49             return "STOP";
50         case GCState::WAITING:
51             return "WAITING";
52         case GCState::RUNNING:
53             return "RUNNING";
54         default:
55             return "UNKNOWN";
56     }
57 }
58 
GetState() const59 State PGOState::GetState() const
60 {
61     return state_.load(std::memory_order_acquire);
62 }
63 
SetState(State state)64 void PGOState::SetState(State state)
65 {
66 #if PRINT_STATE_CHANGE
67     PrintStateChange(GetState(), state);
68 #endif
69     state_.store(state, std::memory_order_release);
70 }
71 
GCIsWaiting() const72 bool PGOState::GCIsWaiting() const
73 {
74     GCState gcState = GetGCState();
75     return gcState == GCState::WAITING;
76 }
77 
GCIsRunning() const78 bool PGOState::GCIsRunning() const
79 {
80     GCState gcState = GetGCState();
81     return gcState == GCState::RUNNING;
82 }
83 
GCIsStop() const84 bool PGOState::GCIsStop() const
85 {
86     GCState gcState = GetGCState();
87     return gcState == GCState::STOP;
88 }
89 
StateIsStop() const90 bool PGOState::StateIsStop() const
91 {
92     State state = GetState();
93     return state == State::STOP;
94 }
95 
StateIsStart() const96 bool PGOState::StateIsStart() const
97 {
98     State state = GetState();
99     return state == State::START;
100 }
101 
StateIsSave() const102 bool PGOState::StateIsSave() const
103 {
104     State state = GetState();
105     return state == State::SAVE;
106 }
107 
108 #if PRINT_STATE_CHANGE
TryChangeState(State expected,State desired)109 bool PGOState::TryChangeState(State expected, State desired)
110 {
111     auto original = expected;
112     if (state_.compare_exchange_strong(expected, desired, std::memory_order_acq_rel)) {
113         PrintStateChange(expected, desired);
114         return true;
115     }
116     PrintStateChange(original, expected, desired);
117     return false;
118 }
119 #endif
120 
121 #if !PRINT_STATE_CHANGE
TryChangeState(State expected,State desired)122 bool PGOState::TryChangeState(State expected, State desired)
123 {
124     if (state_.compare_exchange_strong(expected, desired, std::memory_order_acq_rel)) {
125         return true;
126     }
127     return false;
128 }
129 #endif
130 
SetGCState(GCState state)131 void PGOState::SetGCState(GCState state)
132 {
133     gcState_.store(state, std::memory_order_release);
134 }
135 
GetGCState() const136 GCState PGOState::GetGCState() const
137 {
138     return gcState_.load(std::memory_order_acquire);
139 }
140 
SuspendByGC()141 void PGOState::SuspendByGC()
142 {
143     LockHolder lock(stateMutex_);
144     // possible state: START, SAVE, STOP
145     if (StateIsStart()) {
146         // possible gc state: STOP
147         SetGCState(GCState::WAITING);
148         needRedump_ = true;
149         WaitDump();
150     }
151     // possible gc state: STOP, WAITING
152     SetGCState(GCState::RUNNING);
153 }
154 
ResumeByGC(PGOProfiler * profiler)155 void PGOState::ResumeByGC(PGOProfiler* profiler)
156 {
157     LockHolder lock(stateMutex_);
158     // possible state: START, SAVE, STOP
159     SetGCState(GCState::STOP);
160     if (needRedump_) {
161         manager_->TryDispatchDumpTask(profiler);
162         needRedump_ = false;
163     }
164     NotifyAllGCWaiters();
165 }
166 
SetStartIfStop()167 bool PGOState::SetStartIfStop()
168 {
169     LockHolder lock(stateMutex_);
170     // possible state: STOP, SAVE
171     // possible gc state: STOP, WAITING, RUNNING
172     if (GCIsStop() && TryChangeState(State::STOP, State::START)) {
173         return true;
174     }
175     return false;
176 }
177 
SetStopAndNotify()178 void PGOState::SetStopAndNotify()
179 {
180     LockHolder lock(stateMutex_);
181     // possible state: START, SAVE
182     SetState(State::STOP);
183     NotifyAllDumpWaiters();
184 }
185 
SetSaveAndNotify()186 void PGOState::SetSaveAndNotify()
187 {
188     LockHolder lock(stateMutex_);
189     // possible state: START
190     SetState(State::SAVE);
191     NotifyAllDumpWaiters();
192 }
193 
StartDumpBeforeDestroy(JSThread * thread)194 void PGOState::StartDumpBeforeDestroy([[maybe_unused]] JSThread *thread)
195 {
196     LockHolder lock(stateMutex_);
197     // possible state: STOP, SAVE, START
198     // may notify after change to STOP and SAVE, we need to make sure state is STOP
199     while (!StateIsStop()) {
200         WaitDump();
201     }
202     // possible gc state: STOP, WAITING, RUNNING
203     if (!GCIsStop()) {
204         WaitGC();
205     }
206     SetState(State::START);
207 }
208 
WaitDump()209 void PGOState::WaitDump()
210 {
211     stateCondition_.Wait(&stateMutex_);
212 }
213 
NotifyAllDumpWaiters()214 void PGOState::NotifyAllDumpWaiters()
215 {
216     stateCondition_.SignalAll();
217 }
218 
WaitGC()219 void PGOState::WaitGC()
220 {
221     gcCondition_.Wait(&stateMutex_);
222 }
223 
NotifyAllGCWaiters()224 void PGOState::NotifyAllGCWaiters()
225 {
226     gcCondition_.SignalAll();
227 }
228 } // namespace panda::ecmascript::pgo
229