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(); |
| 198 uword handler_pc = NULL; | |
|
hausner
2013/08/28 16:08:20
Should a uword variable not be initialized with 0?
siva
2013/08/28 17:00:09
Maybe intialize it to kUwordMax.
srdjan
2013/08/28 20:38:29
Initialized to kUWordMax and moved close to frame-
srdjan
2013/08/28 20:38:29
Using kUWordMax
| |
| 204 bool dart_handler_found = false; | 199 bool dart_handler_found = false; |
| 205 bool handler_pc_set = false; | 200 bool handler_pc_set = false; |
|
siva
2013/08/28 17:00:09
The variable dart_handler_found is not needed anym
srdjan
2013/08/28 20:38:29
Offline discussion: it is needed to note the catch
| |
| 206 while (frame != NULL) { | 201 while (frame != NULL) { |
| 207 while (!frame->IsEntryFrame()) { | 202 while (!frame->IsEntryFrame()) { |
| 208 if (frame->IsDartFrame()) { | 203 if (frame->IsDartFrame()) { |
| 209 code = frame->LookupDartCode(); | 204 code = frame->LookupDartCode(); |
| 210 if (code.is_optimized()) { | 205 if (code.is_optimized()) { |
| 211 // For optimized frames, extract all the inlined functions if any | 206 // For optimized frames, extract all the inlined functions if any |
| 212 // into the stack trace. | 207 // into the stack trace. |
| 213 for (InlinedFunctionsIterator it(frame); !it.Done(); it.Advance()) { | 208 for (InlinedFunctionsIterator it(frame); !it.Done(); it.Advance()) { |
| 214 func = it.function(); | 209 func = it.function(); |
| 215 code = it.code(); | 210 code = it.code(); |
| 216 uword pc = it.pc(); | 211 uword pc = it.pc(); |
| 217 ASSERT(pc != 0); | 212 ASSERT(pc != 0); |
| 218 ASSERT(code.EntryPoint() <= pc); | 213 ASSERT(code.EntryPoint() <= pc); |
| 219 ASSERT(pc < (code.EntryPoint() + code.Size())); | 214 ASSERT(pc < (code.EntryPoint() + code.Size())); |
| 220 if (ShouldShowFunction(func)) { | 215 if (ShouldShowFunction(func)) { |
| 221 offset = Smi::New(pc - code.EntryPoint()); | 216 offset = Smi::New(pc - code.EntryPoint()); |
| 222 builder->AddFrame(func, code, offset, dart_handler_found); | 217 builder->AddFrame(func, code, offset, dart_handler_found); |
| 223 } | 218 } |
| 224 } | 219 } |
| 225 } else { | 220 } else { |
| 226 offset = Smi::New(frame->pc() - code.EntryPoint()); | 221 offset = Smi::New(frame->pc() - code.EntryPoint()); |
| 227 func = code.function(); | 222 func = code.function(); |
| 228 if (ShouldShowFunction(func)) { | 223 if (ShouldShowFunction(func)) { |
| 229 builder->AddFrame(func, code, offset, dart_handler_found); | 224 builder->AddFrame(func, code, offset, dart_handler_found); |
| 230 } | 225 } |
| 231 } | 226 } |
| 232 if (!handler_pc_set && frame->FindExceptionHandler(handler_pc)) { | 227 bool needs_stacktrace = false; |
| 228 if (!handler_pc_set && | |
| 229 frame->FindExceptionHandler(&handler_pc, &needs_stacktrace)) { | |
| 233 handler_pc_set = true; | 230 handler_pc_set = true; |
| 234 *handler_sp = frame->sp(); | |
| 235 *handler_fp = frame->fp(); | |
| 236 dart_handler_found = true; | 231 dart_handler_found = true; |
| 237 if (!builder->FullStacktrace()) { | 232 if (!builder->FullStacktrace()) { |
| 238 return dart_handler_found; | 233 return; |
| 239 } | 234 } |
| 240 } | 235 } |
| 241 } | 236 } |
| 242 frame = frames.NextFrame(); | 237 frame = frames.NextFrame(); |
| 243 ASSERT(frame != NULL); | 238 ASSERT(frame != NULL); |
| 244 } | 239 } |
| 245 ASSERT(frame->IsEntryFrame()); | 240 ASSERT(frame->IsEntryFrame()); |
| 246 if (!handler_pc_set) { | 241 if (!handler_pc_set) { |
| 247 handler_pc_set = true; | 242 handler_pc_set = true; |
| 243 handler_pc = frame->pc(); | |
| 244 if (!builder->FullStacktrace()) { | |
| 245 return; | |
| 246 } | |
| 247 } | |
| 248 frame = frames.NextFrame(); | |
| 249 } | |
| 250 } | |
| 251 | |
| 252 | |
| 253 // Iterate through the stack frames and try to find a frame with an | |
| 254 // exception handler. Once found, set the pc, sp and fp so that execution | |
| 255 // can continue in that frame. | |
| 256 static bool FindExceptionHandler(uword* handler_pc, | |
| 257 uword* handler_sp, | |
| 258 uword* handler_fp, | |
| 259 bool* handler_needs_stacktrace) { | |
| 260 StackFrameIterator frames(StackFrameIterator::kDontValidateFrames); | |
| 261 StackFrame* frame = frames.NextFrame(); | |
| 262 ASSERT(frame != NULL); // We expect to find a dart invocation frame. | |
| 263 bool handler_pc_set = false; | |
| 264 *handler_needs_stacktrace = false; | |
| 265 while (frame != NULL) { | |
| 266 while (!frame->IsEntryFrame()) { | |
| 267 if (frame->IsDartFrame()) { | |
| 268 if (!handler_pc_set && | |
| 269 frame->FindExceptionHandler(handler_pc, handler_needs_stacktrace)) { | |
| 270 handler_pc_set = true; | |
| 271 *handler_sp = frame->sp(); | |
| 272 *handler_fp = frame->fp(); | |
| 273 return true; | |
|
siva
2013/08/28 17:00:09
Don't you have to keep going till you hit the entr
srdjan
2013/08/28 20:38:29
Good 'catch'!
| |
| 274 } | |
| 275 } | |
| 276 frame = frames.NextFrame(); | |
| 277 ASSERT(frame != NULL); | |
| 278 } // while !frame->IsEntryFrame. | |
| 279 ASSERT(frame->IsEntryFrame()); | |
| 280 if (!handler_pc_set) { | |
| 281 handler_pc_set = true; | |
| 248 *handler_pc = frame->pc(); | 282 *handler_pc = frame->pc(); |
| 249 *handler_sp = frame->sp(); | 283 *handler_sp = frame->sp(); |
| 250 *handler_fp = frame->fp(); | 284 *handler_fp = frame->fp(); |
| 251 if (!builder->FullStacktrace()) { | 285 *handler_needs_stacktrace = true; |
| 252 return dart_handler_found; | |
| 253 } | |
| 254 } | 286 } |
| 255 frame = frames.NextFrame(); | 287 frame = frames.NextFrame(); |
| 256 } | 288 } // while frame != NULL. |
| 257 return dart_handler_found; | 289 return false; |
|
siva
2013/08/28 17:00:09
Since you are not building a full stack trace anym
srdjan
2013/08/28 20:38:29
Done.
| |
| 258 } | 290 } |
| 259 | 291 |
| 260 | 292 |
| 261 static void FindErrorHandler(uword* handler_pc, | 293 static void FindErrorHandler(uword* handler_pc, |
| 262 uword* handler_sp, | 294 uword* handler_sp, |
| 263 uword* handler_fp) { | 295 uword* handler_fp) { |
| 264 // TODO(turnidge): Is there a faster way to get the next entry frame? | 296 // TODO(turnidge): Is there a faster way to get the next entry frame? |
| 265 StackFrameIterator frames(StackFrameIterator::kDontValidateFrames); | 297 StackFrameIterator frames(StackFrameIterator::kDontValidateFrames); |
| 266 StackFrame* frame = frames.NextFrame(); | 298 StackFrame* frame = frames.NextFrame(); |
| 267 ASSERT(frame != NULL); | 299 ASSERT(frame != NULL); |
| (...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 357 Object::empty_array()); | 389 Object::empty_array()); |
| 358 } else if (exception.raw() == isolate->object_store()->out_of_memory() || | 390 } else if (exception.raw() == isolate->object_store()->out_of_memory() || |
| 359 exception.raw() == isolate->object_store()->stack_overflow()) { | 391 exception.raw() == isolate->object_store()->stack_overflow()) { |
| 360 use_preallocated_stacktrace = true; | 392 use_preallocated_stacktrace = true; |
| 361 } | 393 } |
| 362 uword handler_pc = 0; | 394 uword handler_pc = 0; |
| 363 uword handler_sp = 0; | 395 uword handler_sp = 0; |
| 364 uword handler_fp = 0; | 396 uword handler_fp = 0; |
| 365 Stacktrace& stacktrace = Stacktrace::Handle(isolate); | 397 Stacktrace& stacktrace = Stacktrace::Handle(isolate); |
| 366 bool handler_exists = false; | 398 bool handler_exists = false; |
| 399 bool handler_needs_stacktrace = false; | |
| 367 if (use_preallocated_stacktrace) { | 400 if (use_preallocated_stacktrace) { |
| 368 stacktrace ^= isolate->object_store()->preallocated_stack_trace(); | 401 stacktrace ^= isolate->object_store()->preallocated_stack_trace(); |
| 369 PreallocatedStacktraceBuilder frame_builder(stacktrace); | 402 PreallocatedStacktraceBuilder frame_builder(stacktrace); |
| 370 handler_exists = FindExceptionHandler(&handler_pc, | 403 handler_exists = FindExceptionHandler(&handler_pc, |
| 371 &handler_sp, | 404 &handler_sp, |
| 372 &handler_fp, | 405 &handler_fp, |
| 373 &frame_builder); | 406 &handler_needs_stacktrace); |
| 407 if (handler_needs_stacktrace) { | |
| 408 BuildStackTrace(&frame_builder); | |
| 409 } | |
| 374 } else { | 410 } else { |
| 411 // Get stacktrace field of class Error. | |
| 375 const Field& stacktrace_field = | 412 const Field& stacktrace_field = |
| 376 Field::Handle(LookupStacktraceField(exception)); | 413 Field::Handle(isolate, LookupStacktraceField(exception)); |
| 377 bool full_stacktrace = !stacktrace_field.IsNull(); | 414 bool full_stacktrace = !stacktrace_field.IsNull(); |
| 378 RegularStacktraceBuilder frame_builder(full_stacktrace); | |
| 379 handler_exists = FindExceptionHandler(&handler_pc, | 415 handler_exists = FindExceptionHandler(&handler_pc, |
| 380 &handler_sp, | 416 &handler_sp, |
| 381 &handler_fp, | 417 &handler_fp, |
| 382 &frame_builder); | 418 &handler_needs_stacktrace); |
| 383 // Create arrays for function, code and pc_offset triplet of each frame. | 419 Array& func_array = Array::Handle(isolate, Object::empty_array().raw()); |
| 384 const Array& func_array = | 420 Array& code_array = Array::Handle(isolate, Object::empty_array().raw()); |
| 385 Array::Handle(isolate, Array::MakeArray(frame_builder.func_list())); | 421 Array& pc_offset_array = |
| 386 const Array& code_array = | 422 Array::Handle(isolate, Object::empty_array().raw()); |
| 387 Array::Handle(isolate, Array::MakeArray(frame_builder.code_list())); | 423 if (handler_needs_stacktrace || full_stacktrace) { |
| 388 const Array& pc_offset_array = | 424 RegularStacktraceBuilder frame_builder(full_stacktrace); |
| 389 Array::Handle(isolate, | 425 BuildStackTrace(&frame_builder); |
| 390 Array::MakeArray(frame_builder.pc_offset_list())); | 426 |
| 391 if (!stacktrace_field.IsNull()) { | 427 // 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 | 428 func_array = Array::MakeArray(frame_builder.func_list()); |
| 393 // here implicitly, so we set up the stack trace. The stack trace field | 429 code_array = Array::MakeArray(frame_builder.code_list()); |
| 394 // is set only once, it is not overriden. | 430 pc_offset_array = Array::MakeArray(frame_builder.pc_offset_list()); |
| 395 const Array& catch_func_array = | 431 if (!stacktrace_field.IsNull()) { |
| 396 Array::Handle(isolate, | 432 // This is an error object and we need to capture the full stack trace |
| 397 Array::MakeArray(frame_builder.catch_func_list())); | 433 // here implicitly, so we set up the stack trace. The stack trace field |
| 398 const Array& catch_code_array = | 434 // is set only once, it is not overriden. |
| 399 Array::Handle(isolate, | 435 const Array& catch_func_array = Array::Handle(isolate, |
| 400 Array::MakeArray(frame_builder.catch_code_list())); | 436 Array::MakeArray(frame_builder.catch_func_list())); |
| 401 const Array& catch_pc_offset_array = | 437 const Array& catch_code_array = Array::Handle(isolate, |
| 402 Array::Handle(isolate, | 438 Array::MakeArray(frame_builder.catch_code_list())); |
| 403 Array::MakeArray(frame_builder.catch_pc_offset_list())); | 439 const Array& catch_pc_offset_array = Array::Handle(isolate, |
| 440 Array::MakeArray(frame_builder.catch_pc_offset_list())); | |
| 441 stacktrace = Stacktrace::New(func_array, code_array, pc_offset_array); | |
| 442 stacktrace.SetCatchStacktrace(catch_func_array, | |
| 443 catch_code_array, | |
| 444 catch_pc_offset_array); | |
| 445 if (exception.GetField(stacktrace_field) == Object::null()) { | |
| 446 exception.SetField(stacktrace_field, stacktrace); | |
| 447 } | |
| 448 } // if stacktrace needed. | |
| 449 } | |
| 450 if (existing_stacktrace.IsNull()) { | |
| 404 stacktrace = Stacktrace::New(func_array, code_array, pc_offset_array); | 451 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 { | 452 } else { |
| 418 stacktrace ^= existing_stacktrace.raw(); | 453 stacktrace ^= existing_stacktrace.raw(); |
| 419 if (pc_offset_array.Length() != 0) { | 454 if (pc_offset_array.Length() != 0) { |
| 420 stacktrace.Append(func_array, code_array, pc_offset_array); | 455 stacktrace.Append(func_array, code_array, pc_offset_array); |
| 421 } | 456 } |
| 422 // Since we are re throwing and appending to the existing stack trace | 457 // 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 | 458 // we clear out the catch trace collected in the existing stack trace |
| 424 // as that trace will not be valid anymore. | 459 // as that trace will not be valid anymore. |
| 425 stacktrace.SetCatchStacktrace(Object::empty_array(), | 460 stacktrace.SetCatchStacktrace(Object::empty_array(), |
| 426 Object::empty_array(), | 461 Object::empty_array(), |
| (...skipping 275 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 702 break; | 737 break; |
| 703 } | 738 } |
| 704 | 739 |
| 705 return DartLibraryCalls::InstanceCreate(library, | 740 return DartLibraryCalls::InstanceCreate(library, |
| 706 *class_name, | 741 *class_name, |
| 707 *constructor_name, | 742 *constructor_name, |
| 708 arguments); | 743 arguments); |
| 709 } | 744 } |
| 710 | 745 |
| 711 } // namespace dart | 746 } // namespace dart |
| OLD | NEW |