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" |
(...skipping 176 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
187 frame = frames.NextFrame(); | 187 frame = frames.NextFrame(); |
188 ASSERT(frame != NULL); | 188 ASSERT(frame != NULL); |
189 } | 189 } |
190 ASSERT(frame->IsEntryFrame()); | 190 ASSERT(frame->IsEntryFrame()); |
191 *handler_pc = frame->pc(); | 191 *handler_pc = frame->pc(); |
192 *handler_sp = frame->sp(); | 192 *handler_sp = frame->sp(); |
193 *handler_fp = frame->fp(); | 193 *handler_fp = frame->fp(); |
194 } | 194 } |
195 | 195 |
196 | 196 |
197 static void JumpToExceptionHandler(Isolate* isolate, | 197 static void JumpToExceptionHandler(Thread* thread, |
198 uword program_counter, | 198 uword program_counter, |
199 uword stack_pointer, | 199 uword stack_pointer, |
200 uword frame_pointer, | 200 uword frame_pointer, |
201 const Object& exception_object, | 201 const Object& exception_object, |
202 const Object& stacktrace_object) { | 202 const Object& stacktrace_object) { |
203 // The no_gc StackResource is unwound through the tear down of | 203 // The no_gc StackResource is unwound through the tear down of |
204 // stack resources below. | 204 // stack resources below. |
205 NoSafepointScope no_safepoint; | 205 NoSafepointScope no_safepoint; |
206 RawObject* raw_exception = exception_object.raw(); | 206 RawObject* raw_exception = exception_object.raw(); |
207 RawObject* raw_stacktrace = stacktrace_object.raw(); | 207 RawObject* raw_stacktrace = stacktrace_object.raw(); |
208 | 208 |
209 #if defined(USING_SIMULATOR) | 209 #if defined(USING_SIMULATOR) |
210 // Unwinding of the C++ frames and destroying of their stack resources is done | 210 // Unwinding of the C++ frames and destroying of their stack resources is done |
211 // by the simulator, because the target stack_pointer is a simulated stack | 211 // by the simulator, because the target stack_pointer is a simulated stack |
212 // pointer and not the C++ stack pointer. | 212 // pointer and not the C++ stack pointer. |
213 | 213 |
214 // Continue simulating at the given pc in the given frame after setting up the | 214 // Continue simulating at the given pc in the given frame after setting up the |
215 // exception object in the kExceptionObjectReg register and the stacktrace | 215 // exception object in the kExceptionObjectReg register and the stacktrace |
216 // object (may be raw null) in the kStackTraceObjectReg register. | 216 // object (may be raw null) in the kStackTraceObjectReg register. |
217 | 217 |
218 Simulator::Current()->Longjmp(program_counter, stack_pointer, frame_pointer, | 218 Simulator::Current()->Longjmp(program_counter, stack_pointer, frame_pointer, |
219 raw_exception, raw_stacktrace, isolate); | 219 raw_exception, raw_stacktrace, thread); |
220 #else | 220 #else |
221 // Prepare for unwinding frames by destroying all the stack resources | 221 // Prepare for unwinding frames by destroying all the stack resources |
222 // in the previous frames. | 222 // in the previous frames. |
223 StackResource::Unwind(isolate); | 223 StackResource::Unwind(thread->isolate()); |
224 | 224 |
225 // Call a stub to set up the exception object in kExceptionObjectReg, | 225 // Call a stub to set up the exception object in kExceptionObjectReg, |
226 // to set up the stacktrace object in kStackTraceObjectReg, and to | 226 // to set up the stacktrace object in kStackTraceObjectReg, and to |
227 // continue execution at the given pc in the given frame. | 227 // continue execution at the given pc in the given frame. |
228 typedef void (*ExcpHandler)(uword, uword, uword, RawObject*, RawObject*, | 228 typedef void (*ExcpHandler)(uword, uword, uword, RawObject*, RawObject*, |
229 Isolate*); | 229 Thread*); |
230 ExcpHandler func = reinterpret_cast<ExcpHandler>( | 230 ExcpHandler func = reinterpret_cast<ExcpHandler>( |
231 StubCode::JumpToExceptionHandlerEntryPoint()); | 231 StubCode::JumpToExceptionHandlerEntryPoint()); |
232 | 232 |
233 // Unpoison the stack before we tear it down in the generated stub code. | 233 // Unpoison the stack before we tear it down in the generated stub code. |
234 uword current_sp = Isolate::GetCurrentStackPointer() - 1024; | 234 uword current_sp = Isolate::GetCurrentStackPointer() - 1024; |
235 ASAN_UNPOISON(reinterpret_cast<void*>(current_sp), | 235 ASAN_UNPOISON(reinterpret_cast<void*>(current_sp), |
236 stack_pointer - current_sp); | 236 stack_pointer - current_sp); |
237 | 237 |
238 func(program_counter, stack_pointer, frame_pointer, | 238 func(program_counter, stack_pointer, frame_pointer, |
239 raw_exception, raw_stacktrace, isolate); | 239 raw_exception, raw_stacktrace, thread); |
240 #endif | 240 #endif |
241 UNREACHABLE(); | 241 UNREACHABLE(); |
242 } | 242 } |
243 | 243 |
244 | 244 |
245 static RawField* LookupStacktraceField(const Instance& instance) { | 245 static RawField* LookupStacktraceField(const Instance& instance) { |
246 if (instance.GetClassId() < kNumPredefinedCids) { | 246 if (instance.GetClassId() < kNumPredefinedCids) { |
247 // 'class Error' is not a predefined class. | 247 // 'class Error' is not a predefined class. |
248 return Field::null(); | 248 return Field::null(); |
249 } | 249 } |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
281 const Array& full_code_array = Array::Handle(isolate, | 281 const Array& full_code_array = Array::Handle(isolate, |
282 Array::MakeArray(frame_builder.code_list())); | 282 Array::MakeArray(frame_builder.code_list())); |
283 const Array& full_pc_offset_array = Array::Handle(isolate, | 283 const Array& full_pc_offset_array = Array::Handle(isolate, |
284 Array::MakeArray(frame_builder.pc_offset_list())); | 284 Array::MakeArray(frame_builder.pc_offset_list())); |
285 const Stacktrace& full_stacktrace = Stacktrace::Handle( | 285 const Stacktrace& full_stacktrace = Stacktrace::Handle( |
286 Stacktrace::New(full_code_array, full_pc_offset_array)); | 286 Stacktrace::New(full_code_array, full_pc_offset_array)); |
287 return full_stacktrace.raw(); | 287 return full_stacktrace.raw(); |
288 } | 288 } |
289 | 289 |
290 | 290 |
291 static void ThrowExceptionHelper(Isolate* isolate, | 291 static void ThrowExceptionHelper(Thread* thread, |
292 const Instance& incoming_exception, | 292 const Instance& incoming_exception, |
293 const Instance& existing_stacktrace, | 293 const Instance& existing_stacktrace, |
294 const bool is_rethrow) { | 294 const bool is_rethrow) { |
| 295 Isolate* isolate = thread->isolate(); |
295 bool use_preallocated_stacktrace = false; | 296 bool use_preallocated_stacktrace = false; |
296 Instance& exception = Instance::Handle(isolate, incoming_exception.raw()); | 297 Instance& exception = Instance::Handle(isolate, incoming_exception.raw()); |
297 if (exception.IsNull()) { | 298 if (exception.IsNull()) { |
298 exception ^= Exceptions::Create(Exceptions::kNullThrown, | 299 exception ^= Exceptions::Create(Exceptions::kNullThrown, |
299 Object::empty_array()); | 300 Object::empty_array()); |
300 } else if (exception.raw() == isolate->object_store()->out_of_memory() || | 301 } else if (exception.raw() == isolate->object_store()->out_of_memory() || |
301 exception.raw() == isolate->object_store()->stack_overflow()) { | 302 exception.raw() == isolate->object_store()->stack_overflow()) { |
302 use_preallocated_stacktrace = true; | 303 use_preallocated_stacktrace = true; |
303 } | 304 } |
304 uword handler_pc = 0; | 305 uword handler_pc = 0; |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
356 // stack as Exceptions::Throw should happen only after a dart | 357 // stack as Exceptions::Throw should happen only after a dart |
357 // invocation has been done. | 358 // invocation has been done. |
358 ASSERT(handler_pc != 0); | 359 ASSERT(handler_pc != 0); |
359 | 360 |
360 if (FLAG_print_stacktrace_at_throw) { | 361 if (FLAG_print_stacktrace_at_throw) { |
361 OS::Print("Exception '%s' thrown:\n", exception.ToCString()); | 362 OS::Print("Exception '%s' thrown:\n", exception.ToCString()); |
362 OS::Print("%s\n", stacktrace.ToCString()); | 363 OS::Print("%s\n", stacktrace.ToCString()); |
363 } | 364 } |
364 if (handler_exists) { | 365 if (handler_exists) { |
365 // Found a dart handler for the exception, jump to it. | 366 // Found a dart handler for the exception, jump to it. |
366 JumpToExceptionHandler(isolate, | 367 JumpToExceptionHandler(thread, |
367 handler_pc, | 368 handler_pc, |
368 handler_sp, | 369 handler_sp, |
369 handler_fp, | 370 handler_fp, |
370 exception, | 371 exception, |
371 stacktrace); | 372 stacktrace); |
372 } else { | 373 } else { |
373 // No dart exception handler found in this invocation sequence, | 374 // No dart exception handler found in this invocation sequence, |
374 // so we create an unhandled exception object and return to the | 375 // so we create an unhandled exception object and return to the |
375 // invocation stub so that it returns this unhandled exception | 376 // invocation stub so that it returns this unhandled exception |
376 // object. The C++ code which invoked this dart sequence can check | 377 // object. The C++ code which invoked this dart sequence can check |
377 // and do the appropriate thing (rethrow the exception to the | 378 // and do the appropriate thing (rethrow the exception to the |
378 // dart invocation sequence above it, print diagnostics and terminate | 379 // dart invocation sequence above it, print diagnostics and terminate |
379 // the isolate etc.). | 380 // the isolate etc.). |
380 const UnhandledException& unhandled_exception = UnhandledException::Handle( | 381 const UnhandledException& unhandled_exception = UnhandledException::Handle( |
381 isolate, UnhandledException::New(exception, stacktrace)); | 382 isolate, UnhandledException::New(exception, stacktrace)); |
382 stacktrace = Stacktrace::null(); | 383 stacktrace = Stacktrace::null(); |
383 JumpToExceptionHandler(isolate, | 384 JumpToExceptionHandler(thread, |
384 handler_pc, | 385 handler_pc, |
385 handler_sp, | 386 handler_sp, |
386 handler_fp, | 387 handler_fp, |
387 unhandled_exception, | 388 unhandled_exception, |
388 stacktrace); | 389 stacktrace); |
389 } | 390 } |
390 UNREACHABLE(); | 391 UNREACHABLE(); |
391 } | 392 } |
392 | 393 |
393 | 394 |
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
467 } else { | 468 } else { |
468 OS::Print("type error.\n"); | 469 OS::Print("type error.\n"); |
469 } | 470 } |
470 } | 471 } |
471 // Throw TypeError or CastError instance. | 472 // Throw TypeError or CastError instance. |
472 Exceptions::ThrowByType(exception_type, args); | 473 Exceptions::ThrowByType(exception_type, args); |
473 UNREACHABLE(); | 474 UNREACHABLE(); |
474 } | 475 } |
475 | 476 |
476 | 477 |
477 void Exceptions::Throw(Isolate* isolate, const Instance& exception) { | 478 void Exceptions::Throw(Thread* thread, const Instance& exception) { |
478 // Do not notify debugger on stack overflow and out of memory exceptions. | 479 // Do not notify debugger on stack overflow and out of memory exceptions. |
479 // The VM would crash when the debugger calls back into the VM to | 480 // The VM would crash when the debugger calls back into the VM to |
480 // get values of variables. | 481 // get values of variables. |
| 482 Isolate* isolate = thread->isolate(); |
481 if (exception.raw() != isolate->object_store()->out_of_memory() && | 483 if (exception.raw() != isolate->object_store()->out_of_memory() && |
482 exception.raw() != isolate->object_store()->stack_overflow()) { | 484 exception.raw() != isolate->object_store()->stack_overflow()) { |
483 isolate->debugger()->SignalExceptionThrown(exception); | 485 isolate->debugger()->SignalExceptionThrown(exception); |
484 } | 486 } |
485 // Null object is a valid exception object. | 487 // Null object is a valid exception object. |
486 ThrowExceptionHelper(isolate, exception, Stacktrace::Handle(isolate), false); | 488 ThrowExceptionHelper(thread, exception, Stacktrace::Handle(isolate), false); |
487 } | 489 } |
488 | 490 |
489 | 491 void Exceptions::ReThrow(Thread* thread, |
490 void Exceptions::ReThrow(Isolate* isolate, | |
491 const Instance& exception, | 492 const Instance& exception, |
492 const Instance& stacktrace) { | 493 const Instance& stacktrace) { |
493 // Null object is a valid exception object. | 494 // Null object is a valid exception object. |
494 ThrowExceptionHelper(isolate, exception, stacktrace, true); | 495 ThrowExceptionHelper(thread, exception, stacktrace, true); |
495 } | 496 } |
496 | 497 |
497 | 498 |
498 void Exceptions::PropagateError(const Error& error) { | 499 void Exceptions::PropagateError(const Error& error) { |
499 Isolate* isolate = Isolate::Current(); | 500 Thread* thread = Thread::Current(); |
| 501 Isolate* isolate = thread->isolate(); |
500 ASSERT(isolate->top_exit_frame_info() != 0); | 502 ASSERT(isolate->top_exit_frame_info() != 0); |
501 if (error.IsUnhandledException()) { | 503 if (error.IsUnhandledException()) { |
502 // If the error object represents an unhandled exception, then | 504 // If the error object represents an unhandled exception, then |
503 // rethrow the exception in the normal fashion. | 505 // rethrow the exception in the normal fashion. |
504 const UnhandledException& uhe = UnhandledException::Cast(error); | 506 const UnhandledException& uhe = UnhandledException::Cast(error); |
505 const Instance& exc = Instance::Handle(isolate, uhe.exception()); | 507 const Instance& exc = Instance::Handle(isolate, uhe.exception()); |
506 const Instance& stk = Instance::Handle(isolate, uhe.stacktrace()); | 508 const Instance& stk = Instance::Handle(isolate, uhe.stacktrace()); |
507 Exceptions::ReThrow(isolate, exc, stk); | 509 Exceptions::ReThrow(thread, exc, stk); |
508 } else { | 510 } else { |
509 // Return to the invocation stub and return this error object. The | 511 // Return to the invocation stub and return this error object. The |
510 // C++ code which invoked this dart sequence can check and do the | 512 // C++ code which invoked this dart sequence can check and do the |
511 // appropriate thing. | 513 // appropriate thing. |
512 uword handler_pc = 0; | 514 uword handler_pc = 0; |
513 uword handler_sp = 0; | 515 uword handler_sp = 0; |
514 uword handler_fp = 0; | 516 uword handler_fp = 0; |
515 FindErrorHandler(&handler_pc, &handler_sp, &handler_fp); | 517 FindErrorHandler(&handler_pc, &handler_sp, &handler_fp); |
516 JumpToExceptionHandler(isolate, handler_pc, handler_sp, handler_fp, error, | 518 JumpToExceptionHandler(thread, handler_pc, handler_sp, handler_fp, error, |
517 Stacktrace::Handle(isolate)); // Null stacktrace. | 519 Stacktrace::Handle(isolate)); // Null stacktrace. |
518 } | 520 } |
519 UNREACHABLE(); | 521 UNREACHABLE(); |
520 } | 522 } |
521 | 523 |
522 | 524 |
523 void Exceptions::ThrowByType(ExceptionType type, const Array& arguments) { | 525 void Exceptions::ThrowByType(ExceptionType type, const Array& arguments) { |
524 Isolate* isolate = Isolate::Current(); | 526 Thread* thread = Thread::Current(); |
| 527 Isolate* isolate = thread->isolate(); |
525 const Object& result = Object::Handle(isolate, Create(type, arguments)); | 528 const Object& result = Object::Handle(isolate, Create(type, arguments)); |
526 if (result.IsError()) { | 529 if (result.IsError()) { |
527 // We got an error while constructing the exception object. | 530 // We got an error while constructing the exception object. |
528 // Propagate the error instead of throwing the exception. | 531 // Propagate the error instead of throwing the exception. |
529 PropagateError(Error::Cast(result)); | 532 PropagateError(Error::Cast(result)); |
530 } else { | 533 } else { |
531 ASSERT(result.IsInstance()); | 534 ASSERT(result.IsInstance()); |
532 Throw(isolate, Instance::Cast(result)); | 535 Throw(thread, Instance::Cast(result)); |
533 } | 536 } |
534 } | 537 } |
535 | 538 |
536 | 539 |
537 void Exceptions::ThrowOOM() { | 540 void Exceptions::ThrowOOM() { |
538 Isolate* isolate = Isolate::Current(); | 541 Thread* thread = Thread::Current(); |
| 542 Isolate* isolate = thread->isolate(); |
539 const Instance& oom = Instance::Handle( | 543 const Instance& oom = Instance::Handle( |
540 isolate, isolate->object_store()->out_of_memory()); | 544 isolate, isolate->object_store()->out_of_memory()); |
541 Throw(isolate, oom); | 545 Throw(thread, oom); |
542 } | 546 } |
543 | 547 |
544 | 548 |
545 void Exceptions::ThrowStackOverflow() { | 549 void Exceptions::ThrowStackOverflow() { |
546 Isolate* isolate = Isolate::Current(); | 550 Thread* thread = Thread::Current(); |
| 551 Isolate* isolate = thread->isolate(); |
547 const Instance& stack_overflow = Instance::Handle( | 552 const Instance& stack_overflow = Instance::Handle( |
548 isolate, isolate->object_store()->stack_overflow()); | 553 isolate, isolate->object_store()->stack_overflow()); |
549 Throw(isolate, stack_overflow); | 554 Throw(thread, stack_overflow); |
550 } | 555 } |
551 | 556 |
552 | 557 |
553 void Exceptions::ThrowArgumentError(const Instance& arg) { | 558 void Exceptions::ThrowArgumentError(const Instance& arg) { |
554 const Array& args = Array::Handle(Array::New(1)); | 559 const Array& args = Array::Handle(Array::New(1)); |
555 args.SetAt(0, arg); | 560 args.SetAt(0, arg); |
556 Exceptions::ThrowByType(Exceptions::kArgument, args); | 561 Exceptions::ThrowByType(Exceptions::kArgument, args); |
557 } | 562 } |
558 | 563 |
559 | 564 |
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
664 | 669 |
665 // Throw JavascriptCompatibilityError exception. | 670 // Throw JavascriptCompatibilityError exception. |
666 void Exceptions::ThrowJavascriptCompatibilityError(const char* msg) { | 671 void Exceptions::ThrowJavascriptCompatibilityError(const char* msg) { |
667 const Array& exc_args = Array::Handle(Array::New(1)); | 672 const Array& exc_args = Array::Handle(Array::New(1)); |
668 const String& msg_str = String::Handle(String::New(msg)); | 673 const String& msg_str = String::Handle(String::New(msg)); |
669 exc_args.SetAt(0, msg_str); | 674 exc_args.SetAt(0, msg_str); |
670 Exceptions::ThrowByType(Exceptions::kJavascriptCompatibilityError, exc_args); | 675 Exceptions::ThrowByType(Exceptions::kJavascriptCompatibilityError, exc_args); |
671 } | 676 } |
672 | 677 |
673 } // namespace dart | 678 } // namespace dart |
OLD | NEW |