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 |