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 126 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
137 | 137 |
138 | 138 |
139 // Iterate through the stack frames and try to find a frame with an | 139 // Iterate through the stack frames and try to find a frame with an |
140 // exception handler. Once found, set the pc, sp and fp so that execution | 140 // exception handler. Once found, set the pc, sp and fp so that execution |
141 // can continue in that frame. Sets 'needs_stacktrace' if there is no | 141 // can continue in that frame. Sets 'needs_stacktrace' if there is no |
142 // cath-all handler or if a stack-trace is specified in the catch. | 142 // cath-all handler or if a stack-trace is specified in the catch. |
143 static bool FindExceptionHandler(Thread* thread, | 143 static bool FindExceptionHandler(Thread* thread, |
144 uword* handler_pc, | 144 uword* handler_pc, |
145 uword* handler_sp, | 145 uword* handler_sp, |
146 uword* handler_fp, | 146 uword* handler_fp, |
147 uword* handler_pp, | |
147 bool* needs_stacktrace) { | 148 bool* needs_stacktrace) { |
148 StackFrameIterator frames(StackFrameIterator::kDontValidateFrames); | 149 StackFrameIterator frames(StackFrameIterator::kDontValidateFrames); |
149 StackFrame* frame = frames.NextFrame(); | 150 StackFrame* frame = frames.NextFrame(); |
150 if (frame == NULL) return false; // No Dart frame. | 151 if (frame == NULL) return false; // No Dart frame. |
151 bool handler_pc_set = false; | 152 bool handler_pc_set = false; |
152 *needs_stacktrace = false; | 153 *needs_stacktrace = false; |
153 bool is_catch_all = false; | 154 bool is_catch_all = false; |
154 uword temp_handler_pc = kUwordMax; | 155 uword temp_handler_pc = kUwordMax; |
156 uword saved_pp = 0; | |
Florian Schneider
2016/09/27 22:21:08
ObjectPool& saved_pp = ObjectPool::Handle();
| |
155 while (!frame->IsEntryFrame()) { | 157 while (!frame->IsEntryFrame()) { |
156 if (frame->IsDartFrame()) { | 158 if (frame->IsDartFrame()) { |
157 if (frame->FindExceptionHandler(thread, | 159 if (frame->FindExceptionHandler(thread, |
158 &temp_handler_pc, | 160 &temp_handler_pc, |
159 needs_stacktrace, | 161 needs_stacktrace, |
160 &is_catch_all)) { | 162 &is_catch_all)) { |
161 if (!handler_pc_set) { | 163 if (!handler_pc_set) { |
162 handler_pc_set = true; | 164 handler_pc_set = true; |
163 *handler_pc = temp_handler_pc; | 165 *handler_pc = temp_handler_pc; |
164 *handler_sp = frame->sp(); | 166 *handler_sp = frame->sp(); |
165 *handler_fp = frame->fp(); | 167 *handler_fp = frame->fp(); |
168 *handler_pp = saved_pp; | |
166 } | 169 } |
167 if (*needs_stacktrace || is_catch_all) { | 170 if (*needs_stacktrace || is_catch_all) { |
168 return true; | 171 return true; |
169 } | 172 } |
170 } | 173 } |
171 } // if frame->IsDartFrame | 174 } // if frame->IsDartFrame |
175 #if !defined(TARGET_ARCH_IA32) && !defined(TARGET_ARCH_DBC) | |
176 saved_pp = frame->saved_caller_pp(); | |
177 #endif | |
172 frame = frames.NextFrame(); | 178 frame = frames.NextFrame(); |
173 ASSERT(frame != NULL); | 179 ASSERT(frame != NULL); |
174 } // while !frame->IsEntryFrame | 180 } // while !frame->IsEntryFrame |
175 ASSERT(frame->IsEntryFrame()); | 181 ASSERT(frame->IsEntryFrame()); |
176 if (!handler_pc_set) { | 182 if (!handler_pc_set) { |
177 *handler_pc = frame->pc(); | 183 *handler_pc = frame->pc(); |
178 *handler_sp = frame->sp(); | 184 *handler_sp = frame->sp(); |
179 *handler_fp = frame->fp(); | 185 *handler_fp = frame->fp(); |
186 *handler_pp = saved_pp; | |
180 } | 187 } |
181 // No catch-all encountered, needs stacktrace. | 188 // No catch-all encountered, needs stacktrace. |
182 *needs_stacktrace = true; | 189 *needs_stacktrace = true; |
183 return handler_pc_set; | 190 return handler_pc_set; |
184 } | 191 } |
185 | 192 |
186 | 193 |
187 static void FindErrorHandler(uword* handler_pc, | 194 static void FindErrorHandler(uword* handler_pc, |
188 uword* handler_sp, | 195 uword* handler_sp, |
189 uword* handler_fp) { | 196 uword* handler_fp, |
197 uword* handler_pp) { | |
190 // TODO(turnidge): Is there a faster way to get the next entry frame? | 198 // TODO(turnidge): Is there a faster way to get the next entry frame? |
191 StackFrameIterator frames(StackFrameIterator::kDontValidateFrames); | 199 StackFrameIterator frames(StackFrameIterator::kDontValidateFrames); |
192 StackFrame* frame = frames.NextFrame(); | 200 StackFrame* frame = frames.NextFrame(); |
193 ASSERT(frame != NULL); | 201 ASSERT(frame != NULL); |
194 while (!frame->IsEntryFrame()) { | 202 while (!frame->IsEntryFrame()) { |
195 frame = frames.NextFrame(); | 203 frame = frames.NextFrame(); |
196 ASSERT(frame != NULL); | 204 ASSERT(frame != NULL); |
197 } | 205 } |
198 ASSERT(frame->IsEntryFrame()); | 206 ASSERT(frame->IsEntryFrame()); |
199 *handler_pc = frame->pc(); | 207 *handler_pc = frame->pc(); |
200 *handler_sp = frame->sp(); | 208 *handler_sp = frame->sp(); |
201 *handler_fp = frame->fp(); | 209 *handler_fp = frame->fp(); |
210 *handler_pp = 0; | |
202 } | 211 } |
203 | 212 |
204 | 213 |
205 static void JumpToExceptionHandler(Thread* thread, | 214 static void JumpToExceptionHandler(Thread* thread, |
206 uword program_counter, | 215 uword program_counter, |
207 uword stack_pointer, | 216 uword stack_pointer, |
208 uword frame_pointer, | 217 uword frame_pointer, |
218 uword pool_pointer, | |
Florian Schneider
2016/09/27 22:21:08
Pass const ObjectPool& pool_pointer like we pass t
| |
209 const Object& exception_object, | 219 const Object& exception_object, |
210 const Object& stacktrace_object) { | 220 const Object& stacktrace_object) { |
211 // The no_gc StackResource is unwound through the tear down of | 221 // The no_gc StackResource is unwound through the tear down of |
212 // stack resources below. | 222 // stack resources below. |
213 NoSafepointScope no_safepoint; | 223 NoSafepointScope no_safepoint; |
214 RawObject* raw_exception = exception_object.raw(); | 224 RawObject* raw_exception = exception_object.raw(); |
215 RawObject* raw_stacktrace = stacktrace_object.raw(); | 225 RawObject* raw_stacktrace = stacktrace_object.raw(); |
216 | 226 |
217 #if defined(USING_SIMULATOR) | 227 #if defined(USING_SIMULATOR) |
218 // Unwinding of the C++ frames and destroying of their stack resources is done | 228 // Unwinding of the C++ frames and destroying of their stack resources is done |
219 // by the simulator, because the target stack_pointer is a simulated stack | 229 // by the simulator, because the target stack_pointer is a simulated stack |
220 // pointer and not the C++ stack pointer. | 230 // pointer and not the C++ stack pointer. |
221 | 231 |
222 // Continue simulating at the given pc in the given frame after setting up the | 232 // Continue simulating at the given pc in the given frame after setting up the |
223 // exception object in the kExceptionObjectReg register and the stacktrace | 233 // exception object in the kExceptionObjectReg register and the stacktrace |
224 // object (may be raw null) in the kStackTraceObjectReg register. | 234 // object (may be raw null) in the kStackTraceObjectReg register. |
225 | 235 |
226 Simulator::Current()->Longjmp(program_counter, stack_pointer, frame_pointer, | 236 Simulator::Current()->Longjmp(program_counter, stack_pointer, frame_pointer, |
227 raw_exception, raw_stacktrace, thread); | 237 pool_pointer, raw_exception, raw_stacktrace, |
238 thread); | |
228 #else | 239 #else |
229 // Prepare for unwinding frames by destroying all the stack resources | 240 // Prepare for unwinding frames by destroying all the stack resources |
230 // in the previous frames. | 241 // in the previous frames. |
231 StackResource::Unwind(thread); | 242 StackResource::Unwind(thread); |
232 | 243 |
233 // Call a stub to set up the exception object in kExceptionObjectReg, | 244 // Call a stub to set up the exception object in kExceptionObjectReg, |
234 // to set up the stacktrace object in kStackTraceObjectReg, and to | 245 // to set up the stacktrace object in kStackTraceObjectReg, and to |
235 // continue execution at the given pc in the given frame. | 246 // continue execution at the given pc in the given frame. |
236 typedef void (*ExcpHandler)(uword, uword, uword, RawObject*, RawObject*, | 247 typedef void (*ExcpHandler)(uword, uword, uword, RawObject*, RawObject*, |
237 Thread*); | 248 Thread*, uword); |
Florian Schneider
2016/09/27 22:21:08
Can you make the pool pointer argument RawObject*?
| |
238 ExcpHandler func = reinterpret_cast<ExcpHandler>( | 249 ExcpHandler func = reinterpret_cast<ExcpHandler>( |
239 StubCode::JumpToExceptionHandler_entry()->EntryPoint()); | 250 StubCode::JumpToExceptionHandler_entry()->EntryPoint()); |
240 | 251 |
241 // Unpoison the stack before we tear it down in the generated stub code. | 252 // Unpoison the stack before we tear it down in the generated stub code. |
242 uword current_sp = Thread::GetCurrentStackPointer() - 1024; | 253 uword current_sp = Thread::GetCurrentStackPointer() - 1024; |
243 ASAN_UNPOISON(reinterpret_cast<void*>(current_sp), | 254 ASAN_UNPOISON(reinterpret_cast<void*>(current_sp), |
244 stack_pointer - current_sp); | 255 stack_pointer - current_sp); |
245 | 256 |
246 func(program_counter, stack_pointer, frame_pointer, | 257 func(program_counter, stack_pointer, frame_pointer, |
247 raw_exception, raw_stacktrace, thread); | 258 raw_exception, raw_stacktrace, thread, pool_pointer); |
248 #endif | 259 #endif |
249 UNREACHABLE(); | 260 UNREACHABLE(); |
250 } | 261 } |
251 | 262 |
252 | 263 |
253 static RawField* LookupStacktraceField(const Instance& instance) { | 264 static RawField* LookupStacktraceField(const Instance& instance) { |
254 if (instance.GetClassId() < kNumPredefinedCids) { | 265 if (instance.GetClassId() < kNumPredefinedCids) { |
255 // 'class Error' is not a predefined class. | 266 // 'class Error' is not a predefined class. |
256 return Field::null(); | 267 return Field::null(); |
257 } | 268 } |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
310 if (exception.IsNull()) { | 321 if (exception.IsNull()) { |
311 exception ^= Exceptions::Create(Exceptions::kNullThrown, | 322 exception ^= Exceptions::Create(Exceptions::kNullThrown, |
312 Object::empty_array()); | 323 Object::empty_array()); |
313 } else if (exception.raw() == isolate->object_store()->out_of_memory() || | 324 } else if (exception.raw() == isolate->object_store()->out_of_memory() || |
314 exception.raw() == isolate->object_store()->stack_overflow()) { | 325 exception.raw() == isolate->object_store()->stack_overflow()) { |
315 use_preallocated_stacktrace = true; | 326 use_preallocated_stacktrace = true; |
316 } | 327 } |
317 uword handler_pc = 0; | 328 uword handler_pc = 0; |
318 uword handler_sp = 0; | 329 uword handler_sp = 0; |
319 uword handler_fp = 0; | 330 uword handler_fp = 0; |
331 uword handler_pp = 0; | |
320 Instance& stacktrace = Instance::Handle(zone); | 332 Instance& stacktrace = Instance::Handle(zone); |
321 bool handler_exists = false; | 333 bool handler_exists = false; |
322 bool handler_needs_stacktrace = false; | 334 bool handler_needs_stacktrace = false; |
323 if (use_preallocated_stacktrace) { | 335 if (use_preallocated_stacktrace) { |
324 stacktrace ^= isolate->object_store()->preallocated_stack_trace(); | 336 stacktrace ^= isolate->object_store()->preallocated_stack_trace(); |
325 PreallocatedStacktraceBuilder frame_builder(stacktrace); | 337 PreallocatedStacktraceBuilder frame_builder(stacktrace); |
326 handler_exists = FindExceptionHandler(thread, | 338 handler_exists = FindExceptionHandler(thread, |
327 &handler_pc, | 339 &handler_pc, |
328 &handler_sp, | 340 &handler_sp, |
329 &handler_fp, | 341 &handler_fp, |
342 &handler_pp, | |
330 &handler_needs_stacktrace); | 343 &handler_needs_stacktrace); |
331 if (handler_pc == 0) { | 344 if (handler_pc == 0) { |
332 // No Dart frame. | 345 // No Dart frame. |
333 ASSERT(incoming_exception.raw() == | 346 ASSERT(incoming_exception.raw() == |
334 isolate->object_store()->out_of_memory()); | 347 isolate->object_store()->out_of_memory()); |
335 const UnhandledException& error = UnhandledException::Handle( | 348 const UnhandledException& error = UnhandledException::Handle( |
336 zone, isolate->object_store()->preallocated_unhandled_exception()); | 349 zone, isolate->object_store()->preallocated_unhandled_exception()); |
337 thread->long_jump_base()->Jump(1, error); | 350 thread->long_jump_base()->Jump(1, error); |
338 UNREACHABLE(); | 351 UNREACHABLE(); |
339 } | 352 } |
340 if (handler_needs_stacktrace) { | 353 if (handler_needs_stacktrace) { |
341 BuildStackTrace(&frame_builder); | 354 BuildStackTrace(&frame_builder); |
342 } | 355 } |
343 } else { | 356 } else { |
344 // Get stacktrace field of class Error. This is needed to determine whether | 357 // Get stacktrace field of class Error. This is needed to determine whether |
345 // we have a subclass of Error which carries around its stack trace. | 358 // we have a subclass of Error which carries around its stack trace. |
346 const Field& stacktrace_field = | 359 const Field& stacktrace_field = |
347 Field::Handle(zone, LookupStacktraceField(exception)); | 360 Field::Handle(zone, LookupStacktraceField(exception)); |
348 | 361 |
349 // Find the exception handler and determine if the handler needs a | 362 // Find the exception handler and determine if the handler needs a |
350 // stacktrace. | 363 // stacktrace. |
351 handler_exists = FindExceptionHandler(thread, | 364 handler_exists = FindExceptionHandler(thread, |
352 &handler_pc, | 365 &handler_pc, |
353 &handler_sp, | 366 &handler_sp, |
354 &handler_fp, | 367 &handler_fp, |
368 &handler_pp, | |
355 &handler_needs_stacktrace); | 369 &handler_needs_stacktrace); |
356 if (!existing_stacktrace.IsNull()) { | 370 if (!existing_stacktrace.IsNull()) { |
357 // If we have an existing stack trace then this better be a rethrow. The | 371 // If we have an existing stack trace then this better be a rethrow. The |
358 // reverse is not necessarily true (e.g. Dart_PropagateError can cause | 372 // reverse is not necessarily true (e.g. Dart_PropagateError can cause |
359 // a rethrow being called without an existing stacktrace.) | 373 // a rethrow being called without an existing stacktrace.) |
360 ASSERT(is_rethrow); | 374 ASSERT(is_rethrow); |
361 ASSERT(stacktrace_field.IsNull() || | 375 ASSERT(stacktrace_field.IsNull() || |
362 (exception.GetField(stacktrace_field) != Object::null())); | 376 (exception.GetField(stacktrace_field) != Object::null())); |
363 stacktrace = existing_stacktrace.raw(); | 377 stacktrace = existing_stacktrace.raw(); |
364 } else if (!stacktrace_field.IsNull() || handler_needs_stacktrace) { | 378 } else if (!stacktrace_field.IsNull() || handler_needs_stacktrace) { |
(...skipping 17 matching lines...) Expand all Loading... | |
382 if (FLAG_print_stacktrace_at_throw) { | 396 if (FLAG_print_stacktrace_at_throw) { |
383 THR_Print("Exception '%s' thrown:\n", exception.ToCString()); | 397 THR_Print("Exception '%s' thrown:\n", exception.ToCString()); |
384 THR_Print("%s\n", stacktrace.ToCString()); | 398 THR_Print("%s\n", stacktrace.ToCString()); |
385 } | 399 } |
386 if (handler_exists) { | 400 if (handler_exists) { |
387 // Found a dart handler for the exception, jump to it. | 401 // Found a dart handler for the exception, jump to it. |
388 JumpToExceptionHandler(thread, | 402 JumpToExceptionHandler(thread, |
389 handler_pc, | 403 handler_pc, |
390 handler_sp, | 404 handler_sp, |
391 handler_fp, | 405 handler_fp, |
406 handler_pp, | |
392 exception, | 407 exception, |
393 stacktrace); | 408 stacktrace); |
394 } else { | 409 } else { |
395 // No dart exception handler found in this invocation sequence, | 410 // No dart exception handler found in this invocation sequence, |
396 // so we create an unhandled exception object and return to the | 411 // so we create an unhandled exception object and return to the |
397 // invocation stub so that it returns this unhandled exception | 412 // invocation stub so that it returns this unhandled exception |
398 // object. The C++ code which invoked this dart sequence can check | 413 // object. The C++ code which invoked this dart sequence can check |
399 // and do the appropriate thing (rethrow the exception to the | 414 // and do the appropriate thing (rethrow the exception to the |
400 // dart invocation sequence above it, print diagnostics and terminate | 415 // dart invocation sequence above it, print diagnostics and terminate |
401 // the isolate etc.). | 416 // the isolate etc.). |
402 const UnhandledException& unhandled_exception = UnhandledException::Handle( | 417 const UnhandledException& unhandled_exception = UnhandledException::Handle( |
403 zone, UnhandledException::New(exception, stacktrace)); | 418 zone, UnhandledException::New(exception, stacktrace)); |
404 stacktrace = Stacktrace::null(); | 419 stacktrace = Stacktrace::null(); |
405 JumpToExceptionHandler(thread, | 420 JumpToExceptionHandler(thread, |
406 handler_pc, | 421 handler_pc, |
407 handler_sp, | 422 handler_sp, |
408 handler_fp, | 423 handler_fp, |
424 handler_pp, | |
409 unhandled_exception, | 425 unhandled_exception, |
410 stacktrace); | 426 stacktrace); |
411 } | 427 } |
412 UNREACHABLE(); | 428 UNREACHABLE(); |
413 } | 429 } |
414 | 430 |
415 | 431 |
416 // Static helpers for allocating, initializing, and throwing an error instance. | 432 // Static helpers for allocating, initializing, and throwing an error instance. |
417 | 433 |
418 // Return the script of the Dart function that called the native entry or the | 434 // Return the script of the Dart function that called the native entry or the |
(...skipping 163 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
582 const Instance& exc = Instance::Handle(zone, uhe.exception()); | 598 const Instance& exc = Instance::Handle(zone, uhe.exception()); |
583 const Instance& stk = Instance::Handle(zone, uhe.stacktrace()); | 599 const Instance& stk = Instance::Handle(zone, uhe.stacktrace()); |
584 Exceptions::ReThrow(thread, exc, stk); | 600 Exceptions::ReThrow(thread, exc, stk); |
585 } else { | 601 } else { |
586 // Return to the invocation stub and return this error object. The | 602 // Return to the invocation stub and return this error object. The |
587 // C++ code which invoked this dart sequence can check and do the | 603 // C++ code which invoked this dart sequence can check and do the |
588 // appropriate thing. | 604 // appropriate thing. |
589 uword handler_pc = 0; | 605 uword handler_pc = 0; |
590 uword handler_sp = 0; | 606 uword handler_sp = 0; |
591 uword handler_fp = 0; | 607 uword handler_fp = 0; |
592 FindErrorHandler(&handler_pc, &handler_sp, &handler_fp); | 608 uword handler_pp = 0; |
593 JumpToExceptionHandler(thread, handler_pc, handler_sp, handler_fp, error, | 609 const Stacktrace& stacktrace = Stacktrace::Handle(zone); // null |
594 Stacktrace::Handle(zone)); // Null stacktrace. | 610 FindErrorHandler(&handler_pc, &handler_sp, &handler_fp, &handler_pp); |
611 JumpToExceptionHandler(thread, handler_pc, handler_sp, handler_fp, | |
612 handler_pp, error, stacktrace); | |
595 } | 613 } |
596 UNREACHABLE(); | 614 UNREACHABLE(); |
597 } | 615 } |
598 | 616 |
599 | 617 |
600 void Exceptions::ThrowByType(ExceptionType type, const Array& arguments) { | 618 void Exceptions::ThrowByType(ExceptionType type, const Array& arguments) { |
601 Thread* thread = Thread::Current(); | 619 Thread* thread = Thread::Current(); |
602 const Object& result = | 620 const Object& result = |
603 Object::Handle(thread->zone(), Create(type, arguments)); | 621 Object::Handle(thread->zone(), Create(type, arguments)); |
604 if (result.IsError()) { | 622 if (result.IsError()) { |
(...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
738 } | 756 } |
739 | 757 |
740 return DartLibraryCalls::InstanceCreate(library, | 758 return DartLibraryCalls::InstanceCreate(library, |
741 *class_name, | 759 *class_name, |
742 *constructor_name, | 760 *constructor_name, |
743 arguments); | 761 arguments); |
744 } | 762 } |
745 | 763 |
746 | 764 |
747 } // namespace dart | 765 } // namespace dart |
OLD | NEW |