OLD | NEW |
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 #include "vm/debugger.h" | 5 #include "vm/debugger.h" |
6 | 6 |
7 #include "include/dart_api.h" | 7 #include "include/dart_api.h" |
8 | 8 |
9 #include "platform/address_sanitizer.h" | 9 #include "platform/address_sanitizer.h" |
10 | 10 |
(...skipping 18 matching lines...) Expand all Loading... |
29 #include "vm/service_isolate.h" | 29 #include "vm/service_isolate.h" |
30 #include "vm/stack_frame.h" | 30 #include "vm/stack_frame.h" |
31 #include "vm/stack_trace.h" | 31 #include "vm/stack_trace.h" |
32 #include "vm/stub_code.h" | 32 #include "vm/stub_code.h" |
33 #include "vm/symbols.h" | 33 #include "vm/symbols.h" |
34 #include "vm/thread_interrupter.h" | 34 #include "vm/thread_interrupter.h" |
35 #include "vm/timeline.h" | 35 #include "vm/timeline.h" |
36 #include "vm/token_position.h" | 36 #include "vm/token_position.h" |
37 #include "vm/visitor.h" | 37 #include "vm/visitor.h" |
38 | 38 |
39 | |
40 namespace dart { | 39 namespace dart { |
41 | 40 |
42 DEFINE_FLAG(bool, | 41 DEFINE_FLAG(bool, |
43 show_invisible_frames, | 42 show_invisible_frames, |
44 false, | 43 false, |
45 "Show invisible frames in debugger stack traces"); | 44 "Show invisible frames in debugger stack traces"); |
46 DEFINE_FLAG(bool, | 45 DEFINE_FLAG(bool, |
47 trace_debugger_stacktrace, | 46 trace_debugger_stacktrace, |
48 false, | 47 false, |
49 "Trace debugger stacktrace collection"); | 48 "Trace debugger stacktrace collection"); |
50 DEFINE_FLAG(bool, trace_rewind, false, "Trace frame rewind"); | 49 DEFINE_FLAG(bool, trace_rewind, false, "Trace frame rewind"); |
51 DEFINE_FLAG(bool, verbose_debug, false, "Verbose debugger messages"); | 50 DEFINE_FLAG(bool, verbose_debug, false, "Verbose debugger messages"); |
52 DEFINE_FLAG(bool, | 51 DEFINE_FLAG(bool, |
53 steal_breakpoints, | 52 steal_breakpoints, |
54 false, | 53 false, |
55 "Intercept breakpoints and other pause events before they " | 54 "Intercept breakpoints and other pause events before they " |
56 "are sent to the embedder and use a generic VM breakpoint " | 55 "are sent to the embedder and use a generic VM breakpoint " |
57 "handler instead. This handler dispatches breakpoints to " | 56 "handler instead. This handler dispatches breakpoints to " |
58 "the VM service."); | 57 "the VM service."); |
59 | 58 |
60 DECLARE_FLAG(bool, warn_on_pause_with_no_debugger); | 59 DECLARE_FLAG(bool, warn_on_pause_with_no_debugger); |
61 | 60 |
62 | |
63 #ifndef PRODUCT | 61 #ifndef PRODUCT |
64 | 62 |
65 Debugger::EventHandler* Debugger::event_handler_ = NULL; | 63 Debugger::EventHandler* Debugger::event_handler_ = NULL; |
66 | 64 |
67 | |
68 class RemoteObjectCache : public ZoneAllocated { | 65 class RemoteObjectCache : public ZoneAllocated { |
69 public: | 66 public: |
70 explicit RemoteObjectCache(intptr_t initial_size); | 67 explicit RemoteObjectCache(intptr_t initial_size); |
71 intptr_t AddObject(const Object& obj); | 68 intptr_t AddObject(const Object& obj); |
72 RawObject* GetObj(intptr_t obj_id) const; | 69 RawObject* GetObj(intptr_t obj_id) const; |
73 bool IsValidId(intptr_t obj_id) const { return obj_id < objs_->Length(); } | 70 bool IsValidId(intptr_t obj_id) const { return obj_id < objs_->Length(); } |
74 | 71 |
75 private: | 72 private: |
76 GrowableObjectArray* objs_; | 73 GrowableObjectArray* objs_; |
77 | 74 |
78 DISALLOW_COPY_AND_ASSIGN(RemoteObjectCache); | 75 DISALLOW_COPY_AND_ASSIGN(RemoteObjectCache); |
79 }; | 76 }; |
80 | 77 |
81 | |
82 // Create an unresolved breakpoint in given token range and script. | 78 // Create an unresolved breakpoint in given token range and script. |
83 BreakpointLocation::BreakpointLocation(const Script& script, | 79 BreakpointLocation::BreakpointLocation(const Script& script, |
84 TokenPosition token_pos, | 80 TokenPosition token_pos, |
85 TokenPosition end_token_pos, | 81 TokenPosition end_token_pos, |
86 intptr_t requested_line_number, | 82 intptr_t requested_line_number, |
87 intptr_t requested_column_number) | 83 intptr_t requested_column_number) |
88 : script_(script.raw()), | 84 : script_(script.raw()), |
89 url_(script.url()), | 85 url_(script.url()), |
90 token_pos_(token_pos), | 86 token_pos_(token_pos), |
91 end_token_pos_(end_token_pos), | 87 end_token_pos_(end_token_pos), |
(...skipping 21 matching lines...) Expand all Loading... |
113 next_(NULL), | 109 next_(NULL), |
114 conditions_(NULL), | 110 conditions_(NULL), |
115 requested_line_number_(requested_line_number), | 111 requested_line_number_(requested_line_number), |
116 requested_column_number_(requested_column_number), | 112 requested_column_number_(requested_column_number), |
117 function_(Function::null()), | 113 function_(Function::null()), |
118 line_number_(-1), | 114 line_number_(-1), |
119 column_number_(-1) { | 115 column_number_(-1) { |
120 ASSERT(requested_line_number_ >= 0); | 116 ASSERT(requested_line_number_ >= 0); |
121 } | 117 } |
122 | 118 |
123 | |
124 BreakpointLocation::~BreakpointLocation() { | 119 BreakpointLocation::~BreakpointLocation() { |
125 Breakpoint* bpt = breakpoints(); | 120 Breakpoint* bpt = breakpoints(); |
126 while (bpt != NULL) { | 121 while (bpt != NULL) { |
127 Breakpoint* temp = bpt; | 122 Breakpoint* temp = bpt; |
128 bpt = bpt->next(); | 123 bpt = bpt->next(); |
129 delete temp; | 124 delete temp; |
130 } | 125 } |
131 } | 126 } |
132 | 127 |
133 | |
134 bool BreakpointLocation::AnyEnabled() const { | 128 bool BreakpointLocation::AnyEnabled() const { |
135 return breakpoints() != NULL; | 129 return breakpoints() != NULL; |
136 } | 130 } |
137 | 131 |
138 | |
139 void BreakpointLocation::SetResolved(const Function& func, | 132 void BreakpointLocation::SetResolved(const Function& func, |
140 TokenPosition token_pos) { | 133 TokenPosition token_pos) { |
141 ASSERT(!IsLatent()); | 134 ASSERT(!IsLatent()); |
142 ASSERT(func.script() == script_); | 135 ASSERT(func.script() == script_); |
143 ASSERT((func.token_pos() <= token_pos) && | 136 ASSERT((func.token_pos() <= token_pos) && |
144 (token_pos <= func.end_token_pos())); | 137 (token_pos <= func.end_token_pos())); |
145 ASSERT(func.is_debuggable()); | 138 ASSERT(func.is_debuggable()); |
146 function_ = func.raw(); | 139 function_ = func.raw(); |
147 token_pos_ = token_pos; | 140 token_pos_ = token_pos; |
148 end_token_pos_ = token_pos; | 141 end_token_pos_ = token_pos; |
149 is_resolved_ = true; | 142 is_resolved_ = true; |
150 } | 143 } |
151 | 144 |
152 | |
153 // TODO(hausner): Get rid of library parameter. A source breakpoint location | 145 // TODO(hausner): Get rid of library parameter. A source breakpoint location |
154 // does not imply a library, since the same source code can be included | 146 // does not imply a library, since the same source code can be included |
155 // in more than one library, e.g. the text location of mixin functions. | 147 // in more than one library, e.g. the text location of mixin functions. |
156 void BreakpointLocation::GetCodeLocation(Library* lib, | 148 void BreakpointLocation::GetCodeLocation(Library* lib, |
157 Script* script, | 149 Script* script, |
158 TokenPosition* pos) const { | 150 TokenPosition* pos) const { |
159 if (IsLatent()) { | 151 if (IsLatent()) { |
160 *lib = Library::null(); | 152 *lib = Library::null(); |
161 *script = Script::null(); | 153 *script = Script::null(); |
162 *pos = TokenPosition::kNoSource; | 154 *pos = TokenPosition::kNoSource; |
163 } else { | 155 } else { |
164 *script = this->script(); | 156 *script = this->script(); |
165 *pos = token_pos_; | 157 *pos = token_pos_; |
166 if (IsResolved()) { | 158 if (IsResolved()) { |
167 const Function& func = Function::Handle(function_); | 159 const Function& func = Function::Handle(function_); |
168 ASSERT(!func.IsNull()); | 160 ASSERT(!func.IsNull()); |
169 const Class& cls = Class::Handle(func.origin()); | 161 const Class& cls = Class::Handle(func.origin()); |
170 *lib = cls.library(); | 162 *lib = cls.library(); |
171 } else { | 163 } else { |
172 *lib = Library::null(); | 164 *lib = Library::null(); |
173 } | 165 } |
174 } | 166 } |
175 } | 167 } |
176 | 168 |
177 | |
178 intptr_t BreakpointLocation::LineNumber() { | 169 intptr_t BreakpointLocation::LineNumber() { |
179 ASSERT(IsResolved()); | 170 ASSERT(IsResolved()); |
180 // Compute line number lazily since it causes scanning of the script. | 171 // Compute line number lazily since it causes scanning of the script. |
181 if (line_number_ < 0) { | 172 if (line_number_ < 0) { |
182 const Script& script = Script::Handle(this->script()); | 173 const Script& script = Script::Handle(this->script()); |
183 script.GetTokenLocation(token_pos_, &line_number_, NULL); | 174 script.GetTokenLocation(token_pos_, &line_number_, NULL); |
184 } | 175 } |
185 return line_number_; | 176 return line_number_; |
186 } | 177 } |
187 | 178 |
188 | |
189 intptr_t BreakpointLocation::ColumnNumber() { | 179 intptr_t BreakpointLocation::ColumnNumber() { |
190 ASSERT(IsResolved()); | 180 ASSERT(IsResolved()); |
191 // Compute column number lazily since it causes scanning of the script. | 181 // Compute column number lazily since it causes scanning of the script. |
192 if (column_number_ < 0) { | 182 if (column_number_ < 0) { |
193 const Script& script = Script::Handle(this->script()); | 183 const Script& script = Script::Handle(this->script()); |
194 script.GetTokenLocation(token_pos_, &line_number_, &column_number_); | 184 script.GetTokenLocation(token_pos_, &line_number_, &column_number_); |
195 } | 185 } |
196 return column_number_; | 186 return column_number_; |
197 } | 187 } |
198 | 188 |
199 | |
200 void Breakpoint::set_bpt_location(BreakpointLocation* new_bpt_location) { | 189 void Breakpoint::set_bpt_location(BreakpointLocation* new_bpt_location) { |
201 // Only latent breakpoints can be moved. | 190 // Only latent breakpoints can be moved. |
202 ASSERT((new_bpt_location == NULL) || bpt_location_->IsLatent()); | 191 ASSERT((new_bpt_location == NULL) || bpt_location_->IsLatent()); |
203 bpt_location_ = new_bpt_location; | 192 bpt_location_ = new_bpt_location; |
204 } | 193 } |
205 | 194 |
206 | |
207 void Breakpoint::VisitObjectPointers(ObjectPointerVisitor* visitor) { | 195 void Breakpoint::VisitObjectPointers(ObjectPointerVisitor* visitor) { |
208 visitor->VisitPointer(reinterpret_cast<RawObject**>(&closure_)); | 196 visitor->VisitPointer(reinterpret_cast<RawObject**>(&closure_)); |
209 } | 197 } |
210 | 198 |
211 | |
212 void BreakpointLocation::VisitObjectPointers(ObjectPointerVisitor* visitor) { | 199 void BreakpointLocation::VisitObjectPointers(ObjectPointerVisitor* visitor) { |
213 visitor->VisitPointer(reinterpret_cast<RawObject**>(&script_)); | 200 visitor->VisitPointer(reinterpret_cast<RawObject**>(&script_)); |
214 visitor->VisitPointer(reinterpret_cast<RawObject**>(&url_)); | 201 visitor->VisitPointer(reinterpret_cast<RawObject**>(&url_)); |
215 visitor->VisitPointer(reinterpret_cast<RawObject**>(&function_)); | 202 visitor->VisitPointer(reinterpret_cast<RawObject**>(&function_)); |
216 | 203 |
217 Breakpoint* bpt = conditions_; | 204 Breakpoint* bpt = conditions_; |
218 while (bpt != NULL) { | 205 while (bpt != NULL) { |
219 bpt->VisitObjectPointers(visitor); | 206 bpt->VisitObjectPointers(visitor); |
220 bpt = bpt->next(); | 207 bpt = bpt->next(); |
221 } | 208 } |
222 } | 209 } |
223 | 210 |
224 | |
225 void Breakpoint::PrintJSON(JSONStream* stream) { | 211 void Breakpoint::PrintJSON(JSONStream* stream) { |
226 JSONObject jsobj(stream); | 212 JSONObject jsobj(stream); |
227 jsobj.AddProperty("type", "Breakpoint"); | 213 jsobj.AddProperty("type", "Breakpoint"); |
228 | 214 |
229 jsobj.AddFixedServiceId("breakpoints/%" Pd "", id()); | 215 jsobj.AddFixedServiceId("breakpoints/%" Pd "", id()); |
230 jsobj.AddProperty("breakpointNumber", id()); | 216 jsobj.AddProperty("breakpointNumber", id()); |
231 if (is_synthetic_async()) { | 217 if (is_synthetic_async()) { |
232 jsobj.AddProperty("isSyntheticAsyncContinuation", is_synthetic_async()); | 218 jsobj.AddProperty("isSyntheticAsyncContinuation", is_synthetic_async()); |
233 } | 219 } |
234 jsobj.AddProperty("resolved", bpt_location_->IsResolved()); | 220 jsobj.AddProperty("resolved", bpt_location_->IsResolved()); |
235 if (bpt_location_->IsResolved()) { | 221 if (bpt_location_->IsResolved()) { |
236 jsobj.AddLocation(bpt_location_); | 222 jsobj.AddLocation(bpt_location_); |
237 } else { | 223 } else { |
238 jsobj.AddUnresolvedLocation(bpt_location_); | 224 jsobj.AddUnresolvedLocation(bpt_location_); |
239 } | 225 } |
240 } | 226 } |
241 | 227 |
242 | |
243 void CodeBreakpoint::VisitObjectPointers(ObjectPointerVisitor* visitor) { | 228 void CodeBreakpoint::VisitObjectPointers(ObjectPointerVisitor* visitor) { |
244 visitor->VisitPointer(reinterpret_cast<RawObject**>(&code_)); | 229 visitor->VisitPointer(reinterpret_cast<RawObject**>(&code_)); |
245 #if !defined(TARGET_ARCH_DBC) | 230 #if !defined(TARGET_ARCH_DBC) |
246 visitor->VisitPointer(reinterpret_cast<RawObject**>(&saved_value_)); | 231 visitor->VisitPointer(reinterpret_cast<RawObject**>(&saved_value_)); |
247 #endif | 232 #endif |
248 } | 233 } |
249 | 234 |
250 | |
251 ActivationFrame::ActivationFrame(uword pc, | 235 ActivationFrame::ActivationFrame(uword pc, |
252 uword fp, | 236 uword fp, |
253 uword sp, | 237 uword sp, |
254 const Code& code, | 238 const Code& code, |
255 const Array& deopt_frame, | 239 const Array& deopt_frame, |
256 intptr_t deopt_frame_offset, | 240 intptr_t deopt_frame_offset, |
257 ActivationFrame::Kind kind) | 241 ActivationFrame::Kind kind) |
258 : pc_(pc), | 242 : pc_(pc), |
259 fp_(fp), | 243 fp_(fp), |
260 sp_(sp), | 244 sp_(sp), |
261 ctx_(Context::ZoneHandle()), | 245 ctx_(Context::ZoneHandle()), |
262 code_(Code::ZoneHandle(code.raw())), | 246 code_(Code::ZoneHandle(code.raw())), |
263 function_(Function::ZoneHandle(code.function())), | 247 function_(Function::ZoneHandle(code.function())), |
264 live_frame_((kind == kRegular) || (kind == kAsyncActivation)), | 248 live_frame_((kind == kRegular) || (kind == kAsyncActivation)), |
265 token_pos_initialized_(false), | 249 token_pos_initialized_(false), |
266 token_pos_(TokenPosition::kNoSource), | 250 token_pos_(TokenPosition::kNoSource), |
267 try_index_(-1), | 251 try_index_(-1), |
268 deopt_id_(Thread::kNoDeoptId), | 252 deopt_id_(Thread::kNoDeoptId), |
269 line_number_(-1), | 253 line_number_(-1), |
270 column_number_(-1), | 254 column_number_(-1), |
271 context_level_(-1), | 255 context_level_(-1), |
272 deopt_frame_(Array::ZoneHandle(deopt_frame.raw())), | 256 deopt_frame_(Array::ZoneHandle(deopt_frame.raw())), |
273 deopt_frame_offset_(deopt_frame_offset), | 257 deopt_frame_offset_(deopt_frame_offset), |
274 kind_(kind), | 258 kind_(kind), |
275 vars_initialized_(false), | 259 vars_initialized_(false), |
276 var_descriptors_(LocalVarDescriptors::ZoneHandle()), | 260 var_descriptors_(LocalVarDescriptors::ZoneHandle()), |
277 desc_indices_(8), | 261 desc_indices_(8), |
278 pc_desc_(PcDescriptors::ZoneHandle()) {} | 262 pc_desc_(PcDescriptors::ZoneHandle()) {} |
279 | 263 |
280 | |
281 ActivationFrame::ActivationFrame(Kind kind) | 264 ActivationFrame::ActivationFrame(Kind kind) |
282 : pc_(0), | 265 : pc_(0), |
283 fp_(0), | 266 fp_(0), |
284 sp_(0), | 267 sp_(0), |
285 ctx_(Context::ZoneHandle()), | 268 ctx_(Context::ZoneHandle()), |
286 code_(Code::ZoneHandle()), | 269 code_(Code::ZoneHandle()), |
287 function_(Function::ZoneHandle()), | 270 function_(Function::ZoneHandle()), |
288 live_frame_(kind == kRegular), | 271 live_frame_(kind == kRegular), |
289 token_pos_initialized_(false), | 272 token_pos_initialized_(false), |
290 token_pos_(TokenPosition::kNoSource), | 273 token_pos_(TokenPosition::kNoSource), |
291 try_index_(-1), | 274 try_index_(-1), |
292 line_number_(-1), | 275 line_number_(-1), |
293 column_number_(-1), | 276 column_number_(-1), |
294 context_level_(-1), | 277 context_level_(-1), |
295 deopt_frame_(Array::ZoneHandle()), | 278 deopt_frame_(Array::ZoneHandle()), |
296 deopt_frame_offset_(0), | 279 deopt_frame_offset_(0), |
297 kind_(kind), | 280 kind_(kind), |
298 vars_initialized_(false), | 281 vars_initialized_(false), |
299 var_descriptors_(LocalVarDescriptors::ZoneHandle()), | 282 var_descriptors_(LocalVarDescriptors::ZoneHandle()), |
300 desc_indices_(8), | 283 desc_indices_(8), |
301 pc_desc_(PcDescriptors::ZoneHandle()) {} | 284 pc_desc_(PcDescriptors::ZoneHandle()) {} |
302 | 285 |
303 | |
304 ActivationFrame::ActivationFrame(const Closure& async_activation) | 286 ActivationFrame::ActivationFrame(const Closure& async_activation) |
305 : pc_(0), | 287 : pc_(0), |
306 fp_(0), | 288 fp_(0), |
307 sp_(0), | 289 sp_(0), |
308 ctx_(Context::ZoneHandle()), | 290 ctx_(Context::ZoneHandle()), |
309 code_(Code::ZoneHandle()), | 291 code_(Code::ZoneHandle()), |
310 function_(Function::ZoneHandle()), | 292 function_(Function::ZoneHandle()), |
311 live_frame_(false), | 293 live_frame_(false), |
312 token_pos_initialized_(false), | 294 token_pos_initialized_(false), |
313 token_pos_(TokenPosition::kNoSource), | 295 token_pos_(TokenPosition::kNoSource), |
(...skipping 10 matching lines...) Expand all Loading... |
324 pc_desc_(PcDescriptors::ZoneHandle()) { | 306 pc_desc_(PcDescriptors::ZoneHandle()) { |
325 // Extract the function and the code from the asynchronous activation. | 307 // Extract the function and the code from the asynchronous activation. |
326 function_ = async_activation.function(); | 308 function_ = async_activation.function(); |
327 function_.EnsureHasCompiledUnoptimizedCode(); | 309 function_.EnsureHasCompiledUnoptimizedCode(); |
328 code_ = function_.unoptimized_code(); | 310 code_ = function_.unoptimized_code(); |
329 ctx_ = async_activation.context(); | 311 ctx_ = async_activation.context(); |
330 ASSERT(fp_ == 0); | 312 ASSERT(fp_ == 0); |
331 ASSERT(!ctx_.IsNull()); | 313 ASSERT(!ctx_.IsNull()); |
332 } | 314 } |
333 | 315 |
334 | |
335 bool Debugger::NeedsIsolateEvents() { | 316 bool Debugger::NeedsIsolateEvents() { |
336 return ((isolate_ != Dart::vm_isolate()) && | 317 return ((isolate_ != Dart::vm_isolate()) && |
337 !ServiceIsolate::IsServiceIsolateDescendant(isolate_) && | 318 !ServiceIsolate::IsServiceIsolateDescendant(isolate_) && |
338 ((event_handler_ != NULL) || Service::isolate_stream.enabled())); | 319 ((event_handler_ != NULL) || Service::isolate_stream.enabled())); |
339 } | 320 } |
340 | 321 |
341 | |
342 bool Debugger::NeedsDebugEvents() { | 322 bool Debugger::NeedsDebugEvents() { |
343 ASSERT(isolate_ != Dart::vm_isolate() && | 323 ASSERT(isolate_ != Dart::vm_isolate() && |
344 !ServiceIsolate::IsServiceIsolateDescendant(isolate_)); | 324 !ServiceIsolate::IsServiceIsolateDescendant(isolate_)); |
345 return (FLAG_warn_on_pause_with_no_debugger || (event_handler_ != NULL) || | 325 return (FLAG_warn_on_pause_with_no_debugger || (event_handler_ != NULL) || |
346 Service::debug_stream.enabled()); | 326 Service::debug_stream.enabled()); |
347 } | 327 } |
348 | 328 |
349 | |
350 void Debugger::InvokeEventHandler(ServiceEvent* event) { | 329 void Debugger::InvokeEventHandler(ServiceEvent* event) { |
351 ASSERT(!event->IsPause()); // For pause events, call Pause instead. | 330 ASSERT(!event->IsPause()); // For pause events, call Pause instead. |
352 Service::HandleEvent(event); | 331 Service::HandleEvent(event); |
353 | 332 |
354 // Call the embedder's event handler, if it exists. | 333 // Call the embedder's event handler, if it exists. |
355 if (event_handler_ != NULL) { | 334 if (event_handler_ != NULL) { |
356 TransitionVMToNative transition(Thread::Current()); | 335 TransitionVMToNative transition(Thread::Current()); |
357 (*event_handler_)(event); | 336 (*event_handler_)(event); |
358 } | 337 } |
359 } | 338 } |
360 | 339 |
361 | |
362 RawError* Debugger::PauseInterrupted() { | 340 RawError* Debugger::PauseInterrupted() { |
363 return PauseRequest(ServiceEvent::kPauseInterrupted); | 341 return PauseRequest(ServiceEvent::kPauseInterrupted); |
364 } | 342 } |
365 | 343 |
366 | |
367 RawError* Debugger::PausePostRequest() { | 344 RawError* Debugger::PausePostRequest() { |
368 return PauseRequest(ServiceEvent::kPausePostRequest); | 345 return PauseRequest(ServiceEvent::kPausePostRequest); |
369 } | 346 } |
370 | 347 |
371 | |
372 RawError* Debugger::PauseRequest(ServiceEvent::EventKind kind) { | 348 RawError* Debugger::PauseRequest(ServiceEvent::EventKind kind) { |
373 if (ignore_breakpoints_ || IsPaused()) { | 349 if (ignore_breakpoints_ || IsPaused()) { |
374 // We don't let the isolate get interrupted if we are already | 350 // We don't let the isolate get interrupted if we are already |
375 // paused or ignoring breakpoints. | 351 // paused or ignoring breakpoints. |
376 return Error::null(); | 352 return Error::null(); |
377 } | 353 } |
378 ServiceEvent event(isolate_, kind); | 354 ServiceEvent event(isolate_, kind); |
379 DebuggerStackTrace* trace = CollectStackTrace(); | 355 DebuggerStackTrace* trace = CollectStackTrace(); |
380 if (trace->Length() > 0) { | 356 if (trace->Length() > 0) { |
381 event.set_top_frame(trace->FrameAt(0)); | 357 event.set_top_frame(trace->FrameAt(0)); |
382 } | 358 } |
383 CacheStackTraces(trace, CollectAsyncCausalStackTrace(), | 359 CacheStackTraces(trace, CollectAsyncCausalStackTrace(), |
384 CollectAwaiterReturnStackTrace()); | 360 CollectAwaiterReturnStackTrace()); |
385 resume_action_ = kContinue; | 361 resume_action_ = kContinue; |
386 Pause(&event); | 362 Pause(&event); |
387 HandleSteppingRequest(trace); | 363 HandleSteppingRequest(trace); |
388 ClearCachedStackTraces(); | 364 ClearCachedStackTraces(); |
389 | 365 |
390 // If any error occurred while in the debug message loop, return it here. | 366 // If any error occurred while in the debug message loop, return it here. |
391 const Error& error = Error::Handle(Thread::Current()->sticky_error()); | 367 const Error& error = Error::Handle(Thread::Current()->sticky_error()); |
392 ASSERT(error.IsNull() || error.IsUnwindError()); | 368 ASSERT(error.IsNull() || error.IsUnwindError()); |
393 Thread::Current()->clear_sticky_error(); | 369 Thread::Current()->clear_sticky_error(); |
394 return error.raw(); | 370 return error.raw(); |
395 } | 371 } |
396 | 372 |
397 | |
398 void Debugger::SendBreakpointEvent(ServiceEvent::EventKind kind, | 373 void Debugger::SendBreakpointEvent(ServiceEvent::EventKind kind, |
399 Breakpoint* bpt) { | 374 Breakpoint* bpt) { |
400 if (NeedsDebugEvents()) { | 375 if (NeedsDebugEvents()) { |
401 // TODO(turnidge): Currently we send single-shot breakpoint events | 376 // TODO(turnidge): Currently we send single-shot breakpoint events |
402 // to the vm service. Do we want to change this? | 377 // to the vm service. Do we want to change this? |
403 ServiceEvent event(isolate_, kind); | 378 ServiceEvent event(isolate_, kind); |
404 event.set_breakpoint(bpt); | 379 event.set_breakpoint(bpt); |
405 InvokeEventHandler(&event); | 380 InvokeEventHandler(&event); |
406 } | 381 } |
407 } | 382 } |
408 | 383 |
409 | |
410 void BreakpointLocation::AddBreakpoint(Breakpoint* bpt, Debugger* dbg) { | 384 void BreakpointLocation::AddBreakpoint(Breakpoint* bpt, Debugger* dbg) { |
411 bpt->set_next(breakpoints()); | 385 bpt->set_next(breakpoints()); |
412 set_breakpoints(bpt); | 386 set_breakpoints(bpt); |
413 | 387 |
414 dbg->SyncBreakpointLocation(this); | 388 dbg->SyncBreakpointLocation(this); |
415 dbg->SendBreakpointEvent(ServiceEvent::kBreakpointAdded, bpt); | 389 dbg->SendBreakpointEvent(ServiceEvent::kBreakpointAdded, bpt); |
416 } | 390 } |
417 | 391 |
418 | |
419 Breakpoint* BreakpointLocation::AddRepeated(Debugger* dbg) { | 392 Breakpoint* BreakpointLocation::AddRepeated(Debugger* dbg) { |
420 Breakpoint* bpt = breakpoints(); | 393 Breakpoint* bpt = breakpoints(); |
421 while (bpt != NULL) { | 394 while (bpt != NULL) { |
422 if (bpt->IsRepeated()) break; | 395 if (bpt->IsRepeated()) break; |
423 bpt = bpt->next(); | 396 bpt = bpt->next(); |
424 } | 397 } |
425 if (bpt == NULL) { | 398 if (bpt == NULL) { |
426 bpt = new Breakpoint(dbg->nextId(), this); | 399 bpt = new Breakpoint(dbg->nextId(), this); |
427 bpt->SetIsRepeated(); | 400 bpt->SetIsRepeated(); |
428 AddBreakpoint(bpt, dbg); | 401 AddBreakpoint(bpt, dbg); |
429 } | 402 } |
430 return bpt; | 403 return bpt; |
431 } | 404 } |
432 | 405 |
433 | |
434 Breakpoint* BreakpointLocation::AddSingleShot(Debugger* dbg) { | 406 Breakpoint* BreakpointLocation::AddSingleShot(Debugger* dbg) { |
435 Breakpoint* bpt = breakpoints(); | 407 Breakpoint* bpt = breakpoints(); |
436 while (bpt != NULL) { | 408 while (bpt != NULL) { |
437 if (bpt->IsSingleShot()) break; | 409 if (bpt->IsSingleShot()) break; |
438 bpt = bpt->next(); | 410 bpt = bpt->next(); |
439 } | 411 } |
440 if (bpt == NULL) { | 412 if (bpt == NULL) { |
441 bpt = new Breakpoint(dbg->nextId(), this); | 413 bpt = new Breakpoint(dbg->nextId(), this); |
442 bpt->SetIsSingleShot(); | 414 bpt->SetIsSingleShot(); |
443 AddBreakpoint(bpt, dbg); | 415 AddBreakpoint(bpt, dbg); |
444 } | 416 } |
445 return bpt; | 417 return bpt; |
446 } | 418 } |
447 | 419 |
448 | |
449 Breakpoint* BreakpointLocation::AddPerClosure(Debugger* dbg, | 420 Breakpoint* BreakpointLocation::AddPerClosure(Debugger* dbg, |
450 const Instance& closure, | 421 const Instance& closure, |
451 bool for_over_await) { | 422 bool for_over_await) { |
452 Breakpoint* bpt = NULL; | 423 Breakpoint* bpt = NULL; |
453 // Do not reuse existing breakpoints for stepping over await clauses. | 424 // Do not reuse existing breakpoints for stepping over await clauses. |
454 // A second async step-over command will set a new breakpoint before | 425 // A second async step-over command will set a new breakpoint before |
455 // the existing one gets deleted when first async step-over resumes. | 426 // the existing one gets deleted when first async step-over resumes. |
456 if (!for_over_await) { | 427 if (!for_over_await) { |
457 bpt = breakpoints(); | 428 bpt = breakpoints(); |
458 while (bpt != NULL) { | 429 while (bpt != NULL) { |
459 if (bpt->IsPerClosure() && (bpt->closure() == closure.raw())) break; | 430 if (bpt->IsPerClosure() && (bpt->closure() == closure.raw())) break; |
460 bpt = bpt->next(); | 431 bpt = bpt->next(); |
461 } | 432 } |
462 } | 433 } |
463 if (bpt == NULL) { | 434 if (bpt == NULL) { |
464 bpt = new Breakpoint(dbg->nextId(), this); | 435 bpt = new Breakpoint(dbg->nextId(), this); |
465 bpt->SetIsPerClosure(closure); | 436 bpt->SetIsPerClosure(closure); |
466 bpt->set_is_synthetic_async(for_over_await); | 437 bpt->set_is_synthetic_async(for_over_await); |
467 AddBreakpoint(bpt, dbg); | 438 AddBreakpoint(bpt, dbg); |
468 } | 439 } |
469 return bpt; | 440 return bpt; |
470 } | 441 } |
471 | 442 |
472 | |
473 const char* Debugger::QualifiedFunctionName(const Function& func) { | 443 const char* Debugger::QualifiedFunctionName(const Function& func) { |
474 const String& func_name = String::Handle(func.name()); | 444 const String& func_name = String::Handle(func.name()); |
475 Class& func_class = Class::Handle(func.Owner()); | 445 Class& func_class = Class::Handle(func.Owner()); |
476 String& class_name = String::Handle(func_class.Name()); | 446 String& class_name = String::Handle(func_class.Name()); |
477 | 447 |
478 return OS::SCreate(Thread::Current()->zone(), "%s%s%s", | 448 return OS::SCreate(Thread::Current()->zone(), "%s%s%s", |
479 func_class.IsTopLevel() ? "" : class_name.ToCString(), | 449 func_class.IsTopLevel() ? "" : class_name.ToCString(), |
480 func_class.IsTopLevel() ? "" : ".", func_name.ToCString()); | 450 func_class.IsTopLevel() ? "" : ".", func_name.ToCString()); |
481 } | 451 } |
482 | 452 |
483 | |
484 // Returns true if the function |func| overlaps the token range | 453 // Returns true if the function |func| overlaps the token range |
485 // [|token_pos|, |end_token_pos|] in |script|. | 454 // [|token_pos|, |end_token_pos|] in |script|. |
486 static bool FunctionOverlaps(const Function& func, | 455 static bool FunctionOverlaps(const Function& func, |
487 const Script& script, | 456 const Script& script, |
488 TokenPosition token_pos, | 457 TokenPosition token_pos, |
489 TokenPosition end_token_pos) { | 458 TokenPosition end_token_pos) { |
490 TokenPosition func_start = func.token_pos(); | 459 TokenPosition func_start = func.token_pos(); |
491 if (((func_start <= token_pos) && (token_pos <= func.end_token_pos())) || | 460 if (((func_start <= token_pos) && (token_pos <= func.end_token_pos())) || |
492 ((token_pos <= func_start) && (func_start <= end_token_pos))) { | 461 ((token_pos <= func_start) && (func_start <= end_token_pos))) { |
493 // Check script equality second because it allocates | 462 // Check script equality second because it allocates |
494 // handles as a side effect. | 463 // handles as a side effect. |
495 return func.script() == script.raw(); | 464 return func.script() == script.raw(); |
496 } | 465 } |
497 return false; | 466 return false; |
498 } | 467 } |
499 | 468 |
500 | |
501 static bool IsImplicitFunction(const Function& func) { | 469 static bool IsImplicitFunction(const Function& func) { |
502 switch (func.kind()) { | 470 switch (func.kind()) { |
503 case RawFunction::kImplicitGetter: | 471 case RawFunction::kImplicitGetter: |
504 case RawFunction::kImplicitSetter: | 472 case RawFunction::kImplicitSetter: |
505 case RawFunction::kImplicitStaticFinalGetter: | 473 case RawFunction::kImplicitStaticFinalGetter: |
506 case RawFunction::kMethodExtractor: | 474 case RawFunction::kMethodExtractor: |
507 case RawFunction::kNoSuchMethodDispatcher: | 475 case RawFunction::kNoSuchMethodDispatcher: |
508 case RawFunction::kInvokeFieldDispatcher: | 476 case RawFunction::kInvokeFieldDispatcher: |
509 case RawFunction::kIrregexpFunction: | 477 case RawFunction::kIrregexpFunction: |
510 return true; | 478 return true; |
511 default: | 479 default: |
512 if (func.token_pos() == func.end_token_pos()) { | 480 if (func.token_pos() == func.end_token_pos()) { |
513 // |func| could be an implicit constructor for example. | 481 // |func| could be an implicit constructor for example. |
514 return true; | 482 return true; |
515 } | 483 } |
516 } | 484 } |
517 return false; | 485 return false; |
518 } | 486 } |
519 | 487 |
520 | |
521 bool Debugger::HasBreakpoint(const Function& func, Zone* zone) { | 488 bool Debugger::HasBreakpoint(const Function& func, Zone* zone) { |
522 if (!func.HasCode()) { | 489 if (!func.HasCode()) { |
523 // If the function is not compiled yet, just check whether there | 490 // If the function is not compiled yet, just check whether there |
524 // is a user-defined breakpoint that falls into the token | 491 // is a user-defined breakpoint that falls into the token |
525 // range of the function. This may be a false positive: the breakpoint | 492 // range of the function. This may be a false positive: the breakpoint |
526 // might be inside a local closure. | 493 // might be inside a local closure. |
527 Script& script = Script::Handle(zone); | 494 Script& script = Script::Handle(zone); |
528 BreakpointLocation* sbpt = breakpoint_locations_; | 495 BreakpointLocation* sbpt = breakpoint_locations_; |
529 while (sbpt != NULL) { | 496 while (sbpt != NULL) { |
530 script = sbpt->script(); | 497 script = sbpt->script(); |
531 if (FunctionOverlaps(func, script, sbpt->token_pos(), | 498 if (FunctionOverlaps(func, script, sbpt->token_pos(), |
532 sbpt->end_token_pos())) { | 499 sbpt->end_token_pos())) { |
533 return true; | 500 return true; |
534 } | 501 } |
535 sbpt = sbpt->next_; | 502 sbpt = sbpt->next_; |
536 } | 503 } |
537 return false; | 504 return false; |
538 } | 505 } |
539 CodeBreakpoint* cbpt = code_breakpoints_; | 506 CodeBreakpoint* cbpt = code_breakpoints_; |
540 while (cbpt != NULL) { | 507 while (cbpt != NULL) { |
541 if (func.raw() == cbpt->function()) { | 508 if (func.raw() == cbpt->function()) { |
542 return true; | 509 return true; |
543 } | 510 } |
544 cbpt = cbpt->next_; | 511 cbpt = cbpt->next_; |
545 } | 512 } |
546 return false; | 513 return false; |
547 } | 514 } |
548 | 515 |
549 | |
550 bool Debugger::HasBreakpoint(const Code& code) { | 516 bool Debugger::HasBreakpoint(const Code& code) { |
551 CodeBreakpoint* cbpt = code_breakpoints_; | 517 CodeBreakpoint* cbpt = code_breakpoints_; |
552 while (cbpt != NULL) { | 518 while (cbpt != NULL) { |
553 if (code.raw() == cbpt->code_) { | 519 if (code.raw() == cbpt->code_) { |
554 return true; | 520 return true; |
555 } | 521 } |
556 cbpt = cbpt->next_; | 522 cbpt = cbpt->next_; |
557 } | 523 } |
558 return false; | 524 return false; |
559 } | 525 } |
560 | 526 |
561 | |
562 void Debugger::PrintBreakpointsToJSONArray(JSONArray* jsarr) const { | 527 void Debugger::PrintBreakpointsToJSONArray(JSONArray* jsarr) const { |
563 PrintBreakpointsListToJSONArray(breakpoint_locations_, jsarr); | 528 PrintBreakpointsListToJSONArray(breakpoint_locations_, jsarr); |
564 PrintBreakpointsListToJSONArray(latent_locations_, jsarr); | 529 PrintBreakpointsListToJSONArray(latent_locations_, jsarr); |
565 } | 530 } |
566 | 531 |
567 | |
568 void Debugger::PrintBreakpointsListToJSONArray(BreakpointLocation* sbpt, | 532 void Debugger::PrintBreakpointsListToJSONArray(BreakpointLocation* sbpt, |
569 JSONArray* jsarr) const { | 533 JSONArray* jsarr) const { |
570 while (sbpt != NULL) { | 534 while (sbpt != NULL) { |
571 Breakpoint* bpt = sbpt->breakpoints(); | 535 Breakpoint* bpt = sbpt->breakpoints(); |
572 while (bpt != NULL) { | 536 while (bpt != NULL) { |
573 jsarr->AddValue(bpt); | 537 jsarr->AddValue(bpt); |
574 bpt = bpt->next(); | 538 bpt = bpt->next(); |
575 } | 539 } |
576 sbpt = sbpt->next_; | 540 sbpt = sbpt->next_; |
577 } | 541 } |
578 } | 542 } |
579 | 543 |
580 | |
581 void Debugger::PrintSettingsToJSONObject(JSONObject* jsobj) const { | 544 void Debugger::PrintSettingsToJSONObject(JSONObject* jsobj) const { |
582 // This won't cut it when we support filtering by class, etc. | 545 // This won't cut it when we support filtering by class, etc. |
583 switch (GetExceptionPauseInfo()) { | 546 switch (GetExceptionPauseInfo()) { |
584 case kNoPauseOnExceptions: | 547 case kNoPauseOnExceptions: |
585 jsobj->AddProperty("_exceptions", "none"); | 548 jsobj->AddProperty("_exceptions", "none"); |
586 break; | 549 break; |
587 case kPauseOnAllExceptions: | 550 case kPauseOnAllExceptions: |
588 jsobj->AddProperty("_exceptions", "all"); | 551 jsobj->AddProperty("_exceptions", "all"); |
589 break; | 552 break; |
590 case kPauseOnUnhandledExceptions: | 553 case kPauseOnUnhandledExceptions: |
591 jsobj->AddProperty("_exceptions", "unhandled"); | 554 jsobj->AddProperty("_exceptions", "unhandled"); |
592 break; | 555 break; |
593 default: | 556 default: |
594 UNREACHABLE(); | 557 UNREACHABLE(); |
595 } | 558 } |
596 } | 559 } |
597 | 560 |
598 | |
599 RawString* ActivationFrame::QualifiedFunctionName() { | 561 RawString* ActivationFrame::QualifiedFunctionName() { |
600 return String::New(Debugger::QualifiedFunctionName(function())); | 562 return String::New(Debugger::QualifiedFunctionName(function())); |
601 } | 563 } |
602 | 564 |
603 | |
604 RawString* ActivationFrame::SourceUrl() { | 565 RawString* ActivationFrame::SourceUrl() { |
605 const Script& script = Script::Handle(SourceScript()); | 566 const Script& script = Script::Handle(SourceScript()); |
606 return script.url(); | 567 return script.url(); |
607 } | 568 } |
608 | 569 |
609 | |
610 RawScript* ActivationFrame::SourceScript() { | 570 RawScript* ActivationFrame::SourceScript() { |
611 return function().script(); | 571 return function().script(); |
612 } | 572 } |
613 | 573 |
614 | |
615 RawLibrary* ActivationFrame::Library() { | 574 RawLibrary* ActivationFrame::Library() { |
616 const Class& cls = Class::Handle(function().origin()); | 575 const Class& cls = Class::Handle(function().origin()); |
617 return cls.library(); | 576 return cls.library(); |
618 } | 577 } |
619 | 578 |
620 | |
621 void ActivationFrame::GetPcDescriptors() { | 579 void ActivationFrame::GetPcDescriptors() { |
622 if (pc_desc_.IsNull()) { | 580 if (pc_desc_.IsNull()) { |
623 pc_desc_ = code().pc_descriptors(); | 581 pc_desc_ = code().pc_descriptors(); |
624 ASSERT(!pc_desc_.IsNull()); | 582 ASSERT(!pc_desc_.IsNull()); |
625 } | 583 } |
626 } | 584 } |
627 | 585 |
628 | |
629 // Compute token_pos_ and try_index_ and token_pos_initialized_. | 586 // Compute token_pos_ and try_index_ and token_pos_initialized_. |
630 TokenPosition ActivationFrame::TokenPos() { | 587 TokenPosition ActivationFrame::TokenPos() { |
631 if (!token_pos_initialized_) { | 588 if (!token_pos_initialized_) { |
632 token_pos_initialized_ = true; | 589 token_pos_initialized_ = true; |
633 token_pos_ = TokenPosition::kNoSource; | 590 token_pos_ = TokenPosition::kNoSource; |
634 GetPcDescriptors(); | 591 GetPcDescriptors(); |
635 PcDescriptors::Iterator iter(pc_desc_, RawPcDescriptors::kAnyKind); | 592 PcDescriptors::Iterator iter(pc_desc_, RawPcDescriptors::kAnyKind); |
636 uword pc_offset = pc_ - code().PayloadStart(); | 593 uword pc_offset = pc_ - code().PayloadStart(); |
637 while (iter.MoveNext()) { | 594 while (iter.MoveNext()) { |
638 if (iter.PcOffset() == pc_offset) { | 595 if (iter.PcOffset() == pc_offset) { |
639 try_index_ = iter.TryIndex(); | 596 try_index_ = iter.TryIndex(); |
640 token_pos_ = iter.TokenPos(); | 597 token_pos_ = iter.TokenPos(); |
641 deopt_id_ = iter.DeoptId(); | 598 deopt_id_ = iter.DeoptId(); |
642 break; | 599 break; |
643 } | 600 } |
644 } | 601 } |
645 } | 602 } |
646 return token_pos_; | 603 return token_pos_; |
647 } | 604 } |
648 | 605 |
649 | |
650 intptr_t ActivationFrame::TryIndex() { | 606 intptr_t ActivationFrame::TryIndex() { |
651 if (!token_pos_initialized_) { | 607 if (!token_pos_initialized_) { |
652 TokenPos(); // Side effect: computes token_pos_initialized_, try_index_. | 608 TokenPos(); // Side effect: computes token_pos_initialized_, try_index_. |
653 } | 609 } |
654 return try_index_; | 610 return try_index_; |
655 } | 611 } |
656 | 612 |
657 | |
658 intptr_t ActivationFrame::DeoptId() { | 613 intptr_t ActivationFrame::DeoptId() { |
659 if (!token_pos_initialized_) { | 614 if (!token_pos_initialized_) { |
660 TokenPos(); // Side effect: computes token_pos_initialized_, try_index_. | 615 TokenPos(); // Side effect: computes token_pos_initialized_, try_index_. |
661 } | 616 } |
662 return deopt_id_; | 617 return deopt_id_; |
663 } | 618 } |
664 | 619 |
665 | |
666 intptr_t ActivationFrame::LineNumber() { | 620 intptr_t ActivationFrame::LineNumber() { |
667 // Compute line number lazily since it causes scanning of the script. | 621 // Compute line number lazily since it causes scanning of the script. |
668 if ((line_number_ < 0) && TokenPos().IsSourcePosition()) { | 622 if ((line_number_ < 0) && TokenPos().IsSourcePosition()) { |
669 const TokenPosition token_pos = TokenPos().SourcePosition(); | 623 const TokenPosition token_pos = TokenPos().SourcePosition(); |
670 const Script& script = Script::Handle(SourceScript()); | 624 const Script& script = Script::Handle(SourceScript()); |
671 script.GetTokenLocation(token_pos, &line_number_, NULL); | 625 script.GetTokenLocation(token_pos, &line_number_, NULL); |
672 } | 626 } |
673 return line_number_; | 627 return line_number_; |
674 } | 628 } |
675 | 629 |
676 | |
677 intptr_t ActivationFrame::ColumnNumber() { | 630 intptr_t ActivationFrame::ColumnNumber() { |
678 // Compute column number lazily since it causes scanning of the script. | 631 // Compute column number lazily since it causes scanning of the script. |
679 if ((column_number_ < 0) && TokenPos().IsSourcePosition()) { | 632 if ((column_number_ < 0) && TokenPos().IsSourcePosition()) { |
680 const TokenPosition token_pos = TokenPos().SourcePosition(); | 633 const TokenPosition token_pos = TokenPos().SourcePosition(); |
681 const Script& script = Script::Handle(SourceScript()); | 634 const Script& script = Script::Handle(SourceScript()); |
682 if (script.HasSource()) { | 635 if (script.HasSource()) { |
683 script.GetTokenLocation(token_pos, &line_number_, &column_number_); | 636 script.GetTokenLocation(token_pos, &line_number_, &column_number_); |
684 } else { | 637 } else { |
685 column_number_ = -1; | 638 column_number_ = -1; |
686 } | 639 } |
687 } | 640 } |
688 return column_number_; | 641 return column_number_; |
689 } | 642 } |
690 | 643 |
691 | |
692 void ActivationFrame::GetVarDescriptors() { | 644 void ActivationFrame::GetVarDescriptors() { |
693 if (var_descriptors_.IsNull()) { | 645 if (var_descriptors_.IsNull()) { |
694 Code& unoptimized_code = Code::Handle(function().unoptimized_code()); | 646 Code& unoptimized_code = Code::Handle(function().unoptimized_code()); |
695 if (unoptimized_code.IsNull()) { | 647 if (unoptimized_code.IsNull()) { |
696 Thread* thread = Thread::Current(); | 648 Thread* thread = Thread::Current(); |
697 Zone* zone = thread->zone(); | 649 Zone* zone = thread->zone(); |
698 const Error& error = Error::Handle( | 650 const Error& error = Error::Handle( |
699 zone, Compiler::EnsureUnoptimizedCode(thread, function())); | 651 zone, Compiler::EnsureUnoptimizedCode(thread, function())); |
700 if (!error.IsNull()) { | 652 if (!error.IsNull()) { |
701 Exceptions::PropagateError(error); | 653 Exceptions::PropagateError(error); |
702 } | 654 } |
703 unoptimized_code ^= function().unoptimized_code(); | 655 unoptimized_code ^= function().unoptimized_code(); |
704 } | 656 } |
705 ASSERT(!unoptimized_code.IsNull()); | 657 ASSERT(!unoptimized_code.IsNull()); |
706 var_descriptors_ = unoptimized_code.GetLocalVarDescriptors(); | 658 var_descriptors_ = unoptimized_code.GetLocalVarDescriptors(); |
707 ASSERT(!var_descriptors_.IsNull()); | 659 ASSERT(!var_descriptors_.IsNull()); |
708 } | 660 } |
709 } | 661 } |
710 | 662 |
711 | |
712 bool ActivationFrame::IsDebuggable() const { | 663 bool ActivationFrame::IsDebuggable() const { |
713 return Debugger::IsDebuggable(function()); | 664 return Debugger::IsDebuggable(function()); |
714 } | 665 } |
715 | 666 |
716 | |
717 void ActivationFrame::PrintDescriptorsError(const char* message) { | 667 void ActivationFrame::PrintDescriptorsError(const char* message) { |
718 OS::PrintErr("Bad descriptors: %s\n", message); | 668 OS::PrintErr("Bad descriptors: %s\n", message); |
719 OS::PrintErr("function %s\n", function().ToQualifiedCString()); | 669 OS::PrintErr("function %s\n", function().ToQualifiedCString()); |
720 OS::PrintErr("pc_ %" Px "\n", pc_); | 670 OS::PrintErr("pc_ %" Px "\n", pc_); |
721 OS::PrintErr("deopt_id_ %" Px "\n", deopt_id_); | 671 OS::PrintErr("deopt_id_ %" Px "\n", deopt_id_); |
722 OS::PrintErr("context_level_ %" Px "\n", context_level_); | 672 OS::PrintErr("context_level_ %" Px "\n", context_level_); |
723 DisassembleToStdout formatter; | 673 DisassembleToStdout formatter; |
724 code().Disassemble(&formatter); | 674 code().Disassemble(&formatter); |
725 PcDescriptors::Handle(code().pc_descriptors()).Print(); | 675 PcDescriptors::Handle(code().pc_descriptors()).Print(); |
726 StackFrameIterator frames(StackFrameIterator::kDontValidateFrames, | 676 StackFrameIterator frames(StackFrameIterator::kDontValidateFrames, |
727 Thread::Current(), | 677 Thread::Current(), |
728 StackFrameIterator::kNoCrossThreadIteration); | 678 StackFrameIterator::kNoCrossThreadIteration); |
729 StackFrame* frame = frames.NextFrame(); | 679 StackFrame* frame = frames.NextFrame(); |
730 while (frame != NULL) { | 680 while (frame != NULL) { |
731 OS::PrintErr("%s\n", frame->ToCString()); | 681 OS::PrintErr("%s\n", frame->ToCString()); |
732 frame = frames.NextFrame(); | 682 frame = frames.NextFrame(); |
733 } | 683 } |
734 OS::Abort(); | 684 OS::Abort(); |
735 } | 685 } |
736 | 686 |
737 | |
738 // Calculate the context level at the current token index of the frame. | 687 // Calculate the context level at the current token index of the frame. |
739 intptr_t ActivationFrame::ContextLevel() { | 688 intptr_t ActivationFrame::ContextLevel() { |
740 const Context& ctx = GetSavedCurrentContext(); | 689 const Context& ctx = GetSavedCurrentContext(); |
741 if (context_level_ < 0 && !ctx.IsNull()) { | 690 if (context_level_ < 0 && !ctx.IsNull()) { |
742 ASSERT(!code_.is_optimized()); | 691 ASSERT(!code_.is_optimized()); |
743 | 692 |
744 GetVarDescriptors(); | 693 GetVarDescriptors(); |
745 intptr_t deopt_id = DeoptId(); | 694 intptr_t deopt_id = DeoptId(); |
746 if (deopt_id == Thread::kNoDeoptId) { | 695 if (deopt_id == Thread::kNoDeoptId) { |
747 PrintDescriptorsError("Missing deopt id"); | 696 PrintDescriptorsError("Missing deopt id"); |
(...skipping 13 matching lines...) Expand all Loading... |
761 } | 710 } |
762 } | 711 } |
763 if (!found) { | 712 if (!found) { |
764 PrintDescriptorsError("Missing context level"); | 713 PrintDescriptorsError("Missing context level"); |
765 } | 714 } |
766 ASSERT(context_level_ >= 0); | 715 ASSERT(context_level_ >= 0); |
767 } | 716 } |
768 return context_level_; | 717 return context_level_; |
769 } | 718 } |
770 | 719 |
771 | |
772 RawObject* ActivationFrame::GetAsyncContextVariable(const String& name) { | 720 RawObject* ActivationFrame::GetAsyncContextVariable(const String& name) { |
773 if (!function_.IsAsyncClosure() && !function_.IsAsyncGenClosure()) { | 721 if (!function_.IsAsyncClosure() && !function_.IsAsyncGenClosure()) { |
774 return Object::null(); | 722 return Object::null(); |
775 } | 723 } |
776 GetVarDescriptors(); | 724 GetVarDescriptors(); |
777 intptr_t var_desc_len = var_descriptors_.Length(); | 725 intptr_t var_desc_len = var_descriptors_.Length(); |
778 for (intptr_t i = 0; i < var_desc_len; i++) { | 726 for (intptr_t i = 0; i < var_desc_len; i++) { |
779 RawLocalVarDescriptors::VarInfo var_info; | 727 RawLocalVarDescriptors::VarInfo var_info; |
780 var_descriptors_.GetInfo(i, &var_info); | 728 var_descriptors_.GetInfo(i, &var_info); |
781 if (var_descriptors_.GetName(i) == name.raw()) { | 729 if (var_descriptors_.GetName(i) == name.raw()) { |
782 const int8_t kind = var_info.kind(); | 730 const int8_t kind = var_info.kind(); |
783 if (!live_frame_) { | 731 if (!live_frame_) { |
784 ASSERT(kind == RawLocalVarDescriptors::kContextVar); | 732 ASSERT(kind == RawLocalVarDescriptors::kContextVar); |
785 } | 733 } |
786 if (kind == RawLocalVarDescriptors::kStackVar) { | 734 if (kind == RawLocalVarDescriptors::kStackVar) { |
787 return GetStackVar(var_info.index()); | 735 return GetStackVar(var_info.index()); |
788 } else { | 736 } else { |
789 ASSERT(kind == RawLocalVarDescriptors::kContextVar); | 737 ASSERT(kind == RawLocalVarDescriptors::kContextVar); |
790 if (!live_frame_) { | 738 if (!live_frame_) { |
791 ASSERT(!ctx_.IsNull()); | 739 ASSERT(!ctx_.IsNull()); |
792 return ctx_.At(var_info.index()); | 740 return ctx_.At(var_info.index()); |
793 } | 741 } |
794 return GetContextVar(var_info.scope_id, var_info.index()); | 742 return GetContextVar(var_info.scope_id, var_info.index()); |
795 } | 743 } |
796 } | 744 } |
797 } | 745 } |
798 return Object::null(); | 746 return Object::null(); |
799 } | 747 } |
800 | 748 |
801 | |
802 RawObject* ActivationFrame::GetAsyncCompleter() { | 749 RawObject* ActivationFrame::GetAsyncCompleter() { |
803 return GetAsyncContextVariable(Symbols::AsyncCompleter()); | 750 return GetAsyncContextVariable(Symbols::AsyncCompleter()); |
804 } | 751 } |
805 | 752 |
806 | |
807 RawObject* ActivationFrame::GetAsyncCompleterAwaiter(const Object& completer) { | 753 RawObject* ActivationFrame::GetAsyncCompleterAwaiter(const Object& completer) { |
808 const Class& sync_completer_cls = Class::Handle(completer.clazz()); | 754 const Class& sync_completer_cls = Class::Handle(completer.clazz()); |
809 ASSERT(!sync_completer_cls.IsNull()); | 755 ASSERT(!sync_completer_cls.IsNull()); |
810 const Class& completer_cls = Class::Handle(sync_completer_cls.SuperClass()); | 756 const Class& completer_cls = Class::Handle(sync_completer_cls.SuperClass()); |
811 const Field& future_field = | 757 const Field& future_field = |
812 Field::Handle(completer_cls.LookupInstanceFieldAllowPrivate( | 758 Field::Handle(completer_cls.LookupInstanceFieldAllowPrivate( |
813 Symbols::CompleterFuture())); | 759 Symbols::CompleterFuture())); |
814 ASSERT(!future_field.IsNull()); | 760 ASSERT(!future_field.IsNull()); |
815 Instance& future = Instance::Handle(); | 761 Instance& future = Instance::Handle(); |
816 future ^= Instance::Cast(completer).GetField(future_field); | 762 future ^= Instance::Cast(completer).GetField(future_field); |
817 if (future.IsNull()) { | 763 if (future.IsNull()) { |
818 // The completer object may not be fully initialized yet. | 764 // The completer object may not be fully initialized yet. |
819 return Object::null(); | 765 return Object::null(); |
820 } | 766 } |
821 const Class& future_cls = Class::Handle(future.clazz()); | 767 const Class& future_cls = Class::Handle(future.clazz()); |
822 ASSERT(!future_cls.IsNull()); | 768 ASSERT(!future_cls.IsNull()); |
823 const Field& awaiter_field = Field::Handle( | 769 const Field& awaiter_field = Field::Handle( |
824 future_cls.LookupInstanceFieldAllowPrivate(Symbols::_Awaiter())); | 770 future_cls.LookupInstanceFieldAllowPrivate(Symbols::_Awaiter())); |
825 ASSERT(!awaiter_field.IsNull()); | 771 ASSERT(!awaiter_field.IsNull()); |
826 return future.GetField(awaiter_field); | 772 return future.GetField(awaiter_field); |
827 } | 773 } |
828 | 774 |
829 | |
830 RawObject* ActivationFrame::GetAsyncStreamControllerStream() { | 775 RawObject* ActivationFrame::GetAsyncStreamControllerStream() { |
831 return GetAsyncContextVariable(Symbols::ControllerStream()); | 776 return GetAsyncContextVariable(Symbols::ControllerStream()); |
832 } | 777 } |
833 | 778 |
834 | |
835 RawObject* ActivationFrame::GetAsyncStreamControllerStreamAwaiter( | 779 RawObject* ActivationFrame::GetAsyncStreamControllerStreamAwaiter( |
836 const Object& stream) { | 780 const Object& stream) { |
837 const Class& stream_cls = Class::Handle(stream.clazz()); | 781 const Class& stream_cls = Class::Handle(stream.clazz()); |
838 ASSERT(!stream_cls.IsNull()); | 782 ASSERT(!stream_cls.IsNull()); |
839 const Class& stream_impl_cls = Class::Handle(stream_cls.SuperClass()); | 783 const Class& stream_impl_cls = Class::Handle(stream_cls.SuperClass()); |
840 const Field& awaiter_field = Field::Handle( | 784 const Field& awaiter_field = Field::Handle( |
841 stream_impl_cls.LookupInstanceFieldAllowPrivate(Symbols::_Awaiter())); | 785 stream_impl_cls.LookupInstanceFieldAllowPrivate(Symbols::_Awaiter())); |
842 ASSERT(!awaiter_field.IsNull()); | 786 ASSERT(!awaiter_field.IsNull()); |
843 return Instance::Cast(stream).GetField(awaiter_field); | 787 return Instance::Cast(stream).GetField(awaiter_field); |
844 } | 788 } |
845 | 789 |
846 | |
847 RawObject* ActivationFrame::GetAsyncAwaiter() { | 790 RawObject* ActivationFrame::GetAsyncAwaiter() { |
848 const Object& async_stream_controller_stream = | 791 const Object& async_stream_controller_stream = |
849 Object::Handle(GetAsyncStreamControllerStream()); | 792 Object::Handle(GetAsyncStreamControllerStream()); |
850 if (!async_stream_controller_stream.IsNull()) { | 793 if (!async_stream_controller_stream.IsNull()) { |
851 return GetAsyncStreamControllerStreamAwaiter( | 794 return GetAsyncStreamControllerStreamAwaiter( |
852 async_stream_controller_stream); | 795 async_stream_controller_stream); |
853 } | 796 } |
854 const Object& completer = Object::Handle(GetAsyncCompleter()); | 797 const Object& completer = Object::Handle(GetAsyncCompleter()); |
855 if (!completer.IsNull()) { | 798 if (!completer.IsNull()) { |
856 return GetAsyncCompleterAwaiter(completer); | 799 return GetAsyncCompleterAwaiter(completer); |
857 } | 800 } |
858 return Object::null(); | 801 return Object::null(); |
859 } | 802 } |
860 | 803 |
861 | |
862 RawObject* ActivationFrame::GetCausalStack() { | 804 RawObject* ActivationFrame::GetCausalStack() { |
863 return GetAsyncContextVariable(Symbols::AsyncStackTraceVar()); | 805 return GetAsyncContextVariable(Symbols::AsyncStackTraceVar()); |
864 } | 806 } |
865 | 807 |
866 | |
867 bool ActivationFrame::HandlesException(const Instance& exc_obj) { | 808 bool ActivationFrame::HandlesException(const Instance& exc_obj) { |
868 if ((kind_ == kAsyncSuspensionMarker) || (kind_ == kAsyncCausal)) { | 809 if ((kind_ == kAsyncSuspensionMarker) || (kind_ == kAsyncCausal)) { |
869 // These frames are historical. | 810 // These frames are historical. |
870 return false; | 811 return false; |
871 } | 812 } |
872 intptr_t try_index = TryIndex(); | 813 intptr_t try_index = TryIndex(); |
873 if (try_index < 0) { | 814 if (try_index < 0) { |
874 return false; | 815 return false; |
875 } | 816 } |
876 ExceptionHandlers& handlers = ExceptionHandlers::Handle(); | 817 ExceptionHandlers& handlers = ExceptionHandlers::Handle(); |
(...skipping 27 matching lines...) Expand all Loading... |
904 Object::null_type_arguments(), NULL)) { | 845 Object::null_type_arguments(), NULL)) { |
905 return true; | 846 return true; |
906 } | 847 } |
907 } | 848 } |
908 } | 849 } |
909 try_index = handlers.OuterTryIndex(try_index); | 850 try_index = handlers.OuterTryIndex(try_index); |
910 } | 851 } |
911 return false; | 852 return false; |
912 } | 853 } |
913 | 854 |
914 | |
915 void ActivationFrame::ExtractTokenPositionFromAsyncClosure() { | 855 void ActivationFrame::ExtractTokenPositionFromAsyncClosure() { |
916 // Attempt to determine the token position from the async closure. | 856 // Attempt to determine the token position from the async closure. |
917 ASSERT(function_.IsAsyncGenClosure() || function_.IsAsyncClosure()); | 857 ASSERT(function_.IsAsyncGenClosure() || function_.IsAsyncClosure()); |
918 // This should only be called on frames that aren't active on the stack. | 858 // This should only be called on frames that aren't active on the stack. |
919 ASSERT(fp() == 0); | 859 ASSERT(fp() == 0); |
920 const Array& await_to_token_map = | 860 const Array& await_to_token_map = |
921 Array::Handle(code_.await_token_positions()); | 861 Array::Handle(code_.await_token_positions()); |
922 if (await_to_token_map.IsNull()) { | 862 if (await_to_token_map.IsNull()) { |
923 // No mapping. | 863 // No mapping. |
924 return; | 864 return; |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
958 // TODO(johnmccutchan): Is this heuristic precise enough? | 898 // TODO(johnmccutchan): Is this heuristic precise enough? |
959 if (iter.TryIndex() != CatchClauseNode::kInvalidTryIndex) { | 899 if (iter.TryIndex() != CatchClauseNode::kInvalidTryIndex) { |
960 if ((try_index_ == -1) || (iter.TryIndex() < try_index_)) { | 900 if ((try_index_ == -1) || (iter.TryIndex() < try_index_)) { |
961 try_index_ = iter.TryIndex(); | 901 try_index_ = iter.TryIndex(); |
962 } | 902 } |
963 } | 903 } |
964 } | 904 } |
965 } | 905 } |
966 } | 906 } |
967 | 907 |
968 | |
969 bool ActivationFrame::IsAsyncMachinery() const { | 908 bool ActivationFrame::IsAsyncMachinery() const { |
970 Isolate* isolate = Isolate::Current(); | 909 Isolate* isolate = Isolate::Current(); |
971 if (function_.raw() == isolate->object_store()->complete_on_async_return()) { | 910 if (function_.raw() == isolate->object_store()->complete_on_async_return()) { |
972 // We are completing an async function's completer. | 911 // We are completing an async function's completer. |
973 return true; | 912 return true; |
974 } | 913 } |
975 if (function_.Owner() == | 914 if (function_.Owner() == |
976 isolate->object_store()->async_star_stream_controller()) { | 915 isolate->object_store()->async_star_stream_controller()) { |
977 // We are inside the async* stream controller code. | 916 // We are inside the async* stream controller code. |
978 return true; | 917 return true; |
979 } | 918 } |
980 return false; | 919 return false; |
981 } | 920 } |
982 | 921 |
983 | |
984 // Get the saved current context of this activation. | 922 // Get the saved current context of this activation. |
985 const Context& ActivationFrame::GetSavedCurrentContext() { | 923 const Context& ActivationFrame::GetSavedCurrentContext() { |
986 if (!ctx_.IsNull()) return ctx_; | 924 if (!ctx_.IsNull()) return ctx_; |
987 GetVarDescriptors(); | 925 GetVarDescriptors(); |
988 intptr_t var_desc_len = var_descriptors_.Length(); | 926 intptr_t var_desc_len = var_descriptors_.Length(); |
989 Object& obj = Object::Handle(); | 927 Object& obj = Object::Handle(); |
990 for (intptr_t i = 0; i < var_desc_len; i++) { | 928 for (intptr_t i = 0; i < var_desc_len; i++) { |
991 RawLocalVarDescriptors::VarInfo var_info; | 929 RawLocalVarDescriptors::VarInfo var_info; |
992 var_descriptors_.GetInfo(i, &var_info); | 930 var_descriptors_.GetInfo(i, &var_info); |
993 const int8_t kind = var_info.kind(); | 931 const int8_t kind = var_info.kind(); |
(...skipping 12 matching lines...) Expand all Loading... |
1006 ctx_ ^= Context::Cast(obj).raw(); | 944 ctx_ ^= Context::Cast(obj).raw(); |
1007 } else { | 945 } else { |
1008 ASSERT(obj.IsNull()); | 946 ASSERT(obj.IsNull()); |
1009 } | 947 } |
1010 return ctx_; | 948 return ctx_; |
1011 } | 949 } |
1012 } | 950 } |
1013 return ctx_; | 951 return ctx_; |
1014 } | 952 } |
1015 | 953 |
1016 | |
1017 RawObject* ActivationFrame::GetAsyncOperation() { | 954 RawObject* ActivationFrame::GetAsyncOperation() { |
1018 GetVarDescriptors(); | 955 GetVarDescriptors(); |
1019 intptr_t var_desc_len = var_descriptors_.Length(); | 956 intptr_t var_desc_len = var_descriptors_.Length(); |
1020 for (intptr_t i = 0; i < var_desc_len; i++) { | 957 for (intptr_t i = 0; i < var_desc_len; i++) { |
1021 RawLocalVarDescriptors::VarInfo var_info; | 958 RawLocalVarDescriptors::VarInfo var_info; |
1022 var_descriptors_.GetInfo(i, &var_info); | 959 var_descriptors_.GetInfo(i, &var_info); |
1023 if (var_descriptors_.GetName(i) == Symbols::AsyncOperation().raw()) { | 960 if (var_descriptors_.GetName(i) == Symbols::AsyncOperation().raw()) { |
1024 const int8_t kind = var_info.kind(); | 961 const int8_t kind = var_info.kind(); |
1025 if (kind == RawLocalVarDescriptors::kStackVar) { | 962 if (kind == RawLocalVarDescriptors::kStackVar) { |
1026 return GetStackVar(var_info.index()); | 963 return GetStackVar(var_info.index()); |
1027 } else { | 964 } else { |
1028 ASSERT(kind == RawLocalVarDescriptors::kContextVar); | 965 ASSERT(kind == RawLocalVarDescriptors::kContextVar); |
1029 return GetContextVar(var_info.scope_id, var_info.index()); | 966 return GetContextVar(var_info.scope_id, var_info.index()); |
1030 } | 967 } |
1031 } | 968 } |
1032 } | 969 } |
1033 return Object::null(); | 970 return Object::null(); |
1034 } | 971 } |
1035 | 972 |
1036 | |
1037 ActivationFrame* DebuggerStackTrace::GetHandlerFrame( | 973 ActivationFrame* DebuggerStackTrace::GetHandlerFrame( |
1038 const Instance& exc_obj) const { | 974 const Instance& exc_obj) const { |
1039 for (intptr_t frame_index = 0; frame_index < Length(); frame_index++) { | 975 for (intptr_t frame_index = 0; frame_index < Length(); frame_index++) { |
1040 ActivationFrame* frame = FrameAt(frame_index); | 976 ActivationFrame* frame = FrameAt(frame_index); |
1041 if (frame->HandlesException(exc_obj)) { | 977 if (frame->HandlesException(exc_obj)) { |
1042 return frame; | 978 return frame; |
1043 } | 979 } |
1044 } | 980 } |
1045 return NULL; | 981 return NULL; |
1046 } | 982 } |
1047 | 983 |
1048 | |
1049 void ActivationFrame::GetDescIndices() { | 984 void ActivationFrame::GetDescIndices() { |
1050 if (vars_initialized_) { | 985 if (vars_initialized_) { |
1051 return; | 986 return; |
1052 } | 987 } |
1053 GetVarDescriptors(); | 988 GetVarDescriptors(); |
1054 | 989 |
1055 TokenPosition activation_token_pos = TokenPos(); | 990 TokenPosition activation_token_pos = TokenPos(); |
1056 if (!activation_token_pos.IsDebugPause() || !live_frame_) { | 991 if (!activation_token_pos.IsDebugPause() || !live_frame_) { |
1057 // We don't have a token position for this frame, so can't determine | 992 // We don't have a token position for this frame, so can't determine |
1058 // which variables are visible. | 993 // which variables are visible. |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1114 // No duplicate name found. Add the current descriptor index to the | 1049 // No duplicate name found. Add the current descriptor index to the |
1115 // list of visible variables. | 1050 // list of visible variables. |
1116 desc_indices_.Add(cur_idx); | 1051 desc_indices_.Add(cur_idx); |
1117 var_names.Add(&var_name); | 1052 var_names.Add(&var_name); |
1118 } | 1053 } |
1119 } | 1054 } |
1120 } | 1055 } |
1121 vars_initialized_ = true; | 1056 vars_initialized_ = true; |
1122 } | 1057 } |
1123 | 1058 |
1124 | |
1125 intptr_t ActivationFrame::NumLocalVariables() { | 1059 intptr_t ActivationFrame::NumLocalVariables() { |
1126 GetDescIndices(); | 1060 GetDescIndices(); |
1127 return desc_indices_.length(); | 1061 return desc_indices_.length(); |
1128 } | 1062 } |
1129 | 1063 |
1130 | |
1131 DART_FORCE_INLINE static RawObject* GetVariableValue(uword addr) { | 1064 DART_FORCE_INLINE static RawObject* GetVariableValue(uword addr) { |
1132 return *reinterpret_cast<RawObject**>(addr); | 1065 return *reinterpret_cast<RawObject**>(addr); |
1133 } | 1066 } |
1134 | 1067 |
1135 | |
1136 RawObject* ActivationFrame::GetParameter(intptr_t index) { | 1068 RawObject* ActivationFrame::GetParameter(intptr_t index) { |
1137 intptr_t num_parameters = function().num_fixed_parameters(); | 1069 intptr_t num_parameters = function().num_fixed_parameters(); |
1138 ASSERT(0 <= index && index < num_parameters); | 1070 ASSERT(0 <= index && index < num_parameters); |
1139 | 1071 |
1140 if (function().NumOptionalParameters() > 0) { | 1072 if (function().NumOptionalParameters() > 0) { |
1141 // If the function has optional parameters, the first positional parameter | 1073 // If the function has optional parameters, the first positional parameter |
1142 // can be in a number of places in the caller's frame depending on how many | 1074 // can be in a number of places in the caller's frame depending on how many |
1143 // were actually supplied at the call site, but they are copied to a fixed | 1075 // were actually supplied at the call site, but they are copied to a fixed |
1144 // place in the callee's frame. | 1076 // place in the callee's frame. |
1145 return GetVariableValue( | 1077 return GetVariableValue( |
1146 LocalVarAddress(fp(), (kFirstLocalSlotFromFp - index))); | 1078 LocalVarAddress(fp(), (kFirstLocalSlotFromFp - index))); |
1147 } else { | 1079 } else { |
1148 intptr_t reverse_index = num_parameters - index; | 1080 intptr_t reverse_index = num_parameters - index; |
1149 return GetVariableValue(ParamAddress(fp(), reverse_index)); | 1081 return GetVariableValue(ParamAddress(fp(), reverse_index)); |
1150 } | 1082 } |
1151 } | 1083 } |
1152 | 1084 |
1153 | |
1154 RawObject* ActivationFrame::GetClosure() { | 1085 RawObject* ActivationFrame::GetClosure() { |
1155 ASSERT(function().IsClosureFunction()); | 1086 ASSERT(function().IsClosureFunction()); |
1156 return GetParameter(0); | 1087 return GetParameter(0); |
1157 } | 1088 } |
1158 | 1089 |
1159 | |
1160 RawObject* ActivationFrame::GetStackVar(intptr_t slot_index) { | 1090 RawObject* ActivationFrame::GetStackVar(intptr_t slot_index) { |
1161 if (deopt_frame_.IsNull()) { | 1091 if (deopt_frame_.IsNull()) { |
1162 return GetVariableValue(LocalVarAddress(fp(), slot_index)); | 1092 return GetVariableValue(LocalVarAddress(fp(), slot_index)); |
1163 } else { | 1093 } else { |
1164 return deopt_frame_.At(LocalVarIndex(deopt_frame_offset_, slot_index)); | 1094 return deopt_frame_.At(LocalVarIndex(deopt_frame_offset_, slot_index)); |
1165 } | 1095 } |
1166 } | 1096 } |
1167 | 1097 |
1168 | |
1169 bool ActivationFrame::IsRewindable() const { | 1098 bool ActivationFrame::IsRewindable() const { |
1170 if (deopt_frame_.IsNull()) { | 1099 if (deopt_frame_.IsNull()) { |
1171 return true; | 1100 return true; |
1172 } | 1101 } |
1173 // TODO(turnidge): This is conservative. It looks at all values in | 1102 // TODO(turnidge): This is conservative. It looks at all values in |
1174 // the deopt_frame_ even though some of them may correspond to other | 1103 // the deopt_frame_ even though some of them may correspond to other |
1175 // inlined frames. | 1104 // inlined frames. |
1176 Object& obj = Object::Handle(); | 1105 Object& obj = Object::Handle(); |
1177 for (int i = 0; i < deopt_frame_.Length(); i++) { | 1106 for (int i = 0; i < deopt_frame_.Length(); i++) { |
1178 obj = deopt_frame_.At(i); | 1107 obj = deopt_frame_.At(i); |
1179 if (obj.raw() == Symbols::OptimizedOut().raw()) { | 1108 if (obj.raw() == Symbols::OptimizedOut().raw()) { |
1180 return false; | 1109 return false; |
1181 } | 1110 } |
1182 } | 1111 } |
1183 return true; | 1112 return true; |
1184 } | 1113 } |
1185 | 1114 |
1186 | |
1187 void ActivationFrame::PrintContextMismatchError(intptr_t ctx_slot, | 1115 void ActivationFrame::PrintContextMismatchError(intptr_t ctx_slot, |
1188 intptr_t frame_ctx_level, | 1116 intptr_t frame_ctx_level, |
1189 intptr_t var_ctx_level) { | 1117 intptr_t var_ctx_level) { |
1190 OS::PrintErr( | 1118 OS::PrintErr( |
1191 "-------------------------\n" | 1119 "-------------------------\n" |
1192 "Encountered context mismatch\n" | 1120 "Encountered context mismatch\n" |
1193 "\tctx_slot: %" Pd | 1121 "\tctx_slot: %" Pd |
1194 "\n" | 1122 "\n" |
1195 "\tframe_ctx_level: %" Pd | 1123 "\tframe_ctx_level: %" Pd |
1196 "\n" | 1124 "\n" |
(...skipping 28 matching lines...) Expand all Loading... |
1225 Thread::Current(), | 1153 Thread::Current(), |
1226 StackFrameIterator::kNoCrossThreadIteration); | 1154 StackFrameIterator::kNoCrossThreadIteration); |
1227 StackFrame* frame = iterator.NextFrame(); | 1155 StackFrame* frame = iterator.NextFrame(); |
1228 intptr_t num = 0; | 1156 intptr_t num = 0; |
1229 while ((frame != NULL)) { | 1157 while ((frame != NULL)) { |
1230 OS::PrintErr("#%04" Pd " %s\n", num++, frame->ToCString()); | 1158 OS::PrintErr("#%04" Pd " %s\n", num++, frame->ToCString()); |
1231 frame = iterator.NextFrame(); | 1159 frame = iterator.NextFrame(); |
1232 } | 1160 } |
1233 } | 1161 } |
1234 | 1162 |
1235 | |
1236 void ActivationFrame::VariableAt(intptr_t i, | 1163 void ActivationFrame::VariableAt(intptr_t i, |
1237 String* name, | 1164 String* name, |
1238 TokenPosition* declaration_token_pos, | 1165 TokenPosition* declaration_token_pos, |
1239 TokenPosition* visible_start_token_pos, | 1166 TokenPosition* visible_start_token_pos, |
1240 TokenPosition* visible_end_token_pos, | 1167 TokenPosition* visible_end_token_pos, |
1241 Object* value) { | 1168 Object* value) { |
1242 GetDescIndices(); | 1169 GetDescIndices(); |
1243 ASSERT(i < desc_indices_.length()); | 1170 ASSERT(i < desc_indices_.length()); |
1244 intptr_t desc_index = desc_indices_[i]; | 1171 intptr_t desc_index = desc_indices_[i]; |
1245 ASSERT(name != NULL); | 1172 ASSERT(name != NULL); |
(...skipping 11 matching lines...) Expand all Loading... |
1257 ASSERT(value != NULL); | 1184 ASSERT(value != NULL); |
1258 const int8_t kind = var_info.kind(); | 1185 const int8_t kind = var_info.kind(); |
1259 if (kind == RawLocalVarDescriptors::kStackVar) { | 1186 if (kind == RawLocalVarDescriptors::kStackVar) { |
1260 *value = GetStackVar(var_info.index()); | 1187 *value = GetStackVar(var_info.index()); |
1261 } else { | 1188 } else { |
1262 ASSERT(kind == RawLocalVarDescriptors::kContextVar); | 1189 ASSERT(kind == RawLocalVarDescriptors::kContextVar); |
1263 *value = GetContextVar(var_info.scope_id, var_info.index()); | 1190 *value = GetContextVar(var_info.scope_id, var_info.index()); |
1264 } | 1191 } |
1265 } | 1192 } |
1266 | 1193 |
1267 | |
1268 RawObject* ActivationFrame::GetContextVar(intptr_t var_ctx_level, | 1194 RawObject* ActivationFrame::GetContextVar(intptr_t var_ctx_level, |
1269 intptr_t ctx_slot) { | 1195 intptr_t ctx_slot) { |
1270 const Context& ctx = GetSavedCurrentContext(); | 1196 const Context& ctx = GetSavedCurrentContext(); |
1271 ASSERT(!ctx.IsNull()); | 1197 ASSERT(!ctx.IsNull()); |
1272 | 1198 |
1273 // The context level at the PC/token index of this activation frame. | 1199 // The context level at the PC/token index of this activation frame. |
1274 intptr_t frame_ctx_level = ContextLevel(); | 1200 intptr_t frame_ctx_level = ContextLevel(); |
1275 | 1201 |
1276 intptr_t level_diff = frame_ctx_level - var_ctx_level; | 1202 intptr_t level_diff = frame_ctx_level - var_ctx_level; |
1277 if (level_diff == 0) { | 1203 if (level_diff == 0) { |
(...skipping 12 matching lines...) Expand all Loading... |
1290 if (var_ctx.IsNull() || (ctx_slot < 0) || | 1216 if (var_ctx.IsNull() || (ctx_slot < 0) || |
1291 (ctx_slot >= var_ctx.num_variables())) { | 1217 (ctx_slot >= var_ctx.num_variables())) { |
1292 PrintContextMismatchError(ctx_slot, frame_ctx_level, var_ctx_level); | 1218 PrintContextMismatchError(ctx_slot, frame_ctx_level, var_ctx_level); |
1293 } | 1219 } |
1294 ASSERT(!var_ctx.IsNull()); | 1220 ASSERT(!var_ctx.IsNull()); |
1295 ASSERT((ctx_slot >= 0) && (ctx_slot < var_ctx.num_variables())); | 1221 ASSERT((ctx_slot >= 0) && (ctx_slot < var_ctx.num_variables())); |
1296 return var_ctx.At(ctx_slot); | 1222 return var_ctx.At(ctx_slot); |
1297 } | 1223 } |
1298 } | 1224 } |
1299 | 1225 |
1300 | |
1301 RawArray* ActivationFrame::GetLocalVariables() { | 1226 RawArray* ActivationFrame::GetLocalVariables() { |
1302 GetDescIndices(); | 1227 GetDescIndices(); |
1303 intptr_t num_variables = desc_indices_.length(); | 1228 intptr_t num_variables = desc_indices_.length(); |
1304 String& var_name = String::Handle(); | 1229 String& var_name = String::Handle(); |
1305 Object& value = Instance::Handle(); | 1230 Object& value = Instance::Handle(); |
1306 const Array& list = Array::Handle(Array::New(2 * num_variables)); | 1231 const Array& list = Array::Handle(Array::New(2 * num_variables)); |
1307 for (intptr_t i = 0; i < num_variables; i++) { | 1232 for (intptr_t i = 0; i < num_variables; i++) { |
1308 TokenPosition ignore; | 1233 TokenPosition ignore; |
1309 VariableAt(i, &var_name, &ignore, &ignore, &ignore, &value); | 1234 VariableAt(i, &var_name, &ignore, &ignore, &ignore, &value); |
1310 list.SetAt(2 * i, var_name); | 1235 list.SetAt(2 * i, var_name); |
1311 list.SetAt((2 * i) + 1, value); | 1236 list.SetAt((2 * i) + 1, value); |
1312 } | 1237 } |
1313 return list.raw(); | 1238 return list.raw(); |
1314 } | 1239 } |
1315 | 1240 |
1316 | |
1317 RawObject* ActivationFrame::GetReceiver() { | 1241 RawObject* ActivationFrame::GetReceiver() { |
1318 GetDescIndices(); | 1242 GetDescIndices(); |
1319 intptr_t num_variables = desc_indices_.length(); | 1243 intptr_t num_variables = desc_indices_.length(); |
1320 String& var_name = String::Handle(); | 1244 String& var_name = String::Handle(); |
1321 Instance& value = Instance::Handle(); | 1245 Instance& value = Instance::Handle(); |
1322 for (intptr_t i = 0; i < num_variables; i++) { | 1246 for (intptr_t i = 0; i < num_variables; i++) { |
1323 TokenPosition ignore; | 1247 TokenPosition ignore; |
1324 VariableAt(i, &var_name, &ignore, &ignore, &ignore, &value); | 1248 VariableAt(i, &var_name, &ignore, &ignore, &ignore, &value); |
1325 if (var_name.Equals(Symbols::This())) { | 1249 if (var_name.Equals(Symbols::This())) { |
1326 return value.raw(); | 1250 return value.raw(); |
1327 } | 1251 } |
1328 } | 1252 } |
1329 return Symbols::OptimizedOut().raw(); | 1253 return Symbols::OptimizedOut().raw(); |
1330 } | 1254 } |
1331 | 1255 |
1332 | |
1333 static bool IsSyntheticVariableName(const String& var_name) { | 1256 static bool IsSyntheticVariableName(const String& var_name) { |
1334 return (var_name.Length() >= 1) && (var_name.CharAt(0) == ':'); | 1257 return (var_name.Length() >= 1) && (var_name.CharAt(0) == ':'); |
1335 } | 1258 } |
1336 | 1259 |
1337 | |
1338 static bool IsPrivateVariableName(const String& var_name) { | 1260 static bool IsPrivateVariableName(const String& var_name) { |
1339 return (var_name.Length() >= 1) && (var_name.CharAt(0) == '_'); | 1261 return (var_name.Length() >= 1) && (var_name.CharAt(0) == '_'); |
1340 } | 1262 } |
1341 | 1263 |
1342 | |
1343 RawObject* ActivationFrame::Evaluate(const String& expr, | 1264 RawObject* ActivationFrame::Evaluate(const String& expr, |
1344 const GrowableObjectArray& param_names, | 1265 const GrowableObjectArray& param_names, |
1345 const GrowableObjectArray& param_values) { | 1266 const GrowableObjectArray& param_values) { |
1346 GetDescIndices(); | 1267 GetDescIndices(); |
1347 String& name = String::Handle(); | 1268 String& name = String::Handle(); |
1348 String& existing_name = String::Handle(); | 1269 String& existing_name = String::Handle(); |
1349 Object& value = Instance::Handle(); | 1270 Object& value = Instance::Handle(); |
1350 intptr_t num_variables = desc_indices_.length(); | 1271 intptr_t num_variables = desc_indices_.length(); |
1351 for (intptr_t i = 0; i < num_variables; i++) { | 1272 for (intptr_t i = 0; i < num_variables; i++) { |
1352 TokenPosition ignore; | 1273 TokenPosition ignore; |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1387 } | 1308 } |
1388 const Instance& inst = Instance::Cast(receiver); | 1309 const Instance& inst = Instance::Cast(receiver); |
1389 return inst.Evaluate(method_cls, expr, | 1310 return inst.Evaluate(method_cls, expr, |
1390 Array::Handle(Array::MakeFixedLength(param_names)), | 1311 Array::Handle(Array::MakeFixedLength(param_names)), |
1391 Array::Handle(Array::MakeFixedLength(param_values))); | 1312 Array::Handle(Array::MakeFixedLength(param_values))); |
1392 } | 1313 } |
1393 UNREACHABLE(); | 1314 UNREACHABLE(); |
1394 return Object::null(); | 1315 return Object::null(); |
1395 } | 1316 } |
1396 | 1317 |
1397 | |
1398 const char* ActivationFrame::ToCString() { | 1318 const char* ActivationFrame::ToCString() { |
1399 const String& url = String::Handle(SourceUrl()); | 1319 const String& url = String::Handle(SourceUrl()); |
1400 intptr_t line = LineNumber(); | 1320 intptr_t line = LineNumber(); |
1401 const char* func_name = Debugger::QualifiedFunctionName(function()); | 1321 const char* func_name = Debugger::QualifiedFunctionName(function()); |
1402 return Thread::Current()->zone()->PrintToString( | 1322 return Thread::Current()->zone()->PrintToString( |
1403 "[ Frame pc(0x%" Px ") fp(0x%" Px ") sp(0x%" Px | 1323 "[ Frame pc(0x%" Px ") fp(0x%" Px ") sp(0x%" Px |
1404 ")\n" | 1324 ")\n" |
1405 "\tfunction = %s\n" | 1325 "\tfunction = %s\n" |
1406 "\turl = %s\n" | 1326 "\turl = %s\n" |
1407 "\tline = %" Pd | 1327 "\tline = %" Pd |
1408 "\n" | 1328 "\n" |
1409 "\tcontext = %s\n" | 1329 "\tcontext = %s\n" |
1410 "\tcontext level = %" Pd " ]\n", | 1330 "\tcontext level = %" Pd " ]\n", |
1411 pc(), fp(), sp(), func_name, url.ToCString(), line, ctx_.ToCString(), | 1331 pc(), fp(), sp(), func_name, url.ToCString(), line, ctx_.ToCString(), |
1412 ContextLevel()); | 1332 ContextLevel()); |
1413 } | 1333 } |
1414 | 1334 |
1415 | |
1416 void ActivationFrame::PrintToJSONObject(JSONObject* jsobj, bool full) { | 1335 void ActivationFrame::PrintToJSONObject(JSONObject* jsobj, bool full) { |
1417 if (kind_ == kRegular) { | 1336 if (kind_ == kRegular) { |
1418 PrintToJSONObjectRegular(jsobj, full); | 1337 PrintToJSONObjectRegular(jsobj, full); |
1419 } else if (kind_ == kAsyncCausal) { | 1338 } else if (kind_ == kAsyncCausal) { |
1420 PrintToJSONObjectAsyncCausal(jsobj, full); | 1339 PrintToJSONObjectAsyncCausal(jsobj, full); |
1421 } else if (kind_ == kAsyncSuspensionMarker) { | 1340 } else if (kind_ == kAsyncSuspensionMarker) { |
1422 PrintToJSONObjectAsyncSuspensionMarker(jsobj, full); | 1341 PrintToJSONObjectAsyncSuspensionMarker(jsobj, full); |
1423 } else if (kind_ == kAsyncActivation) { | 1342 } else if (kind_ == kAsyncActivation) { |
1424 PrintToJSONObjectAsyncActivation(jsobj, full); | 1343 PrintToJSONObjectAsyncActivation(jsobj, full); |
1425 } else { | 1344 } else { |
1426 UNIMPLEMENTED(); | 1345 UNIMPLEMENTED(); |
1427 } | 1346 } |
1428 } | 1347 } |
1429 | 1348 |
1430 | |
1431 void ActivationFrame::PrintToJSONObjectRegular(JSONObject* jsobj, bool full) { | 1349 void ActivationFrame::PrintToJSONObjectRegular(JSONObject* jsobj, bool full) { |
1432 const Script& script = Script::Handle(SourceScript()); | 1350 const Script& script = Script::Handle(SourceScript()); |
1433 jsobj->AddProperty("type", "Frame"); | 1351 jsobj->AddProperty("type", "Frame"); |
1434 jsobj->AddProperty("kind", KindToCString(kind_)); | 1352 jsobj->AddProperty("kind", KindToCString(kind_)); |
1435 const TokenPosition pos = TokenPos().SourcePosition(); | 1353 const TokenPosition pos = TokenPos().SourcePosition(); |
1436 jsobj->AddLocation(script, pos); | 1354 jsobj->AddLocation(script, pos); |
1437 jsobj->AddProperty("function", function(), !full); | 1355 jsobj->AddProperty("function", function(), !full); |
1438 jsobj->AddProperty("code", code()); | 1356 jsobj->AddProperty("code", code()); |
1439 if (full) { | 1357 if (full) { |
1440 // TODO(cutch): The old "full" script usage no longer fits | 1358 // TODO(cutch): The old "full" script usage no longer fits |
(...skipping 26 matching lines...) Expand all Loading... |
1467 jsvar.AddProperty("declarationTokenPos", declaration_token_pos); | 1385 jsvar.AddProperty("declarationTokenPos", declaration_token_pos); |
1468 // When the variable becomes visible to the scope. | 1386 // When the variable becomes visible to the scope. |
1469 jsvar.AddProperty("scopeStartTokenPos", visible_start_token_pos); | 1387 jsvar.AddProperty("scopeStartTokenPos", visible_start_token_pos); |
1470 // When the variable stops being visible to the scope. | 1388 // When the variable stops being visible to the scope. |
1471 jsvar.AddProperty("scopeEndTokenPos", visible_end_token_pos); | 1389 jsvar.AddProperty("scopeEndTokenPos", visible_end_token_pos); |
1472 } | 1390 } |
1473 } | 1391 } |
1474 } | 1392 } |
1475 } | 1393 } |
1476 | 1394 |
1477 | |
1478 void ActivationFrame::PrintToJSONObjectAsyncCausal(JSONObject* jsobj, | 1395 void ActivationFrame::PrintToJSONObjectAsyncCausal(JSONObject* jsobj, |
1479 bool full) { | 1396 bool full) { |
1480 jsobj->AddProperty("type", "Frame"); | 1397 jsobj->AddProperty("type", "Frame"); |
1481 jsobj->AddProperty("kind", KindToCString(kind_)); | 1398 jsobj->AddProperty("kind", KindToCString(kind_)); |
1482 const Script& script = Script::Handle(SourceScript()); | 1399 const Script& script = Script::Handle(SourceScript()); |
1483 const TokenPosition pos = TokenPos().SourcePosition(); | 1400 const TokenPosition pos = TokenPos().SourcePosition(); |
1484 jsobj->AddLocation(script, pos); | 1401 jsobj->AddLocation(script, pos); |
1485 jsobj->AddProperty("function", function(), !full); | 1402 jsobj->AddProperty("function", function(), !full); |
1486 jsobj->AddProperty("code", code()); | 1403 jsobj->AddProperty("code", code()); |
1487 if (full) { | 1404 if (full) { |
1488 // TODO(cutch): The old "full" script usage no longer fits | 1405 // TODO(cutch): The old "full" script usage no longer fits |
1489 // in the world where we pass the script as part of the | 1406 // in the world where we pass the script as part of the |
1490 // location. | 1407 // location. |
1491 jsobj->AddProperty("script", script, !full); | 1408 jsobj->AddProperty("script", script, !full); |
1492 } | 1409 } |
1493 } | 1410 } |
1494 | 1411 |
1495 | |
1496 void ActivationFrame::PrintToJSONObjectAsyncSuspensionMarker(JSONObject* jsobj, | 1412 void ActivationFrame::PrintToJSONObjectAsyncSuspensionMarker(JSONObject* jsobj, |
1497 bool full) { | 1413 bool full) { |
1498 jsobj->AddProperty("type", "Frame"); | 1414 jsobj->AddProperty("type", "Frame"); |
1499 jsobj->AddProperty("kind", KindToCString(kind_)); | 1415 jsobj->AddProperty("kind", KindToCString(kind_)); |
1500 jsobj->AddProperty("marker", "AsynchronousSuspension"); | 1416 jsobj->AddProperty("marker", "AsynchronousSuspension"); |
1501 } | 1417 } |
1502 | 1418 |
1503 | |
1504 void ActivationFrame::PrintToJSONObjectAsyncActivation(JSONObject* jsobj, | 1419 void ActivationFrame::PrintToJSONObjectAsyncActivation(JSONObject* jsobj, |
1505 bool full) { | 1420 bool full) { |
1506 jsobj->AddProperty("type", "Frame"); | 1421 jsobj->AddProperty("type", "Frame"); |
1507 jsobj->AddProperty("kind", KindToCString(kind_)); | 1422 jsobj->AddProperty("kind", KindToCString(kind_)); |
1508 const Script& script = Script::Handle(SourceScript()); | 1423 const Script& script = Script::Handle(SourceScript()); |
1509 const TokenPosition pos = TokenPos().SourcePosition(); | 1424 const TokenPosition pos = TokenPos().SourcePosition(); |
1510 jsobj->AddLocation(script, pos); | 1425 jsobj->AddLocation(script, pos); |
1511 jsobj->AddProperty("function", function(), !full); | 1426 jsobj->AddProperty("function", function(), !full); |
1512 jsobj->AddProperty("code", code()); | 1427 jsobj->AddProperty("code", code()); |
1513 if (full) { | 1428 if (full) { |
1514 // TODO(cutch): The old "full" script usage no longer fits | 1429 // TODO(cutch): The old "full" script usage no longer fits |
1515 // in the world where we pass the script as part of the | 1430 // in the world where we pass the script as part of the |
1516 // location. | 1431 // location. |
1517 jsobj->AddProperty("script", script, !full); | 1432 jsobj->AddProperty("script", script, !full); |
1518 } | 1433 } |
1519 } | 1434 } |
1520 | 1435 |
1521 | |
1522 static bool IsFunctionVisible(const Function& function) { | 1436 static bool IsFunctionVisible(const Function& function) { |
1523 return FLAG_show_invisible_frames || function.is_visible(); | 1437 return FLAG_show_invisible_frames || function.is_visible(); |
1524 } | 1438 } |
1525 | 1439 |
1526 | |
1527 void DebuggerStackTrace::AddActivation(ActivationFrame* frame) { | 1440 void DebuggerStackTrace::AddActivation(ActivationFrame* frame) { |
1528 if (IsFunctionVisible(frame->function())) { | 1441 if (IsFunctionVisible(frame->function())) { |
1529 trace_.Add(frame); | 1442 trace_.Add(frame); |
1530 } | 1443 } |
1531 } | 1444 } |
1532 | 1445 |
1533 | |
1534 void DebuggerStackTrace::AddMarker(ActivationFrame::Kind marker) { | 1446 void DebuggerStackTrace::AddMarker(ActivationFrame::Kind marker) { |
1535 ASSERT(marker == ActivationFrame::kAsyncSuspensionMarker); | 1447 ASSERT(marker == ActivationFrame::kAsyncSuspensionMarker); |
1536 trace_.Add(new ActivationFrame(marker)); | 1448 trace_.Add(new ActivationFrame(marker)); |
1537 } | 1449 } |
1538 | 1450 |
1539 | |
1540 void DebuggerStackTrace::AddAsyncCausalFrame(uword pc, const Code& code) { | 1451 void DebuggerStackTrace::AddAsyncCausalFrame(uword pc, const Code& code) { |
1541 trace_.Add(new ActivationFrame(pc, 0, 0, code, Array::Handle(), 0, | 1452 trace_.Add(new ActivationFrame(pc, 0, 0, code, Array::Handle(), 0, |
1542 ActivationFrame::kAsyncCausal)); | 1453 ActivationFrame::kAsyncCausal)); |
1543 } | 1454 } |
1544 | 1455 |
1545 | |
1546 const uint8_t kSafepointKind = RawPcDescriptors::kIcCall | | 1456 const uint8_t kSafepointKind = RawPcDescriptors::kIcCall | |
1547 RawPcDescriptors::kUnoptStaticCall | | 1457 RawPcDescriptors::kUnoptStaticCall | |
1548 RawPcDescriptors::kRuntimeCall; | 1458 RawPcDescriptors::kRuntimeCall; |
1549 | 1459 |
1550 | |
1551 CodeBreakpoint::CodeBreakpoint(const Code& code, | 1460 CodeBreakpoint::CodeBreakpoint(const Code& code, |
1552 TokenPosition token_pos, | 1461 TokenPosition token_pos, |
1553 uword pc, | 1462 uword pc, |
1554 RawPcDescriptors::Kind kind) | 1463 RawPcDescriptors::Kind kind) |
1555 : code_(code.raw()), | 1464 : code_(code.raw()), |
1556 token_pos_(token_pos), | 1465 token_pos_(token_pos), |
1557 pc_(pc), | 1466 pc_(pc), |
1558 line_number_(-1), | 1467 line_number_(-1), |
1559 is_enabled_(false), | 1468 is_enabled_(false), |
1560 bpt_location_(NULL), | 1469 bpt_location_(NULL), |
1561 next_(NULL), | 1470 next_(NULL), |
1562 breakpoint_kind_(kind), | 1471 breakpoint_kind_(kind), |
1563 #if !defined(TARGET_ARCH_DBC) | 1472 #if !defined(TARGET_ARCH_DBC) |
1564 saved_value_(Code::null()) | 1473 saved_value_(Code::null()) |
1565 #else | 1474 #else |
1566 saved_value_(Bytecode::kTrap), | 1475 saved_value_(Bytecode::kTrap), |
1567 saved_value_fastsmi_(Bytecode::kTrap) | 1476 saved_value_fastsmi_(Bytecode::kTrap) |
1568 #endif | 1477 #endif |
1569 { | 1478 { |
1570 ASSERT(!code.IsNull()); | 1479 ASSERT(!code.IsNull()); |
1571 ASSERT(token_pos_.IsReal()); | 1480 ASSERT(token_pos_.IsReal()); |
1572 ASSERT(pc_ != 0); | 1481 ASSERT(pc_ != 0); |
1573 ASSERT((breakpoint_kind_ & kSafepointKind) != 0); | 1482 ASSERT((breakpoint_kind_ & kSafepointKind) != 0); |
1574 } | 1483 } |
1575 | 1484 |
1576 | |
1577 CodeBreakpoint::~CodeBreakpoint() { | 1485 CodeBreakpoint::~CodeBreakpoint() { |
1578 // Make sure we don't leave patched code behind. | 1486 // Make sure we don't leave patched code behind. |
1579 ASSERT(!IsEnabled()); | 1487 ASSERT(!IsEnabled()); |
1580 // Poison the data so we catch use after free errors. | 1488 // Poison the data so we catch use after free errors. |
1581 #ifdef DEBUG | 1489 #ifdef DEBUG |
1582 code_ = Code::null(); | 1490 code_ = Code::null(); |
1583 pc_ = 0ul; | 1491 pc_ = 0ul; |
1584 bpt_location_ = NULL; | 1492 bpt_location_ = NULL; |
1585 next_ = NULL; | 1493 next_ = NULL; |
1586 breakpoint_kind_ = RawPcDescriptors::kOther; | 1494 breakpoint_kind_ = RawPcDescriptors::kOther; |
1587 #endif | 1495 #endif |
1588 } | 1496 } |
1589 | 1497 |
1590 | |
1591 RawFunction* CodeBreakpoint::function() const { | 1498 RawFunction* CodeBreakpoint::function() const { |
1592 return Code::Handle(code_).function(); | 1499 return Code::Handle(code_).function(); |
1593 } | 1500 } |
1594 | 1501 |
1595 | |
1596 RawScript* CodeBreakpoint::SourceCode() { | 1502 RawScript* CodeBreakpoint::SourceCode() { |
1597 const Function& func = Function::Handle(this->function()); | 1503 const Function& func = Function::Handle(this->function()); |
1598 return func.script(); | 1504 return func.script(); |
1599 } | 1505 } |
1600 | 1506 |
1601 | |
1602 RawString* CodeBreakpoint::SourceUrl() { | 1507 RawString* CodeBreakpoint::SourceUrl() { |
1603 const Script& script = Script::Handle(SourceCode()); | 1508 const Script& script = Script::Handle(SourceCode()); |
1604 return script.url(); | 1509 return script.url(); |
1605 } | 1510 } |
1606 | 1511 |
1607 | |
1608 intptr_t CodeBreakpoint::LineNumber() { | 1512 intptr_t CodeBreakpoint::LineNumber() { |
1609 // Compute line number lazily since it causes scanning of the script. | 1513 // Compute line number lazily since it causes scanning of the script. |
1610 if (line_number_ < 0) { | 1514 if (line_number_ < 0) { |
1611 const Script& script = Script::Handle(SourceCode()); | 1515 const Script& script = Script::Handle(SourceCode()); |
1612 script.GetTokenLocation(token_pos_, &line_number_, NULL); | 1516 script.GetTokenLocation(token_pos_, &line_number_, NULL); |
1613 } | 1517 } |
1614 return line_number_; | 1518 return line_number_; |
1615 } | 1519 } |
1616 | 1520 |
1617 | |
1618 void CodeBreakpoint::Enable() { | 1521 void CodeBreakpoint::Enable() { |
1619 if (!is_enabled_) { | 1522 if (!is_enabled_) { |
1620 PatchCode(); | 1523 PatchCode(); |
1621 } | 1524 } |
1622 ASSERT(is_enabled_); | 1525 ASSERT(is_enabled_); |
1623 } | 1526 } |
1624 | 1527 |
1625 | |
1626 void CodeBreakpoint::Disable() { | 1528 void CodeBreakpoint::Disable() { |
1627 if (is_enabled_) { | 1529 if (is_enabled_) { |
1628 RestoreCode(); | 1530 RestoreCode(); |
1629 } | 1531 } |
1630 ASSERT(!is_enabled_); | 1532 ASSERT(!is_enabled_); |
1631 } | 1533 } |
1632 | 1534 |
1633 | |
1634 RemoteObjectCache::RemoteObjectCache(intptr_t initial_size) { | 1535 RemoteObjectCache::RemoteObjectCache(intptr_t initial_size) { |
1635 objs_ = | 1536 objs_ = |
1636 &GrowableObjectArray::ZoneHandle(GrowableObjectArray::New(initial_size)); | 1537 &GrowableObjectArray::ZoneHandle(GrowableObjectArray::New(initial_size)); |
1637 } | 1538 } |
1638 | 1539 |
1639 | |
1640 intptr_t RemoteObjectCache::AddObject(const Object& obj) { | 1540 intptr_t RemoteObjectCache::AddObject(const Object& obj) { |
1641 intptr_t len = objs_->Length(); | 1541 intptr_t len = objs_->Length(); |
1642 for (intptr_t i = 0; i < len; i++) { | 1542 for (intptr_t i = 0; i < len; i++) { |
1643 if (objs_->At(i) == obj.raw()) { | 1543 if (objs_->At(i) == obj.raw()) { |
1644 return i; | 1544 return i; |
1645 } | 1545 } |
1646 } | 1546 } |
1647 objs_->Add(obj); | 1547 objs_->Add(obj); |
1648 return len; | 1548 return len; |
1649 } | 1549 } |
1650 | 1550 |
1651 | |
1652 RawObject* RemoteObjectCache::GetObj(intptr_t obj_id) const { | 1551 RawObject* RemoteObjectCache::GetObj(intptr_t obj_id) const { |
1653 ASSERT(IsValidId(obj_id)); | 1552 ASSERT(IsValidId(obj_id)); |
1654 return objs_->At(obj_id); | 1553 return objs_->At(obj_id); |
1655 } | 1554 } |
1656 | 1555 |
1657 | |
1658 Debugger::Debugger() | 1556 Debugger::Debugger() |
1659 : isolate_(NULL), | 1557 : isolate_(NULL), |
1660 isolate_id_(ILLEGAL_ISOLATE_ID), | 1558 isolate_id_(ILLEGAL_ISOLATE_ID), |
1661 initialized_(false), | 1559 initialized_(false), |
1662 next_id_(1), | 1560 next_id_(1), |
1663 latent_locations_(NULL), | 1561 latent_locations_(NULL), |
1664 breakpoint_locations_(NULL), | 1562 breakpoint_locations_(NULL), |
1665 code_breakpoints_(NULL), | 1563 code_breakpoints_(NULL), |
1666 resume_action_(kContinue), | 1564 resume_action_(kContinue), |
1667 resume_frame_index_(-1), | 1565 resume_frame_index_(-1), |
1668 post_deopt_frame_index_(-1), | 1566 post_deopt_frame_index_(-1), |
1669 ignore_breakpoints_(false), | 1567 ignore_breakpoints_(false), |
1670 pause_event_(NULL), | 1568 pause_event_(NULL), |
1671 obj_cache_(NULL), | 1569 obj_cache_(NULL), |
1672 stack_trace_(NULL), | 1570 stack_trace_(NULL), |
1673 async_causal_stack_trace_(NULL), | 1571 async_causal_stack_trace_(NULL), |
1674 awaiter_stack_trace_(NULL), | 1572 awaiter_stack_trace_(NULL), |
1675 stepping_fp_(0), | 1573 stepping_fp_(0), |
1676 async_stepping_fp_(0), | 1574 async_stepping_fp_(0), |
1677 top_frame_awaiter_(Object::null()), | 1575 top_frame_awaiter_(Object::null()), |
1678 skip_next_step_(false), | 1576 skip_next_step_(false), |
1679 needs_breakpoint_cleanup_(false), | 1577 needs_breakpoint_cleanup_(false), |
1680 synthetic_async_breakpoint_(NULL), | 1578 synthetic_async_breakpoint_(NULL), |
1681 exc_pause_info_(kNoPauseOnExceptions) {} | 1579 exc_pause_info_(kNoPauseOnExceptions) {} |
1682 | 1580 |
1683 | |
1684 Debugger::~Debugger() { | 1581 Debugger::~Debugger() { |
1685 isolate_id_ = ILLEGAL_ISOLATE_ID; | 1582 isolate_id_ = ILLEGAL_ISOLATE_ID; |
1686 ASSERT(!IsPaused()); | 1583 ASSERT(!IsPaused()); |
1687 ASSERT(latent_locations_ == NULL); | 1584 ASSERT(latent_locations_ == NULL); |
1688 ASSERT(breakpoint_locations_ == NULL); | 1585 ASSERT(breakpoint_locations_ == NULL); |
1689 ASSERT(code_breakpoints_ == NULL); | 1586 ASSERT(code_breakpoints_ == NULL); |
1690 ASSERT(stack_trace_ == NULL); | 1587 ASSERT(stack_trace_ == NULL); |
1691 ASSERT(async_causal_stack_trace_ == NULL); | 1588 ASSERT(async_causal_stack_trace_ == NULL); |
1692 ASSERT(obj_cache_ == NULL); | 1589 ASSERT(obj_cache_ == NULL); |
1693 ASSERT(synthetic_async_breakpoint_ == NULL); | 1590 ASSERT(synthetic_async_breakpoint_ == NULL); |
1694 } | 1591 } |
1695 | 1592 |
1696 | |
1697 void Debugger::Shutdown() { | 1593 void Debugger::Shutdown() { |
1698 // TODO(johnmccutchan): Do not create a debugger for isolates that don't need | 1594 // TODO(johnmccutchan): Do not create a debugger for isolates that don't need |
1699 // them. Then, assert here that isolate_ is not one of those isolates. | 1595 // them. Then, assert here that isolate_ is not one of those isolates. |
1700 if ((isolate_ == Dart::vm_isolate()) || | 1596 if ((isolate_ == Dart::vm_isolate()) || |
1701 ServiceIsolate::IsServiceIsolateDescendant(isolate_)) { | 1597 ServiceIsolate::IsServiceIsolateDescendant(isolate_)) { |
1702 return; | 1598 return; |
1703 } | 1599 } |
1704 while (breakpoint_locations_ != NULL) { | 1600 while (breakpoint_locations_ != NULL) { |
1705 BreakpointLocation* bpt = breakpoint_locations_; | 1601 BreakpointLocation* bpt = breakpoint_locations_; |
1706 breakpoint_locations_ = breakpoint_locations_->next(); | 1602 breakpoint_locations_ = breakpoint_locations_->next(); |
1707 delete bpt; | 1603 delete bpt; |
1708 } | 1604 } |
1709 while (latent_locations_ != NULL) { | 1605 while (latent_locations_ != NULL) { |
1710 BreakpointLocation* bpt = latent_locations_; | 1606 BreakpointLocation* bpt = latent_locations_; |
1711 latent_locations_ = latent_locations_->next(); | 1607 latent_locations_ = latent_locations_->next(); |
1712 delete bpt; | 1608 delete bpt; |
1713 } | 1609 } |
1714 while (code_breakpoints_ != NULL) { | 1610 while (code_breakpoints_ != NULL) { |
1715 CodeBreakpoint* bpt = code_breakpoints_; | 1611 CodeBreakpoint* bpt = code_breakpoints_; |
1716 code_breakpoints_ = code_breakpoints_->next(); | 1612 code_breakpoints_ = code_breakpoints_->next(); |
1717 bpt->Disable(); | 1613 bpt->Disable(); |
1718 delete bpt; | 1614 delete bpt; |
1719 } | 1615 } |
1720 if (NeedsIsolateEvents()) { | 1616 if (NeedsIsolateEvents()) { |
1721 ServiceEvent event(isolate_, ServiceEvent::kIsolateExit); | 1617 ServiceEvent event(isolate_, ServiceEvent::kIsolateExit); |
1722 InvokeEventHandler(&event); | 1618 InvokeEventHandler(&event); |
1723 } | 1619 } |
1724 } | 1620 } |
1725 | 1621 |
1726 | |
1727 void Debugger::OnIsolateRunnable() {} | 1622 void Debugger::OnIsolateRunnable() {} |
1728 | 1623 |
1729 | |
1730 static RawFunction* ResolveLibraryFunction(const Library& library, | 1624 static RawFunction* ResolveLibraryFunction(const Library& library, |
1731 const String& fname) { | 1625 const String& fname) { |
1732 ASSERT(!library.IsNull()); | 1626 ASSERT(!library.IsNull()); |
1733 const Object& object = Object::Handle(library.ResolveName(fname)); | 1627 const Object& object = Object::Handle(library.ResolveName(fname)); |
1734 if (!object.IsNull() && object.IsFunction()) { | 1628 if (!object.IsNull() && object.IsFunction()) { |
1735 return Function::Cast(object).raw(); | 1629 return Function::Cast(object).raw(); |
1736 } | 1630 } |
1737 return Function::null(); | 1631 return Function::null(); |
1738 } | 1632 } |
1739 | 1633 |
1740 | |
1741 bool Debugger::SetupStepOverAsyncSuspension(const char** error) { | 1634 bool Debugger::SetupStepOverAsyncSuspension(const char** error) { |
1742 ActivationFrame* top_frame = TopDartFrame(); | 1635 ActivationFrame* top_frame = TopDartFrame(); |
1743 if (!IsAtAsyncJump(top_frame)) { | 1636 if (!IsAtAsyncJump(top_frame)) { |
1744 // Not at an async operation. | 1637 // Not at an async operation. |
1745 if (error) { | 1638 if (error) { |
1746 *error = "Isolate must be paused at an async suspension point"; | 1639 *error = "Isolate must be paused at an async suspension point"; |
1747 } | 1640 } |
1748 return false; | 1641 return false; |
1749 } | 1642 } |
1750 Object& closure = Object::Handle(top_frame->GetAsyncOperation()); | 1643 Object& closure = Object::Handle(top_frame->GetAsyncOperation()); |
1751 ASSERT(!closure.IsNull()); | 1644 ASSERT(!closure.IsNull()); |
1752 ASSERT(closure.IsInstance()); | 1645 ASSERT(closure.IsInstance()); |
1753 ASSERT(Instance::Cast(closure).IsClosure()); | 1646 ASSERT(Instance::Cast(closure).IsClosure()); |
1754 Breakpoint* bpt = SetBreakpointAtActivation(Instance::Cast(closure), true); | 1647 Breakpoint* bpt = SetBreakpointAtActivation(Instance::Cast(closure), true); |
1755 if (bpt == NULL) { | 1648 if (bpt == NULL) { |
1756 // Unable to set the breakpoint. | 1649 // Unable to set the breakpoint. |
1757 if (error) { | 1650 if (error) { |
1758 *error = "Unable to set breakpoint at async suspension point"; | 1651 *error = "Unable to set breakpoint at async suspension point"; |
1759 } | 1652 } |
1760 return false; | 1653 return false; |
1761 } | 1654 } |
1762 return true; | 1655 return true; |
1763 } | 1656 } |
1764 | 1657 |
1765 | |
1766 bool Debugger::SetResumeAction(ResumeAction action, | 1658 bool Debugger::SetResumeAction(ResumeAction action, |
1767 intptr_t frame_index, | 1659 intptr_t frame_index, |
1768 const char** error) { | 1660 const char** error) { |
1769 if (error) { | 1661 if (error) { |
1770 *error = NULL; | 1662 *error = NULL; |
1771 } | 1663 } |
1772 resume_frame_index_ = -1; | 1664 resume_frame_index_ = -1; |
1773 switch (action) { | 1665 switch (action) { |
1774 case kStepInto: | 1666 case kStepInto: |
1775 case kStepOver: | 1667 case kStepOver: |
1776 case kStepOut: | 1668 case kStepOut: |
1777 case kContinue: | 1669 case kContinue: |
1778 resume_action_ = action; | 1670 resume_action_ = action; |
1779 return true; | 1671 return true; |
1780 case kStepRewind: | 1672 case kStepRewind: |
1781 if (!CanRewindFrame(frame_index, error)) { | 1673 if (!CanRewindFrame(frame_index, error)) { |
1782 return false; | 1674 return false; |
1783 } | 1675 } |
1784 resume_action_ = kStepRewind; | 1676 resume_action_ = kStepRewind; |
1785 resume_frame_index_ = frame_index; | 1677 resume_frame_index_ = frame_index; |
1786 return true; | 1678 return true; |
1787 case kStepOverAsyncSuspension: | 1679 case kStepOverAsyncSuspension: |
1788 return SetupStepOverAsyncSuspension(error); | 1680 return SetupStepOverAsyncSuspension(error); |
1789 default: | 1681 default: |
1790 UNREACHABLE(); | 1682 UNREACHABLE(); |
1791 return false; | 1683 return false; |
1792 } | 1684 } |
1793 } | 1685 } |
1794 | 1686 |
1795 | |
1796 RawFunction* Debugger::ResolveFunction(const Library& library, | 1687 RawFunction* Debugger::ResolveFunction(const Library& library, |
1797 const String& class_name, | 1688 const String& class_name, |
1798 const String& function_name) { | 1689 const String& function_name) { |
1799 ASSERT(!library.IsNull()); | 1690 ASSERT(!library.IsNull()); |
1800 ASSERT(!class_name.IsNull()); | 1691 ASSERT(!class_name.IsNull()); |
1801 ASSERT(!function_name.IsNull()); | 1692 ASSERT(!function_name.IsNull()); |
1802 if (class_name.Length() == 0) { | 1693 if (class_name.Length() == 0) { |
1803 return ResolveLibraryFunction(library, function_name); | 1694 return ResolveLibraryFunction(library, function_name); |
1804 } | 1695 } |
1805 const Class& cls = Class::Handle(library.LookupClass(class_name)); | 1696 const Class& cls = Class::Handle(library.LookupClass(class_name)); |
1806 Function& function = Function::Handle(); | 1697 Function& function = Function::Handle(); |
1807 if (!cls.IsNull()) { | 1698 if (!cls.IsNull()) { |
1808 function = cls.LookupStaticFunction(function_name); | 1699 function = cls.LookupStaticFunction(function_name); |
1809 if (function.IsNull()) { | 1700 if (function.IsNull()) { |
1810 function = cls.LookupDynamicFunction(function_name); | 1701 function = cls.LookupDynamicFunction(function_name); |
1811 } | 1702 } |
1812 } | 1703 } |
1813 return function.raw(); | 1704 return function.raw(); |
1814 } | 1705 } |
1815 | 1706 |
1816 | |
1817 // Deoptimize all functions in the isolate. | 1707 // Deoptimize all functions in the isolate. |
1818 // TODO(hausner): Actually we only need to deoptimize those functions | 1708 // TODO(hausner): Actually we only need to deoptimize those functions |
1819 // that inline the function that contains the newly created breakpoint. | 1709 // that inline the function that contains the newly created breakpoint. |
1820 // We currently don't have this info so we deoptimize all functions. | 1710 // We currently don't have this info so we deoptimize all functions. |
1821 void Debugger::DeoptimizeWorld() { | 1711 void Debugger::DeoptimizeWorld() { |
1822 BackgroundCompiler::Stop(isolate_); | 1712 BackgroundCompiler::Stop(isolate_); |
1823 DeoptimizeFunctionsOnStack(); | 1713 DeoptimizeFunctionsOnStack(); |
1824 // Iterate over all classes, deoptimize functions. | 1714 // Iterate over all classes, deoptimize functions. |
1825 // TODO(hausner): Could possibly be combined with RemoveOptimizedCode() | 1715 // TODO(hausner): Could possibly be combined with RemoveOptimizedCode() |
1826 const ClassTable& class_table = *isolate_->class_table(); | 1716 const ClassTable& class_table = *isolate_->class_table(); |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1860 const intptr_t num_closures = closures.Length(); | 1750 const intptr_t num_closures = closures.Length(); |
1861 for (intptr_t pos = 0; pos < num_closures; pos++) { | 1751 for (intptr_t pos = 0; pos < num_closures; pos++) { |
1862 function ^= closures.At(pos); | 1752 function ^= closures.At(pos); |
1863 ASSERT(!function.IsNull()); | 1753 ASSERT(!function.IsNull()); |
1864 if (function.HasOptimizedCode()) { | 1754 if (function.HasOptimizedCode()) { |
1865 function.SwitchToUnoptimizedCode(); | 1755 function.SwitchToUnoptimizedCode(); |
1866 } | 1756 } |
1867 } | 1757 } |
1868 } | 1758 } |
1869 | 1759 |
1870 | |
1871 ActivationFrame* Debugger::CollectDartFrame(Isolate* isolate, | 1760 ActivationFrame* Debugger::CollectDartFrame(Isolate* isolate, |
1872 uword pc, | 1761 uword pc, |
1873 StackFrame* frame, | 1762 StackFrame* frame, |
1874 const Code& code, | 1763 const Code& code, |
1875 const Array& deopt_frame, | 1764 const Array& deopt_frame, |
1876 intptr_t deopt_frame_offset, | 1765 intptr_t deopt_frame_offset, |
1877 ActivationFrame::Kind kind) { | 1766 ActivationFrame::Kind kind) { |
1878 ASSERT(code.ContainsInstructionAt(pc)); | 1767 ASSERT(code.ContainsInstructionAt(pc)); |
1879 ActivationFrame* activation = | 1768 ActivationFrame* activation = |
1880 new ActivationFrame(pc, frame->fp(), frame->sp(), code, deopt_frame, | 1769 new ActivationFrame(pc, frame->fp(), frame->sp(), code, deopt_frame, |
1881 deopt_frame_offset, kind); | 1770 deopt_frame_offset, kind); |
1882 if (FLAG_trace_debugger_stacktrace) { | 1771 if (FLAG_trace_debugger_stacktrace) { |
1883 const Context& ctx = activation->GetSavedCurrentContext(); | 1772 const Context& ctx = activation->GetSavedCurrentContext(); |
1884 OS::PrintErr("\tUsing saved context: %s\n", ctx.ToCString()); | 1773 OS::PrintErr("\tUsing saved context: %s\n", ctx.ToCString()); |
1885 } | 1774 } |
1886 if (FLAG_trace_debugger_stacktrace) { | 1775 if (FLAG_trace_debugger_stacktrace) { |
1887 OS::PrintErr("\tLine number: %" Pd "\n", activation->LineNumber()); | 1776 OS::PrintErr("\tLine number: %" Pd "\n", activation->LineNumber()); |
1888 } | 1777 } |
1889 return activation; | 1778 return activation; |
1890 } | 1779 } |
1891 | 1780 |
1892 | |
1893 RawArray* Debugger::DeoptimizeToArray(Thread* thread, | 1781 RawArray* Debugger::DeoptimizeToArray(Thread* thread, |
1894 StackFrame* frame, | 1782 StackFrame* frame, |
1895 const Code& code) { | 1783 const Code& code) { |
1896 ASSERT(code.is_optimized()); | 1784 ASSERT(code.is_optimized()); |
1897 Isolate* isolate = thread->isolate(); | 1785 Isolate* isolate = thread->isolate(); |
1898 // Create the DeoptContext for this deoptimization. | 1786 // Create the DeoptContext for this deoptimization. |
1899 DeoptContext* deopt_context = | 1787 DeoptContext* deopt_context = |
1900 new DeoptContext(frame, code, DeoptContext::kDestIsAllocated, NULL, NULL, | 1788 new DeoptContext(frame, code, DeoptContext::kDestIsAllocated, NULL, NULL, |
1901 true, false /* deoptimizing_code */); | 1789 true, false /* deoptimizing_code */); |
1902 isolate->set_deopt_context(deopt_context); | 1790 isolate->set_deopt_context(deopt_context); |
1903 | 1791 |
1904 deopt_context->FillDestFrame(); | 1792 deopt_context->FillDestFrame(); |
1905 deopt_context->MaterializeDeferredObjects(); | 1793 deopt_context->MaterializeDeferredObjects(); |
1906 const Array& dest_frame = | 1794 const Array& dest_frame = |
1907 Array::Handle(thread->zone(), deopt_context->DestFrameAsArray()); | 1795 Array::Handle(thread->zone(), deopt_context->DestFrameAsArray()); |
1908 | 1796 |
1909 isolate->set_deopt_context(NULL); | 1797 isolate->set_deopt_context(NULL); |
1910 delete deopt_context; | 1798 delete deopt_context; |
1911 | 1799 |
1912 return dest_frame.raw(); | 1800 return dest_frame.raw(); |
1913 } | 1801 } |
1914 | 1802 |
1915 | |
1916 DebuggerStackTrace* Debugger::CollectStackTrace() { | 1803 DebuggerStackTrace* Debugger::CollectStackTrace() { |
1917 Thread* thread = Thread::Current(); | 1804 Thread* thread = Thread::Current(); |
1918 Zone* zone = thread->zone(); | 1805 Zone* zone = thread->zone(); |
1919 Isolate* isolate = thread->isolate(); | 1806 Isolate* isolate = thread->isolate(); |
1920 DebuggerStackTrace* stack_trace = new DebuggerStackTrace(8); | 1807 DebuggerStackTrace* stack_trace = new DebuggerStackTrace(8); |
1921 StackFrameIterator iterator(StackFrameIterator::kDontValidateFrames, | 1808 StackFrameIterator iterator(StackFrameIterator::kDontValidateFrames, |
1922 Thread::Current(), | 1809 Thread::Current(), |
1923 StackFrameIterator::kNoCrossThreadIteration); | 1810 StackFrameIterator::kNoCrossThreadIteration); |
1924 Code& code = Code::Handle(zone); | 1811 Code& code = Code::Handle(zone); |
1925 Code& inlined_code = Code::Handle(zone); | 1812 Code& inlined_code = Code::Handle(zone); |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1965 stack_trace->AddActivation(CollectDartFrame(isolate, it.pc(), frame, | 1852 stack_trace->AddActivation(CollectDartFrame(isolate, it.pc(), frame, |
1966 *inlined_code, *deopt_frame, | 1853 *inlined_code, *deopt_frame, |
1967 deopt_frame_offset)); | 1854 deopt_frame_offset)); |
1968 } | 1855 } |
1969 } else { | 1856 } else { |
1970 stack_trace->AddActivation(CollectDartFrame( | 1857 stack_trace->AddActivation(CollectDartFrame( |
1971 isolate, frame->pc(), frame, *code, Object::null_array(), 0)); | 1858 isolate, frame->pc(), frame, *code, Object::null_array(), 0)); |
1972 } | 1859 } |
1973 } | 1860 } |
1974 | 1861 |
1975 | |
1976 DebuggerStackTrace* Debugger::CollectAsyncCausalStackTrace() { | 1862 DebuggerStackTrace* Debugger::CollectAsyncCausalStackTrace() { |
1977 if (!FLAG_causal_async_stacks) { | 1863 if (!FLAG_causal_async_stacks) { |
1978 return NULL; | 1864 return NULL; |
1979 } | 1865 } |
1980 Thread* thread = Thread::Current(); | 1866 Thread* thread = Thread::Current(); |
1981 Zone* zone = thread->zone(); | 1867 Zone* zone = thread->zone(); |
1982 Isolate* isolate = thread->isolate(); | 1868 Isolate* isolate = thread->isolate(); |
1983 DebuggerStackTrace* stack_trace = new DebuggerStackTrace(8); | 1869 DebuggerStackTrace* stack_trace = new DebuggerStackTrace(8); |
1984 | 1870 |
1985 Code& code = Code::Handle(zone); | 1871 Code& code = Code::Handle(zone); |
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2051 } | 1937 } |
2052 } | 1938 } |
2053 } | 1939 } |
2054 // Follow the link. | 1940 // Follow the link. |
2055 async_stack_trace = async_stack_trace.async_link(); | 1941 async_stack_trace = async_stack_trace.async_link(); |
2056 } | 1942 } |
2057 | 1943 |
2058 return stack_trace; | 1944 return stack_trace; |
2059 } | 1945 } |
2060 | 1946 |
2061 | |
2062 DebuggerStackTrace* Debugger::CollectAwaiterReturnStackTrace() { | 1947 DebuggerStackTrace* Debugger::CollectAwaiterReturnStackTrace() { |
2063 if (!FLAG_async_debugger) { | 1948 if (!FLAG_async_debugger) { |
2064 return NULL; | 1949 return NULL; |
2065 } | 1950 } |
2066 // Causal async stacks are not supported in the AOT runtime. | 1951 // Causal async stacks are not supported in the AOT runtime. |
2067 ASSERT(!FLAG_precompiled_runtime); | 1952 ASSERT(!FLAG_precompiled_runtime); |
2068 | 1953 |
2069 Thread* thread = Thread::Current(); | 1954 Thread* thread = Thread::Current(); |
2070 Zone* zone = thread->zone(); | 1955 Zone* zone = thread->zone(); |
2071 Isolate* isolate = thread->isolate(); | 1956 Isolate* isolate = thread->isolate(); |
(...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2198 } | 2083 } |
2199 } | 2084 } |
2200 } | 2085 } |
2201 // Follow the link. | 2086 // Follow the link. |
2202 async_stack_trace = async_stack_trace.async_link(); | 2087 async_stack_trace = async_stack_trace.async_link(); |
2203 } | 2088 } |
2204 | 2089 |
2205 return stack_trace; | 2090 return stack_trace; |
2206 } | 2091 } |
2207 | 2092 |
2208 | |
2209 ActivationFrame* Debugger::TopDartFrame() const { | 2093 ActivationFrame* Debugger::TopDartFrame() const { |
2210 StackFrameIterator iterator(StackFrameIterator::kDontValidateFrames, | 2094 StackFrameIterator iterator(StackFrameIterator::kDontValidateFrames, |
2211 Thread::Current(), | 2095 Thread::Current(), |
2212 StackFrameIterator::kNoCrossThreadIteration); | 2096 StackFrameIterator::kNoCrossThreadIteration); |
2213 StackFrame* frame = iterator.NextFrame(); | 2097 StackFrame* frame = iterator.NextFrame(); |
2214 while ((frame != NULL) && !frame->IsDartFrame()) { | 2098 while ((frame != NULL) && !frame->IsDartFrame()) { |
2215 frame = iterator.NextFrame(); | 2099 frame = iterator.NextFrame(); |
2216 } | 2100 } |
2217 Code& code = Code::Handle(frame->LookupDartCode()); | 2101 Code& code = Code::Handle(frame->LookupDartCode()); |
2218 ActivationFrame* activation = new ActivationFrame( | 2102 ActivationFrame* activation = new ActivationFrame( |
2219 frame->pc(), frame->fp(), frame->sp(), code, Object::null_array(), 0); | 2103 frame->pc(), frame->fp(), frame->sp(), code, Object::null_array(), 0); |
2220 return activation; | 2104 return activation; |
2221 } | 2105 } |
2222 | 2106 |
2223 | |
2224 DebuggerStackTrace* Debugger::StackTrace() { | 2107 DebuggerStackTrace* Debugger::StackTrace() { |
2225 return (stack_trace_ != NULL) ? stack_trace_ : CollectStackTrace(); | 2108 return (stack_trace_ != NULL) ? stack_trace_ : CollectStackTrace(); |
2226 } | 2109 } |
2227 | 2110 |
2228 | |
2229 DebuggerStackTrace* Debugger::CurrentStackTrace() { | 2111 DebuggerStackTrace* Debugger::CurrentStackTrace() { |
2230 return CollectStackTrace(); | 2112 return CollectStackTrace(); |
2231 } | 2113 } |
2232 | 2114 |
2233 | |
2234 DebuggerStackTrace* Debugger::AsyncCausalStackTrace() { | 2115 DebuggerStackTrace* Debugger::AsyncCausalStackTrace() { |
2235 return (async_causal_stack_trace_ != NULL) ? async_causal_stack_trace_ | 2116 return (async_causal_stack_trace_ != NULL) ? async_causal_stack_trace_ |
2236 : CollectAsyncCausalStackTrace(); | 2117 : CollectAsyncCausalStackTrace(); |
2237 } | 2118 } |
2238 | 2119 |
2239 | |
2240 DebuggerStackTrace* Debugger::CurrentAsyncCausalStackTrace() { | 2120 DebuggerStackTrace* Debugger::CurrentAsyncCausalStackTrace() { |
2241 return CollectAsyncCausalStackTrace(); | 2121 return CollectAsyncCausalStackTrace(); |
2242 } | 2122 } |
2243 | 2123 |
2244 | |
2245 DebuggerStackTrace* Debugger::AwaiterStackTrace() { | 2124 DebuggerStackTrace* Debugger::AwaiterStackTrace() { |
2246 return (awaiter_stack_trace_ != NULL) ? awaiter_stack_trace_ | 2125 return (awaiter_stack_trace_ != NULL) ? awaiter_stack_trace_ |
2247 : CollectAwaiterReturnStackTrace(); | 2126 : CollectAwaiterReturnStackTrace(); |
2248 } | 2127 } |
2249 | 2128 |
2250 | |
2251 DebuggerStackTrace* Debugger::CurrentAwaiterStackTrace() { | 2129 DebuggerStackTrace* Debugger::CurrentAwaiterStackTrace() { |
2252 return CollectAwaiterReturnStackTrace(); | 2130 return CollectAwaiterReturnStackTrace(); |
2253 } | 2131 } |
2254 | 2132 |
2255 | |
2256 DebuggerStackTrace* Debugger::StackTraceFrom(const class StackTrace& ex_trace) { | 2133 DebuggerStackTrace* Debugger::StackTraceFrom(const class StackTrace& ex_trace) { |
2257 DebuggerStackTrace* stack_trace = new DebuggerStackTrace(8); | 2134 DebuggerStackTrace* stack_trace = new DebuggerStackTrace(8); |
2258 Function& function = Function::Handle(); | 2135 Function& function = Function::Handle(); |
2259 Code& code = Code::Handle(); | 2136 Code& code = Code::Handle(); |
2260 | 2137 |
2261 const uword fp = 0; | 2138 const uword fp = 0; |
2262 const uword sp = 0; | 2139 const uword sp = 0; |
2263 const Array& deopt_frame = Array::Handle(); | 2140 const Array& deopt_frame = Array::Handle(); |
2264 const intptr_t deopt_frame_offset = -1; | 2141 const intptr_t deopt_frame_offset = -1; |
2265 | 2142 |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2298 ActivationFrame* activation = new ActivationFrame( | 2175 ActivationFrame* activation = new ActivationFrame( |
2299 pc, fp, sp, code, deopt_frame, deopt_frame_offset); | 2176 pc, fp, sp, code, deopt_frame, deopt_frame_offset); |
2300 stack_trace->AddActivation(activation); | 2177 stack_trace->AddActivation(activation); |
2301 } | 2178 } |
2302 } | 2179 } |
2303 } | 2180 } |
2304 } | 2181 } |
2305 return stack_trace; | 2182 return stack_trace; |
2306 } | 2183 } |
2307 | 2184 |
2308 | |
2309 void Debugger::SetExceptionPauseInfo(Dart_ExceptionPauseInfo pause_info) { | 2185 void Debugger::SetExceptionPauseInfo(Dart_ExceptionPauseInfo pause_info) { |
2310 ASSERT((pause_info == kNoPauseOnExceptions) || | 2186 ASSERT((pause_info == kNoPauseOnExceptions) || |
2311 (pause_info == kPauseOnUnhandledExceptions) || | 2187 (pause_info == kPauseOnUnhandledExceptions) || |
2312 (pause_info == kPauseOnAllExceptions)); | 2188 (pause_info == kPauseOnAllExceptions)); |
2313 exc_pause_info_ = pause_info; | 2189 exc_pause_info_ = pause_info; |
2314 } | 2190 } |
2315 | 2191 |
2316 | |
2317 Dart_ExceptionPauseInfo Debugger::GetExceptionPauseInfo() const { | 2192 Dart_ExceptionPauseInfo Debugger::GetExceptionPauseInfo() const { |
2318 return exc_pause_info_; | 2193 return exc_pause_info_; |
2319 } | 2194 } |
2320 | 2195 |
2321 | |
2322 bool Debugger::ShouldPauseOnException(DebuggerStackTrace* stack_trace, | 2196 bool Debugger::ShouldPauseOnException(DebuggerStackTrace* stack_trace, |
2323 const Instance& exception) { | 2197 const Instance& exception) { |
2324 if (exc_pause_info_ == kNoPauseOnExceptions) { | 2198 if (exc_pause_info_ == kNoPauseOnExceptions) { |
2325 return false; | 2199 return false; |
2326 } | 2200 } |
2327 if (exc_pause_info_ == kPauseOnAllExceptions) { | 2201 if (exc_pause_info_ == kPauseOnAllExceptions) { |
2328 return true; | 2202 return true; |
2329 } | 2203 } |
2330 ASSERT(exc_pause_info_ == kPauseOnUnhandledExceptions); | 2204 ASSERT(exc_pause_info_ == kPauseOnUnhandledExceptions); |
2331 ActivationFrame* handler_frame = stack_trace->GetHandlerFrame(exception); | 2205 ActivationFrame* handler_frame = stack_trace->GetHandlerFrame(exception); |
2332 if (handler_frame == NULL) { | 2206 if (handler_frame == NULL) { |
2333 // Did not find an exception handler that catches this exception. | 2207 // Did not find an exception handler that catches this exception. |
2334 // Note that this check is not precise, since we can't check | 2208 // Note that this check is not precise, since we can't check |
2335 // uninstantiated types, i.e. types containing type parameters. | 2209 // uninstantiated types, i.e. types containing type parameters. |
2336 // Thus, we may report an exception as unhandled when in fact | 2210 // Thus, we may report an exception as unhandled when in fact |
2337 // it will be caught once we unwind the stack. | 2211 // it will be caught once we unwind the stack. |
2338 return true; | 2212 return true; |
2339 } | 2213 } |
2340 return false; | 2214 return false; |
2341 } | 2215 } |
2342 | 2216 |
2343 | |
2344 void Debugger::PauseException(const Instance& exc) { | 2217 void Debugger::PauseException(const Instance& exc) { |
2345 if (FLAG_stress_async_stacks) { | 2218 if (FLAG_stress_async_stacks) { |
2346 CollectAwaiterReturnStackTrace(); | 2219 CollectAwaiterReturnStackTrace(); |
2347 } | 2220 } |
2348 // We ignore this exception event when the VM is executing code invoked | 2221 // We ignore this exception event when the VM is executing code invoked |
2349 // by the debugger to evaluate variables values, when we see a nested | 2222 // by the debugger to evaluate variables values, when we see a nested |
2350 // breakpoint or exception event, or if the debugger is not | 2223 // breakpoint or exception event, or if the debugger is not |
2351 // interested in exception events. | 2224 // interested in exception events. |
2352 if (ignore_breakpoints_ || IsPaused() || | 2225 if (ignore_breakpoints_ || IsPaused() || |
2353 (exc_pause_info_ == kNoPauseOnExceptions)) { | 2226 (exc_pause_info_ == kNoPauseOnExceptions)) { |
(...skipping 15 matching lines...) Expand all Loading... |
2369 if (stack_trace->Length() > 0) { | 2242 if (stack_trace->Length() > 0) { |
2370 event.set_top_frame(stack_trace->FrameAt(0)); | 2243 event.set_top_frame(stack_trace->FrameAt(0)); |
2371 } | 2244 } |
2372 CacheStackTraces(stack_trace, CollectAsyncCausalStackTrace(), | 2245 CacheStackTraces(stack_trace, CollectAsyncCausalStackTrace(), |
2373 CollectAwaiterReturnStackTrace()); | 2246 CollectAwaiterReturnStackTrace()); |
2374 Pause(&event); | 2247 Pause(&event); |
2375 HandleSteppingRequest(stack_trace_); // we may get a rewind request | 2248 HandleSteppingRequest(stack_trace_); // we may get a rewind request |
2376 ClearCachedStackTraces(); | 2249 ClearCachedStackTraces(); |
2377 } | 2250 } |
2378 | 2251 |
2379 | |
2380 static TokenPosition LastTokenOnLine(Zone* zone, | 2252 static TokenPosition LastTokenOnLine(Zone* zone, |
2381 const TokenStream& tokens, | 2253 const TokenStream& tokens, |
2382 TokenPosition pos) { | 2254 TokenPosition pos) { |
2383 TokenStream::Iterator iter(zone, tokens, pos, | 2255 TokenStream::Iterator iter(zone, tokens, pos, |
2384 TokenStream::Iterator::kAllTokens); | 2256 TokenStream::Iterator::kAllTokens); |
2385 ASSERT(iter.IsValid()); | 2257 ASSERT(iter.IsValid()); |
2386 TokenPosition last_pos = pos; | 2258 TokenPosition last_pos = pos; |
2387 while ((iter.CurrentTokenKind() != Token::kNEWLINE) && | 2259 while ((iter.CurrentTokenKind() != Token::kNEWLINE) && |
2388 (iter.CurrentTokenKind() != Token::kEOS)) { | 2260 (iter.CurrentTokenKind() != Token::kEOS)) { |
2389 last_pos = iter.CurrentPosition(); | 2261 last_pos = iter.CurrentPosition(); |
2390 iter.Advance(); | 2262 iter.Advance(); |
2391 } | 2263 } |
2392 return last_pos; | 2264 return last_pos; |
2393 } | 2265 } |
2394 | 2266 |
2395 | |
2396 // Returns the best fit token position for a breakpoint. | 2267 // Returns the best fit token position for a breakpoint. |
2397 // | 2268 // |
2398 // Takes a range of tokens [requested_token_pos, last_token_pos] and | 2269 // Takes a range of tokens [requested_token_pos, last_token_pos] and |
2399 // an optional column (requested_column). The range of tokens usually | 2270 // an optional column (requested_column). The range of tokens usually |
2400 // represents one line of the program text, but can represent a larger | 2271 // represents one line of the program text, but can represent a larger |
2401 // range on recursive calls. | 2272 // range on recursive calls. |
2402 // | 2273 // |
2403 // The best fit is found in two passes. | 2274 // The best fit is found in two passes. |
2404 // | 2275 // |
2405 // The first pass finds a candidate token which: | 2276 // The first pass finds a candidate token which: |
(...skipping 162 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2568 // find a safe point in the remaining source code of the function. | 2439 // find a safe point in the remaining source code of the function. |
2569 // Since we have moved to the next line of the function, we no | 2440 // Since we have moved to the next line of the function, we no |
2570 // longer are requesting a specific column number. | 2441 // longer are requesting a specific column number. |
2571 if (last_token_pos < func.end_token_pos()) { | 2442 if (last_token_pos < func.end_token_pos()) { |
2572 return ResolveBreakpointPos(func, last_token_pos, func.end_token_pos(), | 2443 return ResolveBreakpointPos(func, last_token_pos, func.end_token_pos(), |
2573 -1 /* no column */); | 2444 -1 /* no column */); |
2574 } | 2445 } |
2575 return TokenPosition::kNoSource; | 2446 return TokenPosition::kNoSource; |
2576 } | 2447 } |
2577 | 2448 |
2578 | |
2579 void Debugger::MakeCodeBreakpointAt(const Function& func, | 2449 void Debugger::MakeCodeBreakpointAt(const Function& func, |
2580 BreakpointLocation* loc) { | 2450 BreakpointLocation* loc) { |
2581 ASSERT(loc->token_pos_.IsReal()); | 2451 ASSERT(loc->token_pos_.IsReal()); |
2582 ASSERT((loc != NULL) && loc->IsResolved()); | 2452 ASSERT((loc != NULL) && loc->IsResolved()); |
2583 ASSERT(!func.HasOptimizedCode()); | 2453 ASSERT(!func.HasOptimizedCode()); |
2584 Code& code = Code::Handle(func.unoptimized_code()); | 2454 Code& code = Code::Handle(func.unoptimized_code()); |
2585 ASSERT(!code.IsNull()); | 2455 ASSERT(!code.IsNull()); |
2586 PcDescriptors& desc = PcDescriptors::Handle(code.pc_descriptors()); | 2456 PcDescriptors& desc = PcDescriptors::Handle(code.pc_descriptors()); |
2587 uword lowest_pc_offset = kUwordMax; | 2457 uword lowest_pc_offset = kUwordMax; |
2588 RawPcDescriptors::Kind lowest_kind = RawPcDescriptors::kAnyKind; | 2458 RawPcDescriptors::Kind lowest_kind = RawPcDescriptors::kAnyKind; |
(...skipping 18 matching lines...) Expand all Loading... |
2607 code_bpt = | 2477 code_bpt = |
2608 new CodeBreakpoint(code, loc->token_pos_, lowest_pc, lowest_kind); | 2478 new CodeBreakpoint(code, loc->token_pos_, lowest_pc, lowest_kind); |
2609 RegisterCodeBreakpoint(code_bpt); | 2479 RegisterCodeBreakpoint(code_bpt); |
2610 } | 2480 } |
2611 code_bpt->set_bpt_location(loc); | 2481 code_bpt->set_bpt_location(loc); |
2612 if (loc->AnyEnabled()) { | 2482 if (loc->AnyEnabled()) { |
2613 code_bpt->Enable(); | 2483 code_bpt->Enable(); |
2614 } | 2484 } |
2615 } | 2485 } |
2616 | 2486 |
2617 | |
2618 void Debugger::FindCompiledFunctions(const Script& script, | 2487 void Debugger::FindCompiledFunctions(const Script& script, |
2619 TokenPosition start_pos, | 2488 TokenPosition start_pos, |
2620 TokenPosition end_pos, | 2489 TokenPosition end_pos, |
2621 GrowableObjectArray* function_list) { | 2490 GrowableObjectArray* function_list) { |
2622 Zone* zone = Thread::Current()->zone(); | 2491 Zone* zone = Thread::Current()->zone(); |
2623 Class& cls = Class::Handle(zone); | 2492 Class& cls = Class::Handle(zone); |
2624 Array& functions = Array::Handle(zone); | 2493 Array& functions = Array::Handle(zone); |
2625 GrowableObjectArray& closures = GrowableObjectArray::Handle(zone); | 2494 GrowableObjectArray& closures = GrowableObjectArray::Handle(zone); |
2626 Function& function = Function::Handle(zone); | 2495 Function& function = Function::Handle(zone); |
2627 | 2496 |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2680 function_list->Add(function); | 2549 function_list->Add(function); |
2681 } | 2550 } |
2682 } | 2551 } |
2683 } | 2552 } |
2684 } | 2553 } |
2685 } | 2554 } |
2686 } | 2555 } |
2687 } | 2556 } |
2688 } | 2557 } |
2689 | 2558 |
2690 | |
2691 static void SelectBestFit(Function* best_fit, Function* func) { | 2559 static void SelectBestFit(Function* best_fit, Function* func) { |
2692 if (best_fit->IsNull()) { | 2560 if (best_fit->IsNull()) { |
2693 *best_fit = func->raw(); | 2561 *best_fit = func->raw(); |
2694 } else { | 2562 } else { |
2695 if ((func->token_pos() > best_fit->token_pos()) && | 2563 if ((func->token_pos() > best_fit->token_pos()) && |
2696 ((func->end_token_pos() <= best_fit->end_token_pos()))) { | 2564 ((func->end_token_pos() <= best_fit->end_token_pos()))) { |
2697 *best_fit = func->raw(); | 2565 *best_fit = func->raw(); |
2698 } | 2566 } |
2699 } | 2567 } |
2700 } | 2568 } |
2701 | 2569 |
2702 | |
2703 // Returns true if a best fit is found. A best fit can either be a function | 2570 // Returns true if a best fit is found. A best fit can either be a function |
2704 // or a field. If it is a function, then the best fit function is returned | 2571 // or a field. If it is a function, then the best fit function is returned |
2705 // in |best_fit|. If a best fit is a field, it means that a latent | 2572 // in |best_fit|. If a best fit is a field, it means that a latent |
2706 // breakpoint can be set in the range |token_pos| to |last_token_pos|. | 2573 // breakpoint can be set in the range |token_pos| to |last_token_pos|. |
2707 bool Debugger::FindBestFit(const Script& script, | 2574 bool Debugger::FindBestFit(const Script& script, |
2708 TokenPosition token_pos, | 2575 TokenPosition token_pos, |
2709 TokenPosition last_token_pos, | 2576 TokenPosition last_token_pos, |
2710 Function* best_fit) { | 2577 Function* best_fit) { |
2711 Zone* zone = Thread::Current()->zone(); | 2578 Zone* zone = Thread::Current()->zone(); |
2712 Class& cls = Class::Handle(zone); | 2579 Class& cls = Class::Handle(zone); |
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2800 (token_pos <= start && start <= last_token_pos)) { | 2667 (token_pos <= start && start <= last_token_pos)) { |
2801 return true; | 2668 return true; |
2802 } | 2669 } |
2803 } | 2670 } |
2804 } | 2671 } |
2805 } | 2672 } |
2806 } | 2673 } |
2807 return false; | 2674 return false; |
2808 } | 2675 } |
2809 | 2676 |
2810 | |
2811 BreakpointLocation* Debugger::SetBreakpoint(const Script& script, | 2677 BreakpointLocation* Debugger::SetBreakpoint(const Script& script, |
2812 TokenPosition token_pos, | 2678 TokenPosition token_pos, |
2813 TokenPosition last_token_pos, | 2679 TokenPosition last_token_pos, |
2814 intptr_t requested_line, | 2680 intptr_t requested_line, |
2815 intptr_t requested_column) { | 2681 intptr_t requested_column) { |
2816 Function& func = Function::Handle(); | 2682 Function& func = Function::Handle(); |
2817 if (!FindBestFit(script, token_pos, last_token_pos, &func)) { | 2683 if (!FindBestFit(script, token_pos, last_token_pos, &func)) { |
2818 return NULL; | 2684 return NULL; |
2819 } | 2685 } |
2820 if (!func.IsNull()) { | 2686 if (!func.IsNull()) { |
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2889 BreakpointLocation* bpt = | 2755 BreakpointLocation* bpt = |
2890 GetBreakpointLocation(script, token_pos, requested_column); | 2756 GetBreakpointLocation(script, token_pos, requested_column); |
2891 if (bpt == NULL) { | 2757 if (bpt == NULL) { |
2892 bpt = new BreakpointLocation(script, token_pos, last_token_pos, | 2758 bpt = new BreakpointLocation(script, token_pos, last_token_pos, |
2893 requested_line, requested_column); | 2759 requested_line, requested_column); |
2894 RegisterBreakpointLocation(bpt); | 2760 RegisterBreakpointLocation(bpt); |
2895 } | 2761 } |
2896 return bpt; | 2762 return bpt; |
2897 } | 2763 } |
2898 | 2764 |
2899 | |
2900 // Synchronize the enabled/disabled state of all code breakpoints | 2765 // Synchronize the enabled/disabled state of all code breakpoints |
2901 // associated with the breakpoint location loc. | 2766 // associated with the breakpoint location loc. |
2902 void Debugger::SyncBreakpointLocation(BreakpointLocation* loc) { | 2767 void Debugger::SyncBreakpointLocation(BreakpointLocation* loc) { |
2903 bool any_enabled = loc->AnyEnabled(); | 2768 bool any_enabled = loc->AnyEnabled(); |
2904 | 2769 |
2905 CodeBreakpoint* cbpt = code_breakpoints_; | 2770 CodeBreakpoint* cbpt = code_breakpoints_; |
2906 while (cbpt != NULL) { | 2771 while (cbpt != NULL) { |
2907 if (loc == cbpt->bpt_location()) { | 2772 if (loc == cbpt->bpt_location()) { |
2908 if (any_enabled) { | 2773 if (any_enabled) { |
2909 cbpt->Enable(); | 2774 cbpt->Enable(); |
2910 } else { | 2775 } else { |
2911 cbpt->Disable(); | 2776 cbpt->Disable(); |
2912 } | 2777 } |
2913 } | 2778 } |
2914 cbpt = cbpt->next(); | 2779 cbpt = cbpt->next(); |
2915 } | 2780 } |
2916 } | 2781 } |
2917 | 2782 |
2918 | |
2919 RawError* Debugger::OneTimeBreakAtEntry(const Function& target_function) { | 2783 RawError* Debugger::OneTimeBreakAtEntry(const Function& target_function) { |
2920 LongJumpScope jump; | 2784 LongJumpScope jump; |
2921 if (setjmp(*jump.Set()) == 0) { | 2785 if (setjmp(*jump.Set()) == 0) { |
2922 SetBreakpointAtEntry(target_function, true); | 2786 SetBreakpointAtEntry(target_function, true); |
2923 return Error::null(); | 2787 return Error::null(); |
2924 } else { | 2788 } else { |
2925 return Thread::Current()->sticky_error(); | 2789 return Thread::Current()->sticky_error(); |
2926 } | 2790 } |
2927 } | 2791 } |
2928 | 2792 |
2929 | |
2930 Breakpoint* Debugger::SetBreakpointAtEntry(const Function& target_function, | 2793 Breakpoint* Debugger::SetBreakpointAtEntry(const Function& target_function, |
2931 bool single_shot) { | 2794 bool single_shot) { |
2932 ASSERT(!target_function.IsNull()); | 2795 ASSERT(!target_function.IsNull()); |
2933 if (!target_function.is_debuggable()) { | 2796 if (!target_function.is_debuggable()) { |
2934 return NULL; | 2797 return NULL; |
2935 } | 2798 } |
2936 const Script& script = Script::Handle(target_function.script()); | 2799 const Script& script = Script::Handle(target_function.script()); |
2937 BreakpointLocation* bpt_location = SetBreakpoint( | 2800 BreakpointLocation* bpt_location = SetBreakpoint( |
2938 script, target_function.token_pos(), target_function.end_token_pos(), -1, | 2801 script, target_function.token_pos(), target_function.end_token_pos(), -1, |
2939 -1 /* no requested line/col */); | 2802 -1 /* no requested line/col */); |
2940 if (single_shot) { | 2803 if (single_shot) { |
2941 return bpt_location->AddSingleShot(this); | 2804 return bpt_location->AddSingleShot(this); |
2942 } else { | 2805 } else { |
2943 return bpt_location->AddRepeated(this); | 2806 return bpt_location->AddRepeated(this); |
2944 } | 2807 } |
2945 } | 2808 } |
2946 | 2809 |
2947 | |
2948 Breakpoint* Debugger::SetBreakpointAtActivation(const Instance& closure, | 2810 Breakpoint* Debugger::SetBreakpointAtActivation(const Instance& closure, |
2949 bool for_over_await) { | 2811 bool for_over_await) { |
2950 if (!closure.IsClosure()) { | 2812 if (!closure.IsClosure()) { |
2951 return NULL; | 2813 return NULL; |
2952 } | 2814 } |
2953 const Function& func = Function::Handle(Closure::Cast(closure).function()); | 2815 const Function& func = Function::Handle(Closure::Cast(closure).function()); |
2954 const Script& script = Script::Handle(func.script()); | 2816 const Script& script = Script::Handle(func.script()); |
2955 BreakpointLocation* bpt_location = SetBreakpoint( | 2817 BreakpointLocation* bpt_location = SetBreakpoint( |
2956 script, func.token_pos(), func.end_token_pos(), -1, -1 /* no line/col */); | 2818 script, func.token_pos(), func.end_token_pos(), -1, -1 /* no line/col */); |
2957 return bpt_location->AddPerClosure(this, closure, for_over_await); | 2819 return bpt_location->AddPerClosure(this, closure, for_over_await); |
2958 } | 2820 } |
2959 | 2821 |
2960 | |
2961 Breakpoint* Debugger::BreakpointAtActivation(const Instance& closure) { | 2822 Breakpoint* Debugger::BreakpointAtActivation(const Instance& closure) { |
2962 if (!closure.IsClosure()) { | 2823 if (!closure.IsClosure()) { |
2963 return NULL; | 2824 return NULL; |
2964 } | 2825 } |
2965 | 2826 |
2966 BreakpointLocation* loc = breakpoint_locations_; | 2827 BreakpointLocation* loc = breakpoint_locations_; |
2967 while (loc != NULL) { | 2828 while (loc != NULL) { |
2968 Breakpoint* bpt = loc->breakpoints(); | 2829 Breakpoint* bpt = loc->breakpoints(); |
2969 while (bpt != NULL) { | 2830 while (bpt != NULL) { |
2970 if (bpt->IsPerClosure()) { | 2831 if (bpt->IsPerClosure()) { |
2971 if (closure.raw() == bpt->closure()) { | 2832 if (closure.raw() == bpt->closure()) { |
2972 return bpt; | 2833 return bpt; |
2973 } | 2834 } |
2974 } | 2835 } |
2975 bpt = bpt->next(); | 2836 bpt = bpt->next(); |
2976 } | 2837 } |
2977 loc = loc->next(); | 2838 loc = loc->next(); |
2978 } | 2839 } |
2979 | 2840 |
2980 return NULL; | 2841 return NULL; |
2981 } | 2842 } |
2982 | 2843 |
2983 | |
2984 Breakpoint* Debugger::SetBreakpointAtLine(const String& script_url, | 2844 Breakpoint* Debugger::SetBreakpointAtLine(const String& script_url, |
2985 intptr_t line_number) { | 2845 intptr_t line_number) { |
2986 // Prevent future tests from calling this function in the wrong | 2846 // Prevent future tests from calling this function in the wrong |
2987 // execution state. If you hit this assert, consider using | 2847 // execution state. If you hit this assert, consider using |
2988 // Dart_SetBreakpoint instead. | 2848 // Dart_SetBreakpoint instead. |
2989 ASSERT(Thread::Current()->execution_state() == Thread::kThreadInVM); | 2849 ASSERT(Thread::Current()->execution_state() == Thread::kThreadInVM); |
2990 | 2850 |
2991 BreakpointLocation* loc = | 2851 BreakpointLocation* loc = |
2992 BreakpointLocationAtLineCol(script_url, line_number, -1 /* no column */); | 2852 BreakpointLocationAtLineCol(script_url, line_number, -1 /* no column */); |
2993 if (loc != NULL) { | 2853 if (loc != NULL) { |
2994 return loc->AddRepeated(this); | 2854 return loc->AddRepeated(this); |
2995 } | 2855 } |
2996 return NULL; | 2856 return NULL; |
2997 } | 2857 } |
2998 | 2858 |
2999 | |
3000 Breakpoint* Debugger::SetBreakpointAtLineCol(const String& script_url, | 2859 Breakpoint* Debugger::SetBreakpointAtLineCol(const String& script_url, |
3001 intptr_t line_number, | 2860 intptr_t line_number, |
3002 intptr_t column_number) { | 2861 intptr_t column_number) { |
3003 // Prevent future tests from calling this function in the wrong | 2862 // Prevent future tests from calling this function in the wrong |
3004 // execution state. If you hit this assert, consider using | 2863 // execution state. If you hit this assert, consider using |
3005 // Dart_SetBreakpoint instead. | 2864 // Dart_SetBreakpoint instead. |
3006 ASSERT(Thread::Current()->execution_state() == Thread::kThreadInVM); | 2865 ASSERT(Thread::Current()->execution_state() == Thread::kThreadInVM); |
3007 | 2866 |
3008 BreakpointLocation* loc = | 2867 BreakpointLocation* loc = |
3009 BreakpointLocationAtLineCol(script_url, line_number, column_number); | 2868 BreakpointLocationAtLineCol(script_url, line_number, column_number); |
3010 if (loc != NULL) { | 2869 if (loc != NULL) { |
3011 return loc->AddRepeated(this); | 2870 return loc->AddRepeated(this); |
3012 } | 2871 } |
3013 return NULL; | 2872 return NULL; |
3014 } | 2873 } |
3015 | 2874 |
3016 | |
3017 BreakpointLocation* Debugger::BreakpointLocationAtLineCol( | 2875 BreakpointLocation* Debugger::BreakpointLocationAtLineCol( |
3018 const String& script_url, | 2876 const String& script_url, |
3019 intptr_t line_number, | 2877 intptr_t line_number, |
3020 intptr_t column_number) { | 2878 intptr_t column_number) { |
3021 Zone* zone = Thread::Current()->zone(); | 2879 Zone* zone = Thread::Current()->zone(); |
3022 Library& lib = Library::Handle(zone); | 2880 Library& lib = Library::Handle(zone); |
3023 Script& script = Script::Handle(zone); | 2881 Script& script = Script::Handle(zone); |
3024 const GrowableObjectArray& libs = | 2882 const GrowableObjectArray& libs = |
3025 GrowableObjectArray::Handle(isolate_->object_store()->libraries()); | 2883 GrowableObjectArray::Handle(isolate_->object_store()->libraries()); |
3026 const GrowableObjectArray& scripts = | 2884 const GrowableObjectArray& scripts = |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3077 column_number); | 2935 column_number); |
3078 first_token_idx.Next(); | 2936 first_token_idx.Next(); |
3079 } | 2937 } |
3080 if ((bpt == NULL) && FLAG_verbose_debug) { | 2938 if ((bpt == NULL) && FLAG_verbose_debug) { |
3081 OS::Print("No executable code at line %" Pd " in '%s'\n", line_number, | 2939 OS::Print("No executable code at line %" Pd " in '%s'\n", line_number, |
3082 script_url.ToCString()); | 2940 script_url.ToCString()); |
3083 } | 2941 } |
3084 return bpt; | 2942 return bpt; |
3085 } | 2943 } |
3086 | 2944 |
3087 | |
3088 intptr_t Debugger::CacheObject(const Object& obj) { | 2945 intptr_t Debugger::CacheObject(const Object& obj) { |
3089 ASSERT(obj_cache_ != NULL); | 2946 ASSERT(obj_cache_ != NULL); |
3090 return obj_cache_->AddObject(obj); | 2947 return obj_cache_->AddObject(obj); |
3091 } | 2948 } |
3092 | 2949 |
3093 | |
3094 bool Debugger::IsValidObjectId(intptr_t obj_id) { | 2950 bool Debugger::IsValidObjectId(intptr_t obj_id) { |
3095 ASSERT(obj_cache_ != NULL); | 2951 ASSERT(obj_cache_ != NULL); |
3096 return obj_cache_->IsValidId(obj_id); | 2952 return obj_cache_->IsValidId(obj_id); |
3097 } | 2953 } |
3098 | 2954 |
3099 | |
3100 RawObject* Debugger::GetCachedObject(intptr_t obj_id) { | 2955 RawObject* Debugger::GetCachedObject(intptr_t obj_id) { |
3101 ASSERT(obj_cache_ != NULL); | 2956 ASSERT(obj_cache_ != NULL); |
3102 return obj_cache_->GetObj(obj_id); | 2957 return obj_cache_->GetObj(obj_id); |
3103 } | 2958 } |
3104 | 2959 |
3105 // TODO(hausner): Merge some of this functionality with the code in | 2960 // TODO(hausner): Merge some of this functionality with the code in |
3106 // dart_api_impl.cc. | 2961 // dart_api_impl.cc. |
3107 RawObject* Debugger::GetInstanceField(const Class& cls, | 2962 RawObject* Debugger::GetInstanceField(const Class& cls, |
3108 const String& field_name, | 2963 const String& field_name, |
3109 const Instance& object) { | 2964 const Instance& object) { |
(...skipping 10 matching lines...) Expand all Loading... |
3120 const Array& args = Array::Handle(Array::New(1)); | 2975 const Array& args = Array::Handle(Array::New(1)); |
3121 args.SetAt(0, object); | 2976 args.SetAt(0, object); |
3122 result = DartEntry::InvokeFunction(getter_func, args); | 2977 result = DartEntry::InvokeFunction(getter_func, args); |
3123 } else { | 2978 } else { |
3124 result = Thread::Current()->sticky_error(); | 2979 result = Thread::Current()->sticky_error(); |
3125 } | 2980 } |
3126 ignore_breakpoints_ = saved_ignore_flag; | 2981 ignore_breakpoints_ = saved_ignore_flag; |
3127 return result.raw(); | 2982 return result.raw(); |
3128 } | 2983 } |
3129 | 2984 |
3130 | |
3131 RawObject* Debugger::GetStaticField(const Class& cls, | 2985 RawObject* Debugger::GetStaticField(const Class& cls, |
3132 const String& field_name) { | 2986 const String& field_name) { |
3133 const Field& fld = | 2987 const Field& fld = |
3134 Field::Handle(cls.LookupStaticFieldAllowPrivate(field_name)); | 2988 Field::Handle(cls.LookupStaticFieldAllowPrivate(field_name)); |
3135 if (!fld.IsNull()) { | 2989 if (!fld.IsNull()) { |
3136 // Return the value in the field if it has been initialized already. | 2990 // Return the value in the field if it has been initialized already. |
3137 const Instance& value = Instance::Handle(fld.StaticValue()); | 2991 const Instance& value = Instance::Handle(fld.StaticValue()); |
3138 ASSERT(value.raw() != Object::transition_sentinel().raw()); | 2992 ASSERT(value.raw() != Object::transition_sentinel().raw()); |
3139 if (value.raw() != Object::sentinel().raw()) { | 2993 if (value.raw() != Object::sentinel().raw()) { |
3140 return value.raw(); | 2994 return value.raw(); |
(...skipping 14 matching lines...) Expand all Loading... |
3155 LongJumpScope jump; | 3009 LongJumpScope jump; |
3156 if (setjmp(*jump.Set()) == 0) { | 3010 if (setjmp(*jump.Set()) == 0) { |
3157 result = DartEntry::InvokeFunction(getter_func, Object::empty_array()); | 3011 result = DartEntry::InvokeFunction(getter_func, Object::empty_array()); |
3158 } else { | 3012 } else { |
3159 result = Thread::Current()->sticky_error(); | 3013 result = Thread::Current()->sticky_error(); |
3160 } | 3014 } |
3161 ignore_breakpoints_ = saved_ignore_flag; | 3015 ignore_breakpoints_ = saved_ignore_flag; |
3162 return result.raw(); | 3016 return result.raw(); |
3163 } | 3017 } |
3164 | 3018 |
3165 | |
3166 RawArray* Debugger::GetInstanceFields(const Instance& obj) { | 3019 RawArray* Debugger::GetInstanceFields(const Instance& obj) { |
3167 Class& cls = Class::Handle(obj.clazz()); | 3020 Class& cls = Class::Handle(obj.clazz()); |
3168 Array& fields = Array::Handle(); | 3021 Array& fields = Array::Handle(); |
3169 Field& field = Field::Handle(); | 3022 Field& field = Field::Handle(); |
3170 const GrowableObjectArray& field_list = | 3023 const GrowableObjectArray& field_list = |
3171 GrowableObjectArray::Handle(GrowableObjectArray::New(8)); | 3024 GrowableObjectArray::Handle(GrowableObjectArray::New(8)); |
3172 String& field_name = String::Handle(); | 3025 String& field_name = String::Handle(); |
3173 PassiveObject& field_value = PassiveObject::Handle(); | 3026 PassiveObject& field_value = PassiveObject::Handle(); |
3174 // Iterate over fields in class hierarchy to count all instance fields. | 3027 // Iterate over fields in class hierarchy to count all instance fields. |
3175 while (!cls.IsNull()) { | 3028 while (!cls.IsNull()) { |
3176 fields = cls.fields(); | 3029 fields = cls.fields(); |
3177 for (intptr_t i = 0; i < fields.Length(); i++) { | 3030 for (intptr_t i = 0; i < fields.Length(); i++) { |
3178 field ^= fields.At(i); | 3031 field ^= fields.At(i); |
3179 if (!field.is_static()) { | 3032 if (!field.is_static()) { |
3180 field_name = field.name(); | 3033 field_name = field.name(); |
3181 field_list.Add(field_name); | 3034 field_list.Add(field_name); |
3182 field_value = GetInstanceField(cls, field_name, obj); | 3035 field_value = GetInstanceField(cls, field_name, obj); |
3183 field_list.Add(field_value); | 3036 field_list.Add(field_value); |
3184 } | 3037 } |
3185 } | 3038 } |
3186 cls = cls.SuperClass(); | 3039 cls = cls.SuperClass(); |
3187 } | 3040 } |
3188 return Array::MakeFixedLength(field_list); | 3041 return Array::MakeFixedLength(field_list); |
3189 } | 3042 } |
3190 | 3043 |
3191 | |
3192 RawArray* Debugger::GetStaticFields(const Class& cls) { | 3044 RawArray* Debugger::GetStaticFields(const Class& cls) { |
3193 const GrowableObjectArray& field_list = | 3045 const GrowableObjectArray& field_list = |
3194 GrowableObjectArray::Handle(GrowableObjectArray::New(8)); | 3046 GrowableObjectArray::Handle(GrowableObjectArray::New(8)); |
3195 Array& fields = Array::Handle(cls.fields()); | 3047 Array& fields = Array::Handle(cls.fields()); |
3196 Field& field = Field::Handle(); | 3048 Field& field = Field::Handle(); |
3197 String& field_name = String::Handle(); | 3049 String& field_name = String::Handle(); |
3198 PassiveObject& field_value = PassiveObject::Handle(); | 3050 PassiveObject& field_value = PassiveObject::Handle(); |
3199 for (intptr_t i = 0; i < fields.Length(); i++) { | 3051 for (intptr_t i = 0; i < fields.Length(); i++) { |
3200 field ^= fields.At(i); | 3052 field ^= fields.At(i); |
3201 if (field.is_static()) { | 3053 if (field.is_static()) { |
3202 field_name = field.name(); | 3054 field_name = field.name(); |
3203 field_value = GetStaticField(cls, field_name); | 3055 field_value = GetStaticField(cls, field_name); |
3204 field_list.Add(field_name); | 3056 field_list.Add(field_name); |
3205 field_list.Add(field_value); | 3057 field_list.Add(field_value); |
3206 } | 3058 } |
3207 } | 3059 } |
3208 return Array::MakeFixedLength(field_list); | 3060 return Array::MakeFixedLength(field_list); |
3209 } | 3061 } |
3210 | 3062 |
3211 | |
3212 void Debugger::CollectLibraryFields(const GrowableObjectArray& field_list, | 3063 void Debugger::CollectLibraryFields(const GrowableObjectArray& field_list, |
3213 const Library& lib, | 3064 const Library& lib, |
3214 const String& prefix, | 3065 const String& prefix, |
3215 bool include_private_fields) { | 3066 bool include_private_fields) { |
3216 DictionaryIterator it(lib); | 3067 DictionaryIterator it(lib); |
3217 Zone* zone = Thread::Current()->zone(); | 3068 Zone* zone = Thread::Current()->zone(); |
3218 Object& entry = Object::Handle(zone); | 3069 Object& entry = Object::Handle(zone); |
3219 Field& field = Field::Handle(zone); | 3070 Field& field = Field::Handle(zone); |
3220 String& field_name = String::Handle(zone); | 3071 String& field_name = String::Handle(zone); |
3221 PassiveObject& field_value = PassiveObject::Handle(zone); | 3072 PassiveObject& field_value = PassiveObject::Handle(zone); |
(...skipping 18 matching lines...) Expand all Loading... |
3240 } | 3091 } |
3241 if (!prefix.IsNull()) { | 3092 if (!prefix.IsNull()) { |
3242 field_name = String::Concat(prefix, field_name); | 3093 field_name = String::Concat(prefix, field_name); |
3243 } | 3094 } |
3244 field_list.Add(field_name); | 3095 field_list.Add(field_name); |
3245 field_list.Add(field_value); | 3096 field_list.Add(field_value); |
3246 } | 3097 } |
3247 } | 3098 } |
3248 } | 3099 } |
3249 | 3100 |
3250 | |
3251 RawArray* Debugger::GetLibraryFields(const Library& lib) { | 3101 RawArray* Debugger::GetLibraryFields(const Library& lib) { |
3252 Zone* zone = Thread::Current()->zone(); | 3102 Zone* zone = Thread::Current()->zone(); |
3253 const GrowableObjectArray& field_list = | 3103 const GrowableObjectArray& field_list = |
3254 GrowableObjectArray::Handle(GrowableObjectArray::New(8)); | 3104 GrowableObjectArray::Handle(GrowableObjectArray::New(8)); |
3255 CollectLibraryFields(field_list, lib, String::Handle(zone), true); | 3105 CollectLibraryFields(field_list, lib, String::Handle(zone), true); |
3256 return Array::MakeFixedLength(field_list); | 3106 return Array::MakeFixedLength(field_list); |
3257 } | 3107 } |
3258 | 3108 |
3259 | |
3260 RawArray* Debugger::GetGlobalFields(const Library& lib) { | 3109 RawArray* Debugger::GetGlobalFields(const Library& lib) { |
3261 Zone* zone = Thread::Current()->zone(); | 3110 Zone* zone = Thread::Current()->zone(); |
3262 const GrowableObjectArray& field_list = | 3111 const GrowableObjectArray& field_list = |
3263 GrowableObjectArray::Handle(zone, GrowableObjectArray::New(8)); | 3112 GrowableObjectArray::Handle(zone, GrowableObjectArray::New(8)); |
3264 String& prefix_name = String::Handle(zone); | 3113 String& prefix_name = String::Handle(zone); |
3265 CollectLibraryFields(field_list, lib, prefix_name, true); | 3114 CollectLibraryFields(field_list, lib, prefix_name, true); |
3266 Library& imported = Library::Handle(zone); | 3115 Library& imported = Library::Handle(zone); |
3267 intptr_t num_imports = lib.num_imports(); | 3116 intptr_t num_imports = lib.num_imports(); |
3268 for (intptr_t i = 0; i < num_imports; i++) { | 3117 for (intptr_t i = 0; i < num_imports; i++) { |
3269 imported = lib.ImportLibraryAt(i); | 3118 imported = lib.ImportLibraryAt(i); |
3270 ASSERT(!imported.IsNull()); | 3119 ASSERT(!imported.IsNull()); |
3271 CollectLibraryFields(field_list, imported, prefix_name, false); | 3120 CollectLibraryFields(field_list, imported, prefix_name, false); |
3272 } | 3121 } |
3273 LibraryPrefix& prefix = LibraryPrefix::Handle(zone); | 3122 LibraryPrefix& prefix = LibraryPrefix::Handle(zone); |
3274 LibraryPrefixIterator it(lib); | 3123 LibraryPrefixIterator it(lib); |
3275 while (it.HasNext()) { | 3124 while (it.HasNext()) { |
3276 prefix = it.GetNext(); | 3125 prefix = it.GetNext(); |
3277 prefix_name = prefix.name(); | 3126 prefix_name = prefix.name(); |
3278 ASSERT(!prefix_name.IsNull()); | 3127 ASSERT(!prefix_name.IsNull()); |
3279 prefix_name = String::Concat(prefix_name, Symbols::Dot()); | 3128 prefix_name = String::Concat(prefix_name, Symbols::Dot()); |
3280 for (int32_t i = 0; i < prefix.num_imports(); i++) { | 3129 for (int32_t i = 0; i < prefix.num_imports(); i++) { |
3281 imported = prefix.GetLibrary(i); | 3130 imported = prefix.GetLibrary(i); |
3282 CollectLibraryFields(field_list, imported, prefix_name, false); | 3131 CollectLibraryFields(field_list, imported, prefix_name, false); |
3283 } | 3132 } |
3284 } | 3133 } |
3285 return Array::MakeFixedLength(field_list); | 3134 return Array::MakeFixedLength(field_list); |
3286 } | 3135 } |
3287 | 3136 |
3288 | |
3289 // static | 3137 // static |
3290 void Debugger::VisitObjectPointers(ObjectPointerVisitor* visitor) { | 3138 void Debugger::VisitObjectPointers(ObjectPointerVisitor* visitor) { |
3291 ASSERT(visitor != NULL); | 3139 ASSERT(visitor != NULL); |
3292 BreakpointLocation* bpt = breakpoint_locations_; | 3140 BreakpointLocation* bpt = breakpoint_locations_; |
3293 while (bpt != NULL) { | 3141 while (bpt != NULL) { |
3294 bpt->VisitObjectPointers(visitor); | 3142 bpt->VisitObjectPointers(visitor); |
3295 bpt = bpt->next(); | 3143 bpt = bpt->next(); |
3296 } | 3144 } |
3297 bpt = latent_locations_; | 3145 bpt = latent_locations_; |
3298 while (bpt != NULL) { | 3146 while (bpt != NULL) { |
3299 bpt->VisitObjectPointers(visitor); | 3147 bpt->VisitObjectPointers(visitor); |
3300 bpt = bpt->next(); | 3148 bpt = bpt->next(); |
3301 } | 3149 } |
3302 CodeBreakpoint* cbpt = code_breakpoints_; | 3150 CodeBreakpoint* cbpt = code_breakpoints_; |
3303 while (cbpt != NULL) { | 3151 while (cbpt != NULL) { |
3304 cbpt->VisitObjectPointers(visitor); | 3152 cbpt->VisitObjectPointers(visitor); |
3305 cbpt = cbpt->next(); | 3153 cbpt = cbpt->next(); |
3306 } | 3154 } |
3307 visitor->VisitPointer(reinterpret_cast<RawObject**>(&top_frame_awaiter_)); | 3155 visitor->VisitPointer(reinterpret_cast<RawObject**>(&top_frame_awaiter_)); |
3308 } | 3156 } |
3309 | 3157 |
3310 | |
3311 // static | 3158 // static |
3312 void Debugger::SetEventHandler(EventHandler* handler) { | 3159 void Debugger::SetEventHandler(EventHandler* handler) { |
3313 event_handler_ = handler; | 3160 event_handler_ = handler; |
3314 } | 3161 } |
3315 | 3162 |
3316 | |
3317 void Debugger::Pause(ServiceEvent* event) { | 3163 void Debugger::Pause(ServiceEvent* event) { |
3318 ASSERT(event->IsPause()); // Should call InvokeEventHandler instead. | 3164 ASSERT(event->IsPause()); // Should call InvokeEventHandler instead. |
3319 ASSERT(!ignore_breakpoints_); // We shouldn't get here when ignoring bpts. | 3165 ASSERT(!ignore_breakpoints_); // We shouldn't get here when ignoring bpts. |
3320 ASSERT(!IsPaused()); // No recursive pausing. | 3166 ASSERT(!IsPaused()); // No recursive pausing. |
3321 ASSERT(obj_cache_ == NULL); | 3167 ASSERT(obj_cache_ == NULL); |
3322 | 3168 |
3323 pause_event_ = event; | 3169 pause_event_ = event; |
3324 pause_event_->UpdateTimestamp(); | 3170 pause_event_->UpdateTimestamp(); |
3325 obj_cache_ = new RemoteObjectCache(64); | 3171 obj_cache_ = new RemoteObjectCache(64); |
3326 | 3172 |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3359 } | 3205 } |
3360 } | 3206 } |
3361 | 3207 |
3362 if (needs_breakpoint_cleanup_) { | 3208 if (needs_breakpoint_cleanup_) { |
3363 RemoveUnlinkedCodeBreakpoints(); | 3209 RemoveUnlinkedCodeBreakpoints(); |
3364 } | 3210 } |
3365 pause_event_ = NULL; | 3211 pause_event_ = NULL; |
3366 obj_cache_ = NULL; // Zone allocated | 3212 obj_cache_ = NULL; // Zone allocated |
3367 } | 3213 } |
3368 | 3214 |
3369 | |
3370 void Debugger::EnterSingleStepMode() { | 3215 void Debugger::EnterSingleStepMode() { |
3371 ResetSteppingFramePointers(); | 3216 ResetSteppingFramePointers(); |
3372 DeoptimizeWorld(); | 3217 DeoptimizeWorld(); |
3373 isolate_->set_single_step(true); | 3218 isolate_->set_single_step(true); |
3374 } | 3219 } |
3375 | 3220 |
3376 | |
3377 void Debugger::ResetSteppingFramePointers() { | 3221 void Debugger::ResetSteppingFramePointers() { |
3378 stepping_fp_ = 0; | 3222 stepping_fp_ = 0; |
3379 async_stepping_fp_ = 0; | 3223 async_stepping_fp_ = 0; |
3380 } | 3224 } |
3381 | 3225 |
3382 | |
3383 bool Debugger::SteppedForSyntheticAsyncBreakpoint() const { | 3226 bool Debugger::SteppedForSyntheticAsyncBreakpoint() const { |
3384 return synthetic_async_breakpoint_ != NULL; | 3227 return synthetic_async_breakpoint_ != NULL; |
3385 } | 3228 } |
3386 | 3229 |
3387 | |
3388 void Debugger::CleanupSyntheticAsyncBreakpoint() { | 3230 void Debugger::CleanupSyntheticAsyncBreakpoint() { |
3389 if (synthetic_async_breakpoint_ != NULL) { | 3231 if (synthetic_async_breakpoint_ != NULL) { |
3390 RemoveBreakpoint(synthetic_async_breakpoint_->id()); | 3232 RemoveBreakpoint(synthetic_async_breakpoint_->id()); |
3391 synthetic_async_breakpoint_ = NULL; | 3233 synthetic_async_breakpoint_ = NULL; |
3392 } | 3234 } |
3393 } | 3235 } |
3394 | 3236 |
3395 | |
3396 void Debugger::RememberTopFrameAwaiter() { | 3237 void Debugger::RememberTopFrameAwaiter() { |
3397 if (!FLAG_async_debugger) { | 3238 if (!FLAG_async_debugger) { |
3398 return; | 3239 return; |
3399 } | 3240 } |
3400 if (stack_trace_->Length() > 0) { | 3241 if (stack_trace_->Length() > 0) { |
3401 top_frame_awaiter_ = stack_trace_->FrameAt(0)->GetAsyncAwaiter(); | 3242 top_frame_awaiter_ = stack_trace_->FrameAt(0)->GetAsyncAwaiter(); |
3402 } else { | 3243 } else { |
3403 top_frame_awaiter_ = Object::null(); | 3244 top_frame_awaiter_ = Object::null(); |
3404 } | 3245 } |
3405 } | 3246 } |
3406 | 3247 |
3407 | |
3408 void Debugger::SetAsyncSteppingFramePointer() { | 3248 void Debugger::SetAsyncSteppingFramePointer() { |
3409 if (!FLAG_async_debugger) { | 3249 if (!FLAG_async_debugger) { |
3410 return; | 3250 return; |
3411 } | 3251 } |
3412 if (stack_trace_->FrameAt(0)->function().IsAsyncClosure() || | 3252 if (stack_trace_->FrameAt(0)->function().IsAsyncClosure() || |
3413 stack_trace_->FrameAt(0)->function().IsAsyncGenClosure()) { | 3253 stack_trace_->FrameAt(0)->function().IsAsyncGenClosure()) { |
3414 async_stepping_fp_ = stack_trace_->FrameAt(0)->fp(); | 3254 async_stepping_fp_ = stack_trace_->FrameAt(0)->fp(); |
3415 } else { | 3255 } else { |
3416 async_stepping_fp_ = 0; | 3256 async_stepping_fp_ = 0; |
3417 } | 3257 } |
3418 } | 3258 } |
3419 | 3259 |
3420 | |
3421 void Debugger::HandleSteppingRequest(DebuggerStackTrace* stack_trace, | 3260 void Debugger::HandleSteppingRequest(DebuggerStackTrace* stack_trace, |
3422 bool skip_next_step) { | 3261 bool skip_next_step) { |
3423 ResetSteppingFramePointers(); | 3262 ResetSteppingFramePointers(); |
3424 RememberTopFrameAwaiter(); | 3263 RememberTopFrameAwaiter(); |
3425 if (resume_action_ == kStepInto) { | 3264 if (resume_action_ == kStepInto) { |
3426 // When single stepping, we need to deoptimize because we might be | 3265 // When single stepping, we need to deoptimize because we might be |
3427 // stepping into optimized code. This happens in particular if | 3266 // stepping into optimized code. This happens in particular if |
3428 // the isolate has been interrupted, but can happen in other cases | 3267 // the isolate has been interrupted, but can happen in other cases |
3429 // as well. We need to deoptimize the world in case we are about | 3268 // as well. We need to deoptimize the world in case we are about |
3430 // to call an optimized function. | 3269 // to call an optimized function. |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3488 while ((frame != NULL)) { | 3327 while ((frame != NULL)) { |
3489 OS::PrintErr("#%04" Pd " %s\n", num++, frame->ToCString()); | 3328 OS::PrintErr("#%04" Pd " %s\n", num++, frame->ToCString()); |
3490 frame = iterator.NextFrame(); | 3329 frame = iterator.NextFrame(); |
3491 } | 3330 } |
3492 } | 3331 } |
3493 RewindToFrame(resume_frame_index_); | 3332 RewindToFrame(resume_frame_index_); |
3494 UNREACHABLE(); | 3333 UNREACHABLE(); |
3495 } | 3334 } |
3496 } | 3335 } |
3497 | 3336 |
3498 | |
3499 void Debugger::CacheStackTraces(DebuggerStackTrace* stack_trace, | 3337 void Debugger::CacheStackTraces(DebuggerStackTrace* stack_trace, |
3500 DebuggerStackTrace* async_causal_stack_trace, | 3338 DebuggerStackTrace* async_causal_stack_trace, |
3501 DebuggerStackTrace* awaiter_stack_trace) { | 3339 DebuggerStackTrace* awaiter_stack_trace) { |
3502 ASSERT(stack_trace_ == NULL); | 3340 ASSERT(stack_trace_ == NULL); |
3503 stack_trace_ = stack_trace; | 3341 stack_trace_ = stack_trace; |
3504 ASSERT(async_causal_stack_trace_ == NULL); | 3342 ASSERT(async_causal_stack_trace_ == NULL); |
3505 async_causal_stack_trace_ = async_causal_stack_trace; | 3343 async_causal_stack_trace_ = async_causal_stack_trace; |
3506 ASSERT(awaiter_stack_trace_ == NULL); | 3344 ASSERT(awaiter_stack_trace_ == NULL); |
3507 awaiter_stack_trace_ = awaiter_stack_trace; | 3345 awaiter_stack_trace_ = awaiter_stack_trace; |
3508 } | 3346 } |
3509 | 3347 |
3510 | |
3511 void Debugger::ClearCachedStackTraces() { | 3348 void Debugger::ClearCachedStackTraces() { |
3512 stack_trace_ = NULL; | 3349 stack_trace_ = NULL; |
3513 async_causal_stack_trace_ = NULL; | 3350 async_causal_stack_trace_ = NULL; |
3514 awaiter_stack_trace_ = NULL; | 3351 awaiter_stack_trace_ = NULL; |
3515 } | 3352 } |
3516 | 3353 |
3517 | |
3518 static intptr_t FindNextRewindFrameIndex(DebuggerStackTrace* stack, | 3354 static intptr_t FindNextRewindFrameIndex(DebuggerStackTrace* stack, |
3519 intptr_t frame_index) { | 3355 intptr_t frame_index) { |
3520 for (intptr_t i = frame_index + 1; i < stack->Length(); i++) { | 3356 for (intptr_t i = frame_index + 1; i < stack->Length(); i++) { |
3521 ActivationFrame* frame = stack->FrameAt(i); | 3357 ActivationFrame* frame = stack->FrameAt(i); |
3522 if (frame->IsRewindable()) { | 3358 if (frame->IsRewindable()) { |
3523 return i; | 3359 return i; |
3524 } | 3360 } |
3525 } | 3361 } |
3526 return -1; | 3362 return -1; |
3527 } | 3363 } |
3528 | 3364 |
3529 | |
3530 // Can the top frame be rewound? | 3365 // Can the top frame be rewound? |
3531 bool Debugger::CanRewindFrame(intptr_t frame_index, const char** error) const { | 3366 bool Debugger::CanRewindFrame(intptr_t frame_index, const char** error) const { |
3532 // check rewind pc is found | 3367 // check rewind pc is found |
3533 DebuggerStackTrace* stack = Isolate::Current()->debugger()->StackTrace(); | 3368 DebuggerStackTrace* stack = Isolate::Current()->debugger()->StackTrace(); |
3534 intptr_t num_frames = stack->Length(); | 3369 intptr_t num_frames = stack->Length(); |
3535 if (frame_index < 1 || frame_index >= num_frames) { | 3370 if (frame_index < 1 || frame_index >= num_frames) { |
3536 if (error) { | 3371 if (error) { |
3537 *error = Thread::Current()->zone()->PrintToString( | 3372 *error = Thread::Current()->zone()->PrintToString( |
3538 "Frame must be in bounds [1..%" Pd | 3373 "Frame must be in bounds [1..%" Pd |
3539 "]: " | 3374 "]: " |
(...skipping 21 matching lines...) Expand all Loading... |
3561 "optimizations. " | 3396 "optimizations. " |
3562 "Run the vm with --no-prune-dead-locals to disallow these " | 3397 "Run the vm with --no-prune-dead-locals to disallow these " |
3563 "optimizations.", | 3398 "optimizations.", |
3564 frame_index); | 3399 frame_index); |
3565 } | 3400 } |
3566 return false; | 3401 return false; |
3567 } | 3402 } |
3568 return true; | 3403 return true; |
3569 } | 3404 } |
3570 | 3405 |
3571 | |
3572 // Given a return address pc, find the "rewind" pc, which is the pc | 3406 // Given a return address pc, find the "rewind" pc, which is the pc |
3573 // before the corresponding call. | 3407 // before the corresponding call. |
3574 static uword LookupRewindPc(const Code& code, uword pc) { | 3408 static uword LookupRewindPc(const Code& code, uword pc) { |
3575 ASSERT(!code.is_optimized()); | 3409 ASSERT(!code.is_optimized()); |
3576 ASSERT(code.ContainsInstructionAt(pc)); | 3410 ASSERT(code.ContainsInstructionAt(pc)); |
3577 | 3411 |
3578 uword pc_offset = pc - code.PayloadStart(); | 3412 uword pc_offset = pc - code.PayloadStart(); |
3579 const PcDescriptors& descriptors = | 3413 const PcDescriptors& descriptors = |
3580 PcDescriptors::Handle(code.pc_descriptors()); | 3414 PcDescriptors::Handle(code.pc_descriptors()); |
3581 PcDescriptors::Iterator iter( | 3415 PcDescriptors::Iterator iter( |
3582 descriptors, RawPcDescriptors::kRewind | RawPcDescriptors::kIcCall | | 3416 descriptors, RawPcDescriptors::kRewind | RawPcDescriptors::kIcCall | |
3583 RawPcDescriptors::kUnoptStaticCall); | 3417 RawPcDescriptors::kUnoptStaticCall); |
3584 intptr_t rewind_deopt_id = -1; | 3418 intptr_t rewind_deopt_id = -1; |
3585 uword rewind_pc = 0; | 3419 uword rewind_pc = 0; |
3586 while (iter.MoveNext()) { | 3420 while (iter.MoveNext()) { |
3587 if (iter.Kind() == RawPcDescriptors::kRewind) { | 3421 if (iter.Kind() == RawPcDescriptors::kRewind) { |
3588 // Remember the last rewind so we don't need to iterator twice. | 3422 // Remember the last rewind so we don't need to iterator twice. |
3589 rewind_pc = code.PayloadStart() + iter.PcOffset(); | 3423 rewind_pc = code.PayloadStart() + iter.PcOffset(); |
3590 rewind_deopt_id = iter.DeoptId(); | 3424 rewind_deopt_id = iter.DeoptId(); |
3591 } | 3425 } |
3592 if ((pc_offset == iter.PcOffset()) && (iter.DeoptId() == rewind_deopt_id)) { | 3426 if ((pc_offset == iter.PcOffset()) && (iter.DeoptId() == rewind_deopt_id)) { |
3593 return rewind_pc; | 3427 return rewind_pc; |
3594 } | 3428 } |
3595 } | 3429 } |
3596 return 0; | 3430 return 0; |
3597 } | 3431 } |
3598 | 3432 |
3599 | |
3600 void Debugger::RewindToFrame(intptr_t frame_index) { | 3433 void Debugger::RewindToFrame(intptr_t frame_index) { |
3601 Thread* thread = Thread::Current(); | 3434 Thread* thread = Thread::Current(); |
3602 Zone* zone = thread->zone(); | 3435 Zone* zone = thread->zone(); |
3603 Code& code = Code::Handle(zone); | 3436 Code& code = Code::Handle(zone); |
3604 Function& function = Function::Handle(zone); | 3437 Function& function = Function::Handle(zone); |
3605 | 3438 |
3606 // Find the requested frame. | 3439 // Find the requested frame. |
3607 StackFrameIterator iterator(StackFrameIterator::kDontValidateFrames, | 3440 StackFrameIterator iterator(StackFrameIterator::kDontValidateFrames, |
3608 Thread::Current(), | 3441 Thread::Current(), |
3609 StackFrameIterator::kNoCrossThreadIteration); | 3442 StackFrameIterator::kNoCrossThreadIteration); |
(...skipping 24 matching lines...) Expand all Loading... |
3634 RewindToUnoptimizedFrame(frame, code); | 3467 RewindToUnoptimizedFrame(frame, code); |
3635 UNREACHABLE(); | 3468 UNREACHABLE(); |
3636 } | 3469 } |
3637 current_frame++; | 3470 current_frame++; |
3638 } | 3471 } |
3639 } | 3472 } |
3640 } | 3473 } |
3641 UNIMPLEMENTED(); | 3474 UNIMPLEMENTED(); |
3642 } | 3475 } |
3643 | 3476 |
3644 | |
3645 void Debugger::RewindToUnoptimizedFrame(StackFrame* frame, const Code& code) { | 3477 void Debugger::RewindToUnoptimizedFrame(StackFrame* frame, const Code& code) { |
3646 // We will be jumping out of the debugger rather than exiting this | 3478 // We will be jumping out of the debugger rather than exiting this |
3647 // function, so prepare the debugger state. | 3479 // function, so prepare the debugger state. |
3648 ClearCachedStackTraces(); | 3480 ClearCachedStackTraces(); |
3649 resume_action_ = kContinue; | 3481 resume_action_ = kContinue; |
3650 resume_frame_index_ = -1; | 3482 resume_frame_index_ = -1; |
3651 EnterSingleStepMode(); | 3483 EnterSingleStepMode(); |
3652 | 3484 |
3653 uword rewind_pc = LookupRewindPc(code, frame->pc()); | 3485 uword rewind_pc = LookupRewindPc(code, frame->pc()); |
3654 if (FLAG_trace_rewind && rewind_pc == 0) { | 3486 if (FLAG_trace_rewind && rewind_pc == 0) { |
3655 OS::PrintErr("Unable to find rewind pc for pc(%" Px ")\n", frame->pc()); | 3487 OS::PrintErr("Unable to find rewind pc for pc(%" Px ")\n", frame->pc()); |
3656 } | 3488 } |
3657 ASSERT(rewind_pc != 0); | 3489 ASSERT(rewind_pc != 0); |
3658 if (FLAG_trace_rewind) { | 3490 if (FLAG_trace_rewind) { |
3659 OS::PrintErr( | 3491 OS::PrintErr( |
3660 "===============================\n" | 3492 "===============================\n" |
3661 "Rewinding to unoptimized frame:\n" | 3493 "Rewinding to unoptimized frame:\n" |
3662 " rewind_pc(0x%" Px ") sp(0x%" Px ") fp(0x%" Px | 3494 " rewind_pc(0x%" Px ") sp(0x%" Px ") fp(0x%" Px |
3663 ")\n" | 3495 ")\n" |
3664 "===============================\n", | 3496 "===============================\n", |
3665 rewind_pc, frame->sp(), frame->fp()); | 3497 rewind_pc, frame->sp(), frame->fp()); |
3666 } | 3498 } |
3667 Exceptions::JumpToFrame(Thread::Current(), rewind_pc, frame->sp(), | 3499 Exceptions::JumpToFrame(Thread::Current(), rewind_pc, frame->sp(), |
3668 frame->fp(), true /* clear lazy deopt at target */); | 3500 frame->fp(), true /* clear lazy deopt at target */); |
3669 UNREACHABLE(); | 3501 UNREACHABLE(); |
3670 } | 3502 } |
3671 | 3503 |
3672 | |
3673 void Debugger::RewindToOptimizedFrame(StackFrame* frame, | 3504 void Debugger::RewindToOptimizedFrame(StackFrame* frame, |
3674 const Code& optimized_code, | 3505 const Code& optimized_code, |
3675 intptr_t sub_index) { | 3506 intptr_t sub_index) { |
3676 post_deopt_frame_index_ = sub_index; | 3507 post_deopt_frame_index_ = sub_index; |
3677 | 3508 |
3678 // We will be jumping out of the debugger rather than exiting this | 3509 // We will be jumping out of the debugger rather than exiting this |
3679 // function, so prepare the debugger state. | 3510 // function, so prepare the debugger state. |
3680 ClearCachedStackTraces(); | 3511 ClearCachedStackTraces(); |
3681 resume_action_ = kContinue; | 3512 resume_action_ = kContinue; |
3682 resume_frame_index_ = -1; | 3513 resume_frame_index_ = -1; |
3683 EnterSingleStepMode(); | 3514 EnterSingleStepMode(); |
3684 | 3515 |
3685 if (FLAG_trace_rewind) { | 3516 if (FLAG_trace_rewind) { |
3686 OS::PrintErr( | 3517 OS::PrintErr( |
3687 "===============================\n" | 3518 "===============================\n" |
3688 "Deoptimizing frame for rewind:\n" | 3519 "Deoptimizing frame for rewind:\n" |
3689 " deopt_pc(0x%" Px ") sp(0x%" Px ") fp(0x%" Px | 3520 " deopt_pc(0x%" Px ") sp(0x%" Px ") fp(0x%" Px |
3690 ")\n" | 3521 ")\n" |
3691 "===============================\n", | 3522 "===============================\n", |
3692 frame->pc(), frame->sp(), frame->fp()); | 3523 frame->pc(), frame->sp(), frame->fp()); |
3693 } | 3524 } |
3694 Thread* thread = Thread::Current(); | 3525 Thread* thread = Thread::Current(); |
3695 thread->set_resume_pc(frame->pc()); | 3526 thread->set_resume_pc(frame->pc()); |
3696 uword deopt_stub_pc = StubCode::DeoptForRewind_entry()->EntryPoint(); | 3527 uword deopt_stub_pc = StubCode::DeoptForRewind_entry()->EntryPoint(); |
3697 Exceptions::JumpToFrame(thread, deopt_stub_pc, frame->sp(), frame->fp(), | 3528 Exceptions::JumpToFrame(thread, deopt_stub_pc, frame->sp(), frame->fp(), |
3698 true /* clear lazy deopt at target */); | 3529 true /* clear lazy deopt at target */); |
3699 UNREACHABLE(); | 3530 UNREACHABLE(); |
3700 } | 3531 } |
3701 | 3532 |
3702 | |
3703 void Debugger::RewindPostDeopt() { | 3533 void Debugger::RewindPostDeopt() { |
3704 intptr_t rewind_frame = post_deopt_frame_index_; | 3534 intptr_t rewind_frame = post_deopt_frame_index_; |
3705 post_deopt_frame_index_ = -1; | 3535 post_deopt_frame_index_ = -1; |
3706 if (FLAG_trace_rewind) { | 3536 if (FLAG_trace_rewind) { |
3707 OS::PrintErr("Post deopt, jumping to frame %" Pd "\n", rewind_frame); | 3537 OS::PrintErr("Post deopt, jumping to frame %" Pd "\n", rewind_frame); |
3708 OS::PrintErr( | 3538 OS::PrintErr( |
3709 "-------------------------\n" | 3539 "-------------------------\n" |
3710 "All frames...\n\n"); | 3540 "All frames...\n\n"); |
3711 StackFrameIterator iterator(StackFrameIterator::kDontValidateFrames, | 3541 StackFrameIterator iterator(StackFrameIterator::kDontValidateFrames, |
3712 Thread::Current(), | 3542 Thread::Current(), |
(...skipping 22 matching lines...) Expand all Loading... |
3735 ASSERT(!code.is_optimized()); | 3565 ASSERT(!code.is_optimized()); |
3736 if (current_frame == rewind_frame) { | 3566 if (current_frame == rewind_frame) { |
3737 RewindToUnoptimizedFrame(frame, code); | 3567 RewindToUnoptimizedFrame(frame, code); |
3738 UNREACHABLE(); | 3568 UNREACHABLE(); |
3739 } | 3569 } |
3740 current_frame++; | 3570 current_frame++; |
3741 } | 3571 } |
3742 } | 3572 } |
3743 } | 3573 } |
3744 | 3574 |
3745 | |
3746 // static | 3575 // static |
3747 bool Debugger::IsDebuggable(const Function& func) { | 3576 bool Debugger::IsDebuggable(const Function& func) { |
3748 if (!func.is_debuggable()) { | 3577 if (!func.is_debuggable()) { |
3749 return false; | 3578 return false; |
3750 } | 3579 } |
3751 const Class& cls = Class::Handle(func.Owner()); | 3580 const Class& cls = Class::Handle(func.Owner()); |
3752 const Library& lib = Library::Handle(cls.library()); | 3581 const Library& lib = Library::Handle(cls.library()); |
3753 return lib.IsDebuggable(); | 3582 return lib.IsDebuggable(); |
3754 } | 3583 } |
3755 | 3584 |
3756 | |
3757 void Debugger::SignalPausedEvent(ActivationFrame* top_frame, Breakpoint* bpt) { | 3585 void Debugger::SignalPausedEvent(ActivationFrame* top_frame, Breakpoint* bpt) { |
3758 resume_action_ = kContinue; | 3586 resume_action_ = kContinue; |
3759 ResetSteppingFramePointers(); | 3587 ResetSteppingFramePointers(); |
3760 isolate_->set_single_step(false); | 3588 isolate_->set_single_step(false); |
3761 ASSERT(!IsPaused()); | 3589 ASSERT(!IsPaused()); |
3762 ASSERT(obj_cache_ == NULL); | 3590 ASSERT(obj_cache_ == NULL); |
3763 if ((bpt != NULL) && bpt->IsSingleShot()) { | 3591 if ((bpt != NULL) && bpt->IsSingleShot()) { |
3764 RemoveBreakpoint(bpt->id()); | 3592 RemoveBreakpoint(bpt->id()); |
3765 bpt = NULL; | 3593 bpt = NULL; |
3766 } | 3594 } |
3767 | 3595 |
3768 ServiceEvent event(isolate_, ServiceEvent::kPauseBreakpoint); | 3596 ServiceEvent event(isolate_, ServiceEvent::kPauseBreakpoint); |
3769 event.set_top_frame(top_frame); | 3597 event.set_top_frame(top_frame); |
3770 event.set_breakpoint(bpt); | 3598 event.set_breakpoint(bpt); |
3771 event.set_at_async_jump(IsAtAsyncJump(top_frame)); | 3599 event.set_at_async_jump(IsAtAsyncJump(top_frame)); |
3772 Pause(&event); | 3600 Pause(&event); |
3773 } | 3601 } |
3774 | 3602 |
3775 | |
3776 bool Debugger::IsAtAsyncJump(ActivationFrame* top_frame) { | 3603 bool Debugger::IsAtAsyncJump(ActivationFrame* top_frame) { |
3777 Zone* zone = Thread::Current()->zone(); | 3604 Zone* zone = Thread::Current()->zone(); |
3778 Object& closure_or_null = | 3605 Object& closure_or_null = |
3779 Object::Handle(zone, top_frame->GetAsyncOperation()); | 3606 Object::Handle(zone, top_frame->GetAsyncOperation()); |
3780 if (!closure_or_null.IsNull()) { | 3607 if (!closure_or_null.IsNull()) { |
3781 ASSERT(closure_or_null.IsInstance()); | 3608 ASSERT(closure_or_null.IsInstance()); |
3782 ASSERT(Instance::Cast(closure_or_null).IsClosure()); | 3609 ASSERT(Instance::Cast(closure_or_null).IsClosure()); |
3783 const Script& script = Script::Handle(zone, top_frame->SourceScript()); | 3610 const Script& script = Script::Handle(zone, top_frame->SourceScript()); |
3784 if (script.kind() == RawScript::kKernelTag) { | 3611 if (script.kind() == RawScript::kKernelTag) { |
3785 // Are we at a yield point (previous await)? | 3612 // Are we at a yield point (previous await)? |
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3870 ASSERT(!HasActiveBreakpoint(frame->pc())); | 3697 ASSERT(!HasActiveBreakpoint(frame->pc())); |
3871 | 3698 |
3872 if (FLAG_verbose_debug) { | 3699 if (FLAG_verbose_debug) { |
3873 OS::Print(">>> single step break at %s:%" Pd " (func %s token %s)\n", | 3700 OS::Print(">>> single step break at %s:%" Pd " (func %s token %s)\n", |
3874 String::Handle(frame->SourceUrl()).ToCString(), | 3701 String::Handle(frame->SourceUrl()).ToCString(), |
3875 frame->LineNumber(), | 3702 frame->LineNumber(), |
3876 String::Handle(frame->QualifiedFunctionName()).ToCString(), | 3703 String::Handle(frame->QualifiedFunctionName()).ToCString(), |
3877 frame->TokenPos().ToCString()); | 3704 frame->TokenPos().ToCString()); |
3878 } | 3705 } |
3879 | 3706 |
3880 | |
3881 CacheStackTraces(CollectStackTrace(), CollectAsyncCausalStackTrace(), | 3707 CacheStackTraces(CollectStackTrace(), CollectAsyncCausalStackTrace(), |
3882 CollectAwaiterReturnStackTrace()); | 3708 CollectAwaiterReturnStackTrace()); |
3883 if (SteppedForSyntheticAsyncBreakpoint()) { | 3709 if (SteppedForSyntheticAsyncBreakpoint()) { |
3884 CleanupSyntheticAsyncBreakpoint(); | 3710 CleanupSyntheticAsyncBreakpoint(); |
3885 } | 3711 } |
3886 SignalPausedEvent(frame, NULL); | 3712 SignalPausedEvent(frame, NULL); |
3887 HandleSteppingRequest(stack_trace_); | 3713 HandleSteppingRequest(stack_trace_); |
3888 ClearCachedStackTraces(); | 3714 ClearCachedStackTraces(); |
3889 | 3715 |
3890 // If any error occurred while in the debug message loop, return it here. | 3716 // If any error occurred while in the debug message loop, return it here. |
3891 const Error& error = Error::Handle(Thread::Current()->sticky_error()); | 3717 const Error& error = Error::Handle(Thread::Current()->sticky_error()); |
3892 Thread::Current()->clear_sticky_error(); | 3718 Thread::Current()->clear_sticky_error(); |
3893 return error.raw(); | 3719 return error.raw(); |
3894 } | 3720 } |
3895 | 3721 |
3896 | |
3897 RawError* Debugger::PauseBreakpoint() { | 3722 RawError* Debugger::PauseBreakpoint() { |
3898 // We ignore this breakpoint when the VM is executing code invoked | 3723 // We ignore this breakpoint when the VM is executing code invoked |
3899 // by the debugger to evaluate variables values, or when we see a nested | 3724 // by the debugger to evaluate variables values, or when we see a nested |
3900 // breakpoint or exception event. | 3725 // breakpoint or exception event. |
3901 if (ignore_breakpoints_ || IsPaused()) { | 3726 if (ignore_breakpoints_ || IsPaused()) { |
3902 return Error::null(); | 3727 return Error::null(); |
3903 } | 3728 } |
3904 DebuggerStackTrace* stack_trace = CollectStackTrace(); | 3729 DebuggerStackTrace* stack_trace = CollectStackTrace(); |
3905 ASSERT(stack_trace->Length() > 0); | 3730 ASSERT(stack_trace->Length() > 0); |
3906 ActivationFrame* top_frame = stack_trace->FrameAt(0); | 3731 ActivationFrame* top_frame = stack_trace->FrameAt(0); |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3959 // point will be at the exact same pc. Skip it. | 3784 // point will be at the exact same pc. Skip it. |
3960 HandleSteppingRequest(stack_trace_, true /* skip next step */); | 3785 HandleSteppingRequest(stack_trace_, true /* skip next step */); |
3961 ClearCachedStackTraces(); | 3786 ClearCachedStackTraces(); |
3962 | 3787 |
3963 // If any error occurred while in the debug message loop, return it here. | 3788 // If any error occurred while in the debug message loop, return it here. |
3964 const Error& error = Error::Handle(Thread::Current()->sticky_error()); | 3789 const Error& error = Error::Handle(Thread::Current()->sticky_error()); |
3965 Thread::Current()->clear_sticky_error(); | 3790 Thread::Current()->clear_sticky_error(); |
3966 return error.raw(); | 3791 return error.raw(); |
3967 } | 3792 } |
3968 | 3793 |
3969 | |
3970 Breakpoint* Debugger::FindHitBreakpoint(BreakpointLocation* location, | 3794 Breakpoint* Debugger::FindHitBreakpoint(BreakpointLocation* location, |
3971 ActivationFrame* top_frame) { | 3795 ActivationFrame* top_frame) { |
3972 if (location == NULL) { | 3796 if (location == NULL) { |
3973 return NULL; | 3797 return NULL; |
3974 } | 3798 } |
3975 // There may be more than one applicable breakpoint at this location, but we | 3799 // There may be more than one applicable breakpoint at this location, but we |
3976 // will report only one as reached. If there is a single-shot breakpoint, we | 3800 // will report only one as reached. If there is a single-shot breakpoint, we |
3977 // favor it; then a closure-specific breakpoint ; then an general breakpoint. | 3801 // favor it; then a closure-specific breakpoint ; then an general breakpoint. |
3978 | 3802 |
3979 // First check for a single-shot breakpoint. | 3803 // First check for a single-shot breakpoint. |
(...skipping 24 matching lines...) Expand all Loading... |
4004 while (bpt != NULL) { | 3828 while (bpt != NULL) { |
4005 if (bpt->IsRepeated()) { | 3829 if (bpt->IsRepeated()) { |
4006 return bpt; | 3830 return bpt; |
4007 } | 3831 } |
4008 bpt = bpt->next(); | 3832 bpt = bpt->next(); |
4009 } | 3833 } |
4010 | 3834 |
4011 return NULL; | 3835 return NULL; |
4012 } | 3836 } |
4013 | 3837 |
4014 | |
4015 void Debugger::PauseDeveloper(const String& msg) { | 3838 void Debugger::PauseDeveloper(const String& msg) { |
4016 // We ignore this breakpoint when the VM is executing code invoked | 3839 // We ignore this breakpoint when the VM is executing code invoked |
4017 // by the debugger to evaluate variables values, or when we see a nested | 3840 // by the debugger to evaluate variables values, or when we see a nested |
4018 // breakpoint or exception event. | 3841 // breakpoint or exception event. |
4019 if (ignore_breakpoints_ || IsPaused()) { | 3842 if (ignore_breakpoints_ || IsPaused()) { |
4020 return; | 3843 return; |
4021 } | 3844 } |
4022 | 3845 |
4023 DebuggerStackTrace* stack_trace = CollectStackTrace(); | 3846 DebuggerStackTrace* stack_trace = CollectStackTrace(); |
4024 ASSERT(stack_trace->Length() > 0); | 3847 ASSERT(stack_trace->Length() > 0); |
4025 CacheStackTraces(stack_trace, CollectAsyncCausalStackTrace(), | 3848 CacheStackTraces(stack_trace, CollectAsyncCausalStackTrace(), |
4026 CollectAwaiterReturnStackTrace()); | 3849 CollectAwaiterReturnStackTrace()); |
4027 // TODO(johnmccutchan): Send |msg| to Observatory. | 3850 // TODO(johnmccutchan): Send |msg| to Observatory. |
4028 | 3851 |
4029 // We are in the native call to Developer_debugger. the developer | 3852 // We are in the native call to Developer_debugger. the developer |
4030 // gets a better experience by not seeing this call. To accomplish | 3853 // gets a better experience by not seeing this call. To accomplish |
4031 // this, we continue execution until the call exits (step out). | 3854 // this, we continue execution until the call exits (step out). |
4032 SetResumeAction(kStepOut); | 3855 SetResumeAction(kStepOut); |
4033 HandleSteppingRequest(stack_trace_); | 3856 HandleSteppingRequest(stack_trace_); |
4034 ClearCachedStackTraces(); | 3857 ClearCachedStackTraces(); |
4035 } | 3858 } |
4036 | 3859 |
4037 | |
4038 void Debugger::Initialize(Isolate* isolate) { | 3860 void Debugger::Initialize(Isolate* isolate) { |
4039 if (initialized_) { | 3861 if (initialized_) { |
4040 return; | 3862 return; |
4041 } | 3863 } |
4042 isolate_ = isolate; | 3864 isolate_ = isolate; |
4043 | 3865 |
4044 // Use the isolate's control port as the isolate_id for debugging. | 3866 // Use the isolate's control port as the isolate_id for debugging. |
4045 // This port will be used as a unique ID to represent the isolate in | 3867 // This port will be used as a unique ID to represent the isolate in |
4046 // the debugger embedder api. | 3868 // the debugger embedder api. |
4047 isolate_id_ = isolate_->main_port(); | 3869 isolate_id_ = isolate_->main_port(); |
4048 initialized_ = true; | 3870 initialized_ = true; |
4049 } | 3871 } |
4050 | 3872 |
4051 | |
4052 void Debugger::NotifyIsolateCreated() { | 3873 void Debugger::NotifyIsolateCreated() { |
4053 if (NeedsIsolateEvents()) { | 3874 if (NeedsIsolateEvents()) { |
4054 ServiceEvent event(isolate_, ServiceEvent::kIsolateStart); | 3875 ServiceEvent event(isolate_, ServiceEvent::kIsolateStart); |
4055 InvokeEventHandler(&event); | 3876 InvokeEventHandler(&event); |
4056 } | 3877 } |
4057 } | 3878 } |
4058 | 3879 |
4059 | |
4060 // Return innermost closure contained in 'function' that contains | 3880 // Return innermost closure contained in 'function' that contains |
4061 // the given token position. | 3881 // the given token position. |
4062 RawFunction* Debugger::FindInnermostClosure(const Function& function, | 3882 RawFunction* Debugger::FindInnermostClosure(const Function& function, |
4063 TokenPosition token_pos) { | 3883 TokenPosition token_pos) { |
4064 Zone* zone = Thread::Current()->zone(); | 3884 Zone* zone = Thread::Current()->zone(); |
4065 const Script& outer_origin = Script::Handle(zone, function.script()); | 3885 const Script& outer_origin = Script::Handle(zone, function.script()); |
4066 const GrowableObjectArray& closures = GrowableObjectArray::Handle( | 3886 const GrowableObjectArray& closures = GrowableObjectArray::Handle( |
4067 zone, Isolate::Current()->object_store()->closure_functions()); | 3887 zone, Isolate::Current()->object_store()->closure_functions()); |
4068 const intptr_t num_closures = closures.Length(); | 3888 const intptr_t num_closures = closures.Length(); |
4069 Function& closure = Function::Handle(zone); | 3889 Function& closure = Function::Handle(zone); |
4070 Function& best_fit = Function::Handle(zone); | 3890 Function& best_fit = Function::Handle(zone); |
4071 for (intptr_t i = 0; i < num_closures; i++) { | 3891 for (intptr_t i = 0; i < num_closures; i++) { |
4072 closure ^= closures.At(i); | 3892 closure ^= closures.At(i); |
4073 if ((function.token_pos() < closure.token_pos()) && | 3893 if ((function.token_pos() < closure.token_pos()) && |
4074 (closure.end_token_pos() < function.end_token_pos()) && | 3894 (closure.end_token_pos() < function.end_token_pos()) && |
4075 (closure.token_pos() <= token_pos) && | 3895 (closure.token_pos() <= token_pos) && |
4076 (token_pos <= closure.end_token_pos()) && | 3896 (token_pos <= closure.end_token_pos()) && |
4077 (closure.script() == outer_origin.raw())) { | 3897 (closure.script() == outer_origin.raw())) { |
4078 SelectBestFit(&best_fit, &closure); | 3898 SelectBestFit(&best_fit, &closure); |
4079 } | 3899 } |
4080 } | 3900 } |
4081 return best_fit.raw(); | 3901 return best_fit.raw(); |
4082 } | 3902 } |
4083 | 3903 |
4084 | |
4085 void Debugger::NotifyCompilation(const Function& func) { | 3904 void Debugger::NotifyCompilation(const Function& func) { |
4086 if (breakpoint_locations_ == NULL) { | 3905 if (breakpoint_locations_ == NULL) { |
4087 // Return with minimal overhead if there are no breakpoints. | 3906 // Return with minimal overhead if there are no breakpoints. |
4088 return; | 3907 return; |
4089 } | 3908 } |
4090 if (!func.is_debuggable()) { | 3909 if (!func.is_debuggable()) { |
4091 // Nothing to do if the function is not debuggable. If there is | 3910 // Nothing to do if the function is not debuggable. If there is |
4092 // a pending breakpoint in an inner function (that is debuggable), | 3911 // a pending breakpoint in an inner function (that is debuggable), |
4093 // we'll resolve the breakpoint when the inner function is compiled. | 3912 // we'll resolve the breakpoint when the inner function is compiled. |
4094 return; | 3913 return; |
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4167 func.IsClosureFunction() ? "closure" : "function", | 3986 func.IsClosureFunction() ? "closure" : "function", |
4168 String::Handle(func.name()).ToCString()); | 3987 String::Handle(func.name()).ToCString()); |
4169 bpt = bpt->next(); | 3988 bpt = bpt->next(); |
4170 } | 3989 } |
4171 } | 3990 } |
4172 MakeCodeBreakpointAt(func, loc); | 3991 MakeCodeBreakpointAt(func, loc); |
4173 } | 3992 } |
4174 } | 3993 } |
4175 } | 3994 } |
4176 | 3995 |
4177 | |
4178 void Debugger::NotifyDoneLoading() { | 3996 void Debugger::NotifyDoneLoading() { |
4179 if (latent_locations_ == NULL) { | 3997 if (latent_locations_ == NULL) { |
4180 // Common, fast path. | 3998 // Common, fast path. |
4181 return; | 3999 return; |
4182 } | 4000 } |
4183 Zone* zone = Thread::Current()->zone(); | 4001 Zone* zone = Thread::Current()->zone(); |
4184 Library& lib = Library::Handle(zone); | 4002 Library& lib = Library::Handle(zone); |
4185 Script& script = Script::Handle(zone); | 4003 Script& script = Script::Handle(zone); |
4186 String& url = String::Handle(zone); | 4004 String& url = String::Handle(zone); |
4187 BreakpointLocation* loc = latent_locations_; | 4005 BreakpointLocation* loc = latent_locations_; |
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4283 "%" Pd " with url '%s'\n", | 4101 "%" Pd " with url '%s'\n", |
4284 bpt->id(), url.ToCString()); | 4102 bpt->id(), url.ToCString()); |
4285 bpt = bpt->next(); | 4103 bpt = bpt->next(); |
4286 } | 4104 } |
4287 } | 4105 } |
4288 loc = loc->next(); | 4106 loc = loc->next(); |
4289 } | 4107 } |
4290 } | 4108 } |
4291 } | 4109 } |
4292 | 4110 |
4293 | |
4294 // TODO(hausner): Could potentially make this faster by checking | 4111 // TODO(hausner): Could potentially make this faster by checking |
4295 // whether the call target at pc is a debugger stub. | 4112 // whether the call target at pc is a debugger stub. |
4296 bool Debugger::HasActiveBreakpoint(uword pc) { | 4113 bool Debugger::HasActiveBreakpoint(uword pc) { |
4297 CodeBreakpoint* bpt = GetCodeBreakpoint(pc); | 4114 CodeBreakpoint* bpt = GetCodeBreakpoint(pc); |
4298 return (bpt != NULL) && (bpt->IsEnabled()); | 4115 return (bpt != NULL) && (bpt->IsEnabled()); |
4299 } | 4116 } |
4300 | 4117 |
4301 | |
4302 CodeBreakpoint* Debugger::GetCodeBreakpoint(uword breakpoint_address) { | 4118 CodeBreakpoint* Debugger::GetCodeBreakpoint(uword breakpoint_address) { |
4303 CodeBreakpoint* bpt = code_breakpoints_; | 4119 CodeBreakpoint* bpt = code_breakpoints_; |
4304 while (bpt != NULL) { | 4120 while (bpt != NULL) { |
4305 if (bpt->pc() == breakpoint_address) { | 4121 if (bpt->pc() == breakpoint_address) { |
4306 return bpt; | 4122 return bpt; |
4307 } | 4123 } |
4308 bpt = bpt->next(); | 4124 bpt = bpt->next(); |
4309 } | 4125 } |
4310 return NULL; | 4126 return NULL; |
4311 } | 4127 } |
4312 | 4128 |
4313 | |
4314 RawCode* Debugger::GetPatchedStubAddress(uword breakpoint_address) { | 4129 RawCode* Debugger::GetPatchedStubAddress(uword breakpoint_address) { |
4315 CodeBreakpoint* bpt = GetCodeBreakpoint(breakpoint_address); | 4130 CodeBreakpoint* bpt = GetCodeBreakpoint(breakpoint_address); |
4316 if (bpt != NULL) { | 4131 if (bpt != NULL) { |
4317 return bpt->OrigStubAddress(); | 4132 return bpt->OrigStubAddress(); |
4318 } | 4133 } |
4319 UNREACHABLE(); | 4134 UNREACHABLE(); |
4320 return Code::null(); | 4135 return Code::null(); |
4321 } | 4136 } |
4322 | 4137 |
4323 | |
4324 // Remove and delete the source breakpoint bpt and its associated | 4138 // Remove and delete the source breakpoint bpt and its associated |
4325 // code breakpoints. | 4139 // code breakpoints. |
4326 void Debugger::RemoveBreakpoint(intptr_t bp_id) { | 4140 void Debugger::RemoveBreakpoint(intptr_t bp_id) { |
4327 if (RemoveBreakpointFromTheList(bp_id, &breakpoint_locations_)) { | 4141 if (RemoveBreakpointFromTheList(bp_id, &breakpoint_locations_)) { |
4328 return; | 4142 return; |
4329 } | 4143 } |
4330 RemoveBreakpointFromTheList(bp_id, &latent_locations_); | 4144 RemoveBreakpointFromTheList(bp_id, &latent_locations_); |
4331 } | 4145 } |
4332 | 4146 |
4333 | |
4334 // Remove and delete the source breakpoint bpt and its associated | 4147 // Remove and delete the source breakpoint bpt and its associated |
4335 // code breakpoints. Returns true, if breakpoint was found and removed, | 4148 // code breakpoints. Returns true, if breakpoint was found and removed, |
4336 // returns false, if breakpoint was not found. | 4149 // returns false, if breakpoint was not found. |
4337 bool Debugger::RemoveBreakpointFromTheList(intptr_t bp_id, | 4150 bool Debugger::RemoveBreakpointFromTheList(intptr_t bp_id, |
4338 BreakpointLocation** list) { | 4151 BreakpointLocation** list) { |
4339 BreakpointLocation* prev_loc = NULL; | 4152 BreakpointLocation* prev_loc = NULL; |
4340 BreakpointLocation* curr_loc = *list; | 4153 BreakpointLocation* curr_loc = *list; |
4341 while (curr_loc != NULL) { | 4154 while (curr_loc != NULL) { |
4342 Breakpoint* prev_bpt = NULL; | 4155 Breakpoint* prev_bpt = NULL; |
4343 Breakpoint* curr_bpt = curr_loc->breakpoints(); | 4156 Breakpoint* curr_bpt = curr_loc->breakpoints(); |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4393 prev_bpt = curr_bpt; | 4206 prev_bpt = curr_bpt; |
4394 curr_bpt = curr_bpt->next(); | 4207 curr_bpt = curr_bpt->next(); |
4395 } | 4208 } |
4396 prev_loc = curr_loc; | 4209 prev_loc = curr_loc; |
4397 curr_loc = curr_loc->next(); | 4210 curr_loc = curr_loc->next(); |
4398 } | 4211 } |
4399 // breakpoint with bp_id does not exist, nothing to do. | 4212 // breakpoint with bp_id does not exist, nothing to do. |
4400 return false; | 4213 return false; |
4401 } | 4214 } |
4402 | 4215 |
4403 | |
4404 // Unlink code breakpoints from the given breakpoint location. | 4216 // Unlink code breakpoints from the given breakpoint location. |
4405 // They will later be deleted when control returns from the pause event | 4217 // They will later be deleted when control returns from the pause event |
4406 // callback. Also, disable the breakpoint so it no longer fires if it | 4218 // callback. Also, disable the breakpoint so it no longer fires if it |
4407 // should be hit before it gets deleted. | 4219 // should be hit before it gets deleted. |
4408 void Debugger::UnlinkCodeBreakpoints(BreakpointLocation* bpt_location) { | 4220 void Debugger::UnlinkCodeBreakpoints(BreakpointLocation* bpt_location) { |
4409 ASSERT(bpt_location != NULL); | 4221 ASSERT(bpt_location != NULL); |
4410 CodeBreakpoint* curr_bpt = code_breakpoints_; | 4222 CodeBreakpoint* curr_bpt = code_breakpoints_; |
4411 while (curr_bpt != NULL) { | 4223 while (curr_bpt != NULL) { |
4412 if (curr_bpt->bpt_location() == bpt_location) { | 4224 if (curr_bpt->bpt_location() == bpt_location) { |
4413 curr_bpt->Disable(); | 4225 curr_bpt->Disable(); |
4414 curr_bpt->set_bpt_location(NULL); | 4226 curr_bpt->set_bpt_location(NULL); |
4415 needs_breakpoint_cleanup_ = true; | 4227 needs_breakpoint_cleanup_ = true; |
4416 } | 4228 } |
4417 curr_bpt = curr_bpt->next(); | 4229 curr_bpt = curr_bpt->next(); |
4418 } | 4230 } |
4419 } | 4231 } |
4420 | 4232 |
4421 | |
4422 // Remove and delete unlinked code breakpoints, i.e. breakpoints that | 4233 // Remove and delete unlinked code breakpoints, i.e. breakpoints that |
4423 // are not associated with a breakpoint location. | 4234 // are not associated with a breakpoint location. |
4424 void Debugger::RemoveUnlinkedCodeBreakpoints() { | 4235 void Debugger::RemoveUnlinkedCodeBreakpoints() { |
4425 CodeBreakpoint* prev_bpt = NULL; | 4236 CodeBreakpoint* prev_bpt = NULL; |
4426 CodeBreakpoint* curr_bpt = code_breakpoints_; | 4237 CodeBreakpoint* curr_bpt = code_breakpoints_; |
4427 while (curr_bpt != NULL) { | 4238 while (curr_bpt != NULL) { |
4428 if (curr_bpt->bpt_location() == NULL) { | 4239 if (curr_bpt->bpt_location() == NULL) { |
4429 if (prev_bpt == NULL) { | 4240 if (prev_bpt == NULL) { |
4430 code_breakpoints_ = code_breakpoints_->next(); | 4241 code_breakpoints_ = code_breakpoints_->next(); |
4431 } else { | 4242 } else { |
4432 prev_bpt->set_next(curr_bpt->next()); | 4243 prev_bpt->set_next(curr_bpt->next()); |
4433 } | 4244 } |
4434 CodeBreakpoint* temp_bpt = curr_bpt; | 4245 CodeBreakpoint* temp_bpt = curr_bpt; |
4435 curr_bpt = curr_bpt->next(); | 4246 curr_bpt = curr_bpt->next(); |
4436 temp_bpt->Disable(); | 4247 temp_bpt->Disable(); |
4437 delete temp_bpt; | 4248 delete temp_bpt; |
4438 } else { | 4249 } else { |
4439 prev_bpt = curr_bpt; | 4250 prev_bpt = curr_bpt; |
4440 curr_bpt = curr_bpt->next(); | 4251 curr_bpt = curr_bpt->next(); |
4441 } | 4252 } |
4442 } | 4253 } |
4443 needs_breakpoint_cleanup_ = false; | 4254 needs_breakpoint_cleanup_ = false; |
4444 } | 4255 } |
4445 | 4256 |
4446 | |
4447 BreakpointLocation* Debugger::GetBreakpointLocation(const Script& script, | 4257 BreakpointLocation* Debugger::GetBreakpointLocation(const Script& script, |
4448 TokenPosition token_pos, | 4258 TokenPosition token_pos, |
4449 intptr_t requested_column) { | 4259 intptr_t requested_column) { |
4450 BreakpointLocation* bpt = breakpoint_locations_; | 4260 BreakpointLocation* bpt = breakpoint_locations_; |
4451 while (bpt != NULL) { | 4261 while (bpt != NULL) { |
4452 if ((bpt->script_ == script.raw()) && (bpt->token_pos_ == token_pos) && | 4262 if ((bpt->script_ == script.raw()) && (bpt->token_pos_ == token_pos) && |
4453 (bpt->requested_column_number_ == requested_column)) { | 4263 (bpt->requested_column_number_ == requested_column)) { |
4454 return bpt; | 4264 return bpt; |
4455 } | 4265 } |
4456 bpt = bpt->next(); | 4266 bpt = bpt->next(); |
4457 } | 4267 } |
4458 return NULL; | 4268 return NULL; |
4459 } | 4269 } |
4460 | 4270 |
4461 | |
4462 Breakpoint* Debugger::GetBreakpointById(intptr_t id) { | 4271 Breakpoint* Debugger::GetBreakpointById(intptr_t id) { |
4463 Breakpoint* bpt = GetBreakpointByIdInTheList(id, breakpoint_locations_); | 4272 Breakpoint* bpt = GetBreakpointByIdInTheList(id, breakpoint_locations_); |
4464 if (bpt != NULL) { | 4273 if (bpt != NULL) { |
4465 return bpt; | 4274 return bpt; |
4466 } | 4275 } |
4467 return GetBreakpointByIdInTheList(id, latent_locations_); | 4276 return GetBreakpointByIdInTheList(id, latent_locations_); |
4468 } | 4277 } |
4469 | 4278 |
4470 | |
4471 Breakpoint* Debugger::GetBreakpointByIdInTheList(intptr_t id, | 4279 Breakpoint* Debugger::GetBreakpointByIdInTheList(intptr_t id, |
4472 BreakpointLocation* list) { | 4280 BreakpointLocation* list) { |
4473 BreakpointLocation* loc = list; | 4281 BreakpointLocation* loc = list; |
4474 while (loc != NULL) { | 4282 while (loc != NULL) { |
4475 Breakpoint* bpt = loc->breakpoints(); | 4283 Breakpoint* bpt = loc->breakpoints(); |
4476 while (bpt != NULL) { | 4284 while (bpt != NULL) { |
4477 if (bpt->id() == id) { | 4285 if (bpt->id() == id) { |
4478 return bpt; | 4286 return bpt; |
4479 } | 4287 } |
4480 bpt = bpt->next(); | 4288 bpt = bpt->next(); |
4481 } | 4289 } |
4482 loc = loc->next(); | 4290 loc = loc->next(); |
4483 } | 4291 } |
4484 return NULL; | 4292 return NULL; |
4485 } | 4293 } |
4486 | 4294 |
4487 | |
4488 void Debugger::MaybeAsyncStepInto(const Closure& async_op) { | 4295 void Debugger::MaybeAsyncStepInto(const Closure& async_op) { |
4489 if (FLAG_async_debugger && IsSingleStepping()) { | 4296 if (FLAG_async_debugger && IsSingleStepping()) { |
4490 // We are single stepping, set a breakpoint on the closure activation | 4297 // We are single stepping, set a breakpoint on the closure activation |
4491 // and resume execution so we can hit the breakpoint. | 4298 // and resume execution so we can hit the breakpoint. |
4492 AsyncStepInto(async_op); | 4299 AsyncStepInto(async_op); |
4493 } | 4300 } |
4494 } | 4301 } |
4495 | 4302 |
4496 | |
4497 void Debugger::AsyncStepInto(const Closure& async_op) { | 4303 void Debugger::AsyncStepInto(const Closure& async_op) { |
4498 SetBreakpointAtActivation(async_op, true); | 4304 SetBreakpointAtActivation(async_op, true); |
4499 Continue(); | 4305 Continue(); |
4500 } | 4306 } |
4501 | 4307 |
4502 | |
4503 void Debugger::Continue() { | 4308 void Debugger::Continue() { |
4504 SetResumeAction(kContinue); | 4309 SetResumeAction(kContinue); |
4505 stepping_fp_ = 0; | 4310 stepping_fp_ = 0; |
4506 async_stepping_fp_ = 0; | 4311 async_stepping_fp_ = 0; |
4507 isolate_->set_single_step(false); | 4312 isolate_->set_single_step(false); |
4508 } | 4313 } |
4509 | 4314 |
4510 | |
4511 BreakpointLocation* Debugger::GetLatentBreakpoint(const String& url, | 4315 BreakpointLocation* Debugger::GetLatentBreakpoint(const String& url, |
4512 intptr_t line, | 4316 intptr_t line, |
4513 intptr_t column) { | 4317 intptr_t column) { |
4514 BreakpointLocation* bpt = latent_locations_; | 4318 BreakpointLocation* bpt = latent_locations_; |
4515 String& bpt_url = String::Handle(); | 4319 String& bpt_url = String::Handle(); |
4516 while (bpt != NULL) { | 4320 while (bpt != NULL) { |
4517 bpt_url = bpt->url(); | 4321 bpt_url = bpt->url(); |
4518 if (bpt_url.Equals(url) && (bpt->requested_line_number() == line) && | 4322 if (bpt_url.Equals(url) && (bpt->requested_line_number() == line) && |
4519 (bpt->requested_column_number() == column)) { | 4323 (bpt->requested_column_number() == column)) { |
4520 return bpt; | 4324 return bpt; |
4521 } | 4325 } |
4522 bpt = bpt->next(); | 4326 bpt = bpt->next(); |
4523 } | 4327 } |
4524 // No breakpoint for this location requested. Allocate new one. | 4328 // No breakpoint for this location requested. Allocate new one. |
4525 bpt = new BreakpointLocation(url, line, column); | 4329 bpt = new BreakpointLocation(url, line, column); |
4526 bpt->set_next(latent_locations_); | 4330 bpt->set_next(latent_locations_); |
4527 latent_locations_ = bpt; | 4331 latent_locations_ = bpt; |
4528 return bpt; | 4332 return bpt; |
4529 } | 4333 } |
4530 | 4334 |
4531 | |
4532 void Debugger::RegisterBreakpointLocation(BreakpointLocation* bpt) { | 4335 void Debugger::RegisterBreakpointLocation(BreakpointLocation* bpt) { |
4533 ASSERT(bpt->next() == NULL); | 4336 ASSERT(bpt->next() == NULL); |
4534 bpt->set_next(breakpoint_locations_); | 4337 bpt->set_next(breakpoint_locations_); |
4535 breakpoint_locations_ = bpt; | 4338 breakpoint_locations_ = bpt; |
4536 } | 4339 } |
4537 | 4340 |
4538 | |
4539 void Debugger::RegisterCodeBreakpoint(CodeBreakpoint* bpt) { | 4341 void Debugger::RegisterCodeBreakpoint(CodeBreakpoint* bpt) { |
4540 ASSERT(bpt->next() == NULL); | 4342 ASSERT(bpt->next() == NULL); |
4541 bpt->set_next(code_breakpoints_); | 4343 bpt->set_next(code_breakpoints_); |
4542 code_breakpoints_ = bpt; | 4344 code_breakpoints_ = bpt; |
4543 } | 4345 } |
4544 | 4346 |
4545 #endif // !PRODUCT | 4347 #endif // !PRODUCT |
4546 | 4348 |
4547 } // namespace dart | 4349 } // namespace dart |
OLD | NEW |