| 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 9059 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 |
| OLD | NEW |