| 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 |