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 "lib/stacktrace.h" | 9 #include "lib/stacktrace.h" |
10 | 10 |
11 #include "vm/dart_api_impl.h" | 11 #include "vm/dart_api_impl.h" |
12 #include "vm/dart_entry.h" | 12 #include "vm/dart_entry.h" |
13 #include "vm/datastream.h" | 13 #include "vm/datastream.h" |
14 #include "vm/debugger.h" | 14 #include "vm/debugger.h" |
15 #include "vm/deopt_instructions.h" | 15 #include "vm/deopt_instructions.h" |
16 #include "vm/flags.h" | 16 #include "vm/flags.h" |
17 #include "vm/log.h" | 17 #include "vm/log.h" |
18 #include "vm/longjump.h" | 18 #include "vm/longjump.h" |
19 #include "vm/object.h" | 19 #include "vm/object.h" |
20 #include "vm/object_store.h" | 20 #include "vm/object_store.h" |
21 #include "vm/stack_frame.h" | 21 #include "vm/stack_frame.h" |
22 #include "vm/stub_code.h" | 22 #include "vm/stub_code.h" |
23 #include "vm/symbols.h" | 23 #include "vm/symbols.h" |
24 #include "vm/tags.h" | 24 #include "vm/tags.h" |
25 | 25 |
26 | |
27 namespace dart { | 26 namespace dart { |
28 | 27 |
29 DECLARE_FLAG(bool, trace_deoptimization); | 28 DECLARE_FLAG(bool, trace_deoptimization); |
30 DEFINE_FLAG(bool, | 29 DEFINE_FLAG(bool, |
31 print_stacktrace_at_throw, | 30 print_stacktrace_at_throw, |
32 false, | 31 false, |
33 "Prints a stack trace everytime a throw occurs."); | 32 "Prints a stack trace everytime a throw occurs."); |
34 | 33 |
35 | |
36 class StackTraceBuilder : public ValueObject { | 34 class StackTraceBuilder : public ValueObject { |
37 public: | 35 public: |
38 StackTraceBuilder() {} | 36 StackTraceBuilder() {} |
39 virtual ~StackTraceBuilder() {} | 37 virtual ~StackTraceBuilder() {} |
40 | 38 |
41 virtual void AddFrame(const Code& code, const Smi& offset) = 0; | 39 virtual void AddFrame(const Code& code, const Smi& offset) = 0; |
42 }; | 40 }; |
43 | 41 |
44 | |
45 class RegularStackTraceBuilder : public StackTraceBuilder { | 42 class RegularStackTraceBuilder : public StackTraceBuilder { |
46 public: | 43 public: |
47 explicit RegularStackTraceBuilder(Zone* zone) | 44 explicit RegularStackTraceBuilder(Zone* zone) |
48 : code_list_( | 45 : code_list_( |
49 GrowableObjectArray::Handle(zone, GrowableObjectArray::New())), | 46 GrowableObjectArray::Handle(zone, GrowableObjectArray::New())), |
50 pc_offset_list_( | 47 pc_offset_list_( |
51 GrowableObjectArray::Handle(zone, GrowableObjectArray::New())) {} | 48 GrowableObjectArray::Handle(zone, GrowableObjectArray::New())) {} |
52 ~RegularStackTraceBuilder() {} | 49 ~RegularStackTraceBuilder() {} |
53 | 50 |
54 const GrowableObjectArray& code_list() const { return code_list_; } | 51 const GrowableObjectArray& code_list() const { return code_list_; } |
55 const GrowableObjectArray& pc_offset_list() const { return pc_offset_list_; } | 52 const GrowableObjectArray& pc_offset_list() const { return pc_offset_list_; } |
56 | 53 |
57 virtual void AddFrame(const Code& code, const Smi& offset) { | 54 virtual void AddFrame(const Code& code, const Smi& offset) { |
58 code_list_.Add(code); | 55 code_list_.Add(code); |
59 pc_offset_list_.Add(offset); | 56 pc_offset_list_.Add(offset); |
60 } | 57 } |
61 | 58 |
62 private: | 59 private: |
63 const GrowableObjectArray& code_list_; | 60 const GrowableObjectArray& code_list_; |
64 const GrowableObjectArray& pc_offset_list_; | 61 const GrowableObjectArray& pc_offset_list_; |
65 | 62 |
66 DISALLOW_COPY_AND_ASSIGN(RegularStackTraceBuilder); | 63 DISALLOW_COPY_AND_ASSIGN(RegularStackTraceBuilder); |
67 }; | 64 }; |
68 | 65 |
69 | |
70 class PreallocatedStackTraceBuilder : public StackTraceBuilder { | 66 class PreallocatedStackTraceBuilder : public StackTraceBuilder { |
71 public: | 67 public: |
72 explicit PreallocatedStackTraceBuilder(const Instance& stacktrace) | 68 explicit PreallocatedStackTraceBuilder(const Instance& stacktrace) |
73 : stacktrace_(StackTrace::Cast(stacktrace)), | 69 : stacktrace_(StackTrace::Cast(stacktrace)), |
74 cur_index_(0), | 70 cur_index_(0), |
75 dropped_frames_(0) { | 71 dropped_frames_(0) { |
76 ASSERT(stacktrace_.raw() == | 72 ASSERT(stacktrace_.raw() == |
77 Isolate::Current()->object_store()->preallocated_stack_trace()); | 73 Isolate::Current()->object_store()->preallocated_stack_trace()); |
78 } | 74 } |
79 ~PreallocatedStackTraceBuilder() {} | 75 ~PreallocatedStackTraceBuilder() {} |
80 | 76 |
81 virtual void AddFrame(const Code& code, const Smi& offset); | 77 virtual void AddFrame(const Code& code, const Smi& offset); |
82 | 78 |
83 private: | 79 private: |
84 static const int kNumTopframes = StackTrace::kPreallocatedStackdepth / 2; | 80 static const int kNumTopframes = StackTrace::kPreallocatedStackdepth / 2; |
85 | 81 |
86 const StackTrace& stacktrace_; | 82 const StackTrace& stacktrace_; |
87 intptr_t cur_index_; | 83 intptr_t cur_index_; |
88 intptr_t dropped_frames_; | 84 intptr_t dropped_frames_; |
89 | 85 |
90 DISALLOW_COPY_AND_ASSIGN(PreallocatedStackTraceBuilder); | 86 DISALLOW_COPY_AND_ASSIGN(PreallocatedStackTraceBuilder); |
91 }; | 87 }; |
92 | 88 |
93 | |
94 void PreallocatedStackTraceBuilder::AddFrame(const Code& code, | 89 void PreallocatedStackTraceBuilder::AddFrame(const Code& code, |
95 const Smi& offset) { | 90 const Smi& offset) { |
96 if (cur_index_ >= StackTrace::kPreallocatedStackdepth) { | 91 if (cur_index_ >= StackTrace::kPreallocatedStackdepth) { |
97 // The number of frames is overflowing the preallocated stack trace object. | 92 // The number of frames is overflowing the preallocated stack trace object. |
98 Code& frame_code = Code::Handle(); | 93 Code& frame_code = Code::Handle(); |
99 Smi& frame_offset = Smi::Handle(); | 94 Smi& frame_offset = Smi::Handle(); |
100 intptr_t start = StackTrace::kPreallocatedStackdepth - (kNumTopframes - 1); | 95 intptr_t start = StackTrace::kPreallocatedStackdepth - (kNumTopframes - 1); |
101 intptr_t null_slot = start - 2; | 96 intptr_t null_slot = start - 2; |
102 // We are going to drop one frame. | 97 // We are going to drop one frame. |
103 dropped_frames_++; | 98 dropped_frames_++; |
(...skipping 15 matching lines...) Expand all Loading... |
119 stacktrace_.SetCodeAtFrame(prev, frame_code); | 114 stacktrace_.SetCodeAtFrame(prev, frame_code); |
120 stacktrace_.SetPcOffsetAtFrame(prev, frame_offset); | 115 stacktrace_.SetPcOffsetAtFrame(prev, frame_offset); |
121 } | 116 } |
122 cur_index_ = (StackTrace::kPreallocatedStackdepth - 1); | 117 cur_index_ = (StackTrace::kPreallocatedStackdepth - 1); |
123 } | 118 } |
124 stacktrace_.SetCodeAtFrame(cur_index_, code); | 119 stacktrace_.SetCodeAtFrame(cur_index_, code); |
125 stacktrace_.SetPcOffsetAtFrame(cur_index_, offset); | 120 stacktrace_.SetPcOffsetAtFrame(cur_index_, offset); |
126 cur_index_ += 1; | 121 cur_index_ += 1; |
127 } | 122 } |
128 | 123 |
129 | |
130 static void BuildStackTrace(StackTraceBuilder* builder) { | 124 static void BuildStackTrace(StackTraceBuilder* builder) { |
131 StackFrameIterator frames(StackFrameIterator::kDontValidateFrames, | 125 StackFrameIterator frames(StackFrameIterator::kDontValidateFrames, |
132 Thread::Current(), | 126 Thread::Current(), |
133 StackFrameIterator::kNoCrossThreadIteration); | 127 StackFrameIterator::kNoCrossThreadIteration); |
134 StackFrame* frame = frames.NextFrame(); | 128 StackFrame* frame = frames.NextFrame(); |
135 ASSERT(frame != NULL); // We expect to find a dart invocation frame. | 129 ASSERT(frame != NULL); // We expect to find a dart invocation frame. |
136 Code& code = Code::Handle(); | 130 Code& code = Code::Handle(); |
137 Smi& offset = Smi::Handle(); | 131 Smi& offset = Smi::Handle(); |
138 while (frame != NULL) { | 132 while (frame != NULL) { |
139 if (frame->IsDartFrame()) { | 133 if (frame->IsDartFrame()) { |
140 code = frame->LookupDartCode(); | 134 code = frame->LookupDartCode(); |
141 ASSERT(code.ContainsInstructionAt(frame->pc())); | 135 ASSERT(code.ContainsInstructionAt(frame->pc())); |
142 offset = Smi::New(frame->pc() - code.PayloadStart()); | 136 offset = Smi::New(frame->pc() - code.PayloadStart()); |
143 builder->AddFrame(code, offset); | 137 builder->AddFrame(code, offset); |
144 } | 138 } |
145 frame = frames.NextFrame(); | 139 frame = frames.NextFrame(); |
146 } | 140 } |
147 } | 141 } |
148 | 142 |
149 | |
150 static RawObject** VariableAt(uword fp, int stack_slot) { | 143 static RawObject** VariableAt(uword fp, int stack_slot) { |
151 #if defined(TARGET_ARCH_DBC) | 144 #if defined(TARGET_ARCH_DBC) |
152 return reinterpret_cast<RawObject**>(fp + stack_slot * kWordSize); | 145 return reinterpret_cast<RawObject**>(fp + stack_slot * kWordSize); |
153 #else | 146 #else |
154 if (stack_slot < 0) { | 147 if (stack_slot < 0) { |
155 return reinterpret_cast<RawObject**>(ParamAddress(fp, -stack_slot)); | 148 return reinterpret_cast<RawObject**>(ParamAddress(fp, -stack_slot)); |
156 } else { | 149 } else { |
157 return reinterpret_cast<RawObject**>( | 150 return reinterpret_cast<RawObject**>( |
158 LocalVarAddress(fp, kFirstLocalSlotFromFp - stack_slot)); | 151 LocalVarAddress(fp, kFirstLocalSlotFromFp - stack_slot)); |
159 } | 152 } |
160 #endif | 153 #endif |
161 } | 154 } |
162 | 155 |
163 | |
164 class ExceptionHandlerFinder : public StackResource { | 156 class ExceptionHandlerFinder : public StackResource { |
165 public: | 157 public: |
166 explicit ExceptionHandlerFinder(Thread* thread) | 158 explicit ExceptionHandlerFinder(Thread* thread) |
167 : StackResource(thread), thread_(thread), cache_(NULL), metadata_(NULL) {} | 159 : StackResource(thread), thread_(thread), cache_(NULL), metadata_(NULL) {} |
168 | 160 |
169 // Iterate through the stack frames and try to find a frame with an | 161 // Iterate through the stack frames and try to find a frame with an |
170 // exception handler. Once found, set the pc, sp and fp so that execution | 162 // exception handler. Once found, set the pc, sp and fp so that execution |
171 // can continue in that frame. Sets 'needs_stacktrace' if there is no | 163 // can continue in that frame. Sets 'needs_stacktrace' if there is no |
172 // cath-all handler or if a stack-trace is specified in the catch. | 164 // cath-all handler or if a stack-trace is specified in the catch. |
173 bool Find() { | 165 bool Find() { |
(...skipping 166 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
340 typedef ReadStream::Raw<sizeof(intptr_t), intptr_t> Reader; | 332 typedef ReadStream::Raw<sizeof(intptr_t), intptr_t> Reader; |
341 Thread* thread_; | 333 Thread* thread_; |
342 CatchEntryStateCache* cache_; | 334 CatchEntryStateCache* cache_; |
343 Code* code_; | 335 Code* code_; |
344 bool handler_pc_set_; | 336 bool handler_pc_set_; |
345 intptr_t* metadata_; // MetaData generated from deopt. | 337 intptr_t* metadata_; // MetaData generated from deopt. |
346 CatchEntryState cached_; // Value of per PC MetaData cache. | 338 CatchEntryState cached_; // Value of per PC MetaData cache. |
347 intptr_t pc_; // Current pc in the handler frame. | 339 intptr_t pc_; // Current pc in the handler frame. |
348 }; | 340 }; |
349 | 341 |
350 | |
351 static void FindErrorHandler(uword* handler_pc, | 342 static void FindErrorHandler(uword* handler_pc, |
352 uword* handler_sp, | 343 uword* handler_sp, |
353 uword* handler_fp) { | 344 uword* handler_fp) { |
354 StackFrameIterator frames(StackFrameIterator::kDontValidateFrames, | 345 StackFrameIterator frames(StackFrameIterator::kDontValidateFrames, |
355 Thread::Current(), | 346 Thread::Current(), |
356 StackFrameIterator::kNoCrossThreadIteration); | 347 StackFrameIterator::kNoCrossThreadIteration); |
357 StackFrame* frame = frames.NextFrame(); | 348 StackFrame* frame = frames.NextFrame(); |
358 ASSERT(frame != NULL); | 349 ASSERT(frame != NULL); |
359 while (!frame->IsEntryFrame()) { | 350 while (!frame->IsEntryFrame()) { |
360 frame = frames.NextFrame(); | 351 frame = frames.NextFrame(); |
361 ASSERT(frame != NULL); | 352 ASSERT(frame != NULL); |
362 } | 353 } |
363 ASSERT(frame->IsEntryFrame()); | 354 ASSERT(frame->IsEntryFrame()); |
364 *handler_pc = frame->pc(); | 355 *handler_pc = frame->pc(); |
365 *handler_sp = frame->sp(); | 356 *handler_sp = frame->sp(); |
366 *handler_fp = frame->fp(); | 357 *handler_fp = frame->fp(); |
367 } | 358 } |
368 | 359 |
369 | |
370 static uword RemapExceptionPCForDeopt(Thread* thread, | 360 static uword RemapExceptionPCForDeopt(Thread* thread, |
371 uword program_counter, | 361 uword program_counter, |
372 uword frame_pointer) { | 362 uword frame_pointer) { |
373 #if !defined(TARGET_ARCH_DBC) | 363 #if !defined(TARGET_ARCH_DBC) |
374 MallocGrowableArray<PendingLazyDeopt>* pending_deopts = | 364 MallocGrowableArray<PendingLazyDeopt>* pending_deopts = |
375 thread->isolate()->pending_deopts(); | 365 thread->isolate()->pending_deopts(); |
376 if (pending_deopts->length() > 0) { | 366 if (pending_deopts->length() > 0) { |
377 // Check if the target frame is scheduled for lazy deopt. | 367 // Check if the target frame is scheduled for lazy deopt. |
378 for (intptr_t i = 0; i < pending_deopts->length(); i++) { | 368 for (intptr_t i = 0; i < pending_deopts->length(); i++) { |
379 if ((*pending_deopts)[i].fp() == frame_pointer) { | 369 if ((*pending_deopts)[i].fp() == frame_pointer) { |
380 // Deopt should now resume in the catch handler instead of after the | 370 // Deopt should now resume in the catch handler instead of after the |
381 // call. | 371 // call. |
382 (*pending_deopts)[i].set_pc(program_counter); | 372 (*pending_deopts)[i].set_pc(program_counter); |
383 | 373 |
384 // Jump to the deopt stub instead of the catch handler. | 374 // Jump to the deopt stub instead of the catch handler. |
385 program_counter = | 375 program_counter = |
386 StubCode::DeoptimizeLazyFromThrow_entry()->EntryPoint(); | 376 StubCode::DeoptimizeLazyFromThrow_entry()->EntryPoint(); |
387 if (FLAG_trace_deoptimization) { | 377 if (FLAG_trace_deoptimization) { |
388 THR_Print("Throwing to frame scheduled for lazy deopt fp=%" Pp "\n", | 378 THR_Print("Throwing to frame scheduled for lazy deopt fp=%" Pp "\n", |
389 frame_pointer); | 379 frame_pointer); |
390 } | 380 } |
391 break; | 381 break; |
392 } | 382 } |
393 } | 383 } |
394 } | 384 } |
395 #endif // !DBC | 385 #endif // !DBC |
396 return program_counter; | 386 return program_counter; |
397 } | 387 } |
398 | 388 |
399 | |
400 static void ClearLazyDeopts(Thread* thread, uword frame_pointer) { | 389 static void ClearLazyDeopts(Thread* thread, uword frame_pointer) { |
401 #if !defined(TARGET_ARCH_DBC) | 390 #if !defined(TARGET_ARCH_DBC) |
402 MallocGrowableArray<PendingLazyDeopt>* pending_deopts = | 391 MallocGrowableArray<PendingLazyDeopt>* pending_deopts = |
403 thread->isolate()->pending_deopts(); | 392 thread->isolate()->pending_deopts(); |
404 if (pending_deopts->length() > 0) { | 393 if (pending_deopts->length() > 0) { |
405 // We may be jumping over frames scheduled for lazy deopt. Remove these | 394 // We may be jumping over frames scheduled for lazy deopt. Remove these |
406 // frames from the pending deopt table, but only after unmarking them so | 395 // frames from the pending deopt table, but only after unmarking them so |
407 // any stack walk that happens before the stack is unwound will still work. | 396 // any stack walk that happens before the stack is unwound will still work. |
408 { | 397 { |
409 DartFrameIterator frames(thread, | 398 DartFrameIterator frames(thread, |
(...skipping 23 matching lines...) Expand all Loading... |
433 } | 422 } |
434 } | 423 } |
435 | 424 |
436 #if defined(DEBUG) | 425 #if defined(DEBUG) |
437 ValidateFrames(); | 426 ValidateFrames(); |
438 #endif | 427 #endif |
439 } | 428 } |
440 #endif // !DBC | 429 #endif // !DBC |
441 } | 430 } |
442 | 431 |
443 | |
444 static void JumpToExceptionHandler(Thread* thread, | 432 static void JumpToExceptionHandler(Thread* thread, |
445 uword program_counter, | 433 uword program_counter, |
446 uword stack_pointer, | 434 uword stack_pointer, |
447 uword frame_pointer, | 435 uword frame_pointer, |
448 const Object& exception_object, | 436 const Object& exception_object, |
449 const Object& stacktrace_object) { | 437 const Object& stacktrace_object) { |
450 uword remapped_pc = | 438 uword remapped_pc = |
451 RemapExceptionPCForDeopt(thread, program_counter, frame_pointer); | 439 RemapExceptionPCForDeopt(thread, program_counter, frame_pointer); |
452 thread->set_active_exception(exception_object); | 440 thread->set_active_exception(exception_object); |
453 thread->set_active_stacktrace(stacktrace_object); | 441 thread->set_active_stacktrace(stacktrace_object); |
454 thread->set_resume_pc(remapped_pc); | 442 thread->set_resume_pc(remapped_pc); |
455 uword run_exception_pc = StubCode::RunExceptionHandler_entry()->EntryPoint(); | 443 uword run_exception_pc = StubCode::RunExceptionHandler_entry()->EntryPoint(); |
456 Exceptions::JumpToFrame(thread, run_exception_pc, stack_pointer, | 444 Exceptions::JumpToFrame(thread, run_exception_pc, stack_pointer, |
457 frame_pointer, false /* do not clear deopt */); | 445 frame_pointer, false /* do not clear deopt */); |
458 } | 446 } |
459 | 447 |
460 | |
461 void Exceptions::JumpToFrame(Thread* thread, | 448 void Exceptions::JumpToFrame(Thread* thread, |
462 uword program_counter, | 449 uword program_counter, |
463 uword stack_pointer, | 450 uword stack_pointer, |
464 uword frame_pointer, | 451 uword frame_pointer, |
465 bool clear_deopt_at_target) { | 452 bool clear_deopt_at_target) { |
466 uword fp_for_clearing = | 453 uword fp_for_clearing = |
467 (clear_deopt_at_target ? frame_pointer + 1 : frame_pointer); | 454 (clear_deopt_at_target ? frame_pointer + 1 : frame_pointer); |
468 ClearLazyDeopts(thread, fp_for_clearing); | 455 ClearLazyDeopts(thread, fp_for_clearing); |
469 #if defined(USING_SIMULATOR) | 456 #if defined(USING_SIMULATOR) |
470 // Unwinding of the C++ frames and destroying of their stack resources is done | 457 // Unwinding of the C++ frames and destroying of their stack resources is done |
(...skipping 21 matching lines...) Expand all Loading... |
492 // Unpoison the stack before we tear it down in the generated stub code. | 479 // Unpoison the stack before we tear it down in the generated stub code. |
493 uword current_sp = Thread::GetCurrentStackPointer() - 1024; | 480 uword current_sp = Thread::GetCurrentStackPointer() - 1024; |
494 ASAN_UNPOISON(reinterpret_cast<void*>(current_sp), | 481 ASAN_UNPOISON(reinterpret_cast<void*>(current_sp), |
495 stack_pointer - current_sp); | 482 stack_pointer - current_sp); |
496 | 483 |
497 func(program_counter, stack_pointer, frame_pointer, thread); | 484 func(program_counter, stack_pointer, frame_pointer, thread); |
498 #endif | 485 #endif |
499 UNREACHABLE(); | 486 UNREACHABLE(); |
500 } | 487 } |
501 | 488 |
502 | |
503 static RawField* LookupStackTraceField(const Instance& instance) { | 489 static RawField* LookupStackTraceField(const Instance& instance) { |
504 if (instance.GetClassId() < kNumPredefinedCids) { | 490 if (instance.GetClassId() < kNumPredefinedCids) { |
505 // 'class Error' is not a predefined class. | 491 // 'class Error' is not a predefined class. |
506 return Field::null(); | 492 return Field::null(); |
507 } | 493 } |
508 Thread* thread = Thread::Current(); | 494 Thread* thread = Thread::Current(); |
509 Zone* zone = thread->zone(); | 495 Zone* zone = thread->zone(); |
510 Isolate* isolate = thread->isolate(); | 496 Isolate* isolate = thread->isolate(); |
511 Class& error_class = | 497 Class& error_class = |
512 Class::Handle(zone, isolate->object_store()->error_class()); | 498 Class::Handle(zone, isolate->object_store()->error_class()); |
(...skipping 12 matching lines...) Expand all Loading... |
525 Symbols::_stackTrace()); | 511 Symbols::_stackTrace()); |
526 } | 512 } |
527 type = test_class.super_type(); | 513 type = test_class.super_type(); |
528 if (type.IsNull()) return Field::null(); | 514 if (type.IsNull()) return Field::null(); |
529 test_class = type.type_class(); | 515 test_class = type.type_class(); |
530 } | 516 } |
531 UNREACHABLE(); | 517 UNREACHABLE(); |
532 return Field::null(); | 518 return Field::null(); |
533 } | 519 } |
534 | 520 |
535 | |
536 RawStackTrace* Exceptions::CurrentStackTrace() { | 521 RawStackTrace* Exceptions::CurrentStackTrace() { |
537 return GetStackTraceForException(); | 522 return GetStackTraceForException(); |
538 } | 523 } |
539 | 524 |
540 | |
541 static void ThrowExceptionHelper(Thread* thread, | 525 static void ThrowExceptionHelper(Thread* thread, |
542 const Instance& incoming_exception, | 526 const Instance& incoming_exception, |
543 const Instance& existing_stacktrace, | 527 const Instance& existing_stacktrace, |
544 const bool is_rethrow) { | 528 const bool is_rethrow) { |
545 Zone* zone = thread->zone(); | 529 Zone* zone = thread->zone(); |
546 Isolate* isolate = thread->isolate(); | 530 Isolate* isolate = thread->isolate(); |
547 bool use_preallocated_stacktrace = false; | 531 bool use_preallocated_stacktrace = false; |
548 Instance& exception = Instance::Handle(zone, incoming_exception.raw()); | 532 Instance& exception = Instance::Handle(zone, incoming_exception.raw()); |
549 if (exception.IsNull()) { | 533 if (exception.IsNull()) { |
550 exception ^= | 534 exception ^= |
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
630 // the isolate etc.). | 614 // the isolate etc.). |
631 const UnhandledException& unhandled_exception = UnhandledException::Handle( | 615 const UnhandledException& unhandled_exception = UnhandledException::Handle( |
632 zone, UnhandledException::New(exception, stacktrace)); | 616 zone, UnhandledException::New(exception, stacktrace)); |
633 stacktrace = StackTrace::null(); | 617 stacktrace = StackTrace::null(); |
634 JumpToExceptionHandler(thread, handler_pc, handler_sp, handler_fp, | 618 JumpToExceptionHandler(thread, handler_pc, handler_sp, handler_fp, |
635 unhandled_exception, stacktrace); | 619 unhandled_exception, stacktrace); |
636 } | 620 } |
637 UNREACHABLE(); | 621 UNREACHABLE(); |
638 } | 622 } |
639 | 623 |
640 | |
641 // Static helpers for allocating, initializing, and throwing an error instance. | 624 // Static helpers for allocating, initializing, and throwing an error instance. |
642 | 625 |
643 // Return the script of the Dart function that called the native entry or the | 626 // Return the script of the Dart function that called the native entry or the |
644 // runtime entry. The frame iterator points to the callee. | 627 // runtime entry. The frame iterator points to the callee. |
645 RawScript* Exceptions::GetCallerScript(DartFrameIterator* iterator) { | 628 RawScript* Exceptions::GetCallerScript(DartFrameIterator* iterator) { |
646 StackFrame* caller_frame = iterator->NextFrame(); | 629 StackFrame* caller_frame = iterator->NextFrame(); |
647 ASSERT(caller_frame != NULL && caller_frame->IsDartFrame()); | 630 ASSERT(caller_frame != NULL && caller_frame->IsDartFrame()); |
648 const Function& caller = Function::Handle(caller_frame->LookupDartFunction()); | 631 const Function& caller = Function::Handle(caller_frame->LookupDartFunction()); |
649 ASSERT(!caller.IsNull()); | 632 ASSERT(!caller.IsNull()); |
650 return caller.script(); | 633 return caller.script(); |
651 } | 634 } |
652 | 635 |
653 | |
654 // Allocate a new instance of the given class name. | 636 // Allocate a new instance of the given class name. |
655 // TODO(hausner): Rename this NewCoreInstance to call out the fact that | 637 // TODO(hausner): Rename this NewCoreInstance to call out the fact that |
656 // the class name is resolved in the core library implicitly? | 638 // the class name is resolved in the core library implicitly? |
657 RawInstance* Exceptions::NewInstance(const char* class_name) { | 639 RawInstance* Exceptions::NewInstance(const char* class_name) { |
658 Thread* thread = Thread::Current(); | 640 Thread* thread = Thread::Current(); |
659 Zone* zone = thread->zone(); | 641 Zone* zone = thread->zone(); |
660 const String& cls_name = | 642 const String& cls_name = |
661 String::Handle(zone, Symbols::New(thread, class_name)); | 643 String::Handle(zone, Symbols::New(thread, class_name)); |
662 const Library& core_lib = Library::Handle(Library::CoreLibrary()); | 644 const Library& core_lib = Library::Handle(Library::CoreLibrary()); |
663 // No ambiguity error expected: passing NULL. | 645 // No ambiguity error expected: passing NULL. |
664 Class& cls = Class::Handle(core_lib.LookupClass(cls_name)); | 646 Class& cls = Class::Handle(core_lib.LookupClass(cls_name)); |
665 ASSERT(!cls.IsNull()); | 647 ASSERT(!cls.IsNull()); |
666 // There are no parameterized error types, so no need to set type arguments. | 648 // There are no parameterized error types, so no need to set type arguments. |
667 return Instance::New(cls); | 649 return Instance::New(cls); |
668 } | 650 } |
669 | 651 |
670 | |
671 // Allocate, initialize, and throw a TypeError or CastError. | 652 // Allocate, initialize, and throw a TypeError or CastError. |
672 // If error_msg is not null, throw a TypeError, even for a type cast. | 653 // If error_msg is not null, throw a TypeError, even for a type cast. |
673 void Exceptions::CreateAndThrowTypeError(TokenPosition location, | 654 void Exceptions::CreateAndThrowTypeError(TokenPosition location, |
674 const AbstractType& src_type, | 655 const AbstractType& src_type, |
675 const AbstractType& dst_type, | 656 const AbstractType& dst_type, |
676 const String& dst_name, | 657 const String& dst_name, |
677 const String& bound_error_msg) { | 658 const String& bound_error_msg) { |
678 ASSERT(!dst_name.IsNull()); // Pass Symbols::Empty() instead. | 659 ASSERT(!dst_name.IsNull()); // Pass Symbols::Empty() instead. |
679 Thread* thread = Thread::Current(); | 660 Thread* thread = Thread::Current(); |
680 Zone* zone = thread->zone(); | 661 Zone* zone = thread->zone(); |
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
771 THR_Print("'%s': Failed type check: line %" Pd " pos %" Pd ": ", | 752 THR_Print("'%s': Failed type check: line %" Pd " pos %" Pd ": ", |
772 String::Handle(zone, script.url()).ToCString(), line, column); | 753 String::Handle(zone, script.url()).ToCString(), line, column); |
773 THR_Print("%s\n", error_msg.ToCString()); | 754 THR_Print("%s\n", error_msg.ToCString()); |
774 } | 755 } |
775 | 756 |
776 // Throw TypeError or CastError instance. | 757 // Throw TypeError or CastError instance. |
777 Exceptions::ThrowByType(exception_type, args); | 758 Exceptions::ThrowByType(exception_type, args); |
778 UNREACHABLE(); | 759 UNREACHABLE(); |
779 } | 760 } |
780 | 761 |
781 | |
782 void Exceptions::Throw(Thread* thread, const Instance& exception) { | 762 void Exceptions::Throw(Thread* thread, const Instance& exception) { |
783 // Do not notify debugger on stack overflow and out of memory exceptions. | 763 // Do not notify debugger on stack overflow and out of memory exceptions. |
784 // The VM would crash when the debugger calls back into the VM to | 764 // The VM would crash when the debugger calls back into the VM to |
785 // get values of variables. | 765 // get values of variables. |
786 if (FLAG_support_debugger) { | 766 if (FLAG_support_debugger) { |
787 Isolate* isolate = thread->isolate(); | 767 Isolate* isolate = thread->isolate(); |
788 if (exception.raw() != isolate->object_store()->out_of_memory() && | 768 if (exception.raw() != isolate->object_store()->out_of_memory() && |
789 exception.raw() != isolate->object_store()->stack_overflow()) { | 769 exception.raw() != isolate->object_store()->stack_overflow()) { |
790 isolate->debugger()->PauseException(exception); | 770 isolate->debugger()->PauseException(exception); |
791 } | 771 } |
792 } | 772 } |
793 // Null object is a valid exception object. | 773 // Null object is a valid exception object. |
794 ThrowExceptionHelper(thread, exception, StackTrace::Handle(thread->zone()), | 774 ThrowExceptionHelper(thread, exception, StackTrace::Handle(thread->zone()), |
795 false); | 775 false); |
796 } | 776 } |
797 | 777 |
798 | |
799 void Exceptions::ReThrow(Thread* thread, | 778 void Exceptions::ReThrow(Thread* thread, |
800 const Instance& exception, | 779 const Instance& exception, |
801 const Instance& stacktrace) { | 780 const Instance& stacktrace) { |
802 // Null object is a valid exception object. | 781 // Null object is a valid exception object. |
803 ThrowExceptionHelper(thread, exception, stacktrace, true); | 782 ThrowExceptionHelper(thread, exception, stacktrace, true); |
804 } | 783 } |
805 | 784 |
806 | |
807 void Exceptions::PropagateError(const Error& error) { | 785 void Exceptions::PropagateError(const Error& error) { |
808 Thread* thread = Thread::Current(); | 786 Thread* thread = Thread::Current(); |
809 Zone* zone = thread->zone(); | 787 Zone* zone = thread->zone(); |
810 ASSERT(thread->top_exit_frame_info() != 0); | 788 ASSERT(thread->top_exit_frame_info() != 0); |
811 if (error.IsUnhandledException()) { | 789 if (error.IsUnhandledException()) { |
812 // If the error object represents an unhandled exception, then | 790 // If the error object represents an unhandled exception, then |
813 // rethrow the exception in the normal fashion. | 791 // rethrow the exception in the normal fashion. |
814 const UnhandledException& uhe = UnhandledException::Cast(error); | 792 const UnhandledException& uhe = UnhandledException::Cast(error); |
815 const Instance& exc = Instance::Handle(zone, uhe.exception()); | 793 const Instance& exc = Instance::Handle(zone, uhe.exception()); |
816 const Instance& stk = Instance::Handle(zone, uhe.stacktrace()); | 794 const Instance& stk = Instance::Handle(zone, uhe.stacktrace()); |
817 Exceptions::ReThrow(thread, exc, stk); | 795 Exceptions::ReThrow(thread, exc, stk); |
818 } else { | 796 } else { |
819 // Return to the invocation stub and return this error object. The | 797 // Return to the invocation stub and return this error object. The |
820 // C++ code which invoked this dart sequence can check and do the | 798 // C++ code which invoked this dart sequence can check and do the |
821 // appropriate thing. | 799 // appropriate thing. |
822 uword handler_pc = 0; | 800 uword handler_pc = 0; |
823 uword handler_sp = 0; | 801 uword handler_sp = 0; |
824 uword handler_fp = 0; | 802 uword handler_fp = 0; |
825 FindErrorHandler(&handler_pc, &handler_sp, &handler_fp); | 803 FindErrorHandler(&handler_pc, &handler_sp, &handler_fp); |
826 JumpToExceptionHandler(thread, handler_pc, handler_sp, handler_fp, error, | 804 JumpToExceptionHandler(thread, handler_pc, handler_sp, handler_fp, error, |
827 StackTrace::Handle(zone)); // Null stacktrace. | 805 StackTrace::Handle(zone)); // Null stacktrace. |
828 } | 806 } |
829 UNREACHABLE(); | 807 UNREACHABLE(); |
830 } | 808 } |
831 | 809 |
832 | |
833 void Exceptions::ThrowByType(ExceptionType type, const Array& arguments) { | 810 void Exceptions::ThrowByType(ExceptionType type, const Array& arguments) { |
834 Thread* thread = Thread::Current(); | 811 Thread* thread = Thread::Current(); |
835 const Object& result = | 812 const Object& result = |
836 Object::Handle(thread->zone(), Create(type, arguments)); | 813 Object::Handle(thread->zone(), Create(type, arguments)); |
837 if (result.IsError()) { | 814 if (result.IsError()) { |
838 // We got an error while constructing the exception object. | 815 // We got an error while constructing the exception object. |
839 // Propagate the error instead of throwing the exception. | 816 // Propagate the error instead of throwing the exception. |
840 PropagateError(Error::Cast(result)); | 817 PropagateError(Error::Cast(result)); |
841 } else { | 818 } else { |
842 ASSERT(result.IsInstance()); | 819 ASSERT(result.IsInstance()); |
843 Throw(thread, Instance::Cast(result)); | 820 Throw(thread, Instance::Cast(result)); |
844 } | 821 } |
845 } | 822 } |
846 | 823 |
847 | |
848 void Exceptions::ThrowOOM() { | 824 void Exceptions::ThrowOOM() { |
849 Thread* thread = Thread::Current(); | 825 Thread* thread = Thread::Current(); |
850 Isolate* isolate = thread->isolate(); | 826 Isolate* isolate = thread->isolate(); |
851 const Instance& oom = Instance::Handle( | 827 const Instance& oom = Instance::Handle( |
852 thread->zone(), isolate->object_store()->out_of_memory()); | 828 thread->zone(), isolate->object_store()->out_of_memory()); |
853 Throw(thread, oom); | 829 Throw(thread, oom); |
854 } | 830 } |
855 | 831 |
856 | |
857 void Exceptions::ThrowStackOverflow() { | 832 void Exceptions::ThrowStackOverflow() { |
858 Thread* thread = Thread::Current(); | 833 Thread* thread = Thread::Current(); |
859 Isolate* isolate = thread->isolate(); | 834 Isolate* isolate = thread->isolate(); |
860 const Instance& stack_overflow = Instance::Handle( | 835 const Instance& stack_overflow = Instance::Handle( |
861 thread->zone(), isolate->object_store()->stack_overflow()); | 836 thread->zone(), isolate->object_store()->stack_overflow()); |
862 Throw(thread, stack_overflow); | 837 Throw(thread, stack_overflow); |
863 } | 838 } |
864 | 839 |
865 | |
866 void Exceptions::ThrowArgumentError(const Instance& arg) { | 840 void Exceptions::ThrowArgumentError(const Instance& arg) { |
867 const Array& args = Array::Handle(Array::New(1)); | 841 const Array& args = Array::Handle(Array::New(1)); |
868 args.SetAt(0, arg); | 842 args.SetAt(0, arg); |
869 Exceptions::ThrowByType(Exceptions::kArgument, args); | 843 Exceptions::ThrowByType(Exceptions::kArgument, args); |
870 } | 844 } |
871 | 845 |
872 | |
873 void Exceptions::ThrowRangeError(const char* argument_name, | 846 void Exceptions::ThrowRangeError(const char* argument_name, |
874 const Integer& argument_value, | 847 const Integer& argument_value, |
875 intptr_t expected_from, | 848 intptr_t expected_from, |
876 intptr_t expected_to) { | 849 intptr_t expected_to) { |
877 const Array& args = Array::Handle(Array::New(4)); | 850 const Array& args = Array::Handle(Array::New(4)); |
878 args.SetAt(0, argument_value); | 851 args.SetAt(0, argument_value); |
879 args.SetAt(1, Integer::Handle(Integer::New(expected_from))); | 852 args.SetAt(1, Integer::Handle(Integer::New(expected_from))); |
880 args.SetAt(2, Integer::Handle(Integer::New(expected_to))); | 853 args.SetAt(2, Integer::Handle(Integer::New(expected_to))); |
881 args.SetAt(3, String::Handle(String::New(argument_name))); | 854 args.SetAt(3, String::Handle(String::New(argument_name))); |
882 Exceptions::ThrowByType(Exceptions::kRange, args); | 855 Exceptions::ThrowByType(Exceptions::kRange, args); |
883 } | 856 } |
884 | 857 |
885 | |
886 void Exceptions::ThrowRangeErrorMsg(const char* msg) { | 858 void Exceptions::ThrowRangeErrorMsg(const char* msg) { |
887 const Array& args = Array::Handle(Array::New(1)); | 859 const Array& args = Array::Handle(Array::New(1)); |
888 args.SetAt(0, String::Handle(String::New(msg))); | 860 args.SetAt(0, String::Handle(String::New(msg))); |
889 Exceptions::ThrowByType(Exceptions::kRangeMsg, args); | 861 Exceptions::ThrowByType(Exceptions::kRangeMsg, args); |
890 } | 862 } |
891 | 863 |
892 | |
893 void Exceptions::ThrowCompileTimeError(const LanguageError& error) { | 864 void Exceptions::ThrowCompileTimeError(const LanguageError& error) { |
894 const Array& args = Array::Handle(Array::New(1)); | 865 const Array& args = Array::Handle(Array::New(1)); |
895 args.SetAt(0, String::Handle(error.FormatMessage())); | 866 args.SetAt(0, String::Handle(error.FormatMessage())); |
896 Exceptions::ThrowByType(Exceptions::kCompileTimeError, args); | 867 Exceptions::ThrowByType(Exceptions::kCompileTimeError, args); |
897 } | 868 } |
898 | 869 |
899 | |
900 RawObject* Exceptions::Create(ExceptionType type, const Array& arguments) { | 870 RawObject* Exceptions::Create(ExceptionType type, const Array& arguments) { |
901 Library& library = Library::Handle(); | 871 Library& library = Library::Handle(); |
902 const String* class_name = NULL; | 872 const String* class_name = NULL; |
903 const String* constructor_name = &Symbols::Dot(); | 873 const String* constructor_name = &Symbols::Dot(); |
904 switch (type) { | 874 switch (type) { |
905 case kNone: | 875 case kNone: |
906 case kStackOverflow: | 876 case kStackOverflow: |
907 case kOutOfMemory: | 877 case kOutOfMemory: |
908 UNREACHABLE(); | 878 UNREACHABLE(); |
909 break; | 879 break; |
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
981 class_name = &Symbols::_CompileTimeError(); | 951 class_name = &Symbols::_CompileTimeError(); |
982 break; | 952 break; |
983 } | 953 } |
984 | 954 |
985 Thread* thread = Thread::Current(); | 955 Thread* thread = Thread::Current(); |
986 NoReloadScope no_reload_scope(thread->isolate(), thread); | 956 NoReloadScope no_reload_scope(thread->isolate(), thread); |
987 return DartLibraryCalls::InstanceCreate(library, *class_name, | 957 return DartLibraryCalls::InstanceCreate(library, *class_name, |
988 *constructor_name, arguments); | 958 *constructor_name, arguments); |
989 } | 959 } |
990 | 960 |
991 | |
992 } // namespace dart | 961 } // namespace dart |
OLD | NEW |