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

Side by Side Diff: src/isolate.cc

Issue 11275186: Collect stack trace on stack overflow. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: . Created 8 years, 1 month 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/isolate.h ('k') | src/messages.js » ('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 2012 the V8 project authors. All rights reserved. 1 // Copyright 2012 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 535 matching lines...) Expand 10 before | Expand all | Expand 10 after
546 String::WriteToFlat(*trace, buffer, 0, length); 546 String::WriteToFlat(*trace, buffer, 0, length);
547 buffer[length] = '\0'; 547 buffer[length] = '\0';
548 OS::PrintError("Stacktrace (%x-%x) %p %p: %s\n", 548 OS::PrintError("Stacktrace (%x-%x) %p %p: %s\n",
549 magic, magic2, 549 magic, magic2,
550 static_cast<void*>(object), static_cast<void*>(map), 550 static_cast<void*>(object), static_cast<void*>(map),
551 buffer); 551 buffer);
552 OS::Abort(); 552 OS::Abort();
553 } 553 }
554 554
555 555
556 void Isolate::CaptureAndSetCurrentStackTraceFor(Handle<JSObject> error_object) { 556 // Determines whether the given stack frame should be displayed in
557 // a stack trace. The caller is the error constructor that asked
558 // for the stack trace to be collected. The first time a construct
559 // call to this function is encountered it is skipped. The seen_caller
560 // in/out parameter is used to remember if the caller has been seen
561 // yet.
562 bool ShowFrameInStackTrace(StackFrame* raw_frame,
Sven Panne 2012/11/09 12:25:52 Make this static or a method of StackFrame. Furthe
563 Object* caller,
564 bool* seen_caller) {
565 // Only display JS frames.
566 if (!raw_frame->is_java_script()) {
Sven Panne 2012/11/09 12:25:52 Just for consistency: One-liner if...
567 return false;
568 }
569 JavaScriptFrame* frame = JavaScriptFrame::cast(raw_frame);
570 Object* raw_fun = frame->function();
571 // Not sure when this can happen but skip it just in case.
572 if (!raw_fun->IsJSFunction()) {
Sven Panne 2012/11/09 12:25:52 Again just for consistency: One-liner if...
573 return false;
574 }
575 if ((raw_fun == caller) && !(*seen_caller)) {
576 *seen_caller = true;
577 return false;
578 }
579 // Skip all frames until we've seen the caller.
580 if (!(*seen_caller)) return false;
581 // Also, skip non-visible built-in functions and any call with the builtins
582 // object as receiver, so as to not reveal either the builtins object or
583 // an internal function.
584 // The --builtins-in-stack-traces command line flag allows including
585 // internal call sites in the stack trace for debugging purposes.
586 if (!FLAG_builtins_in_stack_traces) {
587 JSFunction* fun = JSFunction::cast(raw_fun);
588 if (frame->receiver()->IsJSBuiltinsObject() ||
589 (fun->IsBuiltin() && !fun->shared()->native())) {
590 return false;
591 }
592 }
593 return true;
594 }
595
596
597 Handle<JSArray> Isolate::CaptureSimpleStackTrace(Handle<JSObject> error_object,
598 Handle<Object> caller,
599 int limit) {
600 limit = Max(limit, 0); // Ensure that limit is not negative.
601 int initial_size = Min(limit, 10);
602 Handle<FixedArray> elements =
603 factory()->NewFixedArrayWithHoles(initial_size * 4);
604
605 StackFrameIterator iter(this);
606 // If the caller parameter is a function we skip frames until we're
607 // under it before starting to collect.
608 bool seen_caller = !caller->IsJSFunction();
609 int cursor = 0;
610 int frames_seen = 0;
611 while (!iter.done() && frames_seen < limit) {
Sven Panne 2012/11/09 12:25:52 A for-loop with a conditional break in it might be
612 StackFrame* raw_frame = iter.frame();
613 if (ShowFrameInStackTrace(raw_frame, *caller, &seen_caller)) {
614 frames_seen++;
615 JavaScriptFrame* frame = JavaScriptFrame::cast(raw_frame);
616 // Set initial size to the maximum inlining level + 1 for the outermost
617 // function.
618 List<FrameSummary> frames(Compiler::kMaxInliningLevels + 1);
619 frame->Summarize(&frames);
620 for (int i = frames.length() - 1; i >= 0; i--) {
621 if (cursor + 4 > elements->length()) {
622 int new_capacity = JSObject::NewElementsCapacity(elements->length());
623 Handle<FixedArray> new_elements =
624 factory()->NewFixedArrayWithHoles(new_capacity);
625 for (int i = 0; i < cursor; i++) {
626 new_elements->set(i, elements->get(i));
627 }
628 elements = new_elements;
629 }
630 ASSERT(cursor + 4 <= elements->length());
631
632 Handle<Object> recv = frames[i].receiver();
633 Handle<JSFunction> fun = frames[i].function();
634 Handle<Code> code = frames[i].code();
635 Handle<Smi> offset(Smi::FromInt(frames[i].offset()));
636 elements->set(cursor++, *recv);
637 elements->set(cursor++, *fun);
638 elements->set(cursor++, *code);
639 elements->set(cursor++, *offset);
640 }
641 }
642 iter.Advance();
643 }
644 Handle<JSArray> result = factory()->NewJSArrayWithElements(elements);
645 result->set_length(Smi::FromInt(cursor));
646 return result;
647 }
648
649
650 void Isolate::CaptureAndSetDetailedStackTrace(Handle<JSObject> error_object) {
557 if (capture_stack_trace_for_uncaught_exceptions_) { 651 if (capture_stack_trace_for_uncaught_exceptions_) {
558 // Capture stack trace for a detailed exception message. 652 // Capture stack trace for a detailed exception message.
559 Handle<String> key = factory()->hidden_stack_trace_symbol(); 653 Handle<String> key = factory()->hidden_stack_trace_symbol();
560 Handle<JSArray> stack_trace = CaptureCurrentStackTrace( 654 Handle<JSArray> stack_trace = CaptureCurrentStackTrace(
561 stack_trace_for_uncaught_exceptions_frame_limit_, 655 stack_trace_for_uncaught_exceptions_frame_limit_,
562 stack_trace_for_uncaught_exceptions_options_); 656 stack_trace_for_uncaught_exceptions_options_);
563 JSObject::SetHiddenProperty(error_object, key, stack_trace); 657 JSObject::SetHiddenProperty(error_object, key, stack_trace);
564 } 658 }
565 } 659 }
566 660
(...skipping 352 matching lines...) Expand 10 before | Expand all | Expand 10 after
919 1013
920 const char* const Isolate::kStackOverflowMessage = 1014 const char* const Isolate::kStackOverflowMessage =
921 "Uncaught RangeError: Maximum call stack size exceeded"; 1015 "Uncaught RangeError: Maximum call stack size exceeded";
922 1016
923 1017
924 Failure* Isolate::StackOverflow() { 1018 Failure* Isolate::StackOverflow() {
925 HandleScope scope; 1019 HandleScope scope;
926 Handle<String> key = factory()->stack_overflow_symbol(); 1020 Handle<String> key = factory()->stack_overflow_symbol();
927 Handle<JSObject> boilerplate = 1021 Handle<JSObject> boilerplate =
928 Handle<JSObject>::cast(GetProperty(js_builtins_object(), key)); 1022 Handle<JSObject>::cast(GetProperty(js_builtins_object(), key));
929 Handle<Object> exception = Copy(boilerplate); 1023 Handle<JSObject> exception = Copy(boilerplate);
930 // TODO(1240995): To avoid having to call JavaScript code to compute
931 // the message for stack overflow exceptions which is very likely to
932 // double fault with another stack overflow exception, we use a
933 // precomputed message.
934 DoThrow(*exception, NULL); 1024 DoThrow(*exception, NULL);
1025
1026 // Get stack trace limit.
1027 Handle<Object> error = GetProperty(js_builtins_object(), "$Error");
1028 if (!error->IsJSObject()) return Failure::Exception();
1029 Handle<Object> stack_trace_limit =
1030 GetProperty(Handle<JSObject>::cast(error), "stackTraceLimit");
1031 if (!stack_trace_limit->IsNumber()) return Failure::Exception();
1032 int limit = static_cast<int>(stack_trace_limit->Number());
1033
1034 // Store the raw stack trace as hidden property so that the stack trace
1035 // string can be lazily formatted in javascript.
1036 Handle<JSArray> stack_trace = CaptureSimpleStackTrace(
1037 exception, factory()->undefined_value(), limit);
1038 JSObject::SetHiddenProperty(exception,
1039 factory()->hidden_stack_trace_symbol(),
1040 stack_trace);
935 return Failure::Exception(); 1041 return Failure::Exception();
936 } 1042 }
937 1043
938 1044
939 Failure* Isolate::TerminateExecution() { 1045 Failure* Isolate::TerminateExecution() {
940 DoThrow(heap_.termination_exception(), NULL); 1046 DoThrow(heap_.termination_exception(), NULL);
941 return Failure::Exception(); 1047 return Failure::Exception();
942 } 1048 }
943 1049
944 1050
(...skipping 1113 matching lines...) Expand 10 before | Expand all | Expand 10 after
2058 2164
2059 #ifdef DEBUG 2165 #ifdef DEBUG
2060 #define ISOLATE_FIELD_OFFSET(type, name, ignored) \ 2166 #define ISOLATE_FIELD_OFFSET(type, name, ignored) \
2061 const intptr_t Isolate::name##_debug_offset_ = OFFSET_OF(Isolate, name##_); 2167 const intptr_t Isolate::name##_debug_offset_ = OFFSET_OF(Isolate, name##_);
2062 ISOLATE_INIT_LIST(ISOLATE_FIELD_OFFSET) 2168 ISOLATE_INIT_LIST(ISOLATE_FIELD_OFFSET)
2063 ISOLATE_INIT_ARRAY_LIST(ISOLATE_FIELD_OFFSET) 2169 ISOLATE_INIT_ARRAY_LIST(ISOLATE_FIELD_OFFSET)
2064 #undef ISOLATE_FIELD_OFFSET 2170 #undef ISOLATE_FIELD_OFFSET
2065 #endif 2171 #endif
2066 2172
2067 } } // namespace v8::internal 2173 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/isolate.h ('k') | src/messages.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698