| OLD | NEW |
| 1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2011, 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_index_table.h" | 7 #include "vm/code_index_table.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/flags.h" | 10 #include "vm/flags.h" |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 61 } | 61 } |
| 62 return this->line_number_; | 62 return this->line_number_; |
| 63 } | 63 } |
| 64 | 64 |
| 65 | 65 |
| 66 void Breakpoint::VisitObjectPointers(ObjectPointerVisitor* visitor) { | 66 void Breakpoint::VisitObjectPointers(ObjectPointerVisitor* visitor) { |
| 67 visitor->VisitPointer(reinterpret_cast<RawObject**>(&function_)); | 67 visitor->VisitPointer(reinterpret_cast<RawObject**>(&function_)); |
| 68 } | 68 } |
| 69 | 69 |
| 70 | 70 |
| 71 ActivationFrame::ActivationFrame(uword pc) | 71 ActivationFrame::ActivationFrame(uword pc, uword fp) |
| 72 : pc_(pc), | 72 : pc_(pc), fp_(fp), |
| 73 function_(NULL), | 73 function_(Function::ZoneHandle()), |
| 74 token_index_(-1), | 74 token_index_(-1), |
| 75 line_number_(-1), | 75 line_number_(-1), |
| 76 locals_(NULL) { | 76 var_descriptors_(NULL), |
| 77 desc_indices_(8) { |
| 77 } | 78 } |
| 78 | 79 |
| 79 | 80 |
| 80 Function* ActivationFrame::DartFunction() { | 81 const Function& ActivationFrame::DartFunction() { |
| 81 if (function_ == NULL) { | 82 if (function_.IsNull()) { |
| 82 ASSERT(Isolate::Current() != NULL); | 83 ASSERT(Isolate::Current() != NULL); |
| 83 CodeIndexTable* code_index_table = Isolate::Current()->code_index_table(); | 84 CodeIndexTable* code_index_table = Isolate::Current()->code_index_table(); |
| 84 ASSERT(code_index_table != NULL); | 85 ASSERT(code_index_table != NULL); |
| 85 function_ = &Function::ZoneHandle(code_index_table->LookupFunction(pc_)); | 86 function_ = code_index_table->LookupFunction(pc_); |
| 86 } | 87 } |
| 87 return function_; | 88 return function_; |
| 88 } | 89 } |
| 89 | 90 |
| 90 | 91 |
| 91 const char* Debugger::QualifiedFunctionName(const Function& func) { | 92 const char* Debugger::QualifiedFunctionName(const Function& func) { |
| 92 String& func_name = String::Handle(func.name()); | 93 const String& func_name = String::Handle(func.name()); |
| 93 Class& func_class = Class::Handle(func.owner()); | 94 Class& func_class = Class::Handle(func.owner()); |
| 94 String& class_name = String::Handle(func_class.Name()); | 95 String& class_name = String::Handle(func_class.Name()); |
| 95 | 96 |
| 96 const char* kFormat = "%s%s%s"; | 97 const char* kFormat = "%s%s%s"; |
| 97 intptr_t len = OS::SNPrint(NULL, 0, kFormat, | 98 intptr_t len = OS::SNPrint(NULL, 0, kFormat, |
| 98 func_class.IsTopLevel() ? "" : class_name.ToCString(), | 99 func_class.IsTopLevel() ? "" : class_name.ToCString(), |
| 99 func_class.IsTopLevel() ? "" : ".", | 100 func_class.IsTopLevel() ? "" : ".", |
| 100 func_name.ToCString()); | 101 func_name.ToCString()); |
| 101 len++; // String terminator. | 102 len++; // String terminator. |
| 102 char* chars = reinterpret_cast<char*>( | 103 char* chars = reinterpret_cast<char*>( |
| 103 Isolate::Current()->current_zone()->Allocate(len)); | 104 Isolate::Current()->current_zone()->Allocate(len)); |
| 104 OS::SNPrint(chars, len, kFormat, | 105 OS::SNPrint(chars, len, kFormat, |
| 105 func_class.IsTopLevel() ? "" : class_name.ToCString(), | 106 func_class.IsTopLevel() ? "" : class_name.ToCString(), |
| 106 func_class.IsTopLevel() ? "" : ".", | 107 func_class.IsTopLevel() ? "" : ".", |
| 107 func_name.ToCString()); | 108 func_name.ToCString()); |
| 108 return chars; | 109 return chars; |
| 109 } | 110 } |
| 110 | 111 |
| 111 | 112 |
| 112 RawString* ActivationFrame::QualifiedFunctionName() { | 113 RawString* ActivationFrame::QualifiedFunctionName() { |
| 113 Function& func = *DartFunction(); | 114 const Function& func = DartFunction(); |
| 114 return String::New(Debugger::QualifiedFunctionName(func)); | 115 return String::New(Debugger::QualifiedFunctionName(func)); |
| 115 } | 116 } |
| 116 | 117 |
| 117 | 118 |
| 118 RawString* ActivationFrame::SourceUrl() { | 119 RawString* ActivationFrame::SourceUrl() { |
| 119 const Script& script = Script::Handle(SourceScript()); | 120 const Script& script = Script::Handle(SourceScript()); |
| 120 return script.url(); | 121 return script.url(); |
| 121 } | 122 } |
| 122 | 123 |
| 123 | 124 |
| 124 RawScript* ActivationFrame::SourceScript() { | 125 RawScript* ActivationFrame::SourceScript() { |
| 125 const Function& func = *DartFunction(); | 126 const Function& func = DartFunction(); |
| 126 const Class& cls = Class::Handle(func.owner()); | 127 const Class& cls = Class::Handle(func.owner()); |
| 127 return cls.script(); | 128 return cls.script(); |
| 128 } | 129 } |
| 129 | 130 |
| 130 | 131 |
| 131 intptr_t ActivationFrame::TokenIndex() { | 132 intptr_t ActivationFrame::TokenIndex() { |
| 132 if (token_index_ < 0) { | 133 if (token_index_ < 0) { |
| 133 const Function& func = *DartFunction(); | 134 const Function& func = DartFunction(); |
| 134 Code& code = Code::Handle(func.code()); | 135 Code& code = Code::Handle(func.code()); |
| 135 ASSERT(!code.IsNull()); | 136 ASSERT(!code.IsNull()); |
| 136 PcDescriptors& desc = PcDescriptors::Handle(code.pc_descriptors()); | 137 PcDescriptors& desc = PcDescriptors::Handle(code.pc_descriptors()); |
| 137 for (int i = 0; i < desc.Length(); i++) { | 138 for (int i = 0; i < desc.Length(); i++) { |
| 138 if (desc.PC(i) == pc_) { | 139 if (desc.PC(i) == pc_) { |
| 139 token_index_ = desc.TokenIndex(i); | 140 token_index_ = desc.TokenIndex(i); |
| 140 break; | 141 break; |
| 141 } | 142 } |
| 142 } | 143 } |
| 143 ASSERT(token_index_ >= 0); | 144 ASSERT(token_index_ >= 0); |
| 144 } | 145 } |
| 145 return token_index_; | 146 return token_index_; |
| 146 } | 147 } |
| 147 | 148 |
| 148 | 149 |
| 149 intptr_t ActivationFrame::LineNumber() { | 150 intptr_t ActivationFrame::LineNumber() { |
| 150 // Compute line number lazily since it causes scanning of the script. | 151 // Compute line number lazily since it causes scanning of the script. |
| 151 if (line_number_ < 0) { | 152 if (line_number_ < 0) { |
| 152 const Script& script = Script::Handle(SourceScript()); | 153 const Script& script = Script::Handle(SourceScript()); |
| 153 intptr_t ignore_column; | 154 intptr_t ignore_column; |
| 154 script.GetTokenLocation(TokenIndex(), &line_number_, &ignore_column); | 155 script.GetTokenLocation(TokenIndex(), &line_number_, &ignore_column); |
| 155 } | 156 } |
| 156 return line_number_; | 157 return line_number_; |
| 157 } | 158 } |
| 158 | 159 |
| 159 | 160 |
| 160 ActiveVariables* ActivationFrame::LocalVariables() { | 161 void ActivationFrame::GetLocalVariables() { |
| 161 if (locals_ == NULL) { | 162 if (var_descriptors_ == NULL) { |
| 162 const Function& func = *DartFunction(); | 163 const Code& code = Code::Handle(DartFunction().code()); |
| 163 locals_ = new ActiveVariables(func, TokenIndex()); | 164 var_descriptors_ = |
| 165 &LocalVarDescriptors::ZoneHandle(code.var_descriptors()); |
| 166 intptr_t activation_token_pos = TokenIndex(); |
| 167 intptr_t desc_len = var_descriptors_->Length(); |
| 168 for (int i = 0; i < desc_len; i++) { |
| 169 intptr_t begin_pos, end_pos; |
| 170 var_descriptors_->GetRange(i, &begin_pos, &end_pos); |
| 171 if ((begin_pos <= activation_token_pos) && |
| 172 (activation_token_pos <= end_pos)) { |
| 173 desc_indices_.Add(i); |
| 174 } |
| 175 } |
| 164 } | 176 } |
| 165 return locals_; | 177 } |
| 178 |
| 179 |
| 180 intptr_t ActivationFrame::NumLocalVariables() { |
| 181 GetLocalVariables(); |
| 182 return desc_indices_.length(); |
| 183 } |
| 184 |
| 185 |
| 186 void ActivationFrame::VariableAt(intptr_t i, |
| 187 String* name, |
| 188 intptr_t* token_pos, |
| 189 intptr_t* end_pos, |
| 190 Instance* value) { |
| 191 GetLocalVariables(); |
| 192 ASSERT(i < desc_indices_.length()); |
| 193 ASSERT(name != NULL); |
| 194 intptr_t desc_index = desc_indices_[i]; |
| 195 *name ^= var_descriptors_->GetName(desc_index); |
| 196 var_descriptors_->GetRange(i, token_pos, end_pos); |
| 197 ASSERT(value != NULL); |
| 198 *value = GetLocalVarValue(var_descriptors_->GetSlotIndex(i)); |
| 166 } | 199 } |
| 167 | 200 |
| 168 | 201 |
| 169 RawInstance* ActivationFrame::Value(const String& variable_name) { | 202 RawInstance* ActivationFrame::Value(const String& variable_name) { |
| 170 UNIMPLEMENTED(); | 203 UNIMPLEMENTED(); |
| 171 return NULL; | 204 return NULL; |
| 172 } | 205 } |
| 173 | 206 |
| 174 | 207 |
| 175 const char* ActivationFrame::ToCString() { | 208 const char* ActivationFrame::ToCString() { |
| 176 const char* kFormat = "Function: '%s' url: '%s' line: %d"; | 209 const char* kFormat = "Function: '%s' url: '%s' line: %d"; |
| 177 | 210 |
| 178 Function& func = *DartFunction(); | 211 const Function& func = DartFunction(); |
| 179 String& url = String::Handle(SourceUrl()); | 212 const String& url = String::Handle(SourceUrl()); |
| 180 intptr_t line = LineNumber(); | 213 intptr_t line = LineNumber(); |
| 181 const char* func_name = Debugger::QualifiedFunctionName(func); | 214 const char* func_name = Debugger::QualifiedFunctionName(func); |
| 182 | 215 |
| 183 intptr_t len = | 216 intptr_t len = |
| 184 OS::SNPrint(NULL, 0, kFormat, func_name, url.ToCString(), line); | 217 OS::SNPrint(NULL, 0, kFormat, func_name, url.ToCString(), line); |
| 185 len++; // String terminator. | 218 len++; // String terminator. |
| 186 char* chars = reinterpret_cast<char*>( | 219 char* chars = reinterpret_cast<char*>( |
| 187 Isolate::Current()->current_zone()->Allocate(len)); | 220 Isolate::Current()->current_zone()->Allocate(len)); |
| 188 OS::SNPrint(chars, len, kFormat, func_name, url.ToCString(), line); | 221 OS::SNPrint(chars, len, kFormat, func_name, url.ToCString(), line); |
| 189 return chars; | 222 return chars; |
| 190 } | 223 } |
| 191 | 224 |
| 192 | 225 |
| 193 void StackTrace::AddActivation(ActivationFrame* frame) { | 226 void StackTrace::AddActivation(ActivationFrame* frame) { |
| 194 this->trace_.Add(frame); | 227 this->trace_.Add(frame); |
| 195 } | 228 } |
| 196 | 229 |
| 197 | 230 |
| 198 ActiveVariables::ActiveVariables(const Function& function, intptr_t token_pos) | |
| 199 : descriptors_(NULL), | |
| 200 desc_indices_(8) { | |
| 201 const Code& code = Code::Handle(function.code()); | |
| 202 LocalVarDescriptors& var_descs = | |
| 203 LocalVarDescriptors::ZoneHandle(code.var_descriptors()); | |
| 204 descriptors_ = &var_descs; | |
| 205 intptr_t desc_len = var_descs.Length(); | |
| 206 for (int i = 0; i < desc_len; i++) { | |
| 207 intptr_t begin_pos, end_pos; | |
| 208 var_descs.GetRange(i, &begin_pos, &end_pos); | |
| 209 if ((begin_pos <= token_pos) && (token_pos <= end_pos)) { | |
| 210 desc_indices_.Add(i); | |
| 211 } | |
| 212 } | |
| 213 } | |
| 214 | |
| 215 | |
| 216 void ActiveVariables::VariableAt(intptr_t i, | |
| 217 String* name, | |
| 218 intptr_t* token_pos, | |
| 219 intptr_t* end_pos, | |
| 220 Instance* value) const { | |
| 221 ASSERT(i < Length()); | |
| 222 ASSERT(name != NULL); | |
| 223 intptr_t desc_index = desc_indices_[i]; | |
| 224 *name ^= descriptors_->GetName(desc_index); | |
| 225 descriptors_->GetRange(i, token_pos, end_pos); | |
| 226 ASSERT(value != NULL); | |
| 227 *value = Instance::null(); // TODO(hausner): get actual variable value. | |
| 228 } | |
| 229 | |
| 230 | |
| 231 Debugger::Debugger() | 231 Debugger::Debugger() |
| 232 : initialized_(false), | 232 : initialized_(false), |
| 233 bp_handler_(NULL), | 233 bp_handler_(NULL), |
| 234 breakpoints_(NULL) { | 234 breakpoints_(NULL) { |
| 235 } | 235 } |
| 236 | 236 |
| 237 | 237 |
| 238 bool Debugger::IsActive() { | 238 bool Debugger::IsActive() { |
| 239 // TODO(hausner): The code generator uses this function to prevent | 239 // TODO(hausner): The code generator uses this function to prevent |
| 240 // generation of optimized code when Dart code is being debugged. | 240 // generation of optimized code when Dart code is being debugged. |
| (...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 326 } | 326 } |
| 327 | 327 |
| 328 | 328 |
| 329 static void DefaultBreakpointHandler(Breakpoint* bpt, StackTrace* stack) { | 329 static void DefaultBreakpointHandler(Breakpoint* bpt, StackTrace* stack) { |
| 330 String& var_name = String::Handle(); | 330 String& var_name = String::Handle(); |
| 331 Instance& value = Instance::Handle(); | 331 Instance& value = Instance::Handle(); |
| 332 for (intptr_t i = 0; i < stack->Length(); i++) { | 332 for (intptr_t i = 0; i < stack->Length(); i++) { |
| 333 ActivationFrame* frame = stack->ActivationFrameAt(i); | 333 ActivationFrame* frame = stack->ActivationFrameAt(i); |
| 334 OS::Print(" %d. %s\n", | 334 OS::Print(" %d. %s\n", |
| 335 i + 1, frame->ToCString()); | 335 i + 1, frame->ToCString()); |
| 336 ActiveVariables* locals = frame->LocalVariables(); | 336 intptr_t num_locals = frame->NumLocalVariables(); |
| 337 intptr_t num_locals = locals->Length(); | |
| 338 for (intptr_t i = 0; i < num_locals; i++) { | 337 for (intptr_t i = 0; i < num_locals; i++) { |
| 339 intptr_t token_pos, end_pos; | 338 intptr_t token_pos, end_pos; |
| 340 locals->VariableAt(i, &var_name, &token_pos, &end_pos, &value); | 339 frame->VariableAt(i, &var_name, &token_pos, &end_pos, &value); |
| 341 OS::Print(" var %s (pos %d) = %s\n", | 340 OS::Print(" var %s (pos %d) = %s\n", |
| 342 var_name.ToCString(), token_pos, value.ToCString()); | 341 var_name.ToCString(), token_pos, value.ToCString()); |
| 343 } | 342 } |
| 344 } | 343 } |
| 345 } | 344 } |
| 346 | 345 |
| 347 | 346 |
| 348 void Debugger::SetBreakpointHandler(BreakpointHandler* handler) { | 347 void Debugger::SetBreakpointHandler(BreakpointHandler* handler) { |
| 349 bp_handler_ = handler; | 348 bp_handler_ = handler; |
| 350 if (bp_handler_ == NULL) { | 349 if (bp_handler_ == NULL) { |
| (...skipping 12 matching lines...) Expand all Loading... |
| 363 if (verbose) { | 362 if (verbose) { |
| 364 OS::Print(">>> Breakpoint at %s:%d (Address %p)\n", | 363 OS::Print(">>> Breakpoint at %s:%d (Address %p)\n", |
| 365 bpt ? String::Handle(bpt->SourceUrl()).ToCString() : "?", | 364 bpt ? String::Handle(bpt->SourceUrl()).ToCString() : "?", |
| 366 bpt ? bpt->LineNumber() : 0, | 365 bpt ? bpt->LineNumber() : 0, |
| 367 frame->pc()); | 366 frame->pc()); |
| 368 } | 367 } |
| 369 StackTrace* stack_trace = new StackTrace(8); | 368 StackTrace* stack_trace = new StackTrace(8); |
| 370 while (frame != NULL) { | 369 while (frame != NULL) { |
| 371 ASSERT(frame->IsValid()); | 370 ASSERT(frame->IsValid()); |
| 372 ASSERT(frame->IsDartFrame()); | 371 ASSERT(frame->IsDartFrame()); |
| 373 ActivationFrame* activation = new ActivationFrame(frame->pc()); | 372 ActivationFrame* activation = |
| 373 new ActivationFrame(frame->pc(), frame->fp()); |
| 374 stack_trace->AddActivation(activation); | 374 stack_trace->AddActivation(activation); |
| 375 frame = iterator.NextFrame(); | 375 frame = iterator.NextFrame(); |
| 376 } | 376 } |
| 377 | 377 |
| 378 if (bp_handler_ != NULL) { | 378 if (bp_handler_ != NULL) { |
| 379 (*bp_handler_)(bpt, stack_trace); | 379 (*bp_handler_)(bpt, stack_trace); |
| 380 } | 380 } |
| 381 } | 381 } |
| 382 | 382 |
| 383 | 383 |
| (...skipping 19 matching lines...) Expand all Loading... |
| 403 | 403 |
| 404 | 404 |
| 405 void Debugger::AddBreakpoint(Breakpoint* bpt) { | 405 void Debugger::AddBreakpoint(Breakpoint* bpt) { |
| 406 ASSERT(bpt->next() == NULL); | 406 ASSERT(bpt->next() == NULL); |
| 407 bpt->set_next(this->breakpoints_); | 407 bpt->set_next(this->breakpoints_); |
| 408 this->breakpoints_ = bpt; | 408 this->breakpoints_ = bpt; |
| 409 } | 409 } |
| 410 | 410 |
| 411 | 411 |
| 412 } // namespace dart | 412 } // namespace dart |
| OLD | NEW |