Chromium Code Reviews| 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/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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 |
| OLD | NEW |