| 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 12858 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 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 Loading... |
| 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 |
| OLD | NEW |