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

Side by Side Diff: src/runtime.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
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 12858 matching lines...) Expand 10 before | Expand all | Expand 10 after
12869 12869
12870 CONVERT_ARG_CHECKED(String, script_name, 0); 12870 CONVERT_ARG_CHECKED(String, script_name, 0);
12871 12871
12872 // Find the requested script. 12872 // Find the requested script.
12873 Handle<Object> result = 12873 Handle<Object> result =
12874 Runtime_GetScriptFromScriptName(Handle<String>(script_name)); 12874 Runtime_GetScriptFromScriptName(Handle<String>(script_name));
12875 return *result; 12875 return *result;
12876 } 12876 }
12877 12877
12878 12878
12879 // Determines whether the given stack frame should be displayed in
12880 // a stack trace. The caller is the error constructor that asked
12881 // for the stack trace to be collected. The first time a construct
12882 // call to this function is encountered it is skipped. The seen_caller
12883 // in/out parameter is used to remember if the caller has been seen
12884 // yet.
12885 static bool ShowFrameInStackTrace(StackFrame* raw_frame,
12886 Object* caller,
12887 bool* seen_caller) {
12888 // Only display JS frames.
12889 if (!raw_frame->is_java_script()) {
12890 return false;
12891 }
12892 JavaScriptFrame* frame = JavaScriptFrame::cast(raw_frame);
12893 Object* raw_fun = frame->function();
12894 // Not sure when this can happen but skip it just in case.
12895 if (!raw_fun->IsJSFunction()) {
12896 return false;
12897 }
12898 if ((raw_fun == caller) && !(*seen_caller)) {
12899 *seen_caller = true;
12900 return false;
12901 }
12902 // Skip all frames until we've seen the caller.
12903 if (!(*seen_caller)) return false;
12904 // Also, skip non-visible built-in functions and any call with the builtins
12905 // object as receiver, so as to not reveal either the builtins object or
12906 // an internal function.
12907 // The --builtins-in-stack-traces command line flag allows including
12908 // internal call sites in the stack trace for debugging purposes.
12909 if (!FLAG_builtins_in_stack_traces) {
12910 JSFunction* fun = JSFunction::cast(raw_fun);
12911 if (frame->receiver()->IsJSBuiltinsObject() ||
12912 (fun->IsBuiltin() && !fun->shared()->native())) {
12913 return false;
12914 }
12915 }
12916 return true;
12917 }
12918
12919
12920 // Collect the raw data for a stack trace. Returns an array of 4 12879 // Collect the raw data for a stack trace. Returns an array of 4
12921 // element segments each containing a receiver, function, code and 12880 // element segments each containing a receiver, function, code and
12922 // native code offset. 12881 // native code offset.
12923 RUNTIME_FUNCTION(MaybeObject*, Runtime_CollectStackTrace) { 12882 RUNTIME_FUNCTION(MaybeObject*, Runtime_CollectStackTrace) {
12924 ASSERT_EQ(args.length(), 3); 12883 ASSERT_EQ(args.length(), 3);
12925 CONVERT_ARG_HANDLE_CHECKED(JSObject, error_object, 0); 12884 CONVERT_ARG_HANDLE_CHECKED(JSObject, error_object, 0);
12926 Handle<Object> caller = args.at<Object>(1); 12885 Handle<Object> caller = args.at<Object>(1);
12927 CONVERT_NUMBER_CHECKED(int32_t, limit, Int32, args[2]); 12886 CONVERT_NUMBER_CHECKED(int32_t, limit, Int32, args[2]);
12928 12887
12929 HandleScope scope(isolate); 12888 HandleScope scope(isolate);
12930 Factory* factory = isolate->factory(); 12889 // Optionally capture a more detailed stack trace for the message.
12931 12890 isolate->CaptureAndSetDetailedStackTrace(error_object);
12932 limit = Max(limit, 0); // Ensure that limit is not negative. 12891 // Capture a simple stack trace for the stack property.
12933 int initial_size = Min(limit, 10); 12892 return *isolate->CaptureSimpleStackTrace(error_object, caller, limit);
12934 Handle<FixedArray> elements =
12935 factory->NewFixedArrayWithHoles(initial_size * 4);
12936
12937 StackFrameIterator iter(isolate);
12938 // If the caller parameter is a function we skip frames until we're
12939 // under it before starting to collect.
12940 bool seen_caller = !caller->IsJSFunction();
12941 int cursor = 0;
12942 int frames_seen = 0;
12943 while (!iter.done() && frames_seen < limit) {
12944 StackFrame* raw_frame = iter.frame();
12945 if (ShowFrameInStackTrace(raw_frame, *caller, &seen_caller)) {
12946 frames_seen++;
12947 JavaScriptFrame* frame = JavaScriptFrame::cast(raw_frame);
12948 // Set initial size to the maximum inlining level + 1 for the outermost
12949 // function.
12950 List<FrameSummary> frames(Compiler::kMaxInliningLevels + 1);
12951 frame->Summarize(&frames);
12952 for (int i = frames.length() - 1; i >= 0; i--) {
12953 if (cursor + 4 > elements->length()) {
12954 int new_capacity = JSObject::NewElementsCapacity(elements->length());
12955 Handle<FixedArray> new_elements =
12956 factory->NewFixedArrayWithHoles(new_capacity);
12957 for (int i = 0; i < cursor; i++) {
12958 new_elements->set(i, elements->get(i));
12959 }
12960 elements = new_elements;
12961 }
12962 ASSERT(cursor + 4 <= elements->length());
12963
12964 Handle<Object> recv = frames[i].receiver();
12965 Handle<JSFunction> fun = frames[i].function();
12966 Handle<Code> code = frames[i].code();
12967 Handle<Smi> offset(Smi::FromInt(frames[i].offset()));
12968 elements->set(cursor++, *recv);
12969 elements->set(cursor++, *fun);
12970 elements->set(cursor++, *code);
12971 elements->set(cursor++, *offset);
12972 }
12973 }
12974 iter.Advance();
12975 }
12976 Handle<JSArray> result = factory->NewJSArrayWithElements(elements);
12977 // Capture and attach a more detailed stack trace if necessary.
12978 isolate->CaptureAndSetCurrentStackTraceFor(error_object);
12979 result->set_length(Smi::FromInt(cursor));
12980 return *result;
12981 } 12893 }
12982 12894
12983 12895
12896 // Retrieve the raw stack trace collected on stack overflow and delete
12897 // it since it is used only once to avoid keeping it alive.
12898 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetOverflowedRawStackTrace) {
12899 ASSERT_EQ(args.length(), 1);
12900 CONVERT_ARG_CHECKED(JSObject, error_object, 0);
12901 String* key = isolate->heap()->hidden_stack_trace_symbol();
12902 Object* result = error_object->GetHiddenProperty(key);
12903 RUNTIME_ASSERT(result->IsJSArray() || result->IsUndefined());
12904 error_object->DeleteHiddenProperty(key);
12905 return result;
12906 }
12907
12908
12984 // Returns V8 version as a string. 12909 // Returns V8 version as a string.
12985 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetV8Version) { 12910 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetV8Version) {
12986 ASSERT_EQ(args.length(), 0); 12911 ASSERT_EQ(args.length(), 0);
12987 12912
12988 NoHandleAllocation ha; 12913 NoHandleAllocation ha;
12989 12914
12990 const char* version_string = v8::V8::GetVersion(); 12915 const char* version_string = v8::V8::GetVersion();
12991 12916
12992 return isolate->heap()->AllocateStringFromAscii(CStrVector(version_string), 12917 return isolate->heap()->AllocateStringFromAscii(CStrVector(version_string),
12993 NOT_TENURED); 12918 NOT_TENURED);
(...skipping 370 matching lines...) Expand 10 before | Expand all | Expand 10 after
13364 // Handle last resort GC and make sure to allow future allocations 13289 // Handle last resort GC and make sure to allow future allocations
13365 // to grow the heap without causing GCs (if possible). 13290 // to grow the heap without causing GCs (if possible).
13366 isolate->counters()->gc_last_resort_from_js()->Increment(); 13291 isolate->counters()->gc_last_resort_from_js()->Increment();
13367 isolate->heap()->CollectAllGarbage(Heap::kNoGCFlags, 13292 isolate->heap()->CollectAllGarbage(Heap::kNoGCFlags,
13368 "Runtime::PerformGC"); 13293 "Runtime::PerformGC");
13369 } 13294 }
13370 } 13295 }
13371 13296
13372 13297
13373 } } // namespace v8::internal 13298 } } // namespace v8::internal
OLDNEW
« src/isolate.cc ('K') | « src/runtime.h ('k') | test/cctest/test-heap.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698