| 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 bool is_catch_all = false; |
| 269 uword temp_handler_pc = kUwordMax; |
| 270 while (!frame->IsEntryFrame()) { |
| 271 if (frame->IsDartFrame()) { |
| 272 if (frame->FindExceptionHandler(&temp_handler_pc, |
| 273 needs_stacktrace, |
| 274 &is_catch_all)) { |
| 275 if (!handler_pc_set) { |
| 276 handler_pc_set = true; |
| 277 *handler_pc = temp_handler_pc; |
| 278 *handler_sp = frame->sp(); |
| 279 *handler_fp = frame->fp(); |
| 280 } |
| 281 if (*needs_stacktrace || is_catch_all) { |
| 282 return true; |
| 283 } |
| 284 } |
| 285 } // if frame->IsDartFrame |
| 286 frame = frames.NextFrame(); |
| 287 ASSERT(frame != NULL); |
| 288 } // while !frame->IsEntryFrame |
| 289 ASSERT(frame->IsEntryFrame()); |
| 290 if (!handler_pc_set) { |
| 291 *handler_pc = frame->pc(); |
| 292 *handler_sp = frame->sp(); |
| 293 *handler_fp = frame->fp(); |
| 294 } |
| 295 // No catch-all encountered, needs stacktrace. |
| 296 *needs_stacktrace = true; |
| 297 return handler_pc_set; |
| 258 } | 298 } |
| 259 | 299 |
| 260 | 300 |
| 261 static void FindErrorHandler(uword* handler_pc, | 301 static void FindErrorHandler(uword* handler_pc, |
| 262 uword* handler_sp, | 302 uword* handler_sp, |
| 263 uword* handler_fp) { | 303 uword* handler_fp) { |
| 264 // TODO(turnidge): Is there a faster way to get the next entry frame? | 304 // TODO(turnidge): Is there a faster way to get the next entry frame? |
| 265 StackFrameIterator frames(StackFrameIterator::kDontValidateFrames); | 305 StackFrameIterator frames(StackFrameIterator::kDontValidateFrames); |
| 266 StackFrame* frame = frames.NextFrame(); | 306 StackFrame* frame = frames.NextFrame(); |
| 267 ASSERT(frame != NULL); | 307 ASSERT(frame != NULL); |
| (...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 357 Object::empty_array()); | 397 Object::empty_array()); |
| 358 } else if (exception.raw() == isolate->object_store()->out_of_memory() || | 398 } else if (exception.raw() == isolate->object_store()->out_of_memory() || |
| 359 exception.raw() == isolate->object_store()->stack_overflow()) { | 399 exception.raw() == isolate->object_store()->stack_overflow()) { |
| 360 use_preallocated_stacktrace = true; | 400 use_preallocated_stacktrace = true; |
| 361 } | 401 } |
| 362 uword handler_pc = 0; | 402 uword handler_pc = 0; |
| 363 uword handler_sp = 0; | 403 uword handler_sp = 0; |
| 364 uword handler_fp = 0; | 404 uword handler_fp = 0; |
| 365 Stacktrace& stacktrace = Stacktrace::Handle(isolate); | 405 Stacktrace& stacktrace = Stacktrace::Handle(isolate); |
| 366 bool handler_exists = false; | 406 bool handler_exists = false; |
| 407 bool handler_needs_stacktrace = false; |
| 367 if (use_preallocated_stacktrace) { | 408 if (use_preallocated_stacktrace) { |
| 368 stacktrace ^= isolate->object_store()->preallocated_stack_trace(); | 409 stacktrace ^= isolate->object_store()->preallocated_stack_trace(); |
| 369 PreallocatedStacktraceBuilder frame_builder(stacktrace); | 410 PreallocatedStacktraceBuilder frame_builder(stacktrace); |
| 370 handler_exists = FindExceptionHandler(&handler_pc, | 411 handler_exists = FindExceptionHandler(&handler_pc, |
| 371 &handler_sp, | 412 &handler_sp, |
| 372 &handler_fp, | 413 &handler_fp, |
| 373 &frame_builder); | 414 &handler_needs_stacktrace); |
| 415 if (handler_needs_stacktrace) { |
| 416 BuildStackTrace(&frame_builder); |
| 417 } |
| 374 } else { | 418 } else { |
| 419 // Get stacktrace field of class Error. |
| 375 const Field& stacktrace_field = | 420 const Field& stacktrace_field = |
| 376 Field::Handle(LookupStacktraceField(exception)); | 421 Field::Handle(isolate, LookupStacktraceField(exception)); |
| 377 bool full_stacktrace = !stacktrace_field.IsNull(); | 422 bool full_stacktrace = !stacktrace_field.IsNull(); |
| 378 RegularStacktraceBuilder frame_builder(full_stacktrace); | |
| 379 handler_exists = FindExceptionHandler(&handler_pc, | 423 handler_exists = FindExceptionHandler(&handler_pc, |
| 380 &handler_sp, | 424 &handler_sp, |
| 381 &handler_fp, | 425 &handler_fp, |
| 382 &frame_builder); | 426 &handler_needs_stacktrace); |
| 383 // Create arrays for function, code and pc_offset triplet of each frame. | 427 Array& func_array = Array::Handle(isolate, Object::empty_array().raw()); |
| 384 const Array& func_array = | 428 Array& code_array = Array::Handle(isolate, Object::empty_array().raw()); |
| 385 Array::Handle(isolate, Array::MakeArray(frame_builder.func_list())); | 429 Array& pc_offset_array = |
| 386 const Array& code_array = | 430 Array::Handle(isolate, Object::empty_array().raw()); |
| 387 Array::Handle(isolate, Array::MakeArray(frame_builder.code_list())); | 431 if (handler_needs_stacktrace || full_stacktrace) { |
| 388 const Array& pc_offset_array = | 432 RegularStacktraceBuilder frame_builder(full_stacktrace); |
| 389 Array::Handle(isolate, | 433 BuildStackTrace(&frame_builder); |
| 390 Array::MakeArray(frame_builder.pc_offset_list())); | 434 |
| 391 if (!stacktrace_field.IsNull()) { | 435 // 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 | 436 func_array = Array::MakeArray(frame_builder.func_list()); |
| 393 // here implicitly, so we set up the stack trace. The stack trace field | 437 code_array = Array::MakeArray(frame_builder.code_list()); |
| 394 // is set only once, it is not overriden. | 438 pc_offset_array = Array::MakeArray(frame_builder.pc_offset_list()); |
| 395 const Array& catch_func_array = | 439 if (!stacktrace_field.IsNull()) { |
| 396 Array::Handle(isolate, | 440 // This is an error object and we need to capture the full stack trace |
| 397 Array::MakeArray(frame_builder.catch_func_list())); | 441 // here implicitly, so we set up the stack trace. The stack trace field |
| 398 const Array& catch_code_array = | 442 // is set only once, it is not overriden. |
| 399 Array::Handle(isolate, | 443 const Array& catch_func_array = Array::Handle(isolate, |
| 400 Array::MakeArray(frame_builder.catch_code_list())); | 444 Array::MakeArray(frame_builder.catch_func_list())); |
| 401 const Array& catch_pc_offset_array = | 445 const Array& catch_code_array = Array::Handle(isolate, |
| 402 Array::Handle(isolate, | 446 Array::MakeArray(frame_builder.catch_code_list())); |
| 403 Array::MakeArray(frame_builder.catch_pc_offset_list())); | 447 const Array& catch_pc_offset_array = Array::Handle(isolate, |
| 448 Array::MakeArray(frame_builder.catch_pc_offset_list())); |
| 449 stacktrace = Stacktrace::New(func_array, code_array, pc_offset_array); |
| 450 stacktrace.SetCatchStacktrace(catch_func_array, |
| 451 catch_code_array, |
| 452 catch_pc_offset_array); |
| 453 if (exception.GetField(stacktrace_field) == Object::null()) { |
| 454 exception.SetField(stacktrace_field, stacktrace); |
| 455 } |
| 456 } // if stacktrace needed. |
| 457 } |
| 458 if (existing_stacktrace.IsNull()) { |
| 404 stacktrace = Stacktrace::New(func_array, code_array, pc_offset_array); | 459 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 { | 460 } else { |
| 418 stacktrace ^= existing_stacktrace.raw(); | 461 stacktrace ^= existing_stacktrace.raw(); |
| 419 if (pc_offset_array.Length() != 0) { | 462 if (pc_offset_array.Length() != 0) { |
| 420 stacktrace.Append(func_array, code_array, pc_offset_array); | 463 stacktrace.Append(func_array, code_array, pc_offset_array); |
| 421 } | 464 } |
| 422 // Since we are re throwing and appending to the existing stack trace | 465 // 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 | 466 // we clear out the catch trace collected in the existing stack trace |
| 424 // as that trace will not be valid anymore. | 467 // as that trace will not be valid anymore. |
| 425 stacktrace.SetCatchStacktrace(Object::empty_array(), | 468 stacktrace.SetCatchStacktrace(Object::empty_array(), |
| 426 Object::empty_array(), | 469 Object::empty_array(), |
| (...skipping 275 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 702 break; | 745 break; |
| 703 } | 746 } |
| 704 | 747 |
| 705 return DartLibraryCalls::InstanceCreate(library, | 748 return DartLibraryCalls::InstanceCreate(library, |
| 706 *class_name, | 749 *class_name, |
| 707 *constructor_name, | 750 *constructor_name, |
| 708 arguments); | 751 arguments); |
| 709 } | 752 } |
| 710 | 753 |
| 711 } // namespace dart | 754 } // namespace dart |
| OLD | NEW |