Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(156)

Side by Side Diff: src/top.cc

Issue 2961003: Allow to capture stack trace for uncaught exceptions (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: '' Created 10 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/top.h ('k') | test/cctest/test-api.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « src/top.h ('k') | test/cctest/test-api.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698