Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(32)

Side by Side Diff: runtime/vm/object.cc

Issue 2687143005: Include metadata in AOT to expand inline frames in stack traces and provide line numbers. (Closed)
Patch Set: . Created 3 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « runtime/vm/object.h ('k') | runtime/vm/precompiler.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 9059 matching lines...) Expand 10 before | Expand all | Expand 10 after
9070 9070
9071 void Script::SetLocationOffset(intptr_t line_offset, 9071 void Script::SetLocationOffset(intptr_t line_offset,
9072 intptr_t col_offset) const { 9072 intptr_t col_offset) const {
9073 ASSERT(line_offset >= 0); 9073 ASSERT(line_offset >= 0);
9074 ASSERT(col_offset >= 0); 9074 ASSERT(col_offset >= 0);
9075 StoreNonPointer(&raw_ptr()->line_offset_, line_offset); 9075 StoreNonPointer(&raw_ptr()->line_offset_, line_offset);
9076 StoreNonPointer(&raw_ptr()->col_offset_, col_offset); 9076 StoreNonPointer(&raw_ptr()->col_offset_, col_offset);
9077 } 9077 }
9078 9078
9079 9079
9080 // Specialized for AOT compilation, which does this lookup for every token
9081 // position that could be part of a stack trace.
9082 intptr_t Script::GetTokenLineUsingLineStarts(
9083 TokenPosition target_token_pos) const {
9084 Zone* zone = Thread::Current()->zone();
9085 Array& line_starts_array = Array::Handle(zone, line_starts());
9086 Smi& token_pos = Smi::Handle(zone);
9087 if (line_starts_array.IsNull()) {
9088 ASSERT(kind() != RawScript::kKernelTag);
9089 GrowableObjectArray& line_starts_list =
9090 GrowableObjectArray::Handle(zone, GrowableObjectArray::New());
9091 const TokenStream& tkns = TokenStream::Handle(zone, tokens());
9092 TokenStream::Iterator tkit(zone, tkns, TokenPosition::kMinSource,
9093 TokenStream::Iterator::kAllTokens);
9094 intptr_t cur_line = line_offset() + 1;
9095 token_pos = Smi::New(0);
9096 line_starts_list.Add(token_pos);
9097 while (tkit.CurrentTokenKind() != Token::kEOS) {
9098 if (tkit.CurrentTokenKind() == Token::kNEWLINE) {
9099 cur_line++;
9100 token_pos = Smi::New(tkit.CurrentPosition().value() + 1);
9101 line_starts_list.Add(token_pos);
9102 }
9103 tkit.Advance();
9104 }
9105 line_starts_array = Array::MakeArray(line_starts_list);
9106 set_line_starts(line_starts_array);
9107 }
9108
9109 ASSERT(line_starts_array.Length() > 0);
9110 intptr_t offset = target_token_pos.value();
9111 intptr_t min = 0;
9112 intptr_t max = line_starts_array.Length() - 1;
9113
9114 // Binary search to find the line containing this offset.
9115 while (min < max) {
9116 int midpoint = (max - min + 1) / 2 + min;
9117 token_pos ^= line_starts_array.At(midpoint);
9118 if (token_pos.Value() > offset) {
9119 max = midpoint - 1;
9120 } else {
9121 min = midpoint;
9122 }
9123 }
9124 return min + 1; // Line numbers start at 1.
9125 }
9126
9127
9080 void Script::GetTokenLocation(TokenPosition token_pos, 9128 void Script::GetTokenLocation(TokenPosition token_pos,
9081 intptr_t* line, 9129 intptr_t* line,
9082 intptr_t* column, 9130 intptr_t* column,
9083 intptr_t* token_len) const { 9131 intptr_t* token_len) const {
9084 ASSERT(line != NULL); 9132 ASSERT(line != NULL);
9085 Zone* zone = Thread::Current()->zone(); 9133 Zone* zone = Thread::Current()->zone();
9086 9134
9087 if (kind() == RawScript::kKernelTag) { 9135 if (kind() == RawScript::kKernelTag) {
9088 const Array& line_starts_array = Array::Handle(line_starts()); 9136 const Array& line_starts_array = Array::Handle(zone, line_starts());
9089 if (line_starts_array.IsNull()) { 9137 if (line_starts_array.IsNull()) {
9090 // Scripts in the AOT snapshot do not have a line starts array. 9138 // Scripts in the AOT snapshot do not have a line starts array.
9091 *line = -1; 9139 *line = -1;
9092 if (column != NULL) { 9140 if (column != NULL) {
9093 *column = -1; 9141 *column = -1;
9094 } 9142 }
9095 if (token_len != NULL) { 9143 if (token_len != NULL) {
9096 *token_len = 1; 9144 *token_len = 1;
9097 } 9145 }
9098 return; 9146 return;
9099 } 9147 }
9100 ASSERT(line_starts_array.Length() > 0); 9148 ASSERT(line_starts_array.Length() > 0);
9101 intptr_t offset = token_pos.value(); 9149 intptr_t offset = token_pos.value();
9102 int min = 0; 9150 intptr_t min = 0;
9103 int max = line_starts_array.Length() - 1; 9151 intptr_t max = line_starts_array.Length() - 1;
9104 9152
9105 // Binary search to find the line containing this offset. 9153 // Binary search to find the line containing this offset.
9106 Smi& smi = Smi::Handle(); 9154 Smi& smi = Smi::Handle(zone);
9107 while (min < max) { 9155 while (min < max) {
9108 int midpoint = (max - min + 1) / 2 + min; 9156 intptr_t midpoint = (max - min + 1) / 2 + min;
9109 9157
9110 smi ^= line_starts_array.At(midpoint); 9158 smi ^= line_starts_array.At(midpoint);
9111 if (smi.Value() > offset) { 9159 if (smi.Value() > offset) {
9112 max = midpoint - 1; 9160 max = midpoint - 1;
9113 } else { 9161 } else {
9114 min = midpoint; 9162 min = midpoint;
9115 } 9163 }
9116 } 9164 }
9117 *line = min + 1; 9165 *line = min + 1; // Line numbers start at 1.
9118 smi ^= line_starts_array.At(min); 9166 smi ^= line_starts_array.At(min);
9119 if (column != NULL) { 9167 if (column != NULL) {
9120 *column = offset - smi.Value() + 1; 9168 *column = offset - smi.Value() + 1;
9121 } 9169 }
9122 if (token_len != NULL) { 9170 if (token_len != NULL) {
9123 // We don't explicitly save this data. 9171 // We don't explicitly save this data.
9124 // TODO(jensj): Load the source and attempt to find it from there. 9172 // TODO(jensj): Load the source and attempt to find it from there.
9125 *token_len = 1; 9173 *token_len = 1;
9126 } 9174 }
9127 return; 9175 return;
(...skipping 4952 matching lines...) Expand 10 before | Expand all | Expand 10 after
14080 // |return_address_metadata_|. 14128 // |return_address_metadata_|.
14081 if (object.IsNull() || !object.IsSmi()) { 14129 if (object.IsNull() || !object.IsSmi()) {
14082 return -1; 14130 return -1;
14083 } 14131 }
14084 return Smi::Cast(object).Value(); 14132 return Smi::Cast(object).Value();
14085 #endif 14133 #endif
14086 } 14134 }
14087 14135
14088 14136
14089 RawArray* Code::inlined_id_to_function() const { 14137 RawArray* Code::inlined_id_to_function() const {
14090 #if defined(DART_PRECOMPILED_RUNTIME)
14091 return Array::null();
14092 #else
14093 return raw_ptr()->inlined_id_to_function_; 14138 return raw_ptr()->inlined_id_to_function_;
14094 #endif
14095 } 14139 }
14096 14140
14097 14141
14098 void Code::set_inlined_id_to_function(const Array& value) const { 14142 void Code::set_inlined_id_to_function(const Array& value) const {
14099 #if defined(DART_PRECOMPILED_RUNTIME)
14100 UNREACHABLE();
14101 #else
14102 ASSERT(value.IsOld()); 14143 ASSERT(value.IsOld());
14103 StorePointer(&raw_ptr()->inlined_id_to_function_, value.raw()); 14144 StorePointer(&raw_ptr()->inlined_id_to_function_, value.raw());
14104 #endif
14105 } 14145 }
14106 14146
14107 14147
14108 RawCode* Code::New(intptr_t pointer_offsets_length) { 14148 RawCode* Code::New(intptr_t pointer_offsets_length) {
14109 if (pointer_offsets_length < 0 || pointer_offsets_length > kMaxElements) { 14149 if (pointer_offsets_length < 0 || pointer_offsets_length > kMaxElements) {
14110 // This should be caught before we reach here. 14150 // This should be caught before we reach here.
14111 FATAL1("Fatal error in Code::New: invalid pointer_offsets_length %" Pd "\n", 14151 FATAL1("Fatal error in Code::New: invalid pointer_offsets_length %" Pd "\n",
14112 pointer_offsets_length); 14152 pointer_offsets_length);
14113 } 14153 }
14114 ASSERT(Object::code_class() != Class::null()); 14154 ASSERT(Object::code_class() != Class::null());
(...skipping 344 matching lines...) Expand 10 before | Expand all | Expand 10 after
14459 return StackMap::null(); 14499 return StackMap::null();
14460 } 14500 }
14461 14501
14462 14502
14463 void Code::GetInlinedFunctionsAtInstruction( 14503 void Code::GetInlinedFunctionsAtInstruction(
14464 intptr_t pc_offset, 14504 intptr_t pc_offset,
14465 GrowableArray<const Function*>* functions, 14505 GrowableArray<const Function*>* functions,
14466 GrowableArray<TokenPosition>* token_positions) const { 14506 GrowableArray<TokenPosition>* token_positions) const {
14467 const CodeSourceMap& map = CodeSourceMap::Handle(code_source_map()); 14507 const CodeSourceMap& map = CodeSourceMap::Handle(code_source_map());
14468 if (map.IsNull()) { 14508 if (map.IsNull()) {
14469 // Stub code. 14509 ASSERT(!IsFunctionCode());
14470 return; 14510 return; // VM stub or allocation stub.
14471 } 14511 }
14472 const Array& id_map = Array::Handle(inlined_id_to_function()); 14512 const Array& id_map = Array::Handle(inlined_id_to_function());
14473 const Function& root = Function::Handle(function()); 14513 const Function& root = Function::Handle(function());
14474 CodeSourceMapReader reader(map, id_map, root); 14514 CodeSourceMapReader reader(map, id_map, root);
14475 reader.GetInlinedFunctionsAt(pc_offset, functions, token_positions); 14515 reader.GetInlinedFunctionsAt(pc_offset, functions, token_positions);
14476 } 14516 }
14477 14517
14478 14518
14479 #ifndef PRODUCT 14519 #ifndef PRODUCT
14480 void Code::PrintJSONInlineIntervals(JSONObject* jsobj) const { 14520 void Code::PrintJSONInlineIntervals(JSONObject* jsobj) const {
(...skipping 7879 matching lines...) Expand 10 before | Expand all | Expand 10 after
22360 const Function& function, 22400 const Function& function,
22361 TokenPosition token_pos, 22401 TokenPosition token_pos,
22362 intptr_t frame_index) { 22402 intptr_t frame_index) {
22363 const Script& script = Script::Handle(zone, function.script()); 22403 const Script& script = Script::Handle(zone, function.script());
22364 const String& function_name = 22404 const String& function_name =
22365 String::Handle(zone, function.QualifiedUserVisibleName()); 22405 String::Handle(zone, function.QualifiedUserVisibleName());
22366 const String& url = String::Handle( 22406 const String& url = String::Handle(
22367 zone, script.IsNull() ? String::New("Kernel") : script.url()); 22407 zone, script.IsNull() ? String::New("Kernel") : script.url());
22368 intptr_t line = -1; 22408 intptr_t line = -1;
22369 intptr_t column = -1; 22409 intptr_t column = -1;
22370 if (!script.IsNull() && token_pos.IsReal()) { 22410 if (FLAG_precompiled_mode) {
22371 if (script.HasSource() || script.kind() == RawScript::kKernelTag) { 22411 line = token_pos.value();
22372 script.GetTokenLocation(token_pos, &line, &column); 22412 } else {
22373 } else { 22413 if (!script.IsNull() && token_pos.IsReal()) {
22374 script.GetTokenLocation(token_pos, &line, NULL); 22414 if (script.HasSource() || script.kind() == RawScript::kKernelTag) {
22415 script.GetTokenLocation(token_pos, &line, &column);
22416 } else {
22417 script.GetTokenLocation(token_pos, &line, NULL);
22418 }
22375 } 22419 }
22376 } 22420 }
22377 if (column >= 0) { 22421 if (column >= 0) {
22378 buffer->Printf("#%-6" Pd " %s (%s:%" Pd ":%" Pd ")\n", frame_index, 22422 buffer->Printf("#%-6" Pd " %s (%s:%" Pd ":%" Pd ")\n", frame_index,
22379 function_name.ToCString(), url.ToCString(), line, column); 22423 function_name.ToCString(), url.ToCString(), line, column);
22380 } else if (line >= 0) { 22424 } else if (line >= 0) {
22381 buffer->Printf("#%-6" Pd " %s (%s:%" Pd ")\n", frame_index, 22425 buffer->Printf("#%-6" Pd " %s (%s:%" Pd ")\n", frame_index,
22382 function_name.ToCString(), url.ToCString(), line); 22426 function_name.ToCString(), url.ToCString(), line);
22383 } else { 22427 } else {
22384 buffer->Printf("#%-6" Pd " %s (%s)\n", frame_index, 22428 buffer->Printf("#%-6" Pd " %s (%s)\n", frame_index,
(...skipping 28 matching lines...) Expand all
22413 ASSERT(stack_trace.PcOffsetAtFrame(i) != Smi::null()); 22457 ASSERT(stack_trace.PcOffsetAtFrame(i) != Smi::null());
22414 // To account for gap frames. 22458 // To account for gap frames.
22415 (*frame_index) += Smi::Value(stack_trace.PcOffsetAtFrame(i)); 22459 (*frame_index) += Smi::Value(stack_trace.PcOffsetAtFrame(i));
22416 } 22460 }
22417 } else if (code.raw() == 22461 } else if (code.raw() ==
22418 StubCode::AsynchronousGapMarker_entry()->code()) { 22462 StubCode::AsynchronousGapMarker_entry()->code()) {
22419 buffer.AddString("<asynchronous suspension>\n"); 22463 buffer.AddString("<asynchronous suspension>\n");
22420 } else { 22464 } else {
22421 ASSERT(code.IsFunctionCode()); 22465 ASSERT(code.IsFunctionCode());
22422 intptr_t pc_offset = Smi::Value(stack_trace.PcOffsetAtFrame(i)); 22466 intptr_t pc_offset = Smi::Value(stack_trace.PcOffsetAtFrame(i));
22423 if (code.is_optimized() && stack_trace.expand_inlined() && 22467 if (code.is_optimized() && stack_trace.expand_inlined()) {
22424 !FLAG_precompiled_mode) {
22425 code.GetInlinedFunctionsAtReturnAddress(pc_offset, &inlined_functions, 22468 code.GetInlinedFunctionsAtReturnAddress(pc_offset, &inlined_functions,
22426 &inlined_token_positions); 22469 &inlined_token_positions);
22427 ASSERT(inlined_functions.length() >= 1); 22470 ASSERT(inlined_functions.length() >= 1);
22428 for (intptr_t j = inlined_functions.length() - 1; j >= 0; j--) { 22471 for (intptr_t j = inlined_functions.length() - 1; j >= 0; j--) {
22429 if (inlined_functions[j]->is_visible() || 22472 if (inlined_functions[j]->is_visible() ||
22430 FLAG_show_invisible_frames) { 22473 FLAG_show_invisible_frames) {
22431 PrintStackTraceFrame(zone, &buffer, *inlined_functions[j], 22474 PrintStackTraceFrame(zone, &buffer, *inlined_functions[j],
22432 inlined_token_positions[j], *frame_index); 22475 inlined_token_positions[j], *frame_index);
22433 (*frame_index)++; 22476 (*frame_index)++;
22434 } 22477 }
(...skipping 332 matching lines...) Expand 10 before | Expand all | Expand 10 after
22767 return UserTag::null(); 22810 return UserTag::null();
22768 } 22811 }
22769 22812
22770 22813
22771 const char* UserTag::ToCString() const { 22814 const char* UserTag::ToCString() const {
22772 const String& tag_label = String::Handle(label()); 22815 const String& tag_label = String::Handle(label());
22773 return tag_label.ToCString(); 22816 return tag_label.ToCString();
22774 } 22817 }
22775 22818
22776 } // namespace dart 22819 } // namespace dart
OLDNEW
« no previous file with comments | « runtime/vm/object.h ('k') | runtime/vm/precompiler.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698