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 "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" |
11 #include "vm/debugger.h" | 11 #include "vm/debugger.h" |
12 #include "vm/flags.h" | 12 #include "vm/flags.h" |
| 13 #include "vm/log.h" |
13 #include "vm/object.h" | 14 #include "vm/object.h" |
14 #include "vm/object_store.h" | 15 #include "vm/object_store.h" |
15 #include "vm/stack_frame.h" | 16 #include "vm/stack_frame.h" |
16 #include "vm/stub_code.h" | 17 #include "vm/stub_code.h" |
17 #include "vm/symbols.h" | 18 #include "vm/symbols.h" |
18 #include "vm/tags.h" | 19 #include "vm/tags.h" |
19 | 20 |
20 namespace dart { | 21 namespace dart { |
21 | 22 |
22 DEFINE_FLAG(bool, print_stacktrace_at_throw, false, | 23 DEFINE_FLAG(bool, print_stacktrace_at_throw, false, |
23 "Prints a stack trace everytime a throw occurs."); | 24 "Prints a stack trace everytime a throw occurs."); |
24 | 25 |
25 | 26 |
26 const char* Exceptions::kCastErrorDstName = "type cast"; | |
27 | |
28 | |
29 class StacktraceBuilder : public ValueObject { | 27 class StacktraceBuilder : public ValueObject { |
30 public: | 28 public: |
31 StacktraceBuilder() { } | 29 StacktraceBuilder() { } |
32 virtual ~StacktraceBuilder() { } | 30 virtual ~StacktraceBuilder() { } |
33 | 31 |
34 virtual void AddFrame(const Code& code, const Smi& offset) = 0; | 32 virtual void AddFrame(const Code& code, const Smi& offset) = 0; |
35 }; | 33 }; |
36 | 34 |
37 | 35 |
38 class RegularStacktraceBuilder : public StacktraceBuilder { | 36 class RegularStacktraceBuilder : public StacktraceBuilder { |
(...skipping 325 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
364 } | 362 } |
365 } | 363 } |
366 } | 364 } |
367 // We expect to find a handler_pc, if the exception is unhandled | 365 // We expect to find a handler_pc, if the exception is unhandled |
368 // then we expect to at least have the dart entry frame on the | 366 // then we expect to at least have the dart entry frame on the |
369 // stack as Exceptions::Throw should happen only after a dart | 367 // stack as Exceptions::Throw should happen only after a dart |
370 // invocation has been done. | 368 // invocation has been done. |
371 ASSERT(handler_pc != 0); | 369 ASSERT(handler_pc != 0); |
372 | 370 |
373 if (FLAG_print_stacktrace_at_throw) { | 371 if (FLAG_print_stacktrace_at_throw) { |
374 OS::Print("Exception '%s' thrown:\n", exception.ToCString()); | 372 THR_Print("Exception '%s' thrown:\n", exception.ToCString()); |
375 OS::Print("%s\n", stacktrace.ToCString()); | 373 THR_Print("%s\n", stacktrace.ToCString()); |
376 } | 374 } |
377 if (handler_exists) { | 375 if (handler_exists) { |
378 // Found a dart handler for the exception, jump to it. | 376 // Found a dart handler for the exception, jump to it. |
379 JumpToExceptionHandler(thread, | 377 JumpToExceptionHandler(thread, |
380 handler_pc, | 378 handler_pc, |
381 handler_sp, | 379 handler_sp, |
382 handler_fp, | 380 handler_fp, |
383 exception, | 381 exception, |
384 stacktrace); | 382 stacktrace); |
385 } else { | 383 } else { |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
427 Class& cls = Class::Handle(core_lib.LookupClass(cls_name)); | 425 Class& cls = Class::Handle(core_lib.LookupClass(cls_name)); |
428 ASSERT(!cls.IsNull()); | 426 ASSERT(!cls.IsNull()); |
429 // There are no parameterized error types, so no need to set type arguments. | 427 // There are no parameterized error types, so no need to set type arguments. |
430 return Instance::New(cls); | 428 return Instance::New(cls); |
431 } | 429 } |
432 | 430 |
433 | 431 |
434 // Allocate, initialize, and throw a TypeError or CastError. | 432 // Allocate, initialize, and throw a TypeError or CastError. |
435 // If error_msg is not null, throw a TypeError, even for a type cast. | 433 // If error_msg is not null, throw a TypeError, even for a type cast. |
436 void Exceptions::CreateAndThrowTypeError(TokenPosition location, | 434 void Exceptions::CreateAndThrowTypeError(TokenPosition location, |
437 const String& src_type_name, | 435 const AbstractType& src_type, |
438 const String& dst_type_name, | 436 const AbstractType& dst_type, |
439 const String& dst_name, | 437 const String& dst_name, |
440 const String& error_msg) { | 438 const String& bound_error_msg) { |
441 const Array& args = Array::Handle(Array::New(7)); | 439 ASSERT(!dst_name.IsNull()); // Pass Symbols::Empty() instead. |
| 440 Zone* zone = Thread::Current()->zone(); |
| 441 const Array& args = Array::Handle(zone, Array::New(4)); |
442 | 442 |
443 ExceptionType exception_type = | 443 ExceptionType exception_type = |
444 (error_msg.IsNull() && dst_name.Equals(kCastErrorDstName)) ? | 444 (bound_error_msg.IsNull() && |
445 kCast : kType; | 445 (dst_name.raw() == Symbols::InTypeCast().raw())) ? kCast : kType; |
446 | 446 |
447 DartFrameIterator iterator; | 447 DartFrameIterator iterator; |
448 const Script& script = Script::Handle(GetCallerScript(&iterator)); | 448 const Script& script = Script::Handle(zone, GetCallerScript(&iterator)); |
449 intptr_t line; | 449 intptr_t line; |
450 intptr_t column = -1; | 450 intptr_t column = -1; |
451 if (script.HasSource()) { | 451 if (script.HasSource()) { |
452 script.GetTokenLocation(location, &line, &column); | 452 script.GetTokenLocation(location, &line, &column); |
453 } else { | 453 } else { |
454 script.GetTokenLocation(location, &line, NULL); | 454 script.GetTokenLocation(location, &line, NULL); |
455 } | 455 } |
456 // Initialize '_url', '_line', and '_column' arguments. | 456 // Initialize '_url', '_line', and '_column' arguments. |
457 args.SetAt(0, String::Handle(script.url())); | 457 args.SetAt(0, String::Handle(zone, script.url())); |
458 args.SetAt(1, Smi::Handle(Smi::New(line))); | 458 args.SetAt(1, Smi::Handle(zone, Smi::New(line))); |
459 args.SetAt(2, Smi::Handle(Smi::New(column))); | 459 args.SetAt(2, Smi::Handle(zone, Smi::New(column))); |
460 | 460 |
461 // Initialize '_srcType', '_dstType', '_dstName', and '_errorMsg'. | 461 // Construct '_errorMsg'. |
462 args.SetAt(3, src_type_name); | 462 GrowableHandlePtrArray<const String> pieces(zone, 20); |
463 args.SetAt(4, dst_type_name); | 463 |
464 args.SetAt(5, dst_name); | 464 // Print bound error first, if any. |
465 args.SetAt(6, error_msg); | 465 if (!bound_error_msg.IsNull() && (bound_error_msg.Length() > 0)) { |
| 466 pieces.Add(bound_error_msg); |
| 467 pieces.Add(Symbols::NewLine()); |
| 468 } |
| 469 |
| 470 // If dst_type is malformed or malbounded, only print the embedded error. |
| 471 if (!dst_type.IsNull()) { |
| 472 const LanguageError& error = LanguageError::Handle(zone, dst_type.error()); |
| 473 if (!error.IsNull()) { |
| 474 // Print the embedded error only. |
| 475 pieces.Add(String::Handle(zone, Symbols::New(error.ToErrorCString()))); |
| 476 pieces.Add(Symbols::NewLine()); |
| 477 } else { |
| 478 // Describe the type error. |
| 479 if (!src_type.IsNull()) { |
| 480 pieces.Add(Symbols::TypeQuote()); |
| 481 pieces.Add(String::Handle(zone, src_type.UserVisibleName())); |
| 482 pieces.Add(Symbols::QuoteIsNotASubtypeOf()); |
| 483 } |
| 484 pieces.Add(Symbols::TypeQuote()); |
| 485 pieces.Add(String::Handle(zone, dst_type.UserVisibleName())); |
| 486 pieces.Add(Symbols::SingleQuote()); |
| 487 if (exception_type == kCast) { |
| 488 pieces.Add(dst_name); |
| 489 } else if (dst_name.Length() > 0) { |
| 490 pieces.Add(Symbols::SpaceOfSpace()); |
| 491 pieces.Add(Symbols::SingleQuote()); |
| 492 pieces.Add(dst_name); |
| 493 pieces.Add(Symbols::SingleQuote()); |
| 494 } |
| 495 // Print URIs of src and dst types. |
| 496 pieces.Add(Symbols::SpaceWhereNewLine()); |
| 497 if (!src_type.IsNull()) { |
| 498 pieces.Add(String::Handle(zone, src_type.EnumerateURIs())); |
| 499 } |
| 500 if (!dst_type.IsDynamicType() && !dst_type.IsVoidType()) { |
| 501 pieces.Add(String::Handle(zone, dst_type.EnumerateURIs())); |
| 502 } |
| 503 } |
| 504 } |
| 505 const String& error_msg = |
| 506 String::Handle(zone, Symbols::FromConcatAll(pieces)); |
| 507 args.SetAt(3, error_msg); |
466 | 508 |
467 // Type errors in the core library may be difficult to diagnose. | 509 // Type errors in the core library may be difficult to diagnose. |
468 // Print type error information before throwing the error when debugging. | 510 // Print type error information before throwing the error when debugging. |
469 if (FLAG_print_stacktrace_at_throw) { | 511 if (FLAG_print_stacktrace_at_throw) { |
470 if (!error_msg.IsNull()) { | 512 THR_Print("'%s': Failed type check: line %" Pd " pos %" Pd ": ", |
471 OS::Print("%s\n", error_msg.ToCString()); | 513 String::Handle(zone, script.url()).ToCString(), line, column); |
472 } | 514 THR_Print("%s\n", error_msg.ToCString()); |
473 OS::Print("'%s': Failed type check: line %" Pd " pos %" Pd ": ", | |
474 String::Handle(script.url()).ToCString(), line, column); | |
475 if (!dst_name.IsNull() && (dst_name.Length() > 0)) { | |
476 OS::Print("type '%s' is not a subtype of type '%s' of '%s'.\n", | |
477 src_type_name.ToCString(), | |
478 dst_type_name.ToCString(), | |
479 dst_name.ToCString()); | |
480 } else { | |
481 OS::Print("type error.\n"); | |
482 } | |
483 } | 515 } |
484 | 516 |
485 // Throw TypeError or CastError instance. | 517 // Throw TypeError or CastError instance. |
486 Exceptions::ThrowByType(exception_type, args); | 518 Exceptions::ThrowByType(exception_type, args); |
487 UNREACHABLE(); | 519 UNREACHABLE(); |
488 } | 520 } |
489 | 521 |
490 | 522 |
491 void Exceptions::Throw(Thread* thread, const Instance& exception) { | 523 void Exceptions::Throw(Thread* thread, const Instance& exception) { |
492 // Do not notify debugger on stack overflow and out of memory exceptions. | 524 // Do not notify debugger on stack overflow and out of memory exceptions. |
(...skipping 174 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
667 } | 699 } |
668 | 700 |
669 return DartLibraryCalls::InstanceCreate(library, | 701 return DartLibraryCalls::InstanceCreate(library, |
670 *class_name, | 702 *class_name, |
671 *constructor_name, | 703 *constructor_name, |
672 arguments); | 704 arguments); |
673 } | 705 } |
674 | 706 |
675 | 707 |
676 } // namespace dart | 708 } // namespace dart |
OLD | NEW |