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 |