OLD | NEW |
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 #include "vm/object.h" | 5 #include "vm/object.h" |
6 | 6 |
7 #include "include/dart_api.h" | 7 #include "include/dart_api.h" |
8 #include "platform/assert.h" | 8 #include "platform/assert.h" |
9 #include "vm/assembler.h" | 9 #include "vm/assembler.h" |
10 #include "vm/become.h" | 10 #include "vm/become.h" |
(...skipping 12 matching lines...) Expand all Loading... |
23 #include "vm/deopt_instructions.h" | 23 #include "vm/deopt_instructions.h" |
24 #include "vm/disassembler.h" | 24 #include "vm/disassembler.h" |
25 #include "vm/double_conversion.h" | 25 #include "vm/double_conversion.h" |
26 #include "vm/exceptions.h" | 26 #include "vm/exceptions.h" |
27 #include "vm/growable_array.h" | 27 #include "vm/growable_array.h" |
28 #include "vm/hash_table.h" | 28 #include "vm/hash_table.h" |
29 #include "vm/heap.h" | 29 #include "vm/heap.h" |
30 #include "vm/intrinsifier.h" | 30 #include "vm/intrinsifier.h" |
31 #include "vm/isolate_reload.h" | 31 #include "vm/isolate_reload.h" |
32 #include "vm/kernel_to_il.h" | 32 #include "vm/kernel_to_il.h" |
| 33 #include "vm/native_symbol.h" |
33 #include "vm/object_store.h" | 34 #include "vm/object_store.h" |
34 #include "vm/parser.h" | 35 #include "vm/parser.h" |
35 #include "vm/precompiler.h" | 36 #include "vm/precompiler.h" |
36 #include "vm/profiler.h" | 37 #include "vm/profiler.h" |
37 #include "vm/resolver.h" | 38 #include "vm/resolver.h" |
38 #include "vm/reusable_handles.h" | 39 #include "vm/reusable_handles.h" |
39 #include "vm/runtime_entry.h" | 40 #include "vm/runtime_entry.h" |
40 #include "vm/scopes.h" | 41 #include "vm/scopes.h" |
41 #include "vm/stack_frame.h" | 42 #include "vm/stack_frame.h" |
42 #include "vm/symbols.h" | 43 #include "vm/symbols.h" |
(...skipping 9125 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
9168 token_pos = Smi::New(tkit.CurrentPosition().value() + 1); | 9169 token_pos = Smi::New(tkit.CurrentPosition().value() + 1); |
9169 line_starts_list.Add(token_pos); | 9170 line_starts_list.Add(token_pos); |
9170 } | 9171 } |
9171 tkit.Advance(); | 9172 tkit.Advance(); |
9172 } | 9173 } |
9173 line_starts_array = Array::MakeArray(line_starts_list); | 9174 line_starts_array = Array::MakeArray(line_starts_list); |
9174 set_line_starts(line_starts_array); | 9175 set_line_starts(line_starts_array); |
9175 } | 9176 } |
9176 | 9177 |
9177 ASSERT(line_starts_array.Length() > 0); | 9178 ASSERT(line_starts_array.Length() > 0); |
9178 intptr_t offset = target_token_pos.value(); | 9179 intptr_t offset = target_token_pos.Pos(); |
9179 intptr_t min = 0; | 9180 intptr_t min = 0; |
9180 intptr_t max = line_starts_array.Length() - 1; | 9181 intptr_t max = line_starts_array.Length() - 1; |
9181 | 9182 |
9182 // Binary search to find the line containing this offset. | 9183 // Binary search to find the line containing this offset. |
9183 while (min < max) { | 9184 while (min < max) { |
9184 int midpoint = (max - min + 1) / 2 + min; | 9185 int midpoint = (max - min + 1) / 2 + min; |
9185 token_pos ^= line_starts_array.At(midpoint); | 9186 token_pos ^= line_starts_array.At(midpoint); |
9186 if (token_pos.Value() > offset) { | 9187 if (token_pos.Value() > offset) { |
9187 max = midpoint - 1; | 9188 max = midpoint - 1; |
9188 } else { | 9189 } else { |
(...skipping 13358 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
22547 result ^= raw; | 22548 result ^= raw; |
22548 } | 22549 } |
22549 result.set_async_link(async_link); | 22550 result.set_async_link(async_link); |
22550 result.set_code_array(code_array); | 22551 result.set_code_array(code_array); |
22551 result.set_pc_offset_array(pc_offset_array); | 22552 result.set_pc_offset_array(pc_offset_array); |
22552 result.set_expand_inlined(true); // default. | 22553 result.set_expand_inlined(true); // default. |
22553 return result.raw(); | 22554 return result.raw(); |
22554 } | 22555 } |
22555 | 22556 |
22556 | 22557 |
22557 const char* StackTrace::ToCString() const { | |
22558 intptr_t idx = 0; | |
22559 return ToCStringInternal(*this, &idx); | |
22560 } | |
22561 | |
22562 | |
22563 static void PrintStackTraceFrame(Zone* zone, | 22558 static void PrintStackTraceFrame(Zone* zone, |
22564 ZoneTextBuffer* buffer, | 22559 ZoneTextBuffer* buffer, |
22565 const Function& function, | 22560 const Function& function, |
22566 TokenPosition token_pos, | 22561 TokenPosition token_pos, |
22567 intptr_t frame_index) { | 22562 intptr_t frame_index) { |
22568 const Script& script = Script::Handle(zone, function.script()); | 22563 const Script& script = Script::Handle(zone, function.script()); |
22569 const String& function_name = | 22564 const String& function_name = |
22570 String::Handle(zone, function.QualifiedUserVisibleName()); | 22565 String::Handle(zone, function.QualifiedUserVisibleName()); |
22571 const String& url = String::Handle( | 22566 const String& url = String::Handle( |
22572 zone, script.IsNull() ? String::New("Kernel") : script.url()); | 22567 zone, script.IsNull() ? String::New("Kernel") : script.url()); |
(...skipping 16 matching lines...) Expand all Loading... |
22589 } else if (line >= 0) { | 22584 } else if (line >= 0) { |
22590 buffer->Printf("#%-6" Pd " %s (%s:%" Pd ")\n", frame_index, | 22585 buffer->Printf("#%-6" Pd " %s (%s:%" Pd ")\n", frame_index, |
22591 function_name.ToCString(), url.ToCString(), line); | 22586 function_name.ToCString(), url.ToCString(), line); |
22592 } else { | 22587 } else { |
22593 buffer->Printf("#%-6" Pd " %s (%s)\n", frame_index, | 22588 buffer->Printf("#%-6" Pd " %s (%s)\n", frame_index, |
22594 function_name.ToCString(), url.ToCString()); | 22589 function_name.ToCString(), url.ToCString()); |
22595 } | 22590 } |
22596 } | 22591 } |
22597 | 22592 |
22598 | 22593 |
22599 const char* StackTrace::ToCStringInternal(const StackTrace& stack_trace_in, | 22594 const char* StackTrace::ToDartCString(const StackTrace& stack_trace_in) { |
22600 intptr_t* frame_index, | |
22601 intptr_t max_frames) { | |
22602 Zone* zone = Thread::Current()->zone(); | 22595 Zone* zone = Thread::Current()->zone(); |
22603 StackTrace& stack_trace = StackTrace::Handle(zone, stack_trace_in.raw()); | 22596 StackTrace& stack_trace = StackTrace::Handle(zone, stack_trace_in.raw()); |
22604 Function& function = Function::Handle(zone); | 22597 Function& function = Function::Handle(zone); |
22605 Code& code = Code::Handle(zone); | 22598 Code& code = Code::Handle(zone); |
| 22599 |
22606 GrowableArray<const Function*> inlined_functions; | 22600 GrowableArray<const Function*> inlined_functions; |
22607 GrowableArray<TokenPosition> inlined_token_positions; | 22601 GrowableArray<TokenPosition> inlined_token_positions; |
22608 ZoneTextBuffer buffer(zone, 1024); | 22602 ZoneTextBuffer buffer(zone, 1024); |
22609 | 22603 |
22610 // Iterate through the stack frames and create C string description | 22604 // Iterate through the stack frames and create C string description |
22611 // for each frame. | 22605 // for each frame. |
| 22606 intptr_t frame_index = 0; |
22612 do { | 22607 do { |
22613 for (intptr_t i = 0; | 22608 for (intptr_t i = 0; i < stack_trace.Length(); i++) { |
22614 (i < stack_trace.Length()) && (*frame_index < max_frames); i++) { | |
22615 code = stack_trace.CodeAtFrame(i); | 22609 code = stack_trace.CodeAtFrame(i); |
22616 if (code.IsNull()) { | 22610 if (code.IsNull()) { |
22617 // Check for a null function, which indicates a gap in a StackOverflow | 22611 // Check for a null function, which indicates a gap in a StackOverflow |
22618 // or OutOfMemory trace. | 22612 // or OutOfMemory trace. |
22619 if ((i < (stack_trace.Length() - 1)) && | 22613 if ((i < (stack_trace.Length() - 1)) && |
22620 (stack_trace.CodeAtFrame(i + 1) != Code::null())) { | 22614 (stack_trace.CodeAtFrame(i + 1) != Code::null())) { |
22621 buffer.AddString("...\n...\n"); | 22615 buffer.AddString("...\n...\n"); |
22622 ASSERT(stack_trace.PcOffsetAtFrame(i) != Smi::null()); | 22616 ASSERT(stack_trace.PcOffsetAtFrame(i) != Smi::null()); |
22623 // To account for gap frames. | 22617 // To account for gap frames. |
22624 (*frame_index) += Smi::Value(stack_trace.PcOffsetAtFrame(i)); | 22618 frame_index += Smi::Value(stack_trace.PcOffsetAtFrame(i)); |
22625 } | 22619 } |
22626 } else if (code.raw() == | 22620 } else if (code.raw() == |
22627 StubCode::AsynchronousGapMarker_entry()->code()) { | 22621 StubCode::AsynchronousGapMarker_entry()->code()) { |
22628 buffer.AddString("<asynchronous suspension>\n"); | 22622 buffer.AddString("<asynchronous suspension>\n"); |
22629 // The frame immediately after the asynchronous gap marker is the | 22623 // The frame immediately after the asynchronous gap marker is the |
22630 // identical to the frame above the marker. Skip the frame to enhance | 22624 // identical to the frame above the marker. Skip the frame to enhance |
22631 // the readability of the trace. | 22625 // the readability of the trace. |
22632 i++; | 22626 i++; |
22633 } else { | 22627 } else { |
22634 ASSERT(code.IsFunctionCode()); | 22628 ASSERT(code.IsFunctionCode()); |
22635 intptr_t pc_offset = Smi::Value(stack_trace.PcOffsetAtFrame(i)); | 22629 intptr_t pc_offset = Smi::Value(stack_trace.PcOffsetAtFrame(i)); |
22636 if (code.is_optimized() && stack_trace.expand_inlined()) { | 22630 if (code.is_optimized() && stack_trace.expand_inlined()) { |
22637 code.GetInlinedFunctionsAtReturnAddress(pc_offset, &inlined_functions, | 22631 code.GetInlinedFunctionsAtReturnAddress(pc_offset, &inlined_functions, |
22638 &inlined_token_positions); | 22632 &inlined_token_positions); |
22639 ASSERT(inlined_functions.length() >= 1); | 22633 ASSERT(inlined_functions.length() >= 1); |
22640 for (intptr_t j = inlined_functions.length() - 1; j >= 0; j--) { | 22634 for (intptr_t j = inlined_functions.length() - 1; j >= 0; j--) { |
22641 if (inlined_functions[j]->is_visible() || | 22635 if (inlined_functions[j]->is_visible() || |
22642 FLAG_show_invisible_frames) { | 22636 FLAG_show_invisible_frames) { |
22643 PrintStackTraceFrame(zone, &buffer, *inlined_functions[j], | 22637 PrintStackTraceFrame(zone, &buffer, *inlined_functions[j], |
22644 inlined_token_positions[j], *frame_index); | 22638 inlined_token_positions[j], frame_index); |
22645 (*frame_index)++; | 22639 frame_index++; |
22646 } | 22640 } |
22647 } | 22641 } |
22648 } else { | 22642 } else { |
22649 function = code.function(); | 22643 function = code.function(); |
22650 if (function.is_visible() || FLAG_show_invisible_frames) { | 22644 if (function.is_visible() || FLAG_show_invisible_frames) { |
22651 uword pc = code.PayloadStart() + pc_offset; | 22645 uword pc = code.PayloadStart() + pc_offset; |
22652 const TokenPosition token_pos = code.GetTokenIndexOfPC(pc); | 22646 const TokenPosition token_pos = code.GetTokenIndexOfPC(pc); |
22653 PrintStackTraceFrame(zone, &buffer, function, token_pos, | 22647 PrintStackTraceFrame(zone, &buffer, function, token_pos, |
22654 *frame_index); | 22648 frame_index); |
22655 (*frame_index)++; | 22649 frame_index++; |
22656 } | 22650 } |
22657 } | 22651 } |
22658 } | 22652 } |
22659 } | 22653 } |
22660 // Follow the link. | 22654 // Follow the link. |
22661 stack_trace ^= stack_trace.async_link(); | 22655 stack_trace ^= stack_trace.async_link(); |
22662 } while (!stack_trace.IsNull()); | 22656 } while (!stack_trace.IsNull()); |
22663 | 22657 |
22664 return buffer.buffer(); | 22658 return buffer.buffer(); |
22665 } | 22659 } |
22666 | 22660 |
22667 | 22661 |
| 22662 const char* StackTrace::ToDwarfCString(const StackTrace& stack_trace_in) { |
| 22663 #if defined(DART_PRECOMPILER) || defined(DART_PRECOMPILED_RUNTIME) |
| 22664 Zone* zone = Thread::Current()->zone(); |
| 22665 StackTrace& stack_trace = StackTrace::Handle(zone, stack_trace_in.raw()); |
| 22666 Code& code = Code::Handle(zone); |
| 22667 ZoneTextBuffer buffer(zone, 1024); |
| 22668 |
| 22669 // The Dart standard requires the output of StackTrace.toString to include |
| 22670 // all pending activations with precise source locations (i.e., to expand |
| 22671 // inlined frames and provide line and column numbers). |
| 22672 buffer.Printf( |
| 22673 "Warning: This VM has been configured to produce stack traces " |
| 22674 "that violate the Dart standard.\n"); |
| 22675 // This prologue imitates Android's debuggerd to make it possible to paste |
| 22676 // the stack trace into ndk-stack. |
| 22677 buffer.Printf( |
| 22678 "*** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***\n"); |
| 22679 OSThread* thread = OSThread::Current(); |
| 22680 buffer.Printf("pid: %" Pd ", tid: %" Pd ", name %s\n", OS::ProcessId(), |
| 22681 OSThread::ThreadIdToIntPtr(thread->id()), thread->name()); |
| 22682 intptr_t frame_index = 0; |
| 22683 do { |
| 22684 for (intptr_t i = 0; i < stack_trace.Length(); i++) { |
| 22685 code = stack_trace.CodeAtFrame(i); |
| 22686 if (code.IsNull()) { |
| 22687 // Check for a null function, which indicates a gap in a StackOverflow |
| 22688 // or OutOfMemory trace. |
| 22689 if ((i < (stack_trace.Length() - 1)) && |
| 22690 (stack_trace.CodeAtFrame(i + 1) != Code::null())) { |
| 22691 buffer.AddString("...\n...\n"); |
| 22692 ASSERT(stack_trace.PcOffsetAtFrame(i) != Smi::null()); |
| 22693 // To account for gap frames. |
| 22694 frame_index += Smi::Value(stack_trace.PcOffsetAtFrame(i)); |
| 22695 } |
| 22696 } else if (code.raw() == |
| 22697 StubCode::AsynchronousGapMarker_entry()->code()) { |
| 22698 buffer.AddString("<asynchronous suspension>\n"); |
| 22699 // The frame immediately after the asynchronous gap marker is the |
| 22700 // identical to the frame above the marker. Skip the frame to enhance |
| 22701 // the readability of the trace. |
| 22702 i++; |
| 22703 } else { |
| 22704 intptr_t pc_offset = Smi::Value(stack_trace.PcOffsetAtFrame(i)); |
| 22705 // This output is formatted like Android's debuggerd. Note debuggerd |
| 22706 // prints call addresses instead of return addresses. |
| 22707 uword return_addr = code.PayloadStart() + pc_offset; |
| 22708 uword call_addr = return_addr - 1; |
| 22709 uword dso_base; |
| 22710 char* dso_name; |
| 22711 if (NativeSymbolResolver::LookupSharedObject(call_addr, &dso_base, |
| 22712 &dso_name)) { |
| 22713 uword dso_offset = call_addr - dso_base; |
| 22714 buffer.Printf(" #%02" Pd " pc %" Pp " %s\n", frame_index, |
| 22715 dso_offset, dso_name); |
| 22716 NativeSymbolResolver::FreeSymbolName(dso_name); |
| 22717 } else { |
| 22718 buffer.Printf(" #%02" Pd " pc %" Pp " <unknown>\n", frame_index, |
| 22719 call_addr); |
| 22720 } |
| 22721 frame_index++; |
| 22722 } |
| 22723 } |
| 22724 // Follow the link. |
| 22725 stack_trace ^= stack_trace.async_link(); |
| 22726 } while (!stack_trace.IsNull()); |
| 22727 |
| 22728 return buffer.buffer(); |
| 22729 #else |
| 22730 UNREACHABLE(); |
| 22731 return NULL; |
| 22732 #endif // defined(DART_PRECOMPILER) || defined(DART_PRECOMPILED_RUNTIME) |
| 22733 } |
| 22734 |
| 22735 |
| 22736 const char* StackTrace::ToCString() const { |
| 22737 #if defined(DART_PRECOMPILER) || defined(DART_PRECOMPILED_RUNTIME) |
| 22738 if (FLAG_dwarf_stack_traces) { |
| 22739 return ToDwarfCString(*this); |
| 22740 } |
| 22741 #endif |
| 22742 return ToDartCString(*this); |
| 22743 } |
| 22744 |
| 22745 |
22668 void RegExp::set_pattern(const String& pattern) const { | 22746 void RegExp::set_pattern(const String& pattern) const { |
22669 StorePointer(&raw_ptr()->pattern_, pattern.raw()); | 22747 StorePointer(&raw_ptr()->pattern_, pattern.raw()); |
22670 } | 22748 } |
22671 | 22749 |
22672 | 22750 |
22673 void RegExp::set_function(intptr_t cid, | 22751 void RegExp::set_function(intptr_t cid, |
22674 bool sticky, | 22752 bool sticky, |
22675 const Function& value) const { | 22753 const Function& value) const { |
22676 StorePointer(FunctionAddr(cid, sticky), value.raw()); | 22754 StorePointer(FunctionAddr(cid, sticky), value.raw()); |
22677 } | 22755 } |
(...skipping 301 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
22979 return UserTag::null(); | 23057 return UserTag::null(); |
22980 } | 23058 } |
22981 | 23059 |
22982 | 23060 |
22983 const char* UserTag::ToCString() const { | 23061 const char* UserTag::ToCString() const { |
22984 const String& tag_label = String::Handle(label()); | 23062 const String& tag_label = String::Handle(label()); |
22985 return tag_label.ToCString(); | 23063 return tag_label.ToCString(); |
22986 } | 23064 } |
22987 | 23065 |
22988 } // namespace dart | 23066 } // namespace dart |
OLD | NEW |