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