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

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

Issue 23964003: Traverse inlined frames lazily when printing the stacktrace. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 7 years, 3 months 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
« no previous file with comments | « runtime/lib/stacktrace.cc ('k') | runtime/vm/object.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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/exceptions.h" 5 #include "vm/exceptions.h"
6 6
7 #include "vm/dart_api_impl.h" 7 #include "vm/dart_api_impl.h"
8 #include "vm/dart_entry.h" 8 #include "vm/dart_entry.h"
9 #include "vm/debugger.h" 9 #include "vm/debugger.h"
10 #include "vm/flags.h" 10 #include "vm/flags.h"
(...skipping 26 matching lines...) Expand all
37 "Stack traces will include methods marked invisible."); 37 "Stack traces will include methods marked invisible.");
38 38
39 const char* Exceptions::kCastErrorDstName = "type cast"; 39 const char* Exceptions::kCastErrorDstName = "type cast";
40 40
41 41
42 class StacktraceBuilder : public ValueObject { 42 class StacktraceBuilder : public ValueObject {
43 public: 43 public:
44 StacktraceBuilder() { } 44 StacktraceBuilder() { }
45 virtual ~StacktraceBuilder() { } 45 virtual ~StacktraceBuilder() { }
46 46
47 virtual void AddFrame(const Function& func, 47 virtual void AddFrame(const Code& code,
48 const Code& code,
49 const Smi& offset, 48 const Smi& offset,
50 bool is_catch_frame) = 0; 49 bool is_catch_frame) = 0;
51 50
52 virtual bool FullStacktrace() const = 0; 51 virtual bool FullStacktrace() const = 0;
53 }; 52 };
54 53
55 54
56 class RegularStacktraceBuilder : public StacktraceBuilder { 55 class RegularStacktraceBuilder : public StacktraceBuilder {
57 public: 56 public:
58 explicit RegularStacktraceBuilder(bool full_stacktrace) 57 explicit RegularStacktraceBuilder(bool full_stacktrace)
59 : func_list_(GrowableObjectArray::Handle(GrowableObjectArray::New())), 58 : code_list_(GrowableObjectArray::Handle(GrowableObjectArray::New())),
60 code_list_(GrowableObjectArray::Handle(GrowableObjectArray::New())),
61 pc_offset_list_( 59 pc_offset_list_(
62 GrowableObjectArray::Handle(GrowableObjectArray::New())), 60 GrowableObjectArray::Handle(GrowableObjectArray::New())),
63 catch_func_list_(
64 full_stacktrace ?
65 GrowableObjectArray::Handle(GrowableObjectArray::New()) :
66 GrowableObjectArray::Handle()),
67 catch_code_list_( 61 catch_code_list_(
68 full_stacktrace ? 62 full_stacktrace ?
69 GrowableObjectArray::Handle(GrowableObjectArray::New()) : 63 GrowableObjectArray::Handle(GrowableObjectArray::New()) :
70 GrowableObjectArray::Handle()), 64 GrowableObjectArray::Handle()),
71 catch_pc_offset_list_( 65 catch_pc_offset_list_(
72 full_stacktrace ? 66 full_stacktrace ?
73 GrowableObjectArray::Handle(GrowableObjectArray::New()) : 67 GrowableObjectArray::Handle(GrowableObjectArray::New()) :
74 GrowableObjectArray::Handle()), 68 GrowableObjectArray::Handle()),
75 full_stacktrace_(full_stacktrace) { } 69 full_stacktrace_(full_stacktrace) { }
76 ~RegularStacktraceBuilder() { } 70 ~RegularStacktraceBuilder() { }
77 71
78 const GrowableObjectArray& func_list() const { return func_list_; }
79 const GrowableObjectArray& code_list() const { return code_list_; } 72 const GrowableObjectArray& code_list() const { return code_list_; }
80 const GrowableObjectArray& pc_offset_list() const { return pc_offset_list_; } 73 const GrowableObjectArray& pc_offset_list() const { return pc_offset_list_; }
81 const GrowableObjectArray& catch_func_list() const {
82 return catch_func_list_;
83 }
84 const GrowableObjectArray& catch_code_list() const { 74 const GrowableObjectArray& catch_code_list() const {
85 return catch_code_list_; 75 return catch_code_list_;
86 } 76 }
87 const GrowableObjectArray& catch_pc_offset_list() const { 77 const GrowableObjectArray& catch_pc_offset_list() const {
88 return catch_pc_offset_list_; 78 return catch_pc_offset_list_;
89 } 79 }
90 virtual bool FullStacktrace() const { return full_stacktrace_; } 80 virtual bool FullStacktrace() const { return full_stacktrace_; }
91 81
92 virtual void AddFrame(const Function& func, 82 virtual void AddFrame(const Code& code,
93 const Code& code,
94 const Smi& offset, 83 const Smi& offset,
95 bool is_catch_frame) { 84 bool is_catch_frame) {
96 if (is_catch_frame) { 85 if (is_catch_frame) {
97 catch_func_list_.Add(func);
98 catch_code_list_.Add(code); 86 catch_code_list_.Add(code);
99 catch_pc_offset_list_.Add(offset); 87 catch_pc_offset_list_.Add(offset);
100 } else { 88 } else {
101 func_list_.Add(func);
102 code_list_.Add(code); 89 code_list_.Add(code);
103 pc_offset_list_.Add(offset); 90 pc_offset_list_.Add(offset);
104 } 91 }
105 } 92 }
106 93
107 private: 94 private:
108 const GrowableObjectArray& func_list_;
109 const GrowableObjectArray& code_list_; 95 const GrowableObjectArray& code_list_;
110 const GrowableObjectArray& pc_offset_list_; 96 const GrowableObjectArray& pc_offset_list_;
111 const GrowableObjectArray& catch_func_list_;
112 const GrowableObjectArray& catch_code_list_; 97 const GrowableObjectArray& catch_code_list_;
113 const GrowableObjectArray& catch_pc_offset_list_; 98 const GrowableObjectArray& catch_pc_offset_list_;
114 bool full_stacktrace_; 99 bool full_stacktrace_;
115 100
116 DISALLOW_COPY_AND_ASSIGN(RegularStacktraceBuilder); 101 DISALLOW_COPY_AND_ASSIGN(RegularStacktraceBuilder);
117 }; 102 };
118 103
119 104
120 class PreallocatedStacktraceBuilder : public StacktraceBuilder { 105 class PreallocatedStacktraceBuilder : public StacktraceBuilder {
121 public: 106 public:
122 explicit PreallocatedStacktraceBuilder(const Stacktrace& stacktrace) 107 explicit PreallocatedStacktraceBuilder(const Stacktrace& stacktrace)
123 : stacktrace_(stacktrace), 108 : stacktrace_(stacktrace),
124 cur_index_(0) { 109 cur_index_(0) {
125 ASSERT(stacktrace_.raw() == 110 ASSERT(stacktrace_.raw() ==
126 Isolate::Current()->object_store()->preallocated_stack_trace()); 111 Isolate::Current()->object_store()->preallocated_stack_trace());
127 } 112 }
128 ~PreallocatedStacktraceBuilder() { } 113 ~PreallocatedStacktraceBuilder() { }
129 114
130 virtual void AddFrame(const Function& func, 115 virtual void AddFrame(const Code& code,
131 const Code& code,
132 const Smi& offset, 116 const Smi& offset,
133 bool is_catch_frame); 117 bool is_catch_frame);
134 118
135 virtual bool FullStacktrace() const { return false; } 119 virtual bool FullStacktrace() const { return false; }
136 120
137 private: 121 private:
138 static const int kNumTopframes = 3; 122 static const int kNumTopframes = 3;
139 123
140 const Stacktrace& stacktrace_; 124 const Stacktrace& stacktrace_;
141 intptr_t cur_index_; 125 intptr_t cur_index_;
142 126
143 DISALLOW_COPY_AND_ASSIGN(PreallocatedStacktraceBuilder); 127 DISALLOW_COPY_AND_ASSIGN(PreallocatedStacktraceBuilder);
144 }; 128 };
145 129
146 130
147 void PreallocatedStacktraceBuilder::AddFrame(const Function& func, 131 void PreallocatedStacktraceBuilder::AddFrame(const Code& code,
148 const Code& code,
149 const Smi& offset, 132 const Smi& offset,
150 bool is_catch_frame) { 133 bool is_catch_frame) {
151 if (cur_index_ >= Stacktrace::kPreallocatedStackdepth) { 134 if (cur_index_ >= Stacktrace::kPreallocatedStackdepth) {
152 // The number of frames is overflowing the preallocated stack trace object. 135 // The number of frames is overflowing the preallocated stack trace object.
153 Function& frame_func = Function::Handle();
154 Code& frame_code = Code::Handle(); 136 Code& frame_code = Code::Handle();
155 Smi& frame_offset = Smi::Handle(); 137 Smi& frame_offset = Smi::Handle();
156 intptr_t start = Stacktrace::kPreallocatedStackdepth - (kNumTopframes - 1); 138 intptr_t start = Stacktrace::kPreallocatedStackdepth - (kNumTopframes - 1);
157 intptr_t null_slot = start - 2; 139 intptr_t null_slot = start - 2;
158 // Add an empty slot to indicate the overflow so that the toString 140 // Add an empty slot to indicate the overflow so that the toString
159 // method can account for the overflow. 141 // method can account for the overflow.
160 if (stacktrace_.FunctionAtFrame(null_slot) != Function::null()) { 142 if (stacktrace_.FunctionAtFrame(null_slot) != Function::null()) {
161 stacktrace_.SetFunctionAtFrame(null_slot, frame_func);
162 stacktrace_.SetCodeAtFrame(null_slot, frame_code); 143 stacktrace_.SetCodeAtFrame(null_slot, frame_code);
163 } 144 }
164 // Move frames one slot down so that we can accomodate the new frame. 145 // Move frames one slot down so that we can accomodate the new frame.
165 for (intptr_t i = start; i < Stacktrace::kPreallocatedStackdepth; i++) { 146 for (intptr_t i = start; i < Stacktrace::kPreallocatedStackdepth; i++) {
166 intptr_t prev = (i - 1); 147 intptr_t prev = (i - 1);
167 frame_func = stacktrace_.FunctionAtFrame(i);
168 frame_code = stacktrace_.CodeAtFrame(i); 148 frame_code = stacktrace_.CodeAtFrame(i);
169 frame_offset = stacktrace_.PcOffsetAtFrame(i); 149 frame_offset = stacktrace_.PcOffsetAtFrame(i);
170 stacktrace_.SetFunctionAtFrame(prev, frame_func);
171 stacktrace_.SetCodeAtFrame(prev, frame_code); 150 stacktrace_.SetCodeAtFrame(prev, frame_code);
172 stacktrace_.SetPcOffsetAtFrame(prev, frame_offset); 151 stacktrace_.SetPcOffsetAtFrame(prev, frame_offset);
173 } 152 }
174 cur_index_ = (Stacktrace::kPreallocatedStackdepth - 1); 153 cur_index_ = (Stacktrace::kPreallocatedStackdepth - 1);
175 } 154 }
176 stacktrace_.SetFunctionAtFrame(cur_index_, func);
177 stacktrace_.SetCodeAtFrame(cur_index_, code); 155 stacktrace_.SetCodeAtFrame(cur_index_, code);
178 stacktrace_.SetPcOffsetAtFrame(cur_index_, offset); 156 stacktrace_.SetPcOffsetAtFrame(cur_index_, offset);
179 cur_index_ += 1; 157 cur_index_ += 1;
180 } 158 }
181 159
182 160
183 static bool ShouldShowFunction(const Function& function) {
184 if (FLAG_verbose_stacktrace) {
185 return true;
186 }
187 return function.is_visible();
188 }
189
190
191 static void BuildStackTrace(StacktraceBuilder* builder) { 161 static void BuildStackTrace(StacktraceBuilder* builder) {
192 StackFrameIterator frames(StackFrameIterator::kDontValidateFrames); 162 StackFrameIterator frames(StackFrameIterator::kDontValidateFrames);
193 StackFrame* frame = frames.NextFrame(); 163 StackFrame* frame = frames.NextFrame();
194 ASSERT(frame != NULL); // We expect to find a dart invocation frame. 164 ASSERT(frame != NULL); // We expect to find a dart invocation frame.
195 Function& func = Function::Handle();
196 Code& code = Code::Handle(); 165 Code& code = Code::Handle();
197 Smi& offset = Smi::Handle(); 166 Smi& offset = Smi::Handle();
198 bool dart_handler_found = false; 167 bool dart_handler_found = false;
199 bool handler_pc_set = false; 168 bool handler_pc_set = false;
200 while (frame != NULL) { 169 while (frame != NULL) {
201 while (!frame->IsEntryFrame()) { 170 while (!frame->IsEntryFrame()) {
202 if (frame->IsDartFrame()) { 171 if (frame->IsDartFrame()) {
203 code = frame->LookupDartCode(); 172 code = frame->LookupDartCode();
204 if (code.is_optimized()) { 173 offset = Smi::New(frame->pc() - code.EntryPoint());
205 // For optimized frames, extract all the inlined functions if any 174 builder->AddFrame(code, offset, dart_handler_found);
206 // into the stack trace.
207 for (InlinedFunctionsIterator it(code, frame->pc());
208 !it.Done(); it.Advance()) {
209 func = it.function();
210 code = it.code();
211 uword pc = it.pc();
212 ASSERT(pc != 0);
213 ASSERT(code.EntryPoint() <= pc);
214 ASSERT(pc < (code.EntryPoint() + code.Size()));
215 if (ShouldShowFunction(func)) {
216 offset = Smi::New(pc - code.EntryPoint());
217 builder->AddFrame(func, code, offset, dart_handler_found);
218 }
219 }
220 } else {
221 offset = Smi::New(frame->pc() - code.EntryPoint());
222 func = code.function();
223 if (ShouldShowFunction(func)) {
224 builder->AddFrame(func, code, offset, dart_handler_found);
225 }
226 }
227 bool needs_stacktrace = false; 175 bool needs_stacktrace = false;
228 bool is_catch_all = false; 176 bool is_catch_all = false;
229 uword handler_pc = kUwordMax; 177 uword handler_pc = kUwordMax;
230 if (!handler_pc_set && 178 if (!handler_pc_set &&
231 frame->FindExceptionHandler(&handler_pc, 179 frame->FindExceptionHandler(&handler_pc,
232 &needs_stacktrace, 180 &needs_stacktrace,
233 &is_catch_all)) { 181 &is_catch_all)) {
234 handler_pc_set = true; 182 handler_pc_set = true;
235 dart_handler_found = true; 183 dart_handler_found = true;
236 if (!builder->FullStacktrace()) { 184 if (!builder->FullStacktrace()) {
(...skipping 188 matching lines...) Expand 10 before | Expand all | Expand 10 after
425 } 373 }
426 } else { 374 } else {
427 // Get stacktrace field of class Error. 375 // Get stacktrace field of class Error.
428 const Field& stacktrace_field = 376 const Field& stacktrace_field =
429 Field::Handle(isolate, LookupStacktraceField(exception)); 377 Field::Handle(isolate, LookupStacktraceField(exception));
430 bool full_stacktrace = !stacktrace_field.IsNull(); 378 bool full_stacktrace = !stacktrace_field.IsNull();
431 handler_exists = FindExceptionHandler(&handler_pc, 379 handler_exists = FindExceptionHandler(&handler_pc,
432 &handler_sp, 380 &handler_sp,
433 &handler_fp, 381 &handler_fp,
434 &handler_needs_stacktrace); 382 &handler_needs_stacktrace);
435 Array& func_array = Array::Handle(isolate, Object::empty_array().raw());
436 Array& code_array = Array::Handle(isolate, Object::empty_array().raw()); 383 Array& code_array = Array::Handle(isolate, Object::empty_array().raw());
437 Array& pc_offset_array = 384 Array& pc_offset_array =
438 Array::Handle(isolate, Object::empty_array().raw()); 385 Array::Handle(isolate, Object::empty_array().raw());
439 if (handler_needs_stacktrace || full_stacktrace) { 386 if (handler_needs_stacktrace || full_stacktrace) {
440 RegularStacktraceBuilder frame_builder(full_stacktrace); 387 RegularStacktraceBuilder frame_builder(full_stacktrace);
441 BuildStackTrace(&frame_builder); 388 BuildStackTrace(&frame_builder);
442 389
443 // Create arrays for function, code and pc_offset triplet of each frame. 390 // Create arrays for function, code and pc_offset triplet of each frame.
444 func_array = Array::MakeArray(frame_builder.func_list());
445 code_array = Array::MakeArray(frame_builder.code_list()); 391 code_array = Array::MakeArray(frame_builder.code_list());
446 pc_offset_array = Array::MakeArray(frame_builder.pc_offset_list()); 392 pc_offset_array = Array::MakeArray(frame_builder.pc_offset_list());
447 if (!stacktrace_field.IsNull()) { 393 if (!stacktrace_field.IsNull()) {
448 // This is an error object and we need to capture the full stack trace 394 // This is an error object and we need to capture the full stack trace
449 // here implicitly, so we set up the stack trace. The stack trace field 395 // here implicitly, so we set up the stack trace. The stack trace field
450 // is set only once, it is not overriden. 396 // is set only once, it is not overriden.
451 const Array& catch_func_array = Array::Handle(isolate,
452 Array::MakeArray(frame_builder.catch_func_list()));
453 const Array& catch_code_array = Array::Handle(isolate, 397 const Array& catch_code_array = Array::Handle(isolate,
454 Array::MakeArray(frame_builder.catch_code_list())); 398 Array::MakeArray(frame_builder.catch_code_list()));
455 const Array& catch_pc_offset_array = Array::Handle(isolate, 399 const Array& catch_pc_offset_array = Array::Handle(isolate,
456 Array::MakeArray(frame_builder.catch_pc_offset_list())); 400 Array::MakeArray(frame_builder.catch_pc_offset_list()));
457 stacktrace = Stacktrace::New(func_array, code_array, pc_offset_array); 401 stacktrace = Stacktrace::New(code_array, pc_offset_array);
458 stacktrace.SetCatchStacktrace(catch_func_array, 402 stacktrace.SetCatchStacktrace(catch_code_array,
459 catch_code_array,
460 catch_pc_offset_array); 403 catch_pc_offset_array);
461 if (exception.GetField(stacktrace_field) == Object::null()) { 404 if (exception.GetField(stacktrace_field) == Object::null()) {
462 exception.SetField(stacktrace_field, stacktrace); 405 exception.SetField(stacktrace_field, stacktrace);
463 } 406 }
464 } // if stacktrace needed. 407 } // if stacktrace needed.
465 } 408 }
466 if (existing_stacktrace.IsNull()) { 409 if (existing_stacktrace.IsNull()) {
467 stacktrace = Stacktrace::New(func_array, code_array, pc_offset_array); 410 stacktrace = Stacktrace::New(code_array, pc_offset_array);
468 } else { 411 } else {
469 stacktrace ^= existing_stacktrace.raw(); 412 stacktrace ^= existing_stacktrace.raw();
470 if (pc_offset_array.Length() != 0) { 413 if (pc_offset_array.Length() != 0) {
471 stacktrace.Append(func_array, code_array, pc_offset_array); 414 stacktrace.Append(code_array, pc_offset_array);
472 } 415 }
473 // Since we are re throwing and appending to the existing stack trace 416 // Since we are re throwing and appending to the existing stack trace
474 // we clear out the catch trace collected in the existing stack trace 417 // we clear out the catch trace collected in the existing stack trace
475 // as that trace will not be valid anymore. 418 // as that trace will not be valid anymore.
476 stacktrace.SetCatchStacktrace(Object::empty_array(), 419 stacktrace.SetCatchStacktrace(Object::empty_array(),
477 Object::empty_array(),
478 Object::empty_array()); 420 Object::empty_array());
479 } 421 }
480 } 422 }
481 // We expect to find a handler_pc, if the exception is unhandled 423 // We expect to find a handler_pc, if the exception is unhandled
482 // then we expect to at least have the dart entry frame on the 424 // then we expect to at least have the dart entry frame on the
483 // stack as Exceptions::Throw should happen only after a dart 425 // stack as Exceptions::Throw should happen only after a dart
484 // invocation has been done. 426 // invocation has been done.
485 ASSERT(handler_pc != 0); 427 ASSERT(handler_pc != 0);
486 428
487 if (FLAG_print_stacktrace_at_throw) { 429 if (FLAG_print_stacktrace_at_throw) {
(...skipping 265 matching lines...) Expand 10 before | Expand all | Expand 10 after
753 break; 695 break;
754 } 696 }
755 697
756 return DartLibraryCalls::InstanceCreate(library, 698 return DartLibraryCalls::InstanceCreate(library,
757 *class_name, 699 *class_name,
758 *constructor_name, 700 *constructor_name,
759 arguments); 701 arguments);
760 } 702 }
761 703
762 } // namespace dart 704 } // namespace dart
OLDNEW
« no previous file with comments | « runtime/lib/stacktrace.cc ('k') | runtime/vm/object.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698