| Index: runtime/vm/object.cc
|
| diff --git a/runtime/vm/object.cc b/runtime/vm/object.cc
|
| index 8e3284f3020ddb2e84329e0df43cb0984cd0afb6..4e43f454e5909bb42d6549ae3fcdca8cd5852050 100644
|
| --- a/runtime/vm/object.cc
|
| +++ b/runtime/vm/object.cc
|
| @@ -21600,6 +21600,23 @@ static intptr_t PrintOneStacktrace(Zone* zone,
|
| }
|
|
|
|
|
| +static intptr_t PrintOneStacktraceNoCode(Zone* zone,
|
| + GrowableArray<char*>* frame_strings,
|
| + const Function& function,
|
| + intptr_t frame_index) {
|
| + const Script& script = Script::Handle(zone, function.script());
|
| + const String& function_name =
|
| + String::Handle(zone, function.QualifiedUserVisibleName());
|
| + const String& url = String::Handle(zone, script.url());
|
| + char* chars = NULL;
|
| + chars = OS::SCreate(zone,
|
| + "#%-6" Pd " %s (%s)\n",
|
| + frame_index, function_name.ToCString(), url.ToCString());
|
| + frame_strings->Add(chars);
|
| + return strlen(chars);
|
| +}
|
| +
|
| +
|
| const char* Stacktrace::ToCStringInternal(intptr_t* frame_index,
|
| intptr_t max_frames) const {
|
| Zone* zone = Thread::Current()->zone();
|
| @@ -21612,7 +21629,8 @@ const char* Stacktrace::ToCStringInternal(intptr_t* frame_index,
|
| for (intptr_t i = 0; (i < Length()) && (*frame_index < max_frames); i++) {
|
| function = FunctionAtFrame(i);
|
| if (function.IsNull()) {
|
| - // Check if null function object indicates a stack trace overflow.
|
| + // Check if null function object indicates a gap in a StackOverflow or
|
| + // OutOfMemory trace.
|
| if ((i < (Length() - 1)) &&
|
| (FunctionAtFrame(i + 1) != Function::null())) {
|
| const char* kTruncated = "...\n...\n";
|
| @@ -21622,31 +21640,55 @@ const char* Stacktrace::ToCStringInternal(intptr_t* frame_index,
|
| frame_strings.Add(chars);
|
| total_len += truncated_len;
|
| }
|
| - } else if (function.is_visible() || FLAG_show_invisible_frames) {
|
| + } else {
|
| code = CodeAtFrame(i);
|
| ASSERT(function.raw() == code.function());
|
| uword pc = code.EntryPoint() + Smi::Value(PcOffsetAtFrame(i));
|
| if (code.is_optimized() && expand_inlined()) {
|
| // Traverse inlined frames.
|
| - for (InlinedFunctionsIterator it(code, pc);
|
| - !it.Done() && (*frame_index < max_frames); it.Advance()) {
|
| - function = it.function();
|
| - if (function.is_visible() || FLAG_show_invisible_frames) {
|
| - code = it.code();
|
| - ASSERT(function.raw() == code.function());
|
| - uword pc = it.pc();
|
| - ASSERT(pc != 0);
|
| - ASSERT(code.EntryPoint() <= pc);
|
| - ASSERT(pc < (code.EntryPoint() + code.Size()));
|
| - total_len += PrintOneStacktrace(
|
| - zone, &frame_strings, pc, function, code, *frame_index);
|
| - (*frame_index)++; // To account for inlined frames.
|
| + if (Compiler::allow_recompilation()) {
|
| + for (InlinedFunctionsIterator it(code, pc);
|
| + !it.Done() && (*frame_index < max_frames); it.Advance()) {
|
| + function = it.function();
|
| + if (function.is_visible() || FLAG_show_invisible_frames) {
|
| + code = it.code();
|
| + ASSERT(function.raw() == code.function());
|
| + uword pc = it.pc();
|
| + ASSERT(pc != 0);
|
| + ASSERT(code.EntryPoint() <= pc);
|
| + ASSERT(pc < (code.EntryPoint() + code.Size()));
|
| + total_len += PrintOneStacktrace(
|
| + zone, &frame_strings, pc, function, code, *frame_index);
|
| + (*frame_index)++; // To account for inlined frames.
|
| + }
|
| + }
|
| + } else {
|
| + // Precompilation: we don't have deopt info, so we don't know the
|
| + // source position of inlined functions, but we can still name them.
|
| + intptr_t offset = Smi::Value(PcOffsetAtFrame(i));
|
| + // The PC of frames below the top frame is a call's return address,
|
| + // which can belong to a different inlining interval than the call.
|
| + intptr_t effective_offset = offset - 1;
|
| + GrowableArray<Function*> inlined_functions;
|
| + code.GetInlinedFunctionsAt(effective_offset, &inlined_functions);
|
| + ASSERT(inlined_functions.length() >= 1); // At least the inliner.
|
| + for (intptr_t j = 0; j < inlined_functions.length(); j++) {
|
| + Function* inlined_function = inlined_functions[j];
|
| + ASSERT(inlined_function != NULL);
|
| + ASSERT(!inlined_function->IsNull());
|
| + if (inlined_function->is_visible() || FLAG_show_invisible_frames) {
|
| + total_len += PrintOneStacktraceNoCode(
|
| + zone, &frame_strings, *inlined_function, *frame_index);
|
| + (*frame_index)++;
|
| + }
|
| }
|
| }
|
| } else {
|
| - total_len += PrintOneStacktrace(
|
| - zone, &frame_strings, pc, function, code, *frame_index);
|
| - (*frame_index)++;
|
| + if (function.is_visible() || FLAG_show_invisible_frames) {
|
| + total_len += PrintOneStacktrace(
|
| + zone, &frame_strings, pc, function, code, *frame_index);
|
| + (*frame_index)++;
|
| + }
|
| }
|
| }
|
| }
|
|
|