OLD | NEW |
1 // Copyright 2006-2008 the V8 project authors. All rights reserved. | 1 // Copyright 2006-2008 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 26 matching lines...) Expand all Loading... |
37 #include "string-stream.h" | 37 #include "string-stream.h" |
38 | 38 |
39 namespace v8 { | 39 namespace v8 { |
40 namespace internal { | 40 namespace internal { |
41 | 41 |
42 ThreadLocalTop Top::thread_local_; | 42 ThreadLocalTop Top::thread_local_; |
43 Mutex* Top::break_access_ = OS::CreateMutex(); | 43 Mutex* Top::break_access_ = OS::CreateMutex(); |
44 | 44 |
45 NoAllocationStringAllocator* preallocated_message_space = NULL; | 45 NoAllocationStringAllocator* preallocated_message_space = NULL; |
46 | 46 |
| 47 bool capture_stack_trace_for_uncaught_exceptions = false; |
| 48 int stack_trace_for_uncaught_exceptions_frame_limit = 0; |
| 49 StackTrace::StackTraceOptions stack_trace_for_uncaught_exceptions_options = |
| 50 StackTrace::kOverview; |
| 51 |
47 Address top_addresses[] = { | 52 Address top_addresses[] = { |
48 #define C(name) reinterpret_cast<Address>(Top::name()), | 53 #define C(name) reinterpret_cast<Address>(Top::name()), |
49 TOP_ADDRESS_LIST(C) | 54 TOP_ADDRESS_LIST(C) |
50 TOP_ADDRESS_LIST_PROF(C) | 55 TOP_ADDRESS_LIST_PROF(C) |
51 #undef C | 56 #undef C |
52 NULL | 57 NULL |
53 }; | 58 }; |
54 | 59 |
55 | 60 |
56 v8::TryCatch* ThreadLocalTop::TryCatchHandler() { | 61 v8::TryCatch* ThreadLocalTop::TryCatchHandler() { |
(...skipping 301 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
358 incomplete_message->OutputToStdOut(); | 363 incomplete_message->OutputToStdOut(); |
359 return Factory::empty_symbol(); | 364 return Factory::empty_symbol(); |
360 } else { | 365 } else { |
361 OS::Abort(); | 366 OS::Abort(); |
362 // Unreachable | 367 // Unreachable |
363 return Factory::empty_symbol(); | 368 return Factory::empty_symbol(); |
364 } | 369 } |
365 } | 370 } |
366 | 371 |
367 | 372 |
368 Local<StackTrace> Top::CaptureCurrentStackTrace( | 373 Handle<JSArray> Top::CaptureCurrentStackTrace( |
369 int frame_limit, StackTrace::StackTraceOptions options) { | 374 int frame_limit, StackTrace::StackTraceOptions options) { |
370 v8::HandleScope scope; | |
371 // Ensure no negative values. | 375 // Ensure no negative values. |
372 int limit = Max(frame_limit, 0); | 376 int limit = Max(frame_limit, 0); |
373 Handle<JSArray> stack_trace = Factory::NewJSArray(frame_limit); | 377 Handle<JSArray> stack_trace = Factory::NewJSArray(frame_limit); |
374 | 378 |
375 Handle<String> column_key = Factory::LookupAsciiSymbol("column"); | 379 Handle<String> column_key = Factory::LookupAsciiSymbol("column"); |
376 Handle<String> line_key = Factory::LookupAsciiSymbol("lineNumber"); | 380 Handle<String> line_key = Factory::LookupAsciiSymbol("lineNumber"); |
377 Handle<String> script_key = Factory::LookupAsciiSymbol("scriptName"); | 381 Handle<String> script_key = Factory::LookupAsciiSymbol("scriptName"); |
378 Handle<String> function_key = Factory::LookupAsciiSymbol("functionName"); | 382 Handle<String> function_key = Factory::LookupAsciiSymbol("functionName"); |
379 Handle<String> eval_key = Factory::LookupAsciiSymbol("isEval"); | 383 Handle<String> eval_key = Factory::LookupAsciiSymbol("isEval"); |
380 Handle<String> constructor_key = Factory::LookupAsciiSymbol("isConstructor"); | 384 Handle<String> constructor_key = Factory::LookupAsciiSymbol("isConstructor"); |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
436 Factory::true_value() : Factory::false_value(); | 440 Factory::true_value() : Factory::false_value(); |
437 SetProperty(stackFrame, constructor_key, is_constructor, NONE); | 441 SetProperty(stackFrame, constructor_key, is_constructor, NONE); |
438 } | 442 } |
439 | 443 |
440 FixedArray::cast(stack_trace->elements())->set(frames_seen, *stackFrame); | 444 FixedArray::cast(stack_trace->elements())->set(frames_seen, *stackFrame); |
441 frames_seen++; | 445 frames_seen++; |
442 it.Advance(); | 446 it.Advance(); |
443 } | 447 } |
444 | 448 |
445 stack_trace->set_length(Smi::FromInt(frames_seen)); | 449 stack_trace->set_length(Smi::FromInt(frames_seen)); |
446 return scope.Close(Utils::StackTraceToLocal(stack_trace)); | 450 return stack_trace; |
447 } | 451 } |
448 | 452 |
449 | 453 |
450 void Top::PrintStack() { | 454 void Top::PrintStack() { |
451 if (stack_trace_nesting_level == 0) { | 455 if (stack_trace_nesting_level == 0) { |
452 stack_trace_nesting_level++; | 456 stack_trace_nesting_level++; |
453 | 457 |
454 StringAllocator* allocator; | 458 StringAllocator* allocator; |
455 if (preallocated_message_space == NULL) { | 459 if (preallocated_message_space == NULL) { |
456 allocator = new HeapStringAllocator(); | 460 allocator = new HeapStringAllocator(); |
(...skipping 217 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
674 | 678 |
675 Failure* Top::StackOverflow() { | 679 Failure* Top::StackOverflow() { |
676 HandleScope scope; | 680 HandleScope scope; |
677 Handle<String> key = Factory::stack_overflow_symbol(); | 681 Handle<String> key = Factory::stack_overflow_symbol(); |
678 Handle<JSObject> boilerplate = | 682 Handle<JSObject> boilerplate = |
679 Handle<JSObject>::cast(GetProperty(Top::builtins(), key)); | 683 Handle<JSObject>::cast(GetProperty(Top::builtins(), key)); |
680 Handle<Object> exception = Copy(boilerplate); | 684 Handle<Object> exception = Copy(boilerplate); |
681 // TODO(1240995): To avoid having to call JavaScript code to compute | 685 // TODO(1240995): To avoid having to call JavaScript code to compute |
682 // the message for stack overflow exceptions which is very likely to | 686 // the message for stack overflow exceptions which is very likely to |
683 // double fault with another stack overflow exception, we use a | 687 // double fault with another stack overflow exception, we use a |
684 // precomputed message. This is somewhat problematic in that it | 688 // precomputed message. |
685 // doesn't use ReportUncaughtException to determine the location | |
686 // from where the exception occurred. It should probably be | |
687 // reworked. | |
688 DoThrow(*exception, NULL, kStackOverflowMessage); | 689 DoThrow(*exception, NULL, kStackOverflowMessage); |
689 return Failure::Exception(); | 690 return Failure::Exception(); |
690 } | 691 } |
691 | 692 |
692 | 693 |
693 Failure* Top::TerminateExecution() { | 694 Failure* Top::TerminateExecution() { |
694 DoThrow(Heap::termination_exception(), NULL, NULL); | 695 DoThrow(Heap::termination_exception(), NULL, NULL); |
695 return Failure::Exception(); | 696 return Failure::Exception(); |
696 } | 697 } |
697 | 698 |
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
771 !(Script::cast(script)->source()->IsUndefined())) { | 772 !(Script::cast(script)->source()->IsUndefined())) { |
772 int pos = frame->code()->SourcePosition(frame->pc()); | 773 int pos = frame->code()->SourcePosition(frame->pc()); |
773 // Compute the location from the function and the reloc info. | 774 // Compute the location from the function and the reloc info. |
774 Handle<Script> casted_script(Script::cast(script)); | 775 Handle<Script> casted_script(Script::cast(script)); |
775 *target = MessageLocation(casted_script, pos, pos + 1); | 776 *target = MessageLocation(casted_script, pos, pos + 1); |
776 } | 777 } |
777 } | 778 } |
778 } | 779 } |
779 | 780 |
780 | 781 |
781 void Top::ReportUncaughtException(Handle<Object> exception, | |
782 MessageLocation* location, | |
783 Handle<String> stack_trace) { | |
784 Handle<Object> message; | |
785 if (!Bootstrapper::IsActive()) { | |
786 // It's not safe to try to make message objects while the bootstrapper | |
787 // is active since the infrastructure may not have been properly | |
788 // initialized. | |
789 message = | |
790 MessageHandler::MakeMessageObject("uncaught_exception", | |
791 location, | |
792 HandleVector<Object>(&exception, 1), | |
793 stack_trace); | |
794 } | |
795 // Report the uncaught exception. | |
796 MessageHandler::ReportMessage(location, message); | |
797 } | |
798 | |
799 | |
800 bool Top::ShouldReturnException(bool* is_caught_externally, | 782 bool Top::ShouldReturnException(bool* is_caught_externally, |
801 bool catchable_by_javascript) { | 783 bool catchable_by_javascript) { |
802 // Find the top-most try-catch handler. | 784 // Find the top-most try-catch handler. |
803 StackHandler* handler = | 785 StackHandler* handler = |
804 StackHandler::FromAddress(Top::handler(Top::GetCurrentThread())); | 786 StackHandler::FromAddress(Top::handler(Top::GetCurrentThread())); |
805 while (handler != NULL && !handler->is_try_catch()) { | 787 while (handler != NULL && !handler->is_try_catch()) { |
806 handler = handler->next(); | 788 handler = handler->next(); |
807 } | 789 } |
808 | 790 |
809 // Get the address of the external handler so we can compare the address to | 791 // Get the address of the external handler so we can compare the address to |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
862 // If no location was specified we use a computed one instead | 844 // If no location was specified we use a computed one instead |
863 ComputeLocation(&potential_computed_location); | 845 ComputeLocation(&potential_computed_location); |
864 location = &potential_computed_location; | 846 location = &potential_computed_location; |
865 } | 847 } |
866 if (!Bootstrapper::IsActive()) { | 848 if (!Bootstrapper::IsActive()) { |
867 // It's not safe to try to make message objects or collect stack | 849 // It's not safe to try to make message objects or collect stack |
868 // traces while the bootstrapper is active since the infrastructure | 850 // traces while the bootstrapper is active since the infrastructure |
869 // may not have been properly initialized. | 851 // may not have been properly initialized. |
870 Handle<String> stack_trace; | 852 Handle<String> stack_trace; |
871 if (FLAG_trace_exception) stack_trace = StackTraceString(); | 853 if (FLAG_trace_exception) stack_trace = StackTraceString(); |
| 854 Handle<JSArray> stack_trace_object; |
| 855 if (report_exception && capture_stack_trace_for_uncaught_exceptions) { |
| 856 stack_trace_object = Top::CaptureCurrentStackTrace( |
| 857 stack_trace_for_uncaught_exceptions_frame_limit, |
| 858 stack_trace_for_uncaught_exceptions_options); |
| 859 } |
872 message_obj = MessageHandler::MakeMessageObject("uncaught_exception", | 860 message_obj = MessageHandler::MakeMessageObject("uncaught_exception", |
873 location, HandleVector<Object>(&exception_handle, 1), stack_trace); | 861 location, HandleVector<Object>(&exception_handle, 1), stack_trace, |
| 862 stack_trace_object); |
874 } | 863 } |
875 } | 864 } |
876 | 865 |
877 // Save the message for reporting if the the exception remains uncaught. | 866 // Save the message for reporting if the the exception remains uncaught. |
878 thread_local_.has_pending_message_ = report_exception; | 867 thread_local_.has_pending_message_ = report_exception; |
879 thread_local_.pending_message_ = message; | 868 thread_local_.pending_message_ = message; |
880 if (!message_obj.is_null()) { | 869 if (!message_obj.is_null()) { |
881 thread_local_.pending_message_obj_ = *message_obj; | 870 thread_local_.pending_message_obj_ = *message_obj; |
882 if (location != NULL) { | 871 if (location != NULL) { |
883 thread_local_.pending_message_script_ = *location->script(); | 872 thread_local_.pending_message_script_ = *location->script(); |
(...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
990 } | 979 } |
991 } | 980 } |
992 | 981 |
993 // Reschedule the exception. | 982 // Reschedule the exception. |
994 thread_local_.scheduled_exception_ = pending_exception(); | 983 thread_local_.scheduled_exception_ = pending_exception(); |
995 clear_pending_exception(); | 984 clear_pending_exception(); |
996 return true; | 985 return true; |
997 } | 986 } |
998 | 987 |
999 | 988 |
| 989 void Top::SetCaptureStackTraceForUncaughtExceptions( |
| 990 bool capture, |
| 991 int frame_limit, |
| 992 StackTrace::StackTraceOptions options) { |
| 993 capture_stack_trace_for_uncaught_exceptions = capture; |
| 994 stack_trace_for_uncaught_exceptions_frame_limit = frame_limit; |
| 995 stack_trace_for_uncaught_exceptions_options = options; |
| 996 } |
| 997 |
| 998 |
1000 bool Top::is_out_of_memory() { | 999 bool Top::is_out_of_memory() { |
1001 if (has_pending_exception()) { | 1000 if (has_pending_exception()) { |
1002 Object* e = pending_exception(); | 1001 Object* e = pending_exception(); |
1003 if (e->IsFailure() && Failure::cast(e)->IsOutOfMemoryException()) { | 1002 if (e->IsFailure() && Failure::cast(e)->IsOutOfMemoryException()) { |
1004 return true; | 1003 return true; |
1005 } | 1004 } |
1006 } | 1005 } |
1007 if (has_scheduled_exception()) { | 1006 if (has_scheduled_exception()) { |
1008 Object* e = scheduled_exception(); | 1007 Object* e = scheduled_exception(); |
1009 if (e->IsFailure() && Failure::cast(e)->IsOutOfMemoryException()) { | 1008 if (e->IsFailure() && Failure::cast(e)->IsOutOfMemoryException()) { |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1059 Top::break_access_->Lock(); | 1058 Top::break_access_->Lock(); |
1060 } | 1059 } |
1061 | 1060 |
1062 | 1061 |
1063 ExecutionAccess::~ExecutionAccess() { | 1062 ExecutionAccess::~ExecutionAccess() { |
1064 Top::break_access_->Unlock(); | 1063 Top::break_access_->Unlock(); |
1065 } | 1064 } |
1066 | 1065 |
1067 | 1066 |
1068 } } // namespace v8::internal | 1067 } } // namespace v8::internal |
OLD | NEW |