Index: runtime/vm/object.cc |
diff --git a/runtime/vm/object.cc b/runtime/vm/object.cc |
index 0214fd9b87a2217fc8b7c5746a6189a67a4df9cc..c18cd647b6591cef587275973eec9146bfa1ed19 100644 |
--- a/runtime/vm/object.cc |
+++ b/runtime/vm/object.cc |
@@ -30,6 +30,7 @@ |
#include "vm/intrinsifier.h" |
#include "vm/isolate_reload.h" |
#include "vm/kernel_to_il.h" |
+#include "vm/native_symbol.h" |
#include "vm/object_store.h" |
#include "vm/parser.h" |
#include "vm/precompiler.h" |
@@ -9175,7 +9176,7 @@ intptr_t Script::GetTokenLineUsingLineStarts( |
} |
ASSERT(line_starts_array.Length() > 0); |
- intptr_t offset = target_token_pos.value(); |
+ intptr_t offset = target_token_pos.Pos(); |
intptr_t min = 0; |
intptr_t max = line_starts_array.Length() - 1; |
@@ -22554,12 +22555,6 @@ RawStackTrace* StackTrace::New(const Array& code_array, |
} |
-const char* StackTrace::ToCString() const { |
- intptr_t idx = 0; |
- return ToCStringInternal(*this, &idx); |
-} |
- |
- |
static void PrintStackTraceFrame(Zone* zone, |
ZoneTextBuffer* buffer, |
const Function& function, |
@@ -22596,22 +22591,21 @@ static void PrintStackTraceFrame(Zone* zone, |
} |
-const char* StackTrace::ToCStringInternal(const StackTrace& stack_trace_in, |
- intptr_t* frame_index, |
- intptr_t max_frames) { |
+const char* StackTrace::ToDartCString(const StackTrace& stack_trace_in) { |
Zone* zone = Thread::Current()->zone(); |
StackTrace& stack_trace = StackTrace::Handle(zone, stack_trace_in.raw()); |
Function& function = Function::Handle(zone); |
Code& code = Code::Handle(zone); |
+ |
GrowableArray<const Function*> inlined_functions; |
GrowableArray<TokenPosition> inlined_token_positions; |
ZoneTextBuffer buffer(zone, 1024); |
// Iterate through the stack frames and create C string description |
// for each frame. |
+ intptr_t frame_index = 0; |
do { |
- for (intptr_t i = 0; |
- (i < stack_trace.Length()) && (*frame_index < max_frames); i++) { |
+ for (intptr_t i = 0; i < stack_trace.Length(); i++) { |
code = stack_trace.CodeAtFrame(i); |
if (code.IsNull()) { |
// Check for a null function, which indicates a gap in a StackOverflow |
@@ -22621,7 +22615,7 @@ const char* StackTrace::ToCStringInternal(const StackTrace& stack_trace_in, |
buffer.AddString("...\n...\n"); |
ASSERT(stack_trace.PcOffsetAtFrame(i) != Smi::null()); |
// To account for gap frames. |
- (*frame_index) += Smi::Value(stack_trace.PcOffsetAtFrame(i)); |
+ frame_index += Smi::Value(stack_trace.PcOffsetAtFrame(i)); |
} |
} else if (code.raw() == |
StubCode::AsynchronousGapMarker_entry()->code()) { |
@@ -22641,8 +22635,8 @@ const char* StackTrace::ToCStringInternal(const StackTrace& stack_trace_in, |
if (inlined_functions[j]->is_visible() || |
FLAG_show_invisible_frames) { |
PrintStackTraceFrame(zone, &buffer, *inlined_functions[j], |
- inlined_token_positions[j], *frame_index); |
- (*frame_index)++; |
+ inlined_token_positions[j], frame_index); |
+ frame_index++; |
} |
} |
} else { |
@@ -22651,8 +22645,8 @@ const char* StackTrace::ToCStringInternal(const StackTrace& stack_trace_in, |
uword pc = code.PayloadStart() + pc_offset; |
const TokenPosition token_pos = code.GetTokenIndexOfPC(pc); |
PrintStackTraceFrame(zone, &buffer, function, token_pos, |
- *frame_index); |
- (*frame_index)++; |
+ frame_index); |
+ frame_index++; |
} |
} |
} |
@@ -22665,6 +22659,90 @@ const char* StackTrace::ToCStringInternal(const StackTrace& stack_trace_in, |
} |
+const char* StackTrace::ToDwarfCString(const StackTrace& stack_trace_in) { |
+#if defined(DART_PRECOMPILER) || defined(DART_PRECOMPILED_RUNTIME) |
+ Zone* zone = Thread::Current()->zone(); |
+ StackTrace& stack_trace = StackTrace::Handle(zone, stack_trace_in.raw()); |
+ Code& code = Code::Handle(zone); |
+ ZoneTextBuffer buffer(zone, 1024); |
+ |
+ // The Dart standard requires the output of StackTrace.toString to include |
+ // all pending activations with precise source locations (i.e., to expand |
+ // inlined frames and provide line and column numbers). |
+ buffer.Printf( |
+ "Warning: This VM has been configured to produce stack traces " |
+ "that violate the Dart standard.\n"); |
+ // This prologue imitates Android's debuggerd to make it possible to paste |
+ // the stack trace into ndk-stack. |
+ buffer.Printf( |
+ "*** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***\n"); |
+ OSThread* thread = OSThread::Current(); |
+ buffer.Printf("pid: %" Pd ", tid: %" Pd ", name %s\n", OS::ProcessId(), |
+ OSThread::ThreadIdToIntPtr(thread->id()), thread->name()); |
+ intptr_t frame_index = 0; |
+ do { |
+ for (intptr_t i = 0; i < stack_trace.Length(); i++) { |
+ code = stack_trace.CodeAtFrame(i); |
+ if (code.IsNull()) { |
+ // Check for a null function, which indicates a gap in a StackOverflow |
+ // or OutOfMemory trace. |
+ if ((i < (stack_trace.Length() - 1)) && |
+ (stack_trace.CodeAtFrame(i + 1) != Code::null())) { |
+ buffer.AddString("...\n...\n"); |
+ ASSERT(stack_trace.PcOffsetAtFrame(i) != Smi::null()); |
+ // To account for gap frames. |
+ frame_index += Smi::Value(stack_trace.PcOffsetAtFrame(i)); |
+ } |
+ } else if (code.raw() == |
+ StubCode::AsynchronousGapMarker_entry()->code()) { |
+ buffer.AddString("<asynchronous suspension>\n"); |
+ // The frame immediately after the asynchronous gap marker is the |
+ // identical to the frame above the marker. Skip the frame to enhance |
+ // the readability of the trace. |
+ i++; |
+ } else { |
+ intptr_t pc_offset = Smi::Value(stack_trace.PcOffsetAtFrame(i)); |
+ // This output is formatted like Android's debuggerd. Note debuggerd |
+ // prints call addresses instead of return addresses. |
+ uword return_addr = code.PayloadStart() + pc_offset; |
+ uword call_addr = return_addr - 1; |
+ uword dso_base; |
+ char* dso_name; |
+ if (NativeSymbolResolver::LookupSharedObject(call_addr, &dso_base, |
+ &dso_name)) { |
+ uword dso_offset = call_addr - dso_base; |
+ buffer.Printf(" #%02" Pd " pc %" Pp " %s\n", frame_index, |
+ dso_offset, dso_name); |
+ NativeSymbolResolver::FreeSymbolName(dso_name); |
+ } else { |
+ buffer.Printf(" #%02" Pd " pc %" Pp " <unknown>\n", frame_index, |
+ call_addr); |
+ } |
+ frame_index++; |
+ } |
+ } |
+ // Follow the link. |
+ stack_trace ^= stack_trace.async_link(); |
+ } while (!stack_trace.IsNull()); |
+ |
+ return buffer.buffer(); |
+#else |
+ UNREACHABLE(); |
+ return NULL; |
+#endif // defined(DART_PRECOMPILER) || defined(DART_PRECOMPILED_RUNTIME) |
+} |
+ |
+ |
+const char* StackTrace::ToCString() const { |
+#if defined(DART_PRECOMPILER) || defined(DART_PRECOMPILED_RUNTIME) |
+ if (FLAG_dwarf_stack_traces) { |
+ return ToDwarfCString(*this); |
+ } |
+#endif |
+ return ToDartCString(*this); |
+} |
+ |
+ |
void RegExp::set_pattern(const String& pattern) const { |
StorePointer(&raw_ptr()->pattern_, pattern.raw()); |
} |