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

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

Issue 939773003: - Simplify collection of stack traces. If we determine that a stack (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 5 years, 10 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/vm/bootstrap_natives.h ('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 "platform/address_sanitizer.h" 7 #include "platform/address_sanitizer.h"
8 8
9 #include "vm/dart_api_impl.h" 9 #include "vm/dart_api_impl.h"
10 #include "vm/dart_entry.h" 10 #include "vm/dart_entry.h"
(...skipping 13 matching lines...) Expand all
24 24
25 25
26 const char* Exceptions::kCastErrorDstName = "type cast"; 26 const char* Exceptions::kCastErrorDstName = "type cast";
27 27
28 28
29 class StacktraceBuilder : public ValueObject { 29 class StacktraceBuilder : public ValueObject {
30 public: 30 public:
31 StacktraceBuilder() { } 31 StacktraceBuilder() { }
32 virtual ~StacktraceBuilder() { } 32 virtual ~StacktraceBuilder() { }
33 33
34 virtual void AddFrame(const Code& code, 34 virtual void AddFrame(const Code& code, const Smi& offset) = 0;
35 const Smi& offset,
36 bool is_catch_frame) = 0;
37
38 virtual bool FullStacktrace() const = 0;
39 }; 35 };
40 36
41 37
42 class RegularStacktraceBuilder : public StacktraceBuilder { 38 class RegularStacktraceBuilder : public StacktraceBuilder {
43 public: 39 public:
44 explicit RegularStacktraceBuilder(bool full_stacktrace) 40 explicit RegularStacktraceBuilder(Isolate* isolate)
45 : code_list_(GrowableObjectArray::Handle(GrowableObjectArray::New())), 41 : code_list_(
42 GrowableObjectArray::Handle(isolate, GrowableObjectArray::New())),
46 pc_offset_list_( 43 pc_offset_list_(
47 GrowableObjectArray::Handle(GrowableObjectArray::New())), 44 GrowableObjectArray::Handle(isolate, GrowableObjectArray::New())) { }
48 catch_code_list_(
49 full_stacktrace ?
50 GrowableObjectArray::Handle(GrowableObjectArray::New()) :
51 GrowableObjectArray::Handle()),
52 catch_pc_offset_list_(
53 full_stacktrace ?
54 GrowableObjectArray::Handle(GrowableObjectArray::New()) :
55 GrowableObjectArray::Handle()),
56 full_stacktrace_(full_stacktrace) { }
57 ~RegularStacktraceBuilder() { } 45 ~RegularStacktraceBuilder() { }
58 46
59 const GrowableObjectArray& code_list() const { return code_list_; } 47 const GrowableObjectArray& code_list() const { return code_list_; }
60 const GrowableObjectArray& pc_offset_list() const { return pc_offset_list_; } 48 const GrowableObjectArray& pc_offset_list() const { return pc_offset_list_; }
61 const GrowableObjectArray& catch_code_list() const {
62 return catch_code_list_;
63 }
64 const GrowableObjectArray& catch_pc_offset_list() const {
65 return catch_pc_offset_list_;
66 }
67 virtual bool FullStacktrace() const { return full_stacktrace_; }
68 49
69 virtual void AddFrame(const Code& code, 50 virtual void AddFrame(const Code& code, const Smi& offset) {
70 const Smi& offset, 51 code_list_.Add(code);
71 bool is_catch_frame) { 52 pc_offset_list_.Add(offset);
72 if (is_catch_frame) {
73 catch_code_list_.Add(code);
74 catch_pc_offset_list_.Add(offset);
75 } else {
76 code_list_.Add(code);
77 pc_offset_list_.Add(offset);
78 }
79 } 53 }
80 54
81 private: 55 private:
82 const GrowableObjectArray& code_list_; 56 const GrowableObjectArray& code_list_;
83 const GrowableObjectArray& pc_offset_list_; 57 const GrowableObjectArray& pc_offset_list_;
84 const GrowableObjectArray& catch_code_list_;
85 const GrowableObjectArray& catch_pc_offset_list_;
86 bool full_stacktrace_;
87 58
88 DISALLOW_COPY_AND_ASSIGN(RegularStacktraceBuilder); 59 DISALLOW_COPY_AND_ASSIGN(RegularStacktraceBuilder);
89 }; 60 };
90 61
91 62
92 class PreallocatedStacktraceBuilder : public StacktraceBuilder { 63 class PreallocatedStacktraceBuilder : public StacktraceBuilder {
93 public: 64 public:
94 explicit PreallocatedStacktraceBuilder(const Stacktrace& stacktrace) 65 explicit PreallocatedStacktraceBuilder(const Stacktrace& stacktrace)
95 : stacktrace_(stacktrace), 66 : stacktrace_(stacktrace),
96 cur_index_(0) { 67 cur_index_(0) {
97 ASSERT(stacktrace_.raw() == 68 ASSERT(stacktrace_.raw() ==
98 Isolate::Current()->object_store()->preallocated_stack_trace()); 69 Isolate::Current()->object_store()->preallocated_stack_trace());
99 } 70 }
100 ~PreallocatedStacktraceBuilder() { } 71 ~PreallocatedStacktraceBuilder() { }
101 72
102 virtual void AddFrame(const Code& code, 73 virtual void AddFrame(const Code& code, const Smi& offset);
103 const Smi& offset,
104 bool is_catch_frame);
105
106 virtual bool FullStacktrace() const { return false; }
107 74
108 private: 75 private:
109 static const int kNumTopframes = 3; 76 static const int kNumTopframes = 3;
110 77
111 const Stacktrace& stacktrace_; 78 const Stacktrace& stacktrace_;
112 intptr_t cur_index_; 79 intptr_t cur_index_;
113 80
114 DISALLOW_COPY_AND_ASSIGN(PreallocatedStacktraceBuilder); 81 DISALLOW_COPY_AND_ASSIGN(PreallocatedStacktraceBuilder);
115 }; 82 };
116 83
117 84
118 void PreallocatedStacktraceBuilder::AddFrame(const Code& code, 85 void PreallocatedStacktraceBuilder::AddFrame(const Code& code,
119 const Smi& offset, 86 const Smi& offset) {
120 bool is_catch_frame) {
121 if (cur_index_ >= Stacktrace::kPreallocatedStackdepth) { 87 if (cur_index_ >= Stacktrace::kPreallocatedStackdepth) {
122 // The number of frames is overflowing the preallocated stack trace object. 88 // The number of frames is overflowing the preallocated stack trace object.
123 Code& frame_code = Code::Handle(); 89 Code& frame_code = Code::Handle();
124 Smi& frame_offset = Smi::Handle(); 90 Smi& frame_offset = Smi::Handle();
125 intptr_t start = Stacktrace::kPreallocatedStackdepth - (kNumTopframes - 1); 91 intptr_t start = Stacktrace::kPreallocatedStackdepth - (kNumTopframes - 1);
126 intptr_t null_slot = start - 2; 92 intptr_t null_slot = start - 2;
127 // Add an empty slot to indicate the overflow so that the toString 93 // Add an empty slot to indicate the overflow so that the toString
128 // method can account for the overflow. 94 // method can account for the overflow.
129 if (stacktrace_.FunctionAtFrame(null_slot) != Function::null()) { 95 if (stacktrace_.FunctionAtFrame(null_slot) != Function::null()) {
130 stacktrace_.SetCodeAtFrame(null_slot, frame_code); 96 stacktrace_.SetCodeAtFrame(null_slot, frame_code);
(...skipping 13 matching lines...) Expand all
144 cur_index_ += 1; 110 cur_index_ += 1;
145 } 111 }
146 112
147 113
148 static void BuildStackTrace(Isolate* isolate, StacktraceBuilder* builder) { 114 static void BuildStackTrace(Isolate* isolate, StacktraceBuilder* builder) {
149 StackFrameIterator frames(StackFrameIterator::kDontValidateFrames); 115 StackFrameIterator frames(StackFrameIterator::kDontValidateFrames);
150 StackFrame* frame = frames.NextFrame(); 116 StackFrame* frame = frames.NextFrame();
151 ASSERT(frame != NULL); // We expect to find a dart invocation frame. 117 ASSERT(frame != NULL); // We expect to find a dart invocation frame.
152 Code& code = Code::Handle(); 118 Code& code = Code::Handle();
153 Smi& offset = Smi::Handle(); 119 Smi& offset = Smi::Handle();
154 bool dart_handler_found = false;
155 bool handler_pc_set = false;
156 while (frame != NULL) { 120 while (frame != NULL) {
157 while (!frame->IsEntryFrame()) { 121 if (frame->IsDartFrame()) {
158 if (frame->IsDartFrame()) { 122 code = frame->LookupDartCode();
159 code = frame->LookupDartCode(); 123 offset = Smi::New(frame->pc() - code.EntryPoint());
160 offset = Smi::New(frame->pc() - code.EntryPoint()); 124 builder->AddFrame(code, offset);
161 builder->AddFrame(code, offset, dart_handler_found);
162 bool needs_stacktrace = false;
163 bool is_catch_all = false;
164 uword handler_pc = kUwordMax;
165 if (!handler_pc_set &&
166 frame->FindExceptionHandler(isolate,
167 &handler_pc,
168 &needs_stacktrace,
169 &is_catch_all)) {
170 handler_pc_set = true;
171 dart_handler_found = true;
172 if (!builder->FullStacktrace()) {
173 return;
174 }
175 }
176 }
177 frame = frames.NextFrame();
178 ASSERT(frame != NULL);
179 }
180 ASSERT(frame->IsEntryFrame());
181 if (!handler_pc_set) {
182 handler_pc_set = true;
183 if (!builder->FullStacktrace()) {
184 return;
185 }
186 } 125 }
187 frame = frames.NextFrame(); 126 frame = frames.NextFrame();
188 } 127 }
189 } 128 }
190 129
191 130
192 // Iterate through the stack frames and try to find a frame with an 131 // Iterate through the stack frames and try to find a frame with an
193 // exception handler. Once found, set the pc, sp and fp so that execution 132 // exception handler. Once found, set the pc, sp and fp so that execution
194 // can continue in that frame. Sets 'needs_stacktrace' if there is no 133 // can continue in that frame. Sets 'needs_stacktrace' if there is no
195 // cath-all handler or if a stack-trace is specified in the catch. 134 // cath-all handler or if a stack-trace is specified in the catch.
(...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after
332 if (type.IsNull()) return Field::null(); 271 if (type.IsNull()) return Field::null();
333 test_class = type.type_class(); 272 test_class = type.type_class();
334 } 273 }
335 UNREACHABLE(); 274 UNREACHABLE();
336 return Field::null(); 275 return Field::null();
337 } 276 }
338 277
339 278
340 RawStacktrace* Exceptions::CurrentStacktrace() { 279 RawStacktrace* Exceptions::CurrentStacktrace() {
341 Isolate* isolate = Isolate::Current(); 280 Isolate* isolate = Isolate::Current();
342 RegularStacktraceBuilder frame_builder(true); 281 RegularStacktraceBuilder frame_builder(isolate);
343 BuildStackTrace(isolate, &frame_builder); 282 BuildStackTrace(isolate, &frame_builder);
344 283
345 // Create arrays for code and pc_offset tuples of each frame. 284 // Create arrays for code and pc_offset tuples of each frame.
346 const Array& full_code_array = Array::Handle(isolate, 285 const Array& full_code_array = Array::Handle(isolate,
347 Array::MakeArray(frame_builder.code_list())); 286 Array::MakeArray(frame_builder.code_list()));
348 const Array& full_pc_offset_array = Array::Handle(isolate, 287 const Array& full_pc_offset_array = Array::Handle(isolate,
349 Array::MakeArray(frame_builder.pc_offset_list())); 288 Array::MakeArray(frame_builder.pc_offset_list()));
350 const Array& full_catch_code_array = Array::Handle(isolate,
351 Array::MakeArray(frame_builder.catch_code_list()));
352 const Array& full_catch_pc_offset_array = Array::Handle(isolate,
353 Array::MakeArray(frame_builder.catch_pc_offset_list()));
354 const Stacktrace& full_stacktrace = Stacktrace::Handle( 289 const Stacktrace& full_stacktrace = Stacktrace::Handle(
355 Stacktrace::New(full_code_array, full_pc_offset_array)); 290 Stacktrace::New(full_code_array, full_pc_offset_array));
356 full_stacktrace.SetCatchStacktrace(full_catch_code_array,
357 full_catch_pc_offset_array);
358 return full_stacktrace.raw(); 291 return full_stacktrace.raw();
359 } 292 }
360 293
361 294
362 static void ThrowExceptionHelper(Isolate* isolate, 295 static void ThrowExceptionHelper(Isolate* isolate,
363 const Instance& incoming_exception, 296 const Instance& incoming_exception,
364 const Stacktrace& existing_stacktrace, 297 const Stacktrace& existing_stacktrace,
365 const bool is_rethrow) { 298 const bool is_rethrow) {
366 bool use_preallocated_stacktrace = false; 299 bool use_preallocated_stacktrace = false;
367 Instance& exception = Instance::Handle(isolate, incoming_exception.raw()); 300 Instance& exception = Instance::Handle(isolate, incoming_exception.raw());
(...skipping 15 matching lines...) Expand all
383 PreallocatedStacktraceBuilder frame_builder(stacktrace); 316 PreallocatedStacktraceBuilder frame_builder(stacktrace);
384 handler_exists = FindExceptionHandler(isolate, 317 handler_exists = FindExceptionHandler(isolate,
385 &handler_pc, 318 &handler_pc,
386 &handler_sp, 319 &handler_sp,
387 &handler_fp, 320 &handler_fp,
388 &handler_needs_stacktrace); 321 &handler_needs_stacktrace);
389 if (handler_needs_stacktrace) { 322 if (handler_needs_stacktrace) {
390 BuildStackTrace(isolate, &frame_builder); 323 BuildStackTrace(isolate, &frame_builder);
391 } 324 }
392 } else { 325 } else {
393 // Get stacktrace field of class Error. 326 // Get stacktrace field of class Error. This is needed to determine whether
327 // we have a subclass of Error which carries around its stack trace.
394 const Field& stacktrace_field = 328 const Field& stacktrace_field =
395 Field::Handle(isolate, LookupStacktraceField(exception)); 329 Field::Handle(isolate, LookupStacktraceField(exception));
330
331 // Find the exception handler and determine if the handler needs a
332 // stacktrace.
396 handler_exists = FindExceptionHandler(isolate, 333 handler_exists = FindExceptionHandler(isolate,
397 &handler_pc, 334 &handler_pc,
398 &handler_sp, 335 &handler_sp,
399 &handler_fp, 336 &handler_fp,
400 &handler_needs_stacktrace); 337 &handler_needs_stacktrace);
401 if (!stacktrace_field.IsNull() || handler_needs_stacktrace) { 338 if (!existing_stacktrace.IsNull()) {
402 Array& code_array = Array::Handle(isolate, Object::empty_array().raw()); 339 // If we have an existing stack trace then this better be a rethrow. The
403 Array& pc_offset_array = 340 // reverse is not necessarily true (e.g. Dart_PropagateError can cause
404 Array::Handle(isolate, Object::empty_array().raw()); 341 // a rethrow being called without an existing stacktrace.)
405 // If we have an error with a stacktrace field then collect the full stack 342 ASSERT(is_rethrow);
406 // trace and store it into the field. 343 ASSERT(stacktrace_field.IsNull() ||
407 if (!stacktrace_field.IsNull()) { 344 (exception.GetField(stacktrace_field) != Object::null()));
408 if (exception.GetField(stacktrace_field) == Object::null()) { 345 stacktrace = existing_stacktrace.raw();
409 // This is an error object and we need to capture the full stack trace 346 } else if (!stacktrace_field.IsNull() || handler_needs_stacktrace) {
410 // here implicitly, so we set up the stack trace. The stack trace 347 // Collect the stacktrace if needed.
411 // field is set only once, it is not overriden. 348 ASSERT(existing_stacktrace.IsNull());
412 const Stacktrace& full_stacktrace = 349 stacktrace = Exceptions::CurrentStacktrace();
413 Stacktrace::Handle(isolate, Exceptions::CurrentStacktrace()); 350 // If we have an Error object, then set its stackTrace field only if it
414 exception.SetField(stacktrace_field, full_stacktrace); 351 // not yet initialized.
415 } 352 if (!stacktrace_field.IsNull() &&
416 } 353 (exception.GetField(stacktrace_field) == Object::null())) {
417 if (handler_needs_stacktrace) { 354 exception.SetField(stacktrace_field, stacktrace);
418 RegularStacktraceBuilder frame_builder(false);
419 BuildStackTrace(isolate, &frame_builder);
420
421 // Create arrays for code and pc_offset tuples of each frame.
422 code_array = Array::MakeArray(frame_builder.code_list());
423 pc_offset_array = Array::MakeArray(frame_builder.pc_offset_list());
424 }
425 if (existing_stacktrace.IsNull()) {
426 stacktrace = Stacktrace::New(code_array, pc_offset_array);
427 } else {
428 ASSERT(is_rethrow);
429 stacktrace = existing_stacktrace.raw();
430 if (pc_offset_array.Length() != 0) {
431 // Skip the first frame during a rethrow. This is the catch clause
432 // with the rethrow statement, which is not part of the original
433 // trace a rethrow is supposed to preserve.
434 stacktrace.Append(code_array, pc_offset_array, 1);
435 }
436 // Since we are re throwing and appending to the existing stack trace
437 // we clear out the catch trace collected in the existing stack trace
438 // as that trace will not be valid anymore.
439 stacktrace.SetCatchStacktrace(Object::empty_array(),
440 Object::empty_array());
441 } 355 }
442 } 356 }
443 } 357 }
444 // We expect to find a handler_pc, if the exception is unhandled 358 // We expect to find a handler_pc, if the exception is unhandled
445 // then we expect to at least have the dart entry frame on the 359 // then we expect to at least have the dart entry frame on the
446 // stack as Exceptions::Throw should happen only after a dart 360 // stack as Exceptions::Throw should happen only after a dart
447 // invocation has been done. 361 // invocation has been done.
448 ASSERT(handler_pc != 0); 362 ASSERT(handler_pc != 0);
449 363
450 if (FLAG_print_stacktrace_at_throw) { 364 if (FLAG_print_stacktrace_at_throw) {
(...skipping 303 matching lines...) Expand 10 before | Expand all | Expand 10 after
754 668
755 // Throw JavascriptCompatibilityError exception. 669 // Throw JavascriptCompatibilityError exception.
756 void Exceptions::ThrowJavascriptCompatibilityError(const char* msg) { 670 void Exceptions::ThrowJavascriptCompatibilityError(const char* msg) {
757 const Array& exc_args = Array::Handle(Array::New(1)); 671 const Array& exc_args = Array::Handle(Array::New(1));
758 const String& msg_str = String::Handle(String::New(msg)); 672 const String& msg_str = String::Handle(String::New(msg));
759 exc_args.SetAt(0, msg_str); 673 exc_args.SetAt(0, msg_str);
760 Exceptions::ThrowByType(Exceptions::kJavascriptCompatibilityError, exc_args); 674 Exceptions::ThrowByType(Exceptions::kJavascriptCompatibilityError, exc_args);
761 } 675 }
762 676
763 } // namespace dart 677 } // namespace dart
OLDNEW
« no previous file with comments | « runtime/vm/bootstrap_natives.h ('k') | runtime/vm/object.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698