Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(195)

Side by Side Diff: runtime/vm/debugger.cc

Issue 8775060: Debugger step 2 (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 9 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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_patcher.h" 8 #include "vm/code_patcher.h"
8 #include "vm/compiler.h" 9 #include "vm/compiler.h"
9 #include "vm/flags.h" 10 #include "vm/flags.h"
10 #include "vm/globals.h" 11 #include "vm/globals.h"
11 #include "vm/object.h" 12 #include "vm/object.h"
12 #include "vm/object_store.h" 13 #include "vm/object_store.h"
13 #include "vm/os.h" 14 #include "vm/os.h"
15 #include "vm/stack_frame.h"
14 #include "vm/stub_code.h" 16 #include "vm/stub_code.h"
15 #include "vm/visitor.h" 17 #include "vm/visitor.h"
16 18
17 19
18 namespace dart { 20 namespace dart {
19 21
20 DEFINE_FLAG(bool, debugger, false, "Debug breakpoint at main"); 22 DEFINE_FLAG(bool, debugger, false, "Debug breakpoint at main");
21 DEFINE_FLAG(charp, bpt, NULL, "Debug breakpoint at <func>"); 23 DEFINE_FLAG(charp, bpt, NULL, "Debug breakpoint at <func>");
22 24
23 25
24 class Breakpoint { 26
25 public: 27 Breakpoint::Breakpoint(const Function& func, intptr_t pc_desc_index)
26 Breakpoint(const Function& func, intptr_t pc_desc_index, uword pc) 28 : function_(func.raw()),
27 : function_(func.raw()), 29 pc_desc_index_(pc_desc_index),
28 pc_desc_index_(pc_desc_index), 30 token_index_(0),
29 pc_(pc), 31 pc_(0),
30 next_(NULL) { 32 line_number_(-1),
33 next_(NULL) {
34 Code& code = Code::Handle(func.code());
35 ASSERT(!code.IsNull()); // Function must be compiled.
36 PcDescriptors& desc = PcDescriptors::Handle(code.pc_descriptors());
37 ASSERT(pc_desc_index < desc.Length());
38 this->token_index_ = desc.TokenIndex(pc_desc_index);
39 ASSERT(this->token_index_ > 0);
40 this->pc_ = desc.PC(pc_desc_index);
41 ASSERT(this->token_index_ != 0);
siva 2011/12/05 19:21:44 Storing the pc_ and token_index_ in this structure
hausner 2011/12/05 21:11:23 I tried to cache some data so it would not have to
42 }
43
44
45 RawScript* Breakpoint::SourceCode() {
46 const Function& func = Function::Handle(this->function_);
47 const Class& cls = Class::Handle(func.owner());
48 return cls.script();
49 }
50
51
52 RawString* Breakpoint::SourceUrl() {
53 const Script& script = Script::Handle(this->SourceCode());
54 return script.url();
55 }
56
57
58 intptr_t Breakpoint::LineNumber() {
59 // Compute line number lazily since it causes scanning of the script.
60 if (this->line_number_ < 0) {
61 const Script& script = Script::Handle(this->SourceCode());
62 intptr_t ignore_column;
63 script.GetTokenLocation(this->token_index_,
64 &this->line_number_, &ignore_column);
31 } 65 }
66 return this->line_number_;
67 }
32 68
33 RawFunction* function() const { return function_; }
34 uword pc() const { return pc_; }
35 69
36 void set_next(Breakpoint* value) { next_ = value; } 70 void Breakpoint::VisitObjectPointers(ObjectPointerVisitor* visitor) {
37 Breakpoint* next() const { return this->next_; } 71 visitor->VisitPointer(reinterpret_cast<RawObject**>(&function_));
72 }
38 73
39 void VisitObjectPointers(ObjectPointerVisitor* visitor) { 74
40 visitor->VisitPointer(reinterpret_cast<RawObject**>(&function_)); 75 ActivationFrame::ActivationFrame(uword pc)
76 : pc_(pc),
77 function_(Function::null()),
78 token_index_(-1),
79 line_number_(-1) {
80 }
81
82
83 RawFunction* ActivationFrame::DartFunction() {
84 if (function_ == Function::null()) {
85 ASSERT(Isolate::Current() != NULL);
86 CodeIndexTable* code_index_table = Isolate::Current()->code_index_table();
87 ASSERT(code_index_table != NULL);
88 function_ = code_index_table->LookupFunction(pc_);
41 } 89 }
90 return function_;
91 }
42 92
43 private: 93
44 RawFunction* function_; 94 RawString* ActivationFrame::SourceUrl() {
45 intptr_t pc_desc_index_; 95 const Script& script = Script::Handle(SourceScript());
46 uword pc_; 96 return script.url();
47 Breakpoint* next_; 97 }
48 DISALLOW_COPY_AND_ASSIGN(Breakpoint); 98
49 }; 99
100 RawScript* ActivationFrame::SourceScript() {
101 const Function& func = Function::Handle(DartFunction());
102 const Class& cls = Class::Handle(func.owner());
103 return cls.script();
104 }
105
106
107 intptr_t ActivationFrame::TokenIndex() {
108 if (token_index_ < 0) {
109 const Function& func = Function::Handle(DartFunction());
110 Code& code = Code::Handle(func.code());
111 ASSERT(!code.IsNull());
112 PcDescriptors& desc = PcDescriptors::Handle(code.pc_descriptors());
113 for (int i = 0; i < desc.Length(); i++) {
114 if (desc.PC(i) == pc_) {
115 token_index_ = desc.TokenIndex(i);
116 break;
117 }
118 }
119 ASSERT(token_index_ >= 0);
120 }
121 return token_index_;
122 }
123
124
125 intptr_t ActivationFrame::LineNumber() {
126 // Compute line number lazily since it causes scanning of the script.
127 if (line_number_ < 0) {
128 const Script& script = Script::Handle(SourceScript());
129 intptr_t ignore_column;
130 script.GetTokenLocation(TokenIndex(), &line_number_, &ignore_column);
131 }
siva 2011/12/05 19:21:44 The line number computation code is duplicated her
hausner 2011/12/05 21:11:23 I noticed that too, but I could really only factor
132 return line_number_;
133 }
134
135
136 RawArray* ActivationFrame::Variables() {
137 UNIMPLEMENTED();
138 }
139
140
141 RawInstance* ActivationFrame::Value(const String& variable_name) {
142 UNIMPLEMENTED();
143 }
144
145
146 char* ActivationFrame::ToCString() {
147 const char* kFormat = "Function: '%s%s%s' url: '%s' line: %d";
148
149 Function& func = Function::Handle(DartFunction());
150 String& func_name = String::Handle(func.name());
151 Class& func_class = Class::Handle(func.owner());
152 String& class_name = String::Handle(func_class.Name());
153 String& url = String::Handle(SourceUrl());
154 intptr_t line = LineNumber();
155
156 intptr_t len = OS::SNPrint(NULL, 0, kFormat,
157 class_name.ToCString(),
158 func_class.IsTopLevel() ? "" : ".",
159 func_name.ToCString(),
160 url.ToCString(),
161 line);
162 len++; // String terminator.
163 char* chars = reinterpret_cast<char*>(
164 Isolate::Current()->current_zone()->Allocate(len));
165 OS::SNPrint(chars, len, kFormat,
166 class_name.ToCString(),
167 func_class.IsTopLevel() ? "" : ".",
168 func_name.ToCString(),
169 url.ToCString(),
170 line);
171 return chars;
172 }
173
174
175 void StackTrace::AddActivation(ActivationFrame* frame) {
176 this->trace_.Add(frame);
177 }
50 178
51 179
52 Debugger::Debugger() 180 Debugger::Debugger()
53 : initialized_(false), 181 : initialized_(false),
182 bp_handler_(NULL),
54 breakpoints_(NULL) { 183 breakpoints_(NULL) {
55 } 184 }
56 185
57 186
58 static RawFunction* ResolveLibraryFunction(const String& fname) { 187 static RawFunction* ResolveLibraryFunction(const String& fname) {
59 Isolate* isolate = Isolate::Current(); 188 Isolate* isolate = Isolate::Current();
60 const Library& root_lib = 189 const Library& root_lib =
61 Library::Handle(isolate->object_store()->root_library()); 190 Library::Handle(isolate->object_store()->root_library());
62 ASSERT(!root_lib.IsNull()); 191 ASSERT(!root_lib.IsNull());
63 Function& function = Function::Handle(); 192 Function& function = Function::Handle();
(...skipping 16 matching lines...) Expand all
80 if (!cls.IsNull()) { 209 if (!cls.IsNull()) {
81 function = cls.LookupStaticFunction(function_name); 210 function = cls.LookupStaticFunction(function_name);
82 if (function.IsNull()) { 211 if (function.IsNull()) {
83 function = cls.LookupDynamicFunction(function_name); 212 function = cls.LookupDynamicFunction(function_name);
84 } 213 }
85 } 214 }
86 return function.raw(); 215 return function.raw();
87 } 216 }
88 217
89 218
90
91 void Debugger::SetBreakpointAtEntry(const String& class_name, 219 void Debugger::SetBreakpointAtEntry(const String& class_name,
92 const String& function_name) { 220 const String& function_name) {
93 Function& func = Function::Handle(); 221 Function& func = Function::Handle();
94 if (class_name.IsNull() || (class_name.Length() == 0)) { 222 if (class_name.IsNull() || (class_name.Length() == 0)) {
95 func = ResolveLibraryFunction(function_name); 223 func = ResolveLibraryFunction(function_name);
96 } else { 224 } else {
97 func = ResolveFunction(class_name, function_name); 225 func = ResolveFunction(class_name, function_name);
98 } 226 }
99 if (func.IsNull()) { 227 if (func.IsNull()) {
100 OS::Print("could not find function '%s' in class '%s'\n", 228 OS::Print("could not find function '%s'\n", function_name.ToCString());
101 function_name.ToCString(), class_name.ToCString());
102 return; 229 return;
103 } 230 }
104 if (!func.HasCode()) { 231 if (!func.HasCode()) {
105 Compiler::CompileFunction(func); 232 Compiler::CompileFunction(func);
106 } 233 }
107 Code& code = Code::Handle(func.code()); 234 Code& code = Code::Handle(func.code());
108 ASSERT(!code.IsNull()); 235 ASSERT(!code.IsNull());
109 PcDescriptors& desc = PcDescriptors::Handle(code.pc_descriptors()); 236 PcDescriptors& desc = PcDescriptors::Handle(code.pc_descriptors());
110 for (int i = 0; i < desc.Length(); i++) { 237 for (int i = 0; i < desc.Length(); i++) {
111 PcDescriptors::Kind kind = desc.DescriptorKind(i); 238 PcDescriptors::Kind kind = desc.DescriptorKind(i);
239 Breakpoint* bpt = NULL;
112 if (kind == PcDescriptors::kIcCall) { 240 if (kind == PcDescriptors::kIcCall) {
113 OS::Print("patching dynamic call at %p\n", desc.PC(i));
114 CodePatcher::PatchInstanceCallAt( 241 CodePatcher::PatchInstanceCallAt(
115 desc.PC(i), StubCode::BreakpointDynamicEntryPoint()); 242 desc.PC(i), StubCode::BreakpointDynamicEntryPoint());
116 AddBreakpoint(new Breakpoint(func, i, desc.PC(i))); 243 bpt = new Breakpoint(func, i);
117 return;
118 } else if (kind == PcDescriptors::kOther) { 244 } else if (kind == PcDescriptors::kOther) {
119 if (CodePatcher::IsDartCall(desc.PC(i))) { 245 if (CodePatcher::IsDartCall(desc.PC(i))) {
120 OS::Print("patching static call at %p\n", desc.PC(i));
121 CodePatcher::PatchStaticCallAt( 246 CodePatcher::PatchStaticCallAt(
122 desc.PC(i), StubCode::BreakpointStaticEntryPoint()); 247 desc.PC(i), StubCode::BreakpointStaticEntryPoint());
123 AddBreakpoint(new Breakpoint(func, i, desc.PC(i))); 248 bpt = new Breakpoint(func, i);
124 return;
125 } 249 }
126 } 250 }
251 if (bpt != NULL) {
252 OS::Print("Setting breakpoint at '%s' line %d (PC %p)\n",
253 String::Handle(bpt->SourceUrl()).ToCString(),
254 bpt->LineNumber(),
255 bpt->pc());
256 AddBreakpoint(bpt);
257 return;
258 }
127 } 259 }
128 OS::Print("no breakpoint location found in function '%s'\n", 260 OS::Print("no breakpoint location found in function '%s'\n",
129 function_name.ToCString()); 261 function_name.ToCString());
130 } 262 }
131 263
132 264
265 void Debugger::SetBreakpointHandler(BreakpointHandler* handler) {
266 bp_handler_ = handler;
267 }
268
269
133 void Debugger::VisitObjectPointers(ObjectPointerVisitor* visitor) { 270 void Debugger::VisitObjectPointers(ObjectPointerVisitor* visitor) {
134 ASSERT(visitor != NULL); 271 ASSERT(visitor != NULL);
135 Breakpoint* bpt = this->breakpoints_; 272 Breakpoint* bpt = this->breakpoints_;
136 while (bpt != NULL) { 273 while (bpt != NULL) {
137 bpt->VisitObjectPointers(visitor); 274 bpt->VisitObjectPointers(visitor);
138 bpt = bpt->next(); 275 bpt = bpt->next();
139 } 276 }
140 } 277 }
141 278
142 279
280 static void DefaultBreakpointHandler(Breakpoint* bpt, StackTrace* stack) {
281 for (int i = 0; i < stack->Length(); i++) {
siva 2011/12/05 19:21:44 stack->Length() returns an intptr_t so should i al
hausner 2011/12/05 21:11:23 Done.
282 OS::Print(" %d. %s\n",
283 i + 1, stack->ActivationFrameAt(i)->ToCString());
284 }
285 }
286
287
288 void Debugger::BreakpointCallback() {
289 ASSERT(initialized_);
290 DartFrameIterator iterator;
291 DartFrame* frame = iterator.NextFrame();
292 Function& func = Function::Handle();
293 ASSERT(frame != NULL);
294 Breakpoint* bpt = GetBreakpoint(frame->pc());
295 ASSERT(bpt != NULL);
296 OS::Print(">>> Breakpoint at %s:%d (Address %p)\n",
297 bpt ? String::Handle(bpt->SourceUrl()).ToCString() : "?",
298 bpt ? bpt->LineNumber() : 0,
299 frame->pc());
300 StackTrace* stack_trace = new StackTrace(8);
301 while (frame != NULL) {
302 ASSERT(frame->IsValid());
303 ASSERT(frame->IsDartFrame());
304 ActivationFrame* activation = new ActivationFrame(frame->pc());
305 stack_trace->AddActivation(activation);
306 frame = iterator.NextFrame();
307 }
308
309 if (bp_handler_ != NULL) {
310 (*bp_handler_)(bpt, stack_trace);
311 } else {
312 DefaultBreakpointHandler(bpt, stack_trace);
313 }
siva 2011/12/05 19:21:44 Why not register DefaultBreakpointHandler as the d
hausner 2011/12/05 21:11:23 Yes. Done.
314 }
315
316
143 void Debugger::Initialize(Isolate* isolate) { 317 void Debugger::Initialize(Isolate* isolate) {
144 if (initialized_) { 318 if (initialized_) {
145 return; 319 return;
146 } 320 }
147 initialized_ = true; 321 initialized_ = true;
148 if (!FLAG_debugger) { 322 if (!FLAG_debugger) {
149 return; 323 return;
150 } 324 }
151 if (FLAG_bpt == NULL) { 325 if (FLAG_bpt == NULL) {
152 FLAG_bpt = "main"; 326 FLAG_bpt = "main";
(...skipping 25 matching lines...) Expand all
178 352
179 353
180 void Debugger::AddBreakpoint(Breakpoint* bpt) { 354 void Debugger::AddBreakpoint(Breakpoint* bpt) {
181 ASSERT(bpt->next() == NULL); 355 ASSERT(bpt->next() == NULL);
182 bpt->set_next(this->breakpoints_); 356 bpt->set_next(this->breakpoints_);
183 this->breakpoints_ = bpt; 357 this->breakpoints_ = bpt;
184 } 358 }
185 359
186 360
187 } // namespace dart 361 } // namespace dart
OLDNEW
« runtime/vm/debugger.h ('K') | « runtime/vm/debugger.h ('k') | runtime/vm/stub_code_ia32.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698