OLD | NEW |
---|---|
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 Loading... | |
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. | |
Yang
2012/11/07 11:02:38
This part is simply moved over from runtime.cc
| |
562 bool ShowFrameInStackTrace(StackFrame* raw_frame, | |
563 Object* caller, | |
564 bool* seen_caller) { | |
565 // Only display JS frames. | |
566 if (!raw_frame->is_java_script()) { | |
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()) { | |
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) { | |
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 Loading... | |
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 // Store the raw stack trace as hidden property so that the stack trace | |
1026 // string can be lazily formatted in javascript. | |
1027 Handle<JSArray> stack_trace = CaptureSimpleStackTrace( | |
1028 exception, factory()->undefined_value(), FLAG_stack_trace_limit); | |
1029 JSObject::SetHiddenProperty(exception, | |
1030 factory()->hidden_stack_trace_symbol(), | |
1031 stack_trace); | |
935 return Failure::Exception(); | 1032 return Failure::Exception(); |
936 } | 1033 } |
937 | 1034 |
938 | 1035 |
939 Failure* Isolate::TerminateExecution() { | 1036 Failure* Isolate::TerminateExecution() { |
940 DoThrow(heap_.termination_exception(), NULL); | 1037 DoThrow(heap_.termination_exception(), NULL); |
941 return Failure::Exception(); | 1038 return Failure::Exception(); |
942 } | 1039 } |
943 | 1040 |
944 | 1041 |
(...skipping 1113 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2058 | 2155 |
2059 #ifdef DEBUG | 2156 #ifdef DEBUG |
2060 #define ISOLATE_FIELD_OFFSET(type, name, ignored) \ | 2157 #define ISOLATE_FIELD_OFFSET(type, name, ignored) \ |
2061 const intptr_t Isolate::name##_debug_offset_ = OFFSET_OF(Isolate, name##_); | 2158 const intptr_t Isolate::name##_debug_offset_ = OFFSET_OF(Isolate, name##_); |
2062 ISOLATE_INIT_LIST(ISOLATE_FIELD_OFFSET) | 2159 ISOLATE_INIT_LIST(ISOLATE_FIELD_OFFSET) |
2063 ISOLATE_INIT_ARRAY_LIST(ISOLATE_FIELD_OFFSET) | 2160 ISOLATE_INIT_ARRAY_LIST(ISOLATE_FIELD_OFFSET) |
2064 #undef ISOLATE_FIELD_OFFSET | 2161 #undef ISOLATE_FIELD_OFFSET |
2065 #endif | 2162 #endif |
2066 | 2163 |
2067 } } // namespace v8::internal | 2164 } } // namespace v8::internal |
OLD | NEW |