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

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

Issue 23445012: Mark exception handlers if they have a stacktrace specified. Do not build a stacktrace if the handl… (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/vm/code_descriptors.h ('k') | runtime/vm/flow_graph_builder.cc » ('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 170 matching lines...) Expand 10 before | Expand all | Expand 10 after
181 181
182 182
183 static bool ShouldShowFunction(const Function& function) { 183 static bool ShouldShowFunction(const Function& function) {
184 if (FLAG_verbose_stacktrace) { 184 if (FLAG_verbose_stacktrace) {
185 return true; 185 return true;
186 } 186 }
187 return function.is_visible(); 187 return function.is_visible();
188 } 188 }
189 189
190 190
191 // Iterate through the stack frames and try to find a frame with an 191 static void BuildStackTrace(StacktraceBuilder* builder) {
192 // exception handler. Once found, set the pc, sp and fp so that execution
193 // can continue in that frame.
194 static bool FindExceptionHandler(uword* handler_pc,
195 uword* handler_sp,
196 uword* handler_fp,
197 StacktraceBuilder* builder) {
198 StackFrameIterator frames(StackFrameIterator::kDontValidateFrames); 192 StackFrameIterator frames(StackFrameIterator::kDontValidateFrames);
199 StackFrame* frame = frames.NextFrame(); 193 StackFrame* frame = frames.NextFrame();
200 ASSERT(frame != NULL); // We expect to find a dart invocation frame. 194 ASSERT(frame != NULL); // We expect to find a dart invocation frame.
201 Function& func = Function::Handle(); 195 Function& func = Function::Handle();
202 Code& code = Code::Handle(); 196 Code& code = Code::Handle();
203 Smi& offset = Smi::Handle(); 197 Smi& offset = Smi::Handle();
204 bool dart_handler_found = false; 198 bool dart_handler_found = false;
205 bool handler_pc_set = false; 199 bool handler_pc_set = false;
206 while (frame != NULL) { 200 while (frame != NULL) {
207 while (!frame->IsEntryFrame()) { 201 while (!frame->IsEntryFrame()) {
(...skipping 14 matching lines...) Expand all
222 builder->AddFrame(func, code, offset, dart_handler_found); 216 builder->AddFrame(func, code, offset, dart_handler_found);
223 } 217 }
224 } 218 }
225 } else { 219 } else {
226 offset = Smi::New(frame->pc() - code.EntryPoint()); 220 offset = Smi::New(frame->pc() - code.EntryPoint());
227 func = code.function(); 221 func = code.function();
228 if (ShouldShowFunction(func)) { 222 if (ShouldShowFunction(func)) {
229 builder->AddFrame(func, code, offset, dart_handler_found); 223 builder->AddFrame(func, code, offset, dart_handler_found);
230 } 224 }
231 } 225 }
232 if (!handler_pc_set && frame->FindExceptionHandler(handler_pc)) { 226 bool needs_stacktrace = false;
227 bool is_catch_all = false;
228 uword handler_pc = kUwordMax;
229 if (!handler_pc_set &&
230 frame->FindExceptionHandler(&handler_pc,
231 &needs_stacktrace,
232 &is_catch_all)) {
233 handler_pc_set = true; 233 handler_pc_set = true;
234 *handler_sp = frame->sp();
235 *handler_fp = frame->fp();
236 dart_handler_found = true; 234 dart_handler_found = true;
237 if (!builder->FullStacktrace()) { 235 if (!builder->FullStacktrace()) {
238 return dart_handler_found; 236 return;
239 } 237 }
240 } 238 }
241 } 239 }
242 frame = frames.NextFrame(); 240 frame = frames.NextFrame();
243 ASSERT(frame != NULL); 241 ASSERT(frame != NULL);
244 } 242 }
245 ASSERT(frame->IsEntryFrame()); 243 ASSERT(frame->IsEntryFrame());
246 if (!handler_pc_set) { 244 if (!handler_pc_set) {
247 handler_pc_set = true; 245 handler_pc_set = true;
248 *handler_pc = frame->pc();
249 *handler_sp = frame->sp();
250 *handler_fp = frame->fp();
251 if (!builder->FullStacktrace()) { 246 if (!builder->FullStacktrace()) {
252 return dart_handler_found; 247 return;
253 } 248 }
254 } 249 }
255 frame = frames.NextFrame(); 250 frame = frames.NextFrame();
256 } 251 }
257 return dart_handler_found; 252 }
253
254
255 // Iterate through the stack frames and try to find a frame with an
256 // exception handler. Once found, set the pc, sp and fp so that execution
257 // can continue in that frame. Sets 'needs_stacktrace' if there is no
258 // cath-all handler or if a stack-trace is specified in the catch.
259 static bool FindExceptionHandler(uword* handler_pc,
260 uword* handler_sp,
261 uword* handler_fp,
262 bool* needs_stacktrace) {
263 StackFrameIterator frames(StackFrameIterator::kDontValidateFrames);
264 StackFrame* frame = frames.NextFrame();
265 ASSERT(frame != NULL); // We expect to find a dart invocation frame.
266 bool handler_pc_set = false;
267 *needs_stacktrace = false;
268 while (!frame->IsEntryFrame()) {
269 if (frame->IsDartFrame()) {
270 bool is_catch_all = false;
siva 2013/08/28 22:07:00 This can be hoisted above the while (..) loop?
srdjan 2013/08/28 22:37:21 Done
271 if (!handler_pc_set &&
272 frame->FindExceptionHandler(handler_pc,
273 needs_stacktrace,
274 &is_catch_all)) {
275 handler_pc_set = true;
276 *handler_sp = frame->sp();
277 *handler_fp = frame->fp();
278 if (*needs_stacktrace || is_catch_all) {
279 return true;
280 }
281 } else if (handler_pc_set) {
282 // We continue looking if stacktrace is needed.
283 uword dummy_handler_pc;
284 if (frame->FindExceptionHandler(&dummy_handler_pc,
285 needs_stacktrace,
286 &is_catch_all)) {
287 if (*needs_stacktrace || is_catch_all) {
288 return true;
289 }
290 }
291 }
siva 2013/08/28 22:07:00 Maybe the code could be simplified as: uword dumm
srdjan 2013/08/28 22:37:21 Nice! Done.
292 } // if frame->IsDartFrame
293 frame = frames.NextFrame();
294 ASSERT(frame != NULL);
295 } // while !frame->IsEntryFrame
296 ASSERT(frame->IsEntryFrame());
297 if (!handler_pc_set) {
298 *handler_pc = frame->pc();
299 *handler_sp = frame->sp();
300 *handler_fp = frame->fp();
301 }
302 // No catch-all encountered, needs stacktrace.
303 *needs_stacktrace = true;
304 return handler_pc_set;
258 } 305 }
259 306
260 307
261 static void FindErrorHandler(uword* handler_pc, 308 static void FindErrorHandler(uword* handler_pc,
262 uword* handler_sp, 309 uword* handler_sp,
263 uword* handler_fp) { 310 uword* handler_fp) {
264 // TODO(turnidge): Is there a faster way to get the next entry frame? 311 // TODO(turnidge): Is there a faster way to get the next entry frame?
265 StackFrameIterator frames(StackFrameIterator::kDontValidateFrames); 312 StackFrameIterator frames(StackFrameIterator::kDontValidateFrames);
266 StackFrame* frame = frames.NextFrame(); 313 StackFrame* frame = frames.NextFrame();
267 ASSERT(frame != NULL); 314 ASSERT(frame != NULL);
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after
357 Object::empty_array()); 404 Object::empty_array());
358 } else if (exception.raw() == isolate->object_store()->out_of_memory() || 405 } else if (exception.raw() == isolate->object_store()->out_of_memory() ||
359 exception.raw() == isolate->object_store()->stack_overflow()) { 406 exception.raw() == isolate->object_store()->stack_overflow()) {
360 use_preallocated_stacktrace = true; 407 use_preallocated_stacktrace = true;
361 } 408 }
362 uword handler_pc = 0; 409 uword handler_pc = 0;
363 uword handler_sp = 0; 410 uword handler_sp = 0;
364 uword handler_fp = 0; 411 uword handler_fp = 0;
365 Stacktrace& stacktrace = Stacktrace::Handle(isolate); 412 Stacktrace& stacktrace = Stacktrace::Handle(isolate);
366 bool handler_exists = false; 413 bool handler_exists = false;
414 bool handler_needs_stacktrace = false;
367 if (use_preallocated_stacktrace) { 415 if (use_preallocated_stacktrace) {
368 stacktrace ^= isolate->object_store()->preallocated_stack_trace(); 416 stacktrace ^= isolate->object_store()->preallocated_stack_trace();
369 PreallocatedStacktraceBuilder frame_builder(stacktrace); 417 PreallocatedStacktraceBuilder frame_builder(stacktrace);
370 handler_exists = FindExceptionHandler(&handler_pc, 418 handler_exists = FindExceptionHandler(&handler_pc,
371 &handler_sp, 419 &handler_sp,
372 &handler_fp, 420 &handler_fp,
373 &frame_builder); 421 &handler_needs_stacktrace);
422 if (handler_needs_stacktrace) {
423 BuildStackTrace(&frame_builder);
424 }
374 } else { 425 } else {
426 // Get stacktrace field of class Error.
375 const Field& stacktrace_field = 427 const Field& stacktrace_field =
376 Field::Handle(LookupStacktraceField(exception)); 428 Field::Handle(isolate, LookupStacktraceField(exception));
377 bool full_stacktrace = !stacktrace_field.IsNull(); 429 bool full_stacktrace = !stacktrace_field.IsNull();
378 RegularStacktraceBuilder frame_builder(full_stacktrace);
379 handler_exists = FindExceptionHandler(&handler_pc, 430 handler_exists = FindExceptionHandler(&handler_pc,
380 &handler_sp, 431 &handler_sp,
381 &handler_fp, 432 &handler_fp,
382 &frame_builder); 433 &handler_needs_stacktrace);
383 // Create arrays for function, code and pc_offset triplet of each frame. 434 Array& func_array = Array::Handle(isolate, Object::empty_array().raw());
384 const Array& func_array = 435 Array& code_array = Array::Handle(isolate, Object::empty_array().raw());
385 Array::Handle(isolate, Array::MakeArray(frame_builder.func_list())); 436 Array& pc_offset_array =
386 const Array& code_array = 437 Array::Handle(isolate, Object::empty_array().raw());
387 Array::Handle(isolate, Array::MakeArray(frame_builder.code_list())); 438 if (handler_needs_stacktrace || full_stacktrace) {
388 const Array& pc_offset_array = 439 RegularStacktraceBuilder frame_builder(full_stacktrace);
389 Array::Handle(isolate, 440 BuildStackTrace(&frame_builder);
390 Array::MakeArray(frame_builder.pc_offset_list())); 441
391 if (!stacktrace_field.IsNull()) { 442 // Create arrays for function, code and pc_offset triplet of each frame.
392 // This is an error object and we need to capture the full stack trace 443 func_array = Array::MakeArray(frame_builder.func_list());
393 // here implicitly, so we set up the stack trace. The stack trace field 444 code_array = Array::MakeArray(frame_builder.code_list());
394 // is set only once, it is not overriden. 445 pc_offset_array = Array::MakeArray(frame_builder.pc_offset_list());
395 const Array& catch_func_array = 446 if (!stacktrace_field.IsNull()) {
396 Array::Handle(isolate, 447 // This is an error object and we need to capture the full stack trace
397 Array::MakeArray(frame_builder.catch_func_list())); 448 // here implicitly, so we set up the stack trace. The stack trace field
398 const Array& catch_code_array = 449 // is set only once, it is not overriden.
399 Array::Handle(isolate, 450 const Array& catch_func_array = Array::Handle(isolate,
400 Array::MakeArray(frame_builder.catch_code_list())); 451 Array::MakeArray(frame_builder.catch_func_list()));
401 const Array& catch_pc_offset_array = 452 const Array& catch_code_array = Array::Handle(isolate,
402 Array::Handle(isolate, 453 Array::MakeArray(frame_builder.catch_code_list()));
403 Array::MakeArray(frame_builder.catch_pc_offset_list())); 454 const Array& catch_pc_offset_array = Array::Handle(isolate,
455 Array::MakeArray(frame_builder.catch_pc_offset_list()));
456 stacktrace = Stacktrace::New(func_array, code_array, pc_offset_array);
457 stacktrace.SetCatchStacktrace(catch_func_array,
458 catch_code_array,
459 catch_pc_offset_array);
460 if (exception.GetField(stacktrace_field) == Object::null()) {
461 exception.SetField(stacktrace_field, stacktrace);
462 }
463 } // if stacktrace needed.
464 }
465 if (existing_stacktrace.IsNull()) {
404 stacktrace = Stacktrace::New(func_array, code_array, pc_offset_array); 466 stacktrace = Stacktrace::New(func_array, code_array, pc_offset_array);
405 stacktrace.SetCatchStacktrace(catch_func_array,
406 catch_code_array,
407 catch_pc_offset_array);
408 if (exception.GetField(stacktrace_field) == Object::null()) {
409 exception.SetField(stacktrace_field, stacktrace);
410 }
411 }
412 // TODO(5411263): At some point we can optimize by figuring out if a
413 // stack trace is needed based on whether the catch code specifies a
414 // stack trace object or there is a rethrow in the catch clause.
415 if (existing_stacktrace.IsNull()) {
416 stacktrace = Stacktrace::New(func_array, code_array, pc_offset_array);
417 } else { 467 } else {
418 stacktrace ^= existing_stacktrace.raw(); 468 stacktrace ^= existing_stacktrace.raw();
419 if (pc_offset_array.Length() != 0) { 469 if (pc_offset_array.Length() != 0) {
420 stacktrace.Append(func_array, code_array, pc_offset_array); 470 stacktrace.Append(func_array, code_array, pc_offset_array);
421 } 471 }
422 // Since we are re throwing and appending to the existing stack trace 472 // Since we are re throwing and appending to the existing stack trace
423 // we clear out the catch trace collected in the existing stack trace 473 // we clear out the catch trace collected in the existing stack trace
424 // as that trace will not be valid anymore. 474 // as that trace will not be valid anymore.
425 stacktrace.SetCatchStacktrace(Object::empty_array(), 475 stacktrace.SetCatchStacktrace(Object::empty_array(),
426 Object::empty_array(), 476 Object::empty_array(),
(...skipping 275 matching lines...) Expand 10 before | Expand all | Expand 10 after
702 break; 752 break;
703 } 753 }
704 754
705 return DartLibraryCalls::InstanceCreate(library, 755 return DartLibraryCalls::InstanceCreate(library,
706 *class_name, 756 *class_name,
707 *constructor_name, 757 *constructor_name,
708 arguments); 758 arguments);
709 } 759 }
710 760
711 } // namespace dart 761 } // namespace dart
OLDNEW
« no previous file with comments | « runtime/vm/code_descriptors.h ('k') | runtime/vm/flow_graph_builder.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698