• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**
2  * Copyright (c) 2022-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 "thread_state.h"
17 
18 namespace ark::tooling::inspector {
GetBreakpointsByLocation(const PtLocation & location) const19 std::vector<BreakpointId> ThreadState::GetBreakpointsByLocation(const PtLocation &location) const
20 {
21     std::vector<BreakpointId> hitBreakpoints;
22 
23     auto range = breakpointLocations_.equal_range(location);
24     std::transform(range.first, range.second, std::back_inserter(hitBreakpoints), [](auto &p) { return p.second; });
25 
26     return hitBreakpoints;
27 }
28 
Reset()29 void ThreadState::Reset()
30 {
31     if (stepKind_ != StepKind::BREAK_ON_START) {
32         stepKind_ = StepKind::NONE;
33     }
34     stepLocations_.clear();
35     methodEntered_ = false;
36     breakpointsActive_ = true;
37     nextBreakpointId_ = 0;
38     breakpointLocations_.clear();
39     pauseOnExceptionsState_ = PauseOnExceptionsState::NONE;
40 }
41 
BreakOnStart()42 void ThreadState::BreakOnStart()
43 {
44     if (!paused_) {
45         stepKind_ = StepKind::BREAK_ON_START;
46     }
47 }
48 
Continue()49 void ThreadState::Continue()
50 {
51     stepKind_ = StepKind::NONE;
52     paused_ = false;
53 }
54 
ContinueTo(std::unordered_set<PtLocation,HashLocation> locations)55 void ThreadState::ContinueTo(std::unordered_set<PtLocation, HashLocation> locations)
56 {
57     stepKind_ = StepKind::CONTINUE_TO;
58     stepLocations_ = std::move(locations);
59     paused_ = false;
60 }
61 
StepInto(std::unordered_set<PtLocation,HashLocation> locations)62 void ThreadState::StepInto(std::unordered_set<PtLocation, HashLocation> locations)
63 {
64     stepKind_ = StepKind::STEP_INTO;
65     methodEntered_ = false;
66     stepLocations_ = std::move(locations);
67     paused_ = false;
68 }
69 
StepOver(std::unordered_set<PtLocation,HashLocation> locations)70 void ThreadState::StepOver(std::unordered_set<PtLocation, HashLocation> locations)
71 {
72     stepKind_ = StepKind::STEP_OVER;
73     methodEntered_ = false;
74     stepLocations_ = std::move(locations);
75     paused_ = false;
76 }
77 
StepOut()78 void ThreadState::StepOut()
79 {
80     stepKind_ = StepKind::STEP_OUT;
81     methodEntered_ = true;
82     paused_ = false;
83 }
84 
Pause()85 void ThreadState::Pause()
86 {
87     if (!paused_) {
88         stepKind_ = StepKind::PAUSE;
89     }
90 }
91 
SetBreakpointsActive(bool active)92 void ThreadState::SetBreakpointsActive(bool active)
93 {
94     breakpointsActive_ = active;
95 }
96 
SetBreakpoint(const std::vector<PtLocation> & locations)97 BreakpointId ThreadState::SetBreakpoint(const std::vector<PtLocation> &locations)
98 {
99     auto id = nextBreakpointId_++;
100     for (auto &location : locations) {
101         breakpointLocations_.emplace(location, id);
102     }
103 
104     return id;
105 }
106 
RemoveBreakpoint(BreakpointId id)107 void ThreadState::RemoveBreakpoint(BreakpointId id)
108 {
109     for (auto it = breakpointLocations_.begin(); it != breakpointLocations_.end();) {
110         if (it->second == id) {
111             it = breakpointLocations_.erase(it);
112         } else {
113             ++it;
114         }
115     }
116 }
117 
SetPauseOnExceptions(PauseOnExceptionsState state)118 void ThreadState::SetPauseOnExceptions(PauseOnExceptionsState state)
119 {
120     pauseOnExceptionsState_ = state;
121 }
122 
OnException(bool uncaught)123 void ThreadState::OnException(bool uncaught)
124 {
125     ASSERT(!paused_);
126     switch (pauseOnExceptionsState_) {
127         case PauseOnExceptionsState::NONE:
128             break;
129         case PauseOnExceptionsState::CAUGHT:
130             paused_ = !uncaught;
131             break;
132         case PauseOnExceptionsState::UNCAUGHT:
133             paused_ = uncaught;
134             break;
135         case PauseOnExceptionsState::ALL:
136             paused_ = true;
137             break;
138     }
139 }
140 
OnFramePop()141 void ThreadState::OnFramePop()
142 {
143     ASSERT(!paused_);
144     switch (stepKind_) {
145         case StepKind::NONE:
146         case StepKind::BREAK_ON_START:
147         case StepKind::CONTINUE_TO:
148         case StepKind::PAUSE:
149         case StepKind::STEP_INTO: {
150             break;
151         }
152 
153         case StepKind::STEP_OUT:
154         case StepKind::STEP_OVER: {
155             methodEntered_ = false;
156             break;
157         }
158     }
159 }
160 
OnMethodEntry()161 bool ThreadState::OnMethodEntry()
162 {
163     ASSERT(!paused_);
164     switch (stepKind_) {
165         case StepKind::NONE:
166         case StepKind::BREAK_ON_START:
167         case StepKind::CONTINUE_TO:
168         case StepKind::PAUSE:
169         case StepKind::STEP_INTO: {
170             return false;
171         }
172 
173         case StepKind::STEP_OUT:
174         case StepKind::STEP_OVER: {
175             return !std::exchange(methodEntered_, true);
176         }
177     }
178 
179     UNREACHABLE();
180 }
181 
OnSingleStep(const PtLocation & location)182 void ThreadState::OnSingleStep(const PtLocation &location)
183 {
184     ASSERT(!paused_);
185     if (!breakpointsActive_ || breakpointLocations_.find(location) == breakpointLocations_.end()) {
186         switch (stepKind_) {
187             case StepKind::NONE: {
188                 paused_ = false;
189                 break;
190             }
191 
192             case StepKind::BREAK_ON_START: {
193                 paused_ = true;
194                 break;
195             }
196 
197             case StepKind::CONTINUE_TO: {
198                 paused_ = stepLocations_.find(location) != stepLocations_.end();
199                 break;
200             }
201 
202             case StepKind::PAUSE: {
203                 paused_ = true;
204                 break;
205             }
206 
207             case StepKind::STEP_INTO: {
208                 paused_ = stepLocations_.find(location) == stepLocations_.end();
209                 break;
210             }
211 
212             case StepKind::STEP_OUT: {
213                 paused_ = !methodEntered_;
214                 break;
215             }
216 
217             case StepKind::STEP_OVER: {
218                 paused_ = !methodEntered_ && stepLocations_.find(location) == stepLocations_.end();
219                 break;
220             }
221         }
222     } else {
223         paused_ = true;
224     }
225 }
226 }  // namespace ark::tooling::inspector
227