| 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 189 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 200 frame = frames.NextFrame(); | 200 frame = frames.NextFrame(); |
| 201 ASSERT(frame != NULL); | 201 ASSERT(frame != NULL); |
| 202 } | 202 } |
| 203 ASSERT(frame->IsEntryFrame()); | 203 ASSERT(frame->IsEntryFrame()); |
| 204 *handler_pc = frame->pc(); | 204 *handler_pc = frame->pc(); |
| 205 *handler_sp = frame->sp(); | 205 *handler_sp = frame->sp(); |
| 206 *handler_fp = frame->fp(); | 206 *handler_fp = frame->fp(); |
| 207 } | 207 } |
| 208 | 208 |
| 209 | 209 |
| 210 static void JumpToHandler(uword program_counter, | 210 static void JumpToExceptionHandler(uword program_counter, |
| 211 uword stack_pointer, | 211 uword stack_pointer, |
| 212 uword frame_pointer, | 212 uword frame_pointer, |
| 213 RawObject* raw_exception, | 213 const Object& exception_object, |
| 214 RawObject* raw_stacktrace) { | 214 const Object& stacktrace_object) { |
| 215 // The no_gc StackResource is unwound through the tear down of |
| 216 // stack resources below. |
| 217 NoGCScope no_gc; |
| 218 RawObject* raw_exception = exception_object.raw(); |
| 219 RawObject* raw_stacktrace = stacktrace_object.raw(); |
| 220 |
| 215 #if defined(USING_SIMULATOR) | 221 #if defined(USING_SIMULATOR) |
| 216 // Unwinding of the C++ frames and destroying of their stack resources is done | 222 // Unwinding of the C++ frames and destroying of their stack resources is done |
| 217 // by the simulator, because the target stack_pointer is a simulated stack | 223 // by the simulator, because the target stack_pointer is a simulated stack |
| 218 // pointer and not the C++ stack pointer. | 224 // pointer and not the C++ stack pointer. |
| 219 | 225 |
| 220 // Continue simulating at the given pc in the given frame after setting up the | 226 // Continue simulating at the given pc in the given frame after setting up the |
| 221 // exception object in the kExceptionObjectReg register and the stacktrace | 227 // exception object in the kExceptionObjectReg register and the stacktrace |
| 222 // object (if not NULL) in the kStackTraceObjectReg register. | 228 // object (may be raw null) in the kStackTraceObjectReg register. |
| 223 Simulator::Current()->Longjmp(program_counter, stack_pointer, frame_pointer, | 229 Simulator::Current()->Longjmp(program_counter, stack_pointer, frame_pointer, |
| 224 raw_exception, raw_stacktrace); | 230 raw_exception, raw_stacktrace); |
| 225 #else | 231 #else |
| 226 // Prepare for unwinding frames by destroying all the stack resources | 232 // Prepare for unwinding frames by destroying all the stack resources |
| 227 // in the previous frames. | 233 // in the previous frames. |
| 228 Isolate* isolate = Isolate::Current(); | 234 Isolate* isolate = Isolate::Current(); |
| 229 while (isolate->top_resource() != NULL && | 235 while (isolate->top_resource() != NULL && |
| 230 (reinterpret_cast<uword>(isolate->top_resource()) < stack_pointer)) { | 236 (reinterpret_cast<uword>(isolate->top_resource()) < stack_pointer)) { |
| 231 isolate->top_resource()->~StackResource(); | 237 isolate->top_resource()->~StackResource(); |
| 232 } | 238 } |
| 233 | 239 |
| 234 // TODO(regis): Can we safely merge both stubs and pass NULL as | 240 // Call a stub to set up the exception object in kExceptionObjectReg, |
| 235 // stacktrace_object in the case of an error handler? | 241 // to set up the stacktrace object in kStackTraceObjectReg, and to |
| 236 | 242 // continue execution at the given pc in the given frame. |
| 237 // A NULL raw_stacktrace indicates that we are jumping to an ErrorHandler, | 243 typedef void (*ExcpHandler)(uword, uword, uword, RawObject*, RawObject*); |
| 238 // rather than to an ExceptionHandler. TODO(regis): Merge these two cases. | 244 ExcpHandler func = reinterpret_cast<ExcpHandler>( |
| 239 if (raw_stacktrace == NULL) { | 245 StubCode::JumpToExceptionHandlerEntryPoint()); |
| 240 // Call a stub to set up the error object in kExceptionObjectReg and to | 246 func(program_counter, stack_pointer, frame_pointer, |
| 241 // continue execution at the given pc in the given frame. | 247 raw_exception, raw_stacktrace); |
| 242 typedef void (*ErrorHandler)(uword, uword, uword, RawObject*); | |
| 243 ErrorHandler func = reinterpret_cast<ErrorHandler>( | |
| 244 StubCode::JumpToErrorHandlerEntryPoint()); | |
| 245 func(program_counter, stack_pointer, frame_pointer, raw_exception); | |
| 246 } else { | |
| 247 // Call a stub to set up the exception object in kExceptionObjectReg, | |
| 248 // to set up the stacktrace object in kStackTraceObjectReg, and to | |
| 249 // continue execution at the given pc in the given frame. | |
| 250 typedef void (*ExcpHandler)(uword, uword, uword, RawObject*, RawObject*); | |
| 251 ExcpHandler func = reinterpret_cast<ExcpHandler>( | |
| 252 StubCode::JumpToExceptionHandlerEntryPoint()); | |
| 253 func(program_counter, stack_pointer, frame_pointer, | |
| 254 raw_exception, raw_stacktrace); | |
| 255 } | |
| 256 #endif | 248 #endif |
| 257 UNREACHABLE(); | 249 UNREACHABLE(); |
| 258 } | 250 } |
| 259 | 251 |
| 260 | 252 |
| 261 static void JumpToExceptionHandler(uword program_counter, | |
| 262 uword stack_pointer, | |
| 263 uword frame_pointer, | |
| 264 const Instance& exception_object, | |
| 265 const Instance& stacktrace_object) { | |
| 266 // The no_gc StackResource is unwound through the tear down of | |
| 267 // stack resources below. | |
| 268 NoGCScope no_gc; | |
| 269 RawObject* raw_exception = exception_object.raw(); | |
| 270 RawObject* raw_stacktrace = stacktrace_object.raw(); | |
| 271 | |
| 272 JumpToHandler(program_counter, stack_pointer, frame_pointer, | |
| 273 raw_exception, raw_stacktrace); | |
| 274 | |
| 275 UNREACHABLE(); | |
| 276 } | |
| 277 | |
| 278 | |
| 279 static void JumpToErrorHandler(uword program_counter, | |
| 280 uword stack_pointer, | |
| 281 uword frame_pointer, | |
| 282 const Error& error_object) { | |
| 283 // The no_gc StackResource is unwound through the tear down of | |
| 284 // stack resources below. | |
| 285 NoGCScope no_gc; | |
| 286 ASSERT(!error_object.IsNull()); | |
| 287 RawObject* raw_error = error_object.raw(); | |
| 288 | |
| 289 JumpToHandler( | |
| 290 program_counter, stack_pointer, frame_pointer, raw_error, NULL); | |
| 291 | |
| 292 UNREACHABLE(); | |
| 293 } | |
| 294 | |
| 295 | |
| 296 static void ThrowExceptionHelper(const Instance& incoming_exception, | 253 static void ThrowExceptionHelper(const Instance& incoming_exception, |
| 297 const Instance& existing_stacktrace) { | 254 const Instance& existing_stacktrace) { |
| 298 bool use_preallocated_stacktrace = false; | 255 bool use_preallocated_stacktrace = false; |
| 299 Isolate* isolate = Isolate::Current(); | 256 Isolate* isolate = Isolate::Current(); |
| 300 Instance& exception = Instance::Handle(isolate, incoming_exception.raw()); | 257 Instance& exception = Instance::Handle(isolate, incoming_exception.raw()); |
| 301 if (exception.IsNull()) { | 258 if (exception.IsNull()) { |
| 302 exception ^= Exceptions::Create(Exceptions::kNullThrown, | 259 exception ^= Exceptions::Create(Exceptions::kNullThrown, |
| 303 Object::empty_array()); | 260 Object::empty_array()); |
| 304 } else if (exception.raw() == isolate->object_store()->out_of_memory() || | 261 } else if (exception.raw() == isolate->object_store()->out_of_memory() || |
| 305 exception.raw() == isolate->object_store()->stack_overflow()) { | 262 exception.raw() == isolate->object_store()->stack_overflow()) { |
| (...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 382 } | 339 } |
| 383 // No dart exception handler found in this invocation sequence, | 340 // No dart exception handler found in this invocation sequence, |
| 384 // so we create an unhandled exception object and return to the | 341 // so we create an unhandled exception object and return to the |
| 385 // invocation stub so that it returns this unhandled exception | 342 // invocation stub so that it returns this unhandled exception |
| 386 // object. The C++ code which invoked this dart sequence can check | 343 // object. The C++ code which invoked this dart sequence can check |
| 387 // and do the appropriate thing (rethrow the exception to the | 344 // and do the appropriate thing (rethrow the exception to the |
| 388 // dart invocation sequence above it, print diagnostics and terminate | 345 // dart invocation sequence above it, print diagnostics and terminate |
| 389 // the isolate etc.). | 346 // the isolate etc.). |
| 390 const UnhandledException& unhandled_exception = UnhandledException::Handle( | 347 const UnhandledException& unhandled_exception = UnhandledException::Handle( |
| 391 UnhandledException::New(exception, stacktrace)); | 348 UnhandledException::New(exception, stacktrace)); |
| 392 JumpToErrorHandler(handler_pc, handler_sp, handler_fp, unhandled_exception); | 349 stacktrace = Stacktrace::null(); |
| 350 JumpToExceptionHandler(handler_pc, |
| 351 handler_sp, |
| 352 handler_fp, |
| 353 unhandled_exception, |
| 354 stacktrace); |
| 393 } | 355 } |
| 394 UNREACHABLE(); | 356 UNREACHABLE(); |
| 395 } | 357 } |
| 396 | 358 |
| 397 | 359 |
| 398 // Static helpers for allocating, initializing, and throwing an error instance. | 360 // Static helpers for allocating, initializing, and throwing an error instance. |
| 399 | 361 |
| 400 // Return the script of the Dart function that called the native entry or the | 362 // Return the script of the Dart function that called the native entry or the |
| 401 // runtime entry. The frame iterator points to the callee. | 363 // runtime entry. The frame iterator points to the callee. |
| 402 RawScript* Exceptions::GetCallerScript(DartFrameIterator* iterator) { | 364 RawScript* Exceptions::GetCallerScript(DartFrameIterator* iterator) { |
| (...skipping 143 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 546 const Instance& stk = Instance::Handle(uhe.stacktrace()); | 508 const Instance& stk = Instance::Handle(uhe.stacktrace()); |
| 547 Exceptions::ReThrow(exc, stk); | 509 Exceptions::ReThrow(exc, stk); |
| 548 } else { | 510 } else { |
| 549 // Return to the invocation stub and return this error object. The | 511 // Return to the invocation stub and return this error object. The |
| 550 // 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 |
| 551 // appropriate thing. | 513 // appropriate thing. |
| 552 uword handler_pc = 0; | 514 uword handler_pc = 0; |
| 553 uword handler_sp = 0; | 515 uword handler_sp = 0; |
| 554 uword handler_fp = 0; | 516 uword handler_fp = 0; |
| 555 FindErrorHandler(&handler_pc, &handler_sp, &handler_fp); | 517 FindErrorHandler(&handler_pc, &handler_sp, &handler_fp); |
| 556 JumpToErrorHandler(handler_pc, handler_sp, handler_fp, error); | 518 JumpToExceptionHandler(handler_pc, handler_sp, handler_fp, error, |
| 519 Stacktrace::Handle()); // Null stacktrace. |
| 557 } | 520 } |
| 558 UNREACHABLE(); | 521 UNREACHABLE(); |
| 559 } | 522 } |
| 560 | 523 |
| 561 | 524 |
| 562 void Exceptions::ThrowByType(ExceptionType type, const Array& arguments) { | 525 void Exceptions::ThrowByType(ExceptionType type, const Array& arguments) { |
| 563 const Object& result = Object::Handle(Create(type, arguments)); | 526 const Object& result = Object::Handle(Create(type, arguments)); |
| 564 if (result.IsError()) { | 527 if (result.IsError()) { |
| 565 // We got an error while constructing the exception object. | 528 // We got an error while constructing the exception object. |
| 566 // Propagate the error instead of throwing the exception. | 529 // Propagate the error instead of throwing the exception. |
| (...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 627 break; | 590 break; |
| 628 } | 591 } |
| 629 | 592 |
| 630 return DartLibraryCalls::ExceptionCreate(library, | 593 return DartLibraryCalls::ExceptionCreate(library, |
| 631 *class_name, | 594 *class_name, |
| 632 *constructor_name, | 595 *constructor_name, |
| 633 arguments); | 596 arguments); |
| 634 } | 597 } |
| 635 | 598 |
| 636 } // namespace dart | 599 } // namespace dart |
| OLD | NEW |