| 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/log.h" |
| 14 #include "vm/longjump.h" | 14 #include "vm/longjump.h" |
| 15 #include "vm/object.h" | 15 #include "vm/object.h" |
| 16 #include "vm/object_store.h" | 16 #include "vm/object_store.h" |
| 17 #include "vm/stack_frame.h" | 17 #include "vm/stack_frame.h" |
| 18 #include "vm/stub_code.h" | 18 #include "vm/stub_code.h" |
| 19 #include "vm/symbols.h" | 19 #include "vm/symbols.h" |
| 20 #include "vm/tags.h" | 20 #include "vm/tags.h" |
| 21 | 21 |
| 22 namespace dart { | 22 namespace dart { |
| 23 | 23 |
| 24 DECLARE_FLAG(bool, trace_deoptimization); | 24 DECLARE_FLAG(bool, trace_deoptimization); |
| 25 DEFINE_FLAG(bool, print_stacktrace_at_throw, false, | 25 DEFINE_FLAG(bool, |
| 26 print_stacktrace_at_throw, |
| 27 false, |
| 26 "Prints a stack trace everytime a throw occurs."); | 28 "Prints a stack trace everytime a throw occurs."); |
| 27 | 29 |
| 28 | 30 |
| 29 class StacktraceBuilder : public ValueObject { | 31 class StacktraceBuilder : public ValueObject { |
| 30 public: | 32 public: |
| 31 StacktraceBuilder() { } | 33 StacktraceBuilder() {} |
| 32 virtual ~StacktraceBuilder() { } | 34 virtual ~StacktraceBuilder() {} |
| 33 | 35 |
| 34 virtual void AddFrame(const Code& code, const Smi& offset) = 0; | 36 virtual void AddFrame(const Code& code, const Smi& offset) = 0; |
| 35 }; | 37 }; |
| 36 | 38 |
| 37 | 39 |
| 38 class RegularStacktraceBuilder : public StacktraceBuilder { | 40 class RegularStacktraceBuilder : public StacktraceBuilder { |
| 39 public: | 41 public: |
| 40 explicit RegularStacktraceBuilder(Zone* zone) | 42 explicit RegularStacktraceBuilder(Zone* zone) |
| 41 : code_list_( | 43 : code_list_( |
| 42 GrowableObjectArray::Handle(zone, GrowableObjectArray::New())), | 44 GrowableObjectArray::Handle(zone, GrowableObjectArray::New())), |
| 43 pc_offset_list_( | 45 pc_offset_list_( |
| 44 GrowableObjectArray::Handle(zone, GrowableObjectArray::New())) { } | 46 GrowableObjectArray::Handle(zone, GrowableObjectArray::New())) {} |
| 45 ~RegularStacktraceBuilder() { } | 47 ~RegularStacktraceBuilder() {} |
| 46 | 48 |
| 47 const GrowableObjectArray& code_list() const { return code_list_; } | 49 const GrowableObjectArray& code_list() const { return code_list_; } |
| 48 const GrowableObjectArray& pc_offset_list() const { return pc_offset_list_; } | 50 const GrowableObjectArray& pc_offset_list() const { return pc_offset_list_; } |
| 49 | 51 |
| 50 virtual void AddFrame(const Code& code, const Smi& offset) { | 52 virtual void AddFrame(const Code& code, const Smi& offset) { |
| 51 code_list_.Add(code); | 53 code_list_.Add(code); |
| 52 pc_offset_list_.Add(offset); | 54 pc_offset_list_.Add(offset); |
| 53 } | 55 } |
| 54 | 56 |
| 55 private: | 57 private: |
| 56 const GrowableObjectArray& code_list_; | 58 const GrowableObjectArray& code_list_; |
| 57 const GrowableObjectArray& pc_offset_list_; | 59 const GrowableObjectArray& pc_offset_list_; |
| 58 | 60 |
| 59 DISALLOW_COPY_AND_ASSIGN(RegularStacktraceBuilder); | 61 DISALLOW_COPY_AND_ASSIGN(RegularStacktraceBuilder); |
| 60 }; | 62 }; |
| 61 | 63 |
| 62 | 64 |
| 63 class PreallocatedStacktraceBuilder : public StacktraceBuilder { | 65 class PreallocatedStacktraceBuilder : public StacktraceBuilder { |
| 64 public: | 66 public: |
| 65 explicit PreallocatedStacktraceBuilder(const Instance& stacktrace) | 67 explicit PreallocatedStacktraceBuilder(const Instance& stacktrace) |
| 66 : stacktrace_(Stacktrace::Cast(stacktrace)), | 68 : stacktrace_(Stacktrace::Cast(stacktrace)), |
| 67 cur_index_(0), | 69 cur_index_(0), |
| 68 dropped_frames_(0) { | 70 dropped_frames_(0) { |
| 69 ASSERT(stacktrace_.raw() == | 71 ASSERT(stacktrace_.raw() == |
| 70 Isolate::Current()->object_store()->preallocated_stack_trace()); | 72 Isolate::Current()->object_store()->preallocated_stack_trace()); |
| 71 } | 73 } |
| 72 ~PreallocatedStacktraceBuilder() { } | 74 ~PreallocatedStacktraceBuilder() {} |
| 73 | 75 |
| 74 virtual void AddFrame(const Code& code, const Smi& offset); | 76 virtual void AddFrame(const Code& code, const Smi& offset); |
| 75 | 77 |
| 76 private: | 78 private: |
| 77 static const int kNumTopframes = Stacktrace::kPreallocatedStackdepth / 2; | 79 static const int kNumTopframes = Stacktrace::kPreallocatedStackdepth / 2; |
| 78 | 80 |
| 79 const Stacktrace& stacktrace_; | 81 const Stacktrace& stacktrace_; |
| 80 intptr_t cur_index_; | 82 intptr_t cur_index_; |
| 81 intptr_t dropped_frames_; | 83 intptr_t dropped_frames_; |
| 82 | 84 |
| (...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 149 bool* needs_stacktrace) { | 151 bool* needs_stacktrace) { |
| 150 StackFrameIterator frames(StackFrameIterator::kDontValidateFrames); | 152 StackFrameIterator frames(StackFrameIterator::kDontValidateFrames); |
| 151 StackFrame* frame = frames.NextFrame(); | 153 StackFrame* frame = frames.NextFrame(); |
| 152 if (frame == NULL) return false; // No Dart frame. | 154 if (frame == NULL) return false; // No Dart frame. |
| 153 bool handler_pc_set = false; | 155 bool handler_pc_set = false; |
| 154 *needs_stacktrace = false; | 156 *needs_stacktrace = false; |
| 155 bool is_catch_all = false; | 157 bool is_catch_all = false; |
| 156 uword temp_handler_pc = kUwordMax; | 158 uword temp_handler_pc = kUwordMax; |
| 157 while (!frame->IsEntryFrame()) { | 159 while (!frame->IsEntryFrame()) { |
| 158 if (frame->IsDartFrame()) { | 160 if (frame->IsDartFrame()) { |
| 159 if (frame->FindExceptionHandler(thread, | 161 if (frame->FindExceptionHandler(thread, &temp_handler_pc, |
| 160 &temp_handler_pc, | 162 needs_stacktrace, &is_catch_all)) { |
| 161 needs_stacktrace, | |
| 162 &is_catch_all)) { | |
| 163 if (!handler_pc_set) { | 163 if (!handler_pc_set) { |
| 164 handler_pc_set = true; | 164 handler_pc_set = true; |
| 165 *handler_pc = temp_handler_pc; | 165 *handler_pc = temp_handler_pc; |
| 166 *handler_sp = frame->sp(); | 166 *handler_sp = frame->sp(); |
| 167 *handler_fp = frame->fp(); | 167 *handler_fp = frame->fp(); |
| 168 } | 168 } |
| 169 if (*needs_stacktrace || is_catch_all) { | 169 if (*needs_stacktrace || is_catch_all) { |
| 170 return true; | 170 return true; |
| 171 } | 171 } |
| 172 } | 172 } |
| (...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 252 } | 252 } |
| 253 } | 253 } |
| 254 | 254 |
| 255 #if defined(DEBUG) | 255 #if defined(DEBUG) |
| 256 ValidateFrames(); | 256 ValidateFrames(); |
| 257 #endif | 257 #endif |
| 258 | 258 |
| 259 for (intptr_t i = 0; i < pending_deopts->length(); i++) { | 259 for (intptr_t i = 0; i < pending_deopts->length(); i++) { |
| 260 if ((*pending_deopts)[i].fp() < frame_pointer) { | 260 if ((*pending_deopts)[i].fp() < frame_pointer) { |
| 261 if (FLAG_trace_deoptimization) { | 261 if (FLAG_trace_deoptimization) { |
| 262 THR_Print("Lazy deopt skipped due to throw for " | 262 THR_Print( |
| 263 "fp=%" Pp ", pc=%" Pp "\n", | 263 "Lazy deopt skipped due to throw for " |
| 264 (*pending_deopts)[i].fp(), (*pending_deopts)[i].pc()); | 264 "fp=%" Pp ", pc=%" Pp "\n", |
| 265 (*pending_deopts)[i].fp(), (*pending_deopts)[i].pc()); |
| 265 } | 266 } |
| 266 pending_deopts->RemoveAt(i); | 267 pending_deopts->RemoveAt(i); |
| 267 } | 268 } |
| 268 } | 269 } |
| 269 | 270 |
| 270 #if defined(DEBUG) | 271 #if defined(DEBUG) |
| 271 ValidateFrames(); | 272 ValidateFrames(); |
| 272 #endif | 273 #endif |
| 273 } | 274 } |
| 274 #endif // !DBC | 275 #endif // !DBC |
| (...skipping 21 matching lines...) Expand all Loading... |
| 296 typedef void (*ExcpHandler)(uword, uword, uword, RawObject*, RawObject*, | 297 typedef void (*ExcpHandler)(uword, uword, uword, RawObject*, RawObject*, |
| 297 Thread*); | 298 Thread*); |
| 298 ExcpHandler func = reinterpret_cast<ExcpHandler>( | 299 ExcpHandler func = reinterpret_cast<ExcpHandler>( |
| 299 StubCode::JumpToExceptionHandler_entry()->EntryPoint()); | 300 StubCode::JumpToExceptionHandler_entry()->EntryPoint()); |
| 300 | 301 |
| 301 // Unpoison the stack before we tear it down in the generated stub code. | 302 // Unpoison the stack before we tear it down in the generated stub code. |
| 302 uword current_sp = Thread::GetCurrentStackPointer() - 1024; | 303 uword current_sp = Thread::GetCurrentStackPointer() - 1024; |
| 303 ASAN_UNPOISON(reinterpret_cast<void*>(current_sp), | 304 ASAN_UNPOISON(reinterpret_cast<void*>(current_sp), |
| 304 stack_pointer - current_sp); | 305 stack_pointer - current_sp); |
| 305 | 306 |
| 306 func(program_counter, stack_pointer, frame_pointer, | 307 func(program_counter, stack_pointer, frame_pointer, raw_exception, |
| 307 raw_exception, raw_stacktrace, thread); | 308 raw_stacktrace, thread); |
| 308 #endif | 309 #endif |
| 309 UNREACHABLE(); | 310 UNREACHABLE(); |
| 310 } | 311 } |
| 311 | 312 |
| 312 | 313 |
| 313 static RawField* LookupStacktraceField(const Instance& instance) { | 314 static RawField* LookupStacktraceField(const Instance& instance) { |
| 314 if (instance.GetClassId() < kNumPredefinedCids) { | 315 if (instance.GetClassId() < kNumPredefinedCids) { |
| 315 // 'class Error' is not a predefined class. | 316 // 'class Error' is not a predefined class. |
| 316 return Field::null(); | 317 return Field::null(); |
| 317 } | 318 } |
| 318 Thread* thread = Thread::Current(); | 319 Thread* thread = Thread::Current(); |
| 319 Zone* zone = thread->zone(); | 320 Zone* zone = thread->zone(); |
| 320 Isolate* isolate = thread->isolate(); | 321 Isolate* isolate = thread->isolate(); |
| 321 Class& error_class = Class::Handle(zone, | 322 Class& error_class = |
| 322 isolate->object_store()->error_class()); | 323 Class::Handle(zone, isolate->object_store()->error_class()); |
| 323 if (error_class.IsNull()) { | 324 if (error_class.IsNull()) { |
| 324 const Library& core_lib = Library::Handle(zone, Library::CoreLibrary()); | 325 const Library& core_lib = Library::Handle(zone, Library::CoreLibrary()); |
| 325 error_class = core_lib.LookupClass(Symbols::Error()); | 326 error_class = core_lib.LookupClass(Symbols::Error()); |
| 326 ASSERT(!error_class.IsNull()); | 327 ASSERT(!error_class.IsNull()); |
| 327 isolate->object_store()->set_error_class(error_class); | 328 isolate->object_store()->set_error_class(error_class); |
| 328 } | 329 } |
| 329 // If instance class extends 'class Error' return '_stackTrace' field. | 330 // If instance class extends 'class Error' return '_stackTrace' field. |
| 330 Class& test_class = Class::Handle(zone, instance.clazz()); | 331 Class& test_class = Class::Handle(zone, instance.clazz()); |
| 331 AbstractType& type = AbstractType::Handle(zone, AbstractType::null()); | 332 AbstractType& type = AbstractType::Handle(zone, AbstractType::null()); |
| 332 while (true) { | 333 while (true) { |
| 333 if (test_class.raw() == error_class.raw()) { | 334 if (test_class.raw() == error_class.raw()) { |
| 334 return error_class.LookupInstanceFieldAllowPrivate( | 335 return error_class.LookupInstanceFieldAllowPrivate( |
| 335 Symbols::_stackTrace()); | 336 Symbols::_stackTrace()); |
| 336 } | 337 } |
| 337 type = test_class.super_type(); | 338 type = test_class.super_type(); |
| 338 if (type.IsNull()) return Field::null(); | 339 if (type.IsNull()) return Field::null(); |
| 339 test_class = type.type_class(); | 340 test_class = type.type_class(); |
| 340 } | 341 } |
| 341 UNREACHABLE(); | 342 UNREACHABLE(); |
| 342 return Field::null(); | 343 return Field::null(); |
| 343 } | 344 } |
| 344 | 345 |
| 345 | 346 |
| 346 RawStacktrace* Exceptions::CurrentStacktrace() { | 347 RawStacktrace* Exceptions::CurrentStacktrace() { |
| 347 Zone* zone = Thread::Current()->zone(); | 348 Zone* zone = Thread::Current()->zone(); |
| 348 RegularStacktraceBuilder frame_builder(zone); | 349 RegularStacktraceBuilder frame_builder(zone); |
| 349 BuildStackTrace(&frame_builder); | 350 BuildStackTrace(&frame_builder); |
| 350 | 351 |
| 351 // Create arrays for code and pc_offset tuples of each frame. | 352 // Create arrays for code and pc_offset tuples of each frame. |
| 352 const Array& full_code_array = Array::Handle(zone, | 353 const Array& full_code_array = |
| 353 Array::MakeArray(frame_builder.code_list())); | 354 Array::Handle(zone, Array::MakeArray(frame_builder.code_list())); |
| 354 const Array& full_pc_offset_array = Array::Handle(zone, | 355 const Array& full_pc_offset_array = |
| 355 Array::MakeArray(frame_builder.pc_offset_list())); | 356 Array::Handle(zone, Array::MakeArray(frame_builder.pc_offset_list())); |
| 356 const Stacktrace& full_stacktrace = Stacktrace::Handle( | 357 const Stacktrace& full_stacktrace = Stacktrace::Handle( |
| 357 Stacktrace::New(full_code_array, full_pc_offset_array)); | 358 Stacktrace::New(full_code_array, full_pc_offset_array)); |
| 358 return full_stacktrace.raw(); | 359 return full_stacktrace.raw(); |
| 359 } | 360 } |
| 360 | 361 |
| 361 | 362 |
| 362 static void ThrowExceptionHelper(Thread* thread, | 363 static void ThrowExceptionHelper(Thread* thread, |
| 363 const Instance& incoming_exception, | 364 const Instance& incoming_exception, |
| 364 const Instance& existing_stacktrace, | 365 const Instance& existing_stacktrace, |
| 365 const bool is_rethrow) { | 366 const bool is_rethrow) { |
| 366 Zone* zone = thread->zone(); | 367 Zone* zone = thread->zone(); |
| 367 Isolate* isolate = thread->isolate(); | 368 Isolate* isolate = thread->isolate(); |
| 368 bool use_preallocated_stacktrace = false; | 369 bool use_preallocated_stacktrace = false; |
| 369 Instance& exception = Instance::Handle(zone, incoming_exception.raw()); | 370 Instance& exception = Instance::Handle(zone, incoming_exception.raw()); |
| 370 if (exception.IsNull()) { | 371 if (exception.IsNull()) { |
| 371 exception ^= Exceptions::Create(Exceptions::kNullThrown, | 372 exception ^= |
| 372 Object::empty_array()); | 373 Exceptions::Create(Exceptions::kNullThrown, Object::empty_array()); |
| 373 } else if (exception.raw() == isolate->object_store()->out_of_memory() || | 374 } else if (exception.raw() == isolate->object_store()->out_of_memory() || |
| 374 exception.raw() == isolate->object_store()->stack_overflow()) { | 375 exception.raw() == isolate->object_store()->stack_overflow()) { |
| 375 use_preallocated_stacktrace = true; | 376 use_preallocated_stacktrace = true; |
| 376 } | 377 } |
| 377 uword handler_pc = 0; | 378 uword handler_pc = 0; |
| 378 uword handler_sp = 0; | 379 uword handler_sp = 0; |
| 379 uword handler_fp = 0; | 380 uword handler_fp = 0; |
| 380 Instance& stacktrace = Instance::Handle(zone); | 381 Instance& stacktrace = Instance::Handle(zone); |
| 381 bool handler_exists = false; | 382 bool handler_exists = false; |
| 382 bool handler_needs_stacktrace = false; | 383 bool handler_needs_stacktrace = false; |
| 383 if (use_preallocated_stacktrace) { | 384 if (use_preallocated_stacktrace) { |
| 384 stacktrace ^= isolate->object_store()->preallocated_stack_trace(); | 385 stacktrace ^= isolate->object_store()->preallocated_stack_trace(); |
| 385 PreallocatedStacktraceBuilder frame_builder(stacktrace); | 386 PreallocatedStacktraceBuilder frame_builder(stacktrace); |
| 386 handler_exists = FindExceptionHandler(thread, | 387 handler_exists = |
| 387 &handler_pc, | 388 FindExceptionHandler(thread, &handler_pc, &handler_sp, &handler_fp, |
| 388 &handler_sp, | 389 &handler_needs_stacktrace); |
| 389 &handler_fp, | |
| 390 &handler_needs_stacktrace); | |
| 391 if (handler_pc == 0) { | 390 if (handler_pc == 0) { |
| 392 // No Dart frame. | 391 // No Dart frame. |
| 393 ASSERT(incoming_exception.raw() == | 392 ASSERT(incoming_exception.raw() == |
| 394 isolate->object_store()->out_of_memory()); | 393 isolate->object_store()->out_of_memory()); |
| 395 const UnhandledException& error = UnhandledException::Handle( | 394 const UnhandledException& error = UnhandledException::Handle( |
| 396 zone, isolate->object_store()->preallocated_unhandled_exception()); | 395 zone, isolate->object_store()->preallocated_unhandled_exception()); |
| 397 thread->long_jump_base()->Jump(1, error); | 396 thread->long_jump_base()->Jump(1, error); |
| 398 UNREACHABLE(); | 397 UNREACHABLE(); |
| 399 } | 398 } |
| 400 if (handler_needs_stacktrace) { | 399 if (handler_needs_stacktrace) { |
| 401 BuildStackTrace(&frame_builder); | 400 BuildStackTrace(&frame_builder); |
| 402 } | 401 } |
| 403 } else { | 402 } else { |
| 404 // Get stacktrace field of class Error. This is needed to determine whether | 403 // Get stacktrace field of class Error. This is needed to determine whether |
| 405 // we have a subclass of Error which carries around its stack trace. | 404 // we have a subclass of Error which carries around its stack trace. |
| 406 const Field& stacktrace_field = | 405 const Field& stacktrace_field = |
| 407 Field::Handle(zone, LookupStacktraceField(exception)); | 406 Field::Handle(zone, LookupStacktraceField(exception)); |
| 408 | 407 |
| 409 // Find the exception handler and determine if the handler needs a | 408 // Find the exception handler and determine if the handler needs a |
| 410 // stacktrace. | 409 // stacktrace. |
| 411 handler_exists = FindExceptionHandler(thread, | 410 handler_exists = |
| 412 &handler_pc, | 411 FindExceptionHandler(thread, &handler_pc, &handler_sp, &handler_fp, |
| 413 &handler_sp, | 412 &handler_needs_stacktrace); |
| 414 &handler_fp, | |
| 415 &handler_needs_stacktrace); | |
| 416 if (!existing_stacktrace.IsNull()) { | 413 if (!existing_stacktrace.IsNull()) { |
| 417 // If we have an existing stack trace then this better be a rethrow. The | 414 // If we have an existing stack trace then this better be a rethrow. The |
| 418 // reverse is not necessarily true (e.g. Dart_PropagateError can cause | 415 // reverse is not necessarily true (e.g. Dart_PropagateError can cause |
| 419 // a rethrow being called without an existing stacktrace.) | 416 // a rethrow being called without an existing stacktrace.) |
| 420 ASSERT(is_rethrow); | 417 ASSERT(is_rethrow); |
| 421 ASSERT(stacktrace_field.IsNull() || | 418 ASSERT(stacktrace_field.IsNull() || |
| 422 (exception.GetField(stacktrace_field) != Object::null())); | 419 (exception.GetField(stacktrace_field) != Object::null())); |
| 423 stacktrace = existing_stacktrace.raw(); | 420 stacktrace = existing_stacktrace.raw(); |
| 424 } else if (!stacktrace_field.IsNull() || handler_needs_stacktrace) { | 421 } else if (!stacktrace_field.IsNull() || handler_needs_stacktrace) { |
| 425 // Collect the stacktrace if needed. | 422 // Collect the stacktrace if needed. |
| (...skipping 12 matching lines...) Expand all Loading... |
| 438 // stack as Exceptions::Throw should happen only after a dart | 435 // stack as Exceptions::Throw should happen only after a dart |
| 439 // invocation has been done. | 436 // invocation has been done. |
| 440 ASSERT(handler_pc != 0); | 437 ASSERT(handler_pc != 0); |
| 441 | 438 |
| 442 if (FLAG_print_stacktrace_at_throw) { | 439 if (FLAG_print_stacktrace_at_throw) { |
| 443 THR_Print("Exception '%s' thrown:\n", exception.ToCString()); | 440 THR_Print("Exception '%s' thrown:\n", exception.ToCString()); |
| 444 THR_Print("%s\n", stacktrace.ToCString()); | 441 THR_Print("%s\n", stacktrace.ToCString()); |
| 445 } | 442 } |
| 446 if (handler_exists) { | 443 if (handler_exists) { |
| 447 // Found a dart handler for the exception, jump to it. | 444 // Found a dart handler for the exception, jump to it. |
| 448 JumpToExceptionHandler(thread, | 445 JumpToExceptionHandler(thread, handler_pc, handler_sp, handler_fp, |
| 449 handler_pc, | 446 exception, stacktrace); |
| 450 handler_sp, | |
| 451 handler_fp, | |
| 452 exception, | |
| 453 stacktrace); | |
| 454 } else { | 447 } else { |
| 455 // No dart exception handler found in this invocation sequence, | 448 // No dart exception handler found in this invocation sequence, |
| 456 // so we create an unhandled exception object and return to the | 449 // so we create an unhandled exception object and return to the |
| 457 // invocation stub so that it returns this unhandled exception | 450 // invocation stub so that it returns this unhandled exception |
| 458 // object. The C++ code which invoked this dart sequence can check | 451 // object. The C++ code which invoked this dart sequence can check |
| 459 // and do the appropriate thing (rethrow the exception to the | 452 // and do the appropriate thing (rethrow the exception to the |
| 460 // dart invocation sequence above it, print diagnostics and terminate | 453 // dart invocation sequence above it, print diagnostics and terminate |
| 461 // the isolate etc.). | 454 // the isolate etc.). |
| 462 const UnhandledException& unhandled_exception = UnhandledException::Handle( | 455 const UnhandledException& unhandled_exception = UnhandledException::Handle( |
| 463 zone, UnhandledException::New(exception, stacktrace)); | 456 zone, UnhandledException::New(exception, stacktrace)); |
| 464 stacktrace = Stacktrace::null(); | 457 stacktrace = Stacktrace::null(); |
| 465 JumpToExceptionHandler(thread, | 458 JumpToExceptionHandler(thread, handler_pc, handler_sp, handler_fp, |
| 466 handler_pc, | 459 unhandled_exception, stacktrace); |
| 467 handler_sp, | |
| 468 handler_fp, | |
| 469 unhandled_exception, | |
| 470 stacktrace); | |
| 471 } | 460 } |
| 472 UNREACHABLE(); | 461 UNREACHABLE(); |
| 473 } | 462 } |
| 474 | 463 |
| 475 | 464 |
| 476 // Static helpers for allocating, initializing, and throwing an error instance. | 465 // Static helpers for allocating, initializing, and throwing an error instance. |
| 477 | 466 |
| 478 // Return the script of the Dart function that called the native entry or the | 467 // Return the script of the Dart function that called the native entry or the |
| 479 // runtime entry. The frame iterator points to the callee. | 468 // runtime entry. The frame iterator points to the callee. |
| 480 RawScript* Exceptions::GetCallerScript(DartFrameIterator* iterator) { | 469 RawScript* Exceptions::GetCallerScript(DartFrameIterator* iterator) { |
| 481 StackFrame* caller_frame = iterator->NextFrame(); | 470 StackFrame* caller_frame = iterator->NextFrame(); |
| 482 ASSERT(caller_frame != NULL && caller_frame->IsDartFrame()); | 471 ASSERT(caller_frame != NULL && caller_frame->IsDartFrame()); |
| 483 const Function& caller = Function::Handle(caller_frame->LookupDartFunction()); | 472 const Function& caller = Function::Handle(caller_frame->LookupDartFunction()); |
| 484 ASSERT(!caller.IsNull()); | 473 ASSERT(!caller.IsNull()); |
| 485 return caller.script(); | 474 return caller.script(); |
| 486 } | 475 } |
| 487 | 476 |
| 488 | 477 |
| 489 // Allocate a new instance of the given class name. | 478 // Allocate a new instance of the given class name. |
| 490 // TODO(hausner): Rename this NewCoreInstance to call out the fact that | 479 // TODO(hausner): Rename this NewCoreInstance to call out the fact that |
| 491 // the class name is resolved in the core library implicitly? | 480 // the class name is resolved in the core library implicitly? |
| 492 RawInstance* Exceptions::NewInstance(const char* class_name) { | 481 RawInstance* Exceptions::NewInstance(const char* class_name) { |
| 493 Thread* thread = Thread::Current(); | 482 Thread* thread = Thread::Current(); |
| 494 Zone* zone = thread->zone(); | 483 Zone* zone = thread->zone(); |
| 495 const String& cls_name = String::Handle(zone, | 484 const String& cls_name = |
| 496 Symbols::New(thread, class_name)); | 485 String::Handle(zone, Symbols::New(thread, class_name)); |
| 497 const Library& core_lib = Library::Handle(Library::CoreLibrary()); | 486 const Library& core_lib = Library::Handle(Library::CoreLibrary()); |
| 498 // No ambiguity error expected: passing NULL. | 487 // No ambiguity error expected: passing NULL. |
| 499 Class& cls = Class::Handle(core_lib.LookupClass(cls_name)); | 488 Class& cls = Class::Handle(core_lib.LookupClass(cls_name)); |
| 500 ASSERT(!cls.IsNull()); | 489 ASSERT(!cls.IsNull()); |
| 501 // There are no parameterized error types, so no need to set type arguments. | 490 // There are no parameterized error types, so no need to set type arguments. |
| 502 return Instance::New(cls); | 491 return Instance::New(cls); |
| 503 } | 492 } |
| 504 | 493 |
| 505 | 494 |
| 506 // Allocate, initialize, and throw a TypeError or CastError. | 495 // Allocate, initialize, and throw a TypeError or CastError. |
| 507 // If error_msg is not null, throw a TypeError, even for a type cast. | 496 // If error_msg is not null, throw a TypeError, even for a type cast. |
| 508 void Exceptions::CreateAndThrowTypeError(TokenPosition location, | 497 void Exceptions::CreateAndThrowTypeError(TokenPosition location, |
| 509 const AbstractType& src_type, | 498 const AbstractType& src_type, |
| 510 const AbstractType& dst_type, | 499 const AbstractType& dst_type, |
| 511 const String& dst_name, | 500 const String& dst_name, |
| 512 const String& bound_error_msg) { | 501 const String& bound_error_msg) { |
| 513 ASSERT(!dst_name.IsNull()); // Pass Symbols::Empty() instead. | 502 ASSERT(!dst_name.IsNull()); // Pass Symbols::Empty() instead. |
| 514 Zone* zone = Thread::Current()->zone(); | 503 Zone* zone = Thread::Current()->zone(); |
| 515 const Array& args = Array::Handle(zone, Array::New(4)); | 504 const Array& args = Array::Handle(zone, Array::New(4)); |
| 516 | 505 |
| 517 ExceptionType exception_type = | 506 ExceptionType exception_type = |
| 518 (bound_error_msg.IsNull() && | 507 (bound_error_msg.IsNull() && |
| 519 (dst_name.raw() == Symbols::InTypeCast().raw())) ? kCast : kType; | 508 (dst_name.raw() == Symbols::InTypeCast().raw())) |
| 509 ? kCast |
| 510 : kType; |
| 520 | 511 |
| 521 DartFrameIterator iterator; | 512 DartFrameIterator iterator; |
| 522 const Script& script = Script::Handle(zone, GetCallerScript(&iterator)); | 513 const Script& script = Script::Handle(zone, GetCallerScript(&iterator)); |
| 523 intptr_t line; | 514 intptr_t line; |
| 524 intptr_t column = -1; | 515 intptr_t column = -1; |
| 525 if (script.HasSource()) { | 516 if (script.HasSource()) { |
| 526 script.GetTokenLocation(location, &line, &column); | 517 script.GetTokenLocation(location, &line, &column); |
| 527 } else { | 518 } else { |
| 528 script.GetTokenLocation(location, &line, NULL); | 519 script.GetTokenLocation(location, &line, NULL); |
| 529 } | 520 } |
| 530 // Initialize '_url', '_line', and '_column' arguments. | 521 // Initialize '_url', '_line', and '_column' arguments. |
| 531 args.SetAt(0, String::Handle(zone, script.url())); | 522 args.SetAt(0, String::Handle(zone, script.url())); |
| 532 args.SetAt(1, Smi::Handle(zone, Smi::New(line))); | 523 args.SetAt(1, Smi::Handle(zone, Smi::New(line))); |
| 533 args.SetAt(2, Smi::Handle(zone, Smi::New(column))); | 524 args.SetAt(2, Smi::Handle(zone, Smi::New(column))); |
| 534 | 525 |
| 535 // Construct '_errorMsg'. | 526 // Construct '_errorMsg'. |
| 536 const GrowableObjectArray& pieces = GrowableObjectArray::Handle(zone, | 527 const GrowableObjectArray& pieces = |
| 537 GrowableObjectArray::New(20)); | 528 GrowableObjectArray::Handle(zone, GrowableObjectArray::New(20)); |
| 538 | 529 |
| 539 // Print bound error first, if any. | 530 // Print bound error first, if any. |
| 540 if (!bound_error_msg.IsNull() && (bound_error_msg.Length() > 0)) { | 531 if (!bound_error_msg.IsNull() && (bound_error_msg.Length() > 0)) { |
| 541 pieces.Add(bound_error_msg); | 532 pieces.Add(bound_error_msg); |
| 542 pieces.Add(Symbols::NewLine()); | 533 pieces.Add(Symbols::NewLine()); |
| 543 } | 534 } |
| 544 | 535 |
| 545 // If dst_type is malformed or malbounded, only print the embedded error. | 536 // If dst_type is malformed or malbounded, only print the embedded error. |
| 546 if (!dst_type.IsNull()) { | 537 if (!dst_type.IsNull()) { |
| 547 const LanguageError& error = LanguageError::Handle(zone, dst_type.error()); | 538 const LanguageError& error = LanguageError::Handle(zone, dst_type.error()); |
| (...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 612 // The VM would crash when the debugger calls back into the VM to | 603 // The VM would crash when the debugger calls back into the VM to |
| 613 // get values of variables. | 604 // get values of variables. |
| 614 if (FLAG_support_debugger) { | 605 if (FLAG_support_debugger) { |
| 615 Isolate* isolate = thread->isolate(); | 606 Isolate* isolate = thread->isolate(); |
| 616 if (exception.raw() != isolate->object_store()->out_of_memory() && | 607 if (exception.raw() != isolate->object_store()->out_of_memory() && |
| 617 exception.raw() != isolate->object_store()->stack_overflow()) { | 608 exception.raw() != isolate->object_store()->stack_overflow()) { |
| 618 isolate->debugger()->PauseException(exception); | 609 isolate->debugger()->PauseException(exception); |
| 619 } | 610 } |
| 620 } | 611 } |
| 621 // Null object is a valid exception object. | 612 // Null object is a valid exception object. |
| 622 ThrowExceptionHelper(thread, exception, | 613 ThrowExceptionHelper(thread, exception, Stacktrace::Handle(thread->zone()), |
| 623 Stacktrace::Handle(thread->zone()), false); | 614 false); |
| 624 } | 615 } |
| 625 | 616 |
| 626 void Exceptions::ReThrow(Thread* thread, | 617 void Exceptions::ReThrow(Thread* thread, |
| 627 const Instance& exception, | 618 const Instance& exception, |
| 628 const Instance& stacktrace) { | 619 const Instance& stacktrace) { |
| 629 // Null object is a valid exception object. | 620 // Null object is a valid exception object. |
| 630 ThrowExceptionHelper(thread, exception, stacktrace, true); | 621 ThrowExceptionHelper(thread, exception, stacktrace, true); |
| 631 } | 622 } |
| 632 | 623 |
| 633 | 624 |
| (...skipping 156 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 790 case kCyclicInitializationError: | 781 case kCyclicInitializationError: |
| 791 library = Library::CoreLibrary(); | 782 library = Library::CoreLibrary(); |
| 792 class_name = &Symbols::CyclicInitializationError(); | 783 class_name = &Symbols::CyclicInitializationError(); |
| 793 break; | 784 break; |
| 794 case kCompileTimeError: | 785 case kCompileTimeError: |
| 795 library = Library::CoreLibrary(); | 786 library = Library::CoreLibrary(); |
| 796 class_name = &Symbols::_CompileTimeError(); | 787 class_name = &Symbols::_CompileTimeError(); |
| 797 break; | 788 break; |
| 798 } | 789 } |
| 799 | 790 |
| 800 return DartLibraryCalls::InstanceCreate(library, | 791 return DartLibraryCalls::InstanceCreate(library, *class_name, |
| 801 *class_name, | 792 *constructor_name, arguments); |
| 802 *constructor_name, | |
| 803 arguments); | |
| 804 } | 793 } |
| 805 | 794 |
| 806 | 795 |
| 807 } // namespace dart | 796 } // namespace dart |
| OLD | NEW |