| 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 |