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" | |
34 #include "vm/object_store.h" | 33 #include "vm/object_store.h" |
35 #include "vm/parser.h" | 34 #include "vm/parser.h" |
36 #include "vm/precompiler.h" | 35 #include "vm/precompiler.h" |
37 #include "vm/profiler.h" | 36 #include "vm/profiler.h" |
38 #include "vm/resolver.h" | 37 #include "vm/resolver.h" |
39 #include "vm/reusable_handles.h" | 38 #include "vm/reusable_handles.h" |
40 #include "vm/runtime_entry.h" | 39 #include "vm/runtime_entry.h" |
41 #include "vm/scopes.h" | 40 #include "vm/scopes.h" |
42 #include "vm/stack_frame.h" | 41 #include "vm/stack_frame.h" |
43 #include "vm/symbols.h" | 42 #include "vm/symbols.h" |
(...skipping 9125 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
9169 token_pos = Smi::New(tkit.CurrentPosition().value() + 1); | 9168 token_pos = Smi::New(tkit.CurrentPosition().value() + 1); |
9170 line_starts_list.Add(token_pos); | 9169 line_starts_list.Add(token_pos); |
9171 } | 9170 } |
9172 tkit.Advance(); | 9171 tkit.Advance(); |
9173 } | 9172 } |
9174 line_starts_array = Array::MakeArray(line_starts_list); | 9173 line_starts_array = Array::MakeArray(line_starts_list); |
9175 set_line_starts(line_starts_array); | 9174 set_line_starts(line_starts_array); |
9176 } | 9175 } |
9177 | 9176 |
9178 ASSERT(line_starts_array.Length() > 0); | 9177 ASSERT(line_starts_array.Length() > 0); |
9179 intptr_t offset = target_token_pos.Pos(); | 9178 intptr_t offset = target_token_pos.value(); |
9180 intptr_t min = 0; | 9179 intptr_t min = 0; |
9181 intptr_t max = line_starts_array.Length() - 1; | 9180 intptr_t max = line_starts_array.Length() - 1; |
9182 | 9181 |
9183 // Binary search to find the line containing this offset. | 9182 // Binary search to find the line containing this offset. |
9184 while (min < max) { | 9183 while (min < max) { |
9185 int midpoint = (max - min + 1) / 2 + min; | 9184 int midpoint = (max - min + 1) / 2 + min; |
9186 token_pos ^= line_starts_array.At(midpoint); | 9185 token_pos ^= line_starts_array.At(midpoint); |
9187 if (token_pos.Value() > offset) { | 9186 if (token_pos.Value() > offset) { |
9188 max = midpoint - 1; | 9187 max = midpoint - 1; |
9189 } else { | 9188 } else { |
(...skipping 13358 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
22548 result ^= raw; | 22547 result ^= raw; |
22549 } | 22548 } |
22550 result.set_async_link(async_link); | 22549 result.set_async_link(async_link); |
22551 result.set_code_array(code_array); | 22550 result.set_code_array(code_array); |
22552 result.set_pc_offset_array(pc_offset_array); | 22551 result.set_pc_offset_array(pc_offset_array); |
22553 result.set_expand_inlined(true); // default. | 22552 result.set_expand_inlined(true); // default. |
22554 return result.raw(); | 22553 return result.raw(); |
22555 } | 22554 } |
22556 | 22555 |
22557 | 22556 |
| 22557 const char* StackTrace::ToCString() const { |
| 22558 intptr_t idx = 0; |
| 22559 return ToCStringInternal(*this, &idx); |
| 22560 } |
| 22561 |
| 22562 |
22558 static void PrintStackTraceFrame(Zone* zone, | 22563 static void PrintStackTraceFrame(Zone* zone, |
22559 ZoneTextBuffer* buffer, | 22564 ZoneTextBuffer* buffer, |
22560 const Function& function, | 22565 const Function& function, |
22561 TokenPosition token_pos, | 22566 TokenPosition token_pos, |
22562 intptr_t frame_index) { | 22567 intptr_t frame_index) { |
22563 const Script& script = Script::Handle(zone, function.script()); | 22568 const Script& script = Script::Handle(zone, function.script()); |
22564 const String& function_name = | 22569 const String& function_name = |
22565 String::Handle(zone, function.QualifiedUserVisibleName()); | 22570 String::Handle(zone, function.QualifiedUserVisibleName()); |
22566 const String& url = String::Handle( | 22571 const String& url = String::Handle( |
22567 zone, script.IsNull() ? String::New("Kernel") : script.url()); | 22572 zone, script.IsNull() ? String::New("Kernel") : script.url()); |
(...skipping 16 matching lines...) Expand all Loading... |
22584 } else if (line >= 0) { | 22589 } else if (line >= 0) { |
22585 buffer->Printf("#%-6" Pd " %s (%s:%" Pd ")\n", frame_index, | 22590 buffer->Printf("#%-6" Pd " %s (%s:%" Pd ")\n", frame_index, |
22586 function_name.ToCString(), url.ToCString(), line); | 22591 function_name.ToCString(), url.ToCString(), line); |
22587 } else { | 22592 } else { |
22588 buffer->Printf("#%-6" Pd " %s (%s)\n", frame_index, | 22593 buffer->Printf("#%-6" Pd " %s (%s)\n", frame_index, |
22589 function_name.ToCString(), url.ToCString()); | 22594 function_name.ToCString(), url.ToCString()); |
22590 } | 22595 } |
22591 } | 22596 } |
22592 | 22597 |
22593 | 22598 |
22594 const char* StackTrace::ToDartCString(const StackTrace& stack_trace_in) { | 22599 const char* StackTrace::ToCStringInternal(const StackTrace& stack_trace_in, |
| 22600 intptr_t* frame_index, |
| 22601 intptr_t max_frames) { |
22595 Zone* zone = Thread::Current()->zone(); | 22602 Zone* zone = Thread::Current()->zone(); |
22596 StackTrace& stack_trace = StackTrace::Handle(zone, stack_trace_in.raw()); | 22603 StackTrace& stack_trace = StackTrace::Handle(zone, stack_trace_in.raw()); |
22597 Function& function = Function::Handle(zone); | 22604 Function& function = Function::Handle(zone); |
22598 Code& code = Code::Handle(zone); | 22605 Code& code = Code::Handle(zone); |
22599 | |
22600 GrowableArray<const Function*> inlined_functions; | 22606 GrowableArray<const Function*> inlined_functions; |
22601 GrowableArray<TokenPosition> inlined_token_positions; | 22607 GrowableArray<TokenPosition> inlined_token_positions; |
22602 ZoneTextBuffer buffer(zone, 1024); | 22608 ZoneTextBuffer buffer(zone, 1024); |
22603 | 22609 |
22604 // Iterate through the stack frames and create C string description | 22610 // Iterate through the stack frames and create C string description |
22605 // for each frame. | 22611 // for each frame. |
22606 intptr_t frame_index = 0; | |
22607 do { | 22612 do { |
22608 for (intptr_t i = 0; i < stack_trace.Length(); i++) { | 22613 for (intptr_t i = 0; |
| 22614 (i < stack_trace.Length()) && (*frame_index < max_frames); i++) { |
22609 code = stack_trace.CodeAtFrame(i); | 22615 code = stack_trace.CodeAtFrame(i); |
22610 if (code.IsNull()) { | 22616 if (code.IsNull()) { |
22611 // Check for a null function, which indicates a gap in a StackOverflow | 22617 // Check for a null function, which indicates a gap in a StackOverflow |
22612 // or OutOfMemory trace. | 22618 // or OutOfMemory trace. |
22613 if ((i < (stack_trace.Length() - 1)) && | 22619 if ((i < (stack_trace.Length() - 1)) && |
22614 (stack_trace.CodeAtFrame(i + 1) != Code::null())) { | 22620 (stack_trace.CodeAtFrame(i + 1) != Code::null())) { |
22615 buffer.AddString("...\n...\n"); | 22621 buffer.AddString("...\n...\n"); |
22616 ASSERT(stack_trace.PcOffsetAtFrame(i) != Smi::null()); | 22622 ASSERT(stack_trace.PcOffsetAtFrame(i) != Smi::null()); |
22617 // To account for gap frames. | 22623 // To account for gap frames. |
22618 frame_index += Smi::Value(stack_trace.PcOffsetAtFrame(i)); | 22624 (*frame_index) += Smi::Value(stack_trace.PcOffsetAtFrame(i)); |
22619 } | 22625 } |
22620 } else if (code.raw() == | 22626 } else if (code.raw() == |
22621 StubCode::AsynchronousGapMarker_entry()->code()) { | 22627 StubCode::AsynchronousGapMarker_entry()->code()) { |
22622 buffer.AddString("<asynchronous suspension>\n"); | 22628 buffer.AddString("<asynchronous suspension>\n"); |
22623 // The frame immediately after the asynchronous gap marker is the | 22629 // The frame immediately after the asynchronous gap marker is the |
22624 // identical to the frame above the marker. Skip the frame to enhance | 22630 // identical to the frame above the marker. Skip the frame to enhance |
22625 // the readability of the trace. | 22631 // the readability of the trace. |
22626 i++; | 22632 i++; |
22627 } else { | 22633 } else { |
22628 ASSERT(code.IsFunctionCode()); | 22634 ASSERT(code.IsFunctionCode()); |
22629 intptr_t pc_offset = Smi::Value(stack_trace.PcOffsetAtFrame(i)); | 22635 intptr_t pc_offset = Smi::Value(stack_trace.PcOffsetAtFrame(i)); |
22630 if (code.is_optimized() && stack_trace.expand_inlined()) { | 22636 if (code.is_optimized() && stack_trace.expand_inlined()) { |
22631 code.GetInlinedFunctionsAtReturnAddress(pc_offset, &inlined_functions, | 22637 code.GetInlinedFunctionsAtReturnAddress(pc_offset, &inlined_functions, |
22632 &inlined_token_positions); | 22638 &inlined_token_positions); |
22633 ASSERT(inlined_functions.length() >= 1); | 22639 ASSERT(inlined_functions.length() >= 1); |
22634 for (intptr_t j = inlined_functions.length() - 1; j >= 0; j--) { | 22640 for (intptr_t j = inlined_functions.length() - 1; j >= 0; j--) { |
22635 if (inlined_functions[j]->is_visible() || | 22641 if (inlined_functions[j]->is_visible() || |
22636 FLAG_show_invisible_frames) { | 22642 FLAG_show_invisible_frames) { |
22637 PrintStackTraceFrame(zone, &buffer, *inlined_functions[j], | 22643 PrintStackTraceFrame(zone, &buffer, *inlined_functions[j], |
22638 inlined_token_positions[j], frame_index); | 22644 inlined_token_positions[j], *frame_index); |
22639 frame_index++; | 22645 (*frame_index)++; |
22640 } | 22646 } |
22641 } | 22647 } |
22642 } else { | 22648 } else { |
22643 function = code.function(); | 22649 function = code.function(); |
22644 if (function.is_visible() || FLAG_show_invisible_frames) { | 22650 if (function.is_visible() || FLAG_show_invisible_frames) { |
22645 uword pc = code.PayloadStart() + pc_offset; | 22651 uword pc = code.PayloadStart() + pc_offset; |
22646 const TokenPosition token_pos = code.GetTokenIndexOfPC(pc); | 22652 const TokenPosition token_pos = code.GetTokenIndexOfPC(pc); |
22647 PrintStackTraceFrame(zone, &buffer, function, token_pos, | 22653 PrintStackTraceFrame(zone, &buffer, function, token_pos, |
22648 frame_index); | 22654 *frame_index); |
22649 frame_index++; | 22655 (*frame_index)++; |
22650 } | 22656 } |
22651 } | 22657 } |
22652 } | 22658 } |
22653 } | 22659 } |
22654 // Follow the link. | 22660 // Follow the link. |
22655 stack_trace ^= stack_trace.async_link(); | 22661 stack_trace ^= stack_trace.async_link(); |
22656 } while (!stack_trace.IsNull()); | 22662 } while (!stack_trace.IsNull()); |
22657 | 22663 |
22658 return buffer.buffer(); | 22664 return buffer.buffer(); |
22659 } | 22665 } |
22660 | 22666 |
22661 | 22667 |
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 | |
22746 void RegExp::set_pattern(const String& pattern) const { | 22668 void RegExp::set_pattern(const String& pattern) const { |
22747 StorePointer(&raw_ptr()->pattern_, pattern.raw()); | 22669 StorePointer(&raw_ptr()->pattern_, pattern.raw()); |
22748 } | 22670 } |
22749 | 22671 |
22750 | 22672 |
22751 void RegExp::set_function(intptr_t cid, | 22673 void RegExp::set_function(intptr_t cid, |
22752 bool sticky, | 22674 bool sticky, |
22753 const Function& value) const { | 22675 const Function& value) const { |
22754 StorePointer(FunctionAddr(cid, sticky), value.raw()); | 22676 StorePointer(FunctionAddr(cid, sticky), value.raw()); |
22755 } | 22677 } |
(...skipping 301 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
23057 return UserTag::null(); | 22979 return UserTag::null(); |
23058 } | 22980 } |
23059 | 22981 |
23060 | 22982 |
23061 const char* UserTag::ToCString() const { | 22983 const char* UserTag::ToCString() const { |
23062 const String& tag_label = String::Handle(label()); | 22984 const String& tag_label = String::Handle(label()); |
23063 return tag_label.ToCString(); | 22985 return tag_label.ToCString(); |
23064 } | 22986 } |
23065 | 22987 |
23066 } // namespace dart | 22988 } // namespace dart |
OLD | NEW |