Chromium Code Reviews| 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 |