| 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 "vm/code_generator.h" | 7 #include "vm/code_generator.h" |
| 8 #include "vm/code_patcher.h" | 8 #include "vm/code_patcher.h" |
| 9 #include "vm/compiler.h" | 9 #include "vm/compiler.h" |
| 10 #include "vm/dart_entry.h" | 10 #include "vm/dart_entry.h" |
| (...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 99 visitor->VisitPointer(reinterpret_cast<RawObject**>(&function_)); | 99 visitor->VisitPointer(reinterpret_cast<RawObject**>(&function_)); |
| 100 } | 100 } |
| 101 | 101 |
| 102 | 102 |
| 103 | 103 |
| 104 void CodeBreakpoint::VisitObjectPointers(ObjectPointerVisitor* visitor) { | 104 void CodeBreakpoint::VisitObjectPointers(ObjectPointerVisitor* visitor) { |
| 105 visitor->VisitPointer(reinterpret_cast<RawObject**>(&function_)); | 105 visitor->VisitPointer(reinterpret_cast<RawObject**>(&function_)); |
| 106 } | 106 } |
| 107 | 107 |
| 108 | 108 |
| 109 ActivationFrame::ActivationFrame(uword pc, uword fp, uword sp) | 109 ActivationFrame::ActivationFrame(uword pc, uword fp, uword sp, |
| 110 const Context& ctx) |
| 110 : pc_(pc), fp_(fp), sp_(sp), | 111 : pc_(pc), fp_(fp), sp_(sp), |
| 112 ctx_(Context::ZoneHandle(ctx.raw())), |
| 111 function_(Function::ZoneHandle()), | 113 function_(Function::ZoneHandle()), |
| 112 token_index_(-1), | 114 token_index_(-1), |
| 115 pc_desc_index_(-1), |
| 113 line_number_(-1), | 116 line_number_(-1), |
| 117 context_level_(-1), |
| 118 vars_initialized_(false), |
| 114 var_descriptors_(LocalVarDescriptors::ZoneHandle()), | 119 var_descriptors_(LocalVarDescriptors::ZoneHandle()), |
| 115 desc_indices_(8) { | 120 desc_indices_(8), |
| 121 pc_desc_(PcDescriptors::ZoneHandle()) { |
| 116 } | 122 } |
| 117 | 123 |
| 118 | 124 |
| 119 const Function& ActivationFrame::DartFunction() { | 125 const Function& ActivationFrame::DartFunction() { |
| 120 if (function_.IsNull()) { | 126 if (function_.IsNull()) { |
| 121 Isolate* isolate = Isolate::Current(); | 127 Isolate* isolate = Isolate::Current(); |
| 122 ASSERT(isolate != NULL); | 128 ASSERT(isolate != NULL); |
| 123 const Code& code = Code::Handle(Code::LookupCode(pc_)); | 129 const Code& code = Code::Handle(Code::LookupCode(pc_)); |
| 124 function_ = code.function(); | 130 function_ = code.function(); |
| 125 } | 131 } |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 160 } | 166 } |
| 161 | 167 |
| 162 | 168 |
| 163 RawScript* ActivationFrame::SourceScript() { | 169 RawScript* ActivationFrame::SourceScript() { |
| 164 const Function& func = DartFunction(); | 170 const Function& func = DartFunction(); |
| 165 const Class& cls = Class::Handle(func.owner()); | 171 const Class& cls = Class::Handle(func.owner()); |
| 166 return cls.script(); | 172 return cls.script(); |
| 167 } | 173 } |
| 168 | 174 |
| 169 | 175 |
| 170 intptr_t ActivationFrame::TokenIndex() { | 176 void ActivationFrame::GetPcDescriptors() { |
| 171 if (token_index_ < 0) { | 177 if (pc_desc_.IsNull()) { |
| 172 const Function& func = DartFunction(); | 178 const Function& func = DartFunction(); |
| 173 ASSERT(!func.HasOptimizedCode()); | 179 ASSERT(!func.HasOptimizedCode()); |
| 174 Code& code = Code::Handle(func.unoptimized_code()); | 180 Code& code = Code::Handle(func.unoptimized_code()); |
| 175 ASSERT(!code.IsNull()); | 181 ASSERT(!code.IsNull()); |
| 176 PcDescriptors& desc = PcDescriptors::Handle(code.pc_descriptors()); | 182 pc_desc_ = code.pc_descriptors(); |
| 177 for (int i = 0; i < desc.Length(); i++) { | 183 ASSERT(!pc_desc_.IsNull()); |
| 178 if (desc.PC(i) == pc_) { | 184 } |
| 179 token_index_ = desc.TokenIndex(i); | 185 } |
| 186 |
| 187 |
| 188 // Compute token_index_ and pc_desc_index_. |
| 189 intptr_t ActivationFrame::TokenIndex() { |
| 190 if (token_index_ < 0) { |
| 191 GetPcDescriptors(); |
| 192 for (int i = 0; i < pc_desc_.Length(); i++) { |
| 193 if (pc_desc_.PC(i) == pc_) { |
| 194 pc_desc_index_ = i; |
| 195 token_index_ = pc_desc_.TokenIndex(i); |
| 180 break; | 196 break; |
| 181 } | 197 } |
| 182 } | 198 } |
| 183 ASSERT(token_index_ >= 0); | 199 ASSERT(token_index_ >= 0); |
| 184 } | 200 } |
| 185 return token_index_; | 201 return token_index_; |
| 186 } | 202 } |
| 187 | 203 |
| 188 | 204 |
| 205 intptr_t ActivationFrame::PcDescIndex() { |
| 206 if (pc_desc_index_ < 0) { |
| 207 TokenIndex(); |
| 208 ASSERT(pc_desc_index_ >= 0); |
| 209 } |
| 210 return pc_desc_index_; |
| 211 } |
| 212 |
| 213 |
| 189 intptr_t ActivationFrame::LineNumber() { | 214 intptr_t ActivationFrame::LineNumber() { |
| 190 // Compute line number lazily since it causes scanning of the script. | 215 // Compute line number lazily since it causes scanning of the script. |
| 191 if (line_number_ < 0) { | 216 if (line_number_ < 0) { |
| 192 const Script& script = Script::Handle(SourceScript()); | 217 const Script& script = Script::Handle(SourceScript()); |
| 193 intptr_t ignore_column; | 218 intptr_t ignore_column; |
| 194 script.GetTokenLocation(TokenIndex(), &line_number_, &ignore_column); | 219 script.GetTokenLocation(TokenIndex(), &line_number_, &ignore_column); |
| 195 } | 220 } |
| 196 return line_number_; | 221 return line_number_; |
| 197 } | 222 } |
| 198 | 223 |
| 199 | 224 |
| 225 void ActivationFrame::GetVarDescriptors() { |
| 226 if (!var_descriptors_.IsNull()) { |
| 227 return; |
| 228 } |
| 229 ASSERT(!DartFunction().HasOptimizedCode()); |
| 230 const Code& code = Code::Handle(DartFunction().unoptimized_code()); |
| 231 var_descriptors_ = code.var_descriptors(); |
| 232 ASSERT(!var_descriptors_.IsNull()); |
| 233 } |
| 234 |
| 235 |
| 236 // Calculate the context level at the current token index of the frame. |
| 237 intptr_t ActivationFrame::ContextLevel() { |
| 238 if (context_level_ < 0) { |
| 239 context_level_ = 0; |
| 240 intptr_t pc_desc_idx = PcDescIndex(); |
| 241 ASSERT(!pc_desc_.IsNull()); |
| 242 if (pc_desc_.DescriptorKind(pc_desc_idx) == PcDescriptors::kReturn) { |
| 243 // Special case: the context chain has already been deallocated. |
| 244 // The context level is 0. |
| 245 return context_level_; |
| 246 } |
| 247 intptr_t innermost_begin_pos = 0; |
| 248 intptr_t activation_token_pos = TokenIndex(); |
| 249 GetVarDescriptors(); |
| 250 intptr_t var_desc_len = var_descriptors_.Length(); |
| 251 for (int cur_idx = 0; cur_idx < var_desc_len; cur_idx++) { |
| 252 RawLocalVarDescriptors::VarInfo var_info; |
| 253 var_descriptors_.GetInfo(cur_idx, &var_info); |
| 254 if ((var_info.kind == RawLocalVarDescriptors::kContextLevel) && |
| 255 (var_info.begin_pos <= activation_token_pos) && |
| 256 (activation_token_pos < var_info.end_pos)) { |
| 257 // This var_descriptors_ entry is a context scope which is in scope |
| 258 // of the current token position. Now check whether it is shadowing |
| 259 // the previous context scope. |
| 260 if (innermost_begin_pos < var_info.begin_pos) { |
| 261 innermost_begin_pos = var_info.begin_pos; |
| 262 context_level_ = var_info.index; |
| 263 } |
| 264 } |
| 265 } |
| 266 ASSERT(context_level_ >= 0); |
| 267 } |
| 268 return context_level_; |
| 269 } |
| 270 |
| 271 |
| 272 RawContext* ActivationFrame::CallerContext() { |
| 273 GetVarDescriptors(); |
| 274 intptr_t var_desc_len = var_descriptors_.Length(); |
| 275 for (int i = 0; i < var_desc_len; i++) { |
| 276 RawLocalVarDescriptors::VarInfo var_info; |
| 277 var_descriptors_.GetInfo(i, &var_info); |
| 278 if (var_info.kind == RawLocalVarDescriptors::kContextChain) { |
| 279 return reinterpret_cast<RawContext*>(GetLocalVarValue(var_info.index)); |
| 280 } |
| 281 } |
| 282 // Caller uses same context chain. |
| 283 return ctx_.raw(); |
| 284 } |
| 285 |
| 286 |
| 200 void ActivationFrame::GetDescIndices() { | 287 void ActivationFrame::GetDescIndices() { |
| 201 if (var_descriptors_.IsNull()) { | 288 if (vars_initialized_) { |
| 202 ASSERT(!DartFunction().HasOptimizedCode()); | 289 return; |
| 203 const Code& code = Code::Handle(DartFunction().unoptimized_code()); | 290 } |
| 204 var_descriptors_ = code.var_descriptors(); | 291 GetVarDescriptors(); |
| 205 // TODO(Hausner): Consider replacing this GrowableArray. | 292 // TODO(hausner): Consider replacing this GrowableArray. |
| 206 GrowableArray<String*> var_names(8); | 293 GrowableArray<String*> var_names(8); |
| 207 intptr_t activation_token_pos = TokenIndex(); | 294 intptr_t activation_token_pos = TokenIndex(); |
| 208 intptr_t var_desc_len = var_descriptors_.Length(); | 295 intptr_t var_desc_len = var_descriptors_.Length(); |
| 209 for (int cur_idx = 0; cur_idx < var_desc_len; cur_idx++) { | 296 for (int cur_idx = 0; cur_idx < var_desc_len; cur_idx++) { |
| 210 ASSERT(var_names.length() == desc_indices_.length()); | 297 ASSERT(var_names.length() == desc_indices_.length()); |
| 211 intptr_t scope_id, begin_pos, end_pos; | 298 RawLocalVarDescriptors::VarInfo var_info; |
| 212 var_descriptors_.GetScopeInfo(cur_idx, &scope_id, &begin_pos, &end_pos); | 299 var_descriptors_.GetInfo(cur_idx, &var_info); |
| 213 if ((begin_pos <= activation_token_pos) && | 300 if ((var_info.kind != RawLocalVarDescriptors::kStackVar) && |
| 214 (activation_token_pos <= end_pos)) { | 301 (var_info.kind != RawLocalVarDescriptors::kContextVar)) { |
| 215 // The current variable is textually in scope. Now check whether | 302 continue; |
| 216 // there is another local variable with the same name that shadows | 303 } |
| 217 // or is shadowed by this variable. | 304 if ((var_info.begin_pos <= activation_token_pos) && |
| 218 String& var_name = String::Handle(var_descriptors_.GetName(cur_idx)); | 305 (activation_token_pos <= var_info.end_pos)) { |
| 219 intptr_t indices_len = desc_indices_.length(); | 306 if ((var_info.kind == RawLocalVarDescriptors::kContextVar) && |
| 220 bool name_match_found = false; | 307 (ContextLevel() < var_info.scope_id)) { |
| 221 for (int i = 0; i < indices_len; i++) { | 308 // The variable is textually in scope but the context level |
| 222 if (var_name.Equals(*var_names[i])) { | 309 // at the activation frame's PC is lower than the context |
| 223 // Found two local variables with the same name. Now determine | 310 // level of the variable. The context containing the variable |
| 224 // which one is shadowed. | 311 // has already been removed from the chain. This can happen when we |
| 225 name_match_found = true; | 312 // break at a return statement, since the contexts get discarded |
| 226 intptr_t i_begin_pos, ignore; | 313 // before the debugger gets called. |
| 227 var_descriptors_.GetScopeInfo( | 314 continue; |
| 228 desc_indices_[i], &ignore, &i_begin_pos, &ignore); | 315 } |
| 229 if (i_begin_pos < begin_pos) { | 316 // The current variable is textually in scope. Now check whether |
| 230 // The variable we found earlier is in an outer scope | 317 // there is another local variable with the same name that shadows |
| 231 // and is shadowed by the current variable. Replace the | 318 // or is shadowed by this variable. |
| 232 // descriptor index of the previously found variable | 319 String& var_name = String::Handle(var_descriptors_.GetName(cur_idx)); |
| 233 // with the descriptor index of the current variable. | 320 intptr_t indices_len = desc_indices_.length(); |
| 234 desc_indices_[i] = cur_idx; | 321 bool name_match_found = false; |
| 235 } else { | 322 for (int i = 0; i < indices_len; i++) { |
| 236 // The variable we found earlier is in an inner scope | 323 if (var_name.Equals(*var_names[i])) { |
| 237 // and shadows the current variable. Skip the current | 324 // Found two local variables with the same name. Now determine |
| 238 // variable. (Nothing to do.) | 325 // which one is shadowed. |
| 239 } | 326 name_match_found = true; |
| 240 break; // Stop looking for name matches. | 327 RawLocalVarDescriptors::VarInfo i_var_info; |
| 328 var_descriptors_.GetInfo(desc_indices_[i], &i_var_info); |
| 329 if (i_var_info.begin_pos < var_info.begin_pos) { |
| 330 // The variable we found earlier is in an outer scope |
| 331 // and is shadowed by the current variable. Replace the |
| 332 // descriptor index of the previously found variable |
| 333 // with the descriptor index of the current variable. |
| 334 desc_indices_[i] = cur_idx; |
| 335 } else { |
| 336 // The variable we found earlier is in an inner scope |
| 337 // and shadows the current variable. Skip the current |
| 338 // variable. (Nothing to do.) |
| 241 } | 339 } |
| 340 break; // Stop looking for name matches. |
| 242 } | 341 } |
| 243 if (!name_match_found) { | 342 } |
| 244 // No duplicate name found. Add the current descriptor index to the | 343 if (!name_match_found) { |
| 245 // list of visible variables. | 344 // No duplicate name found. Add the current descriptor index to the |
| 246 desc_indices_.Add(cur_idx); | 345 // list of visible variables. |
| 247 var_names.Add(&var_name); | 346 desc_indices_.Add(cur_idx); |
| 248 } | 347 var_names.Add(&var_name); |
| 249 } | 348 } |
| 250 } | 349 } |
| 251 } | 350 } |
| 351 vars_initialized_ = true; |
| 252 } | 352 } |
| 253 | 353 |
| 254 | 354 |
| 255 intptr_t ActivationFrame::NumLocalVariables() { | 355 intptr_t ActivationFrame::NumLocalVariables() { |
| 256 GetDescIndices(); | 356 GetDescIndices(); |
| 257 return desc_indices_.length(); | 357 return desc_indices_.length(); |
| 258 } | 358 } |
| 259 | 359 |
| 260 | 360 |
| 261 void ActivationFrame::VariableAt(intptr_t i, | 361 void ActivationFrame::VariableAt(intptr_t i, |
| 262 String* name, | 362 String* name, |
| 263 intptr_t* token_pos, | 363 intptr_t* token_pos, |
| 264 intptr_t* end_pos, | 364 intptr_t* end_pos, |
| 265 Instance* value) { | 365 Instance* value) { |
| 266 GetDescIndices(); | 366 GetDescIndices(); |
| 267 ASSERT(i < desc_indices_.length()); | 367 ASSERT(i < desc_indices_.length()); |
| 368 intptr_t desc_index = desc_indices_[i]; |
| 268 ASSERT(name != NULL); | 369 ASSERT(name != NULL); |
| 269 intptr_t desc_index = desc_indices_[i]; | |
| 270 *name ^= var_descriptors_.GetName(desc_index); | 370 *name ^= var_descriptors_.GetName(desc_index); |
| 271 intptr_t scope_id; | 371 RawLocalVarDescriptors::VarInfo var_info; |
| 272 var_descriptors_.GetScopeInfo(desc_index, &scope_id, token_pos, end_pos); | 372 var_descriptors_.GetInfo(desc_index, &var_info); |
| 373 ASSERT(token_pos != NULL); |
| 374 *token_pos = var_info.begin_pos; |
| 375 ASSERT(end_pos != NULL); |
| 376 *end_pos = var_info.end_pos; |
| 273 ASSERT(value != NULL); | 377 ASSERT(value != NULL); |
| 274 *value = GetLocalVarValue(var_descriptors_.GetSlotIndex(desc_index)); | 378 if (var_info.kind == RawLocalVarDescriptors::kStackVar) { |
| 379 *value = GetLocalVarValue(var_info.index); |
| 380 } else { |
| 381 ASSERT(var_info.kind == RawLocalVarDescriptors::kContextVar); |
| 382 ASSERT(!ctx_.IsNull()); |
| 383 // The context level at the PC/token index of this activation frame. |
| 384 intptr_t frame_ctx_level = ContextLevel(); |
| 385 // The context level of the variable. |
| 386 intptr_t var_ctx_level = var_info.scope_id; |
| 387 intptr_t level_diff = frame_ctx_level - var_ctx_level; |
| 388 intptr_t ctx_slot = var_info.index; |
| 389 if (level_diff == 0) { |
| 390 *value = ctx_.At(ctx_slot); |
| 391 } else { |
| 392 ASSERT(level_diff > 0); |
| 393 Context& ctx = Context::Handle(ctx_.raw()); |
| 394 while (level_diff > 0) { |
| 395 ASSERT(!ctx.IsNull()); |
| 396 level_diff--; |
| 397 ctx = ctx.parent(); |
| 398 } |
| 399 ASSERT(!ctx.IsNull()); |
| 400 *value = ctx.At(ctx_slot); |
| 401 } |
| 402 } |
| 275 } | 403 } |
| 276 | 404 |
| 277 | 405 |
| 278 RawArray* ActivationFrame::GetLocalVariables() { | 406 RawArray* ActivationFrame::GetLocalVariables() { |
| 279 GetDescIndices(); | 407 GetDescIndices(); |
| 280 intptr_t num_variables = desc_indices_.length(); | 408 intptr_t num_variables = desc_indices_.length(); |
| 281 String& var_name = String::Handle(); | 409 String& var_name = String::Handle(); |
| 282 Instance& value = Instance::Handle(); | 410 Instance& value = Instance::Handle(); |
| 283 const Array& list = Array::Handle(Array::New(2 * num_variables)); | 411 const Array& list = Array::Handle(Array::New(2 * num_variables)); |
| 284 for (int i = 0; i < num_variables; i++) { | 412 for (int i = 0; i < num_variables; i++) { |
| 285 var_name = var_descriptors_.GetName(i); | 413 intptr_t ignore; |
| 414 VariableAt(i, &var_name, &ignore, &ignore, &value); |
| 286 list.SetAt(2 * i, var_name); | 415 list.SetAt(2 * i, var_name); |
| 287 value = GetLocalVarValue(var_descriptors_.GetSlotIndex(i)); | |
| 288 list.SetAt((2 * i) + 1, value); | 416 list.SetAt((2 * i) + 1, value); |
| 289 } | 417 } |
| 290 return list.raw(); | 418 return list.raw(); |
| 291 } | 419 } |
| 292 | 420 |
| 293 | 421 |
| 294 const char* ActivationFrame::ToCString() { | 422 const char* ActivationFrame::ToCString() { |
| 295 const char* kFormat = "Function: '%s' url: '%s' line: %d"; | 423 const char* kFormat = "Function: '%s' url: '%s' line: %d"; |
| 296 | 424 |
| 297 const Function& func = DartFunction(); | 425 const Function& func = DartFunction(); |
| (...skipping 304 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 602 DebuggerEvent event; | 730 DebuggerEvent event; |
| 603 event.type = kBreakpointResolved; | 731 event.type = kBreakpointResolved; |
| 604 event.breakpoint = bpt; | 732 event.breakpoint = bpt; |
| 605 (*event_handler_)(&event); | 733 (*event_handler_)(&event); |
| 606 } | 734 } |
| 607 } | 735 } |
| 608 | 736 |
| 609 | 737 |
| 610 DebuggerStackTrace* Debugger::CollectStackTrace() { | 738 DebuggerStackTrace* Debugger::CollectStackTrace() { |
| 611 DebuggerStackTrace* stack_trace = new DebuggerStackTrace(8); | 739 DebuggerStackTrace* stack_trace = new DebuggerStackTrace(8); |
| 740 Context& ctx = Context::Handle(Isolate::Current()->top_context()); |
| 612 DartFrameIterator iterator; | 741 DartFrameIterator iterator; |
| 613 StackFrame* frame = iterator.NextFrame(); | 742 StackFrame* frame = iterator.NextFrame(); |
| 614 while (frame != NULL) { | 743 while (frame != NULL) { |
| 615 ASSERT(frame->IsValid()); | 744 ASSERT(frame->IsValid()); |
| 616 ASSERT(frame->IsDartFrame()); | 745 ASSERT(frame->IsDartFrame()); |
| 617 ActivationFrame* activation = | 746 ActivationFrame* activation = |
| 618 new ActivationFrame(frame->pc(), frame->fp(), frame->sp()); | 747 new ActivationFrame(frame->pc(), frame->fp(), frame->sp(), ctx); |
| 748 ctx = activation->CallerContext(); |
| 619 stack_trace->AddActivation(activation); | 749 stack_trace->AddActivation(activation); |
| 620 frame = iterator.NextFrame(); | 750 frame = iterator.NextFrame(); |
| 621 } | 751 } |
| 622 return stack_trace; | 752 return stack_trace; |
| 623 } | 753 } |
| 624 | 754 |
| 625 | 755 |
| 626 void Debugger::SetExceptionPauseInfo(Dart_ExceptionPauseInfo pause_info) { | 756 void Debugger::SetExceptionPauseInfo(Dart_ExceptionPauseInfo pause_info) { |
| 627 exc_pause_info_ = pause_info; | 757 exc_pause_info_ = pause_info; |
| 628 } | 758 } |
| (...skipping 705 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1334 } | 1464 } |
| 1335 | 1465 |
| 1336 | 1466 |
| 1337 void Debugger::RegisterCodeBreakpoint(CodeBreakpoint* bpt) { | 1467 void Debugger::RegisterCodeBreakpoint(CodeBreakpoint* bpt) { |
| 1338 ASSERT(bpt->next() == NULL); | 1468 ASSERT(bpt->next() == NULL); |
| 1339 bpt->set_next(code_breakpoints_); | 1469 bpt->set_next(code_breakpoints_); |
| 1340 code_breakpoints_ = bpt; | 1470 code_breakpoints_ = bpt; |
| 1341 } | 1471 } |
| 1342 | 1472 |
| 1343 } // namespace dart | 1473 } // namespace dart |
| OLD | NEW |