| OLD | NEW |
| 1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2015, 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/source_report.h" | 5 #include "vm/source_report.h" |
| 6 | 6 |
| 7 #include "vm/compiler.h" | 7 #include "vm/compiler.h" |
| 8 #include "vm/isolate.h" | 8 #include "vm/isolate.h" |
| 9 #include "vm/object.h" | 9 #include "vm/object.h" |
| 10 #include "vm/object_store.h" | 10 #include "vm/object_store.h" |
| 11 #include "vm/profiler.h" | 11 #include "vm/profiler.h" |
| 12 #include "vm/profiler_service.h" | 12 #include "vm/profiler_service.h" |
| 13 | 13 |
| 14 namespace dart { | 14 namespace dart { |
| 15 | 15 |
| 16 const char* SourceReport::kCallSitesStr = "_CallSites"; | 16 const char* SourceReport::kCallSitesStr = "_CallSites"; |
| 17 const char* SourceReport::kCoverageStr = "Coverage"; | 17 const char* SourceReport::kCoverageStr = "Coverage"; |
| 18 const char* SourceReport::kPossibleBreakpointsStr = "PossibleBreakpoints"; | 18 const char* SourceReport::kPossibleBreakpointsStr = "PossibleBreakpoints"; |
| 19 const char* SourceReport::kProfileStr = "_Profile"; | 19 const char* SourceReport::kProfileStr = "_Profile"; |
| 20 | 20 |
| 21 SourceReport::SourceReport(intptr_t report_set, CompileMode compile_mode) | 21 SourceReport::SourceReport(intptr_t report_set, CompileMode compile_mode) |
| 22 : report_set_(report_set), | 22 : report_set_(report_set), |
| 23 compile_mode_(compile_mode), | 23 compile_mode_(compile_mode), |
| 24 thread_(NULL), | 24 thread_(NULL), |
| 25 script_(NULL), | 25 script_(NULL), |
| 26 start_pos_(TokenPosition::kNoSource), | 26 start_pos_(TokenPosition::kNoSource), |
| 27 end_pos_(TokenPosition::kNoSource), | 27 end_pos_(TokenPosition::kNoSource), |
| 28 profile_(Isolate::Current()), | 28 profile_(Isolate::Current()), |
| 29 next_script_index_(0) { | 29 next_script_index_(0) {} |
| 30 } | |
| 31 | 30 |
| 32 | 31 |
| 33 SourceReport::~SourceReport() { | 32 SourceReport::~SourceReport() { |
| 34 ClearScriptTable(); | 33 ClearScriptTable(); |
| 35 } | 34 } |
| 36 | 35 |
| 37 | 36 |
| 38 void SourceReport::ClearScriptTable() { | 37 void SourceReport::ClearScriptTable() { |
| 39 for (intptr_t i = 0; i < script_table_entries_.length(); i++) { | 38 for (intptr_t i = 0; i < script_table_entries_.length(); i++) { |
| 40 delete script_table_entries_[i]; | 39 delete script_table_entries_[i]; |
| 41 script_table_entries_[i] = NULL; | 40 script_table_entries_[i] = NULL; |
| 42 } | 41 } |
| 43 script_table_entries_.Clear(); | 42 script_table_entries_.Clear(); |
| 44 script_table_.Clear(); | 43 script_table_.Clear(); |
| 45 next_script_index_ = 0; | 44 next_script_index_ = 0; |
| 46 } | 45 } |
| 47 | 46 |
| 48 | 47 |
| 49 void SourceReport::Init(Thread* thread, | 48 void SourceReport::Init(Thread* thread, |
| 50 const Script* script, | 49 const Script* script, |
| 51 TokenPosition start_pos, | 50 TokenPosition start_pos, |
| 52 TokenPosition end_pos) { | 51 TokenPosition end_pos) { |
| 53 thread_ = thread; | 52 thread_ = thread; |
| 54 script_ = script; | 53 script_ = script; |
| 55 start_pos_ = start_pos; | 54 start_pos_ = start_pos; |
| 56 end_pos_ = end_pos; | 55 end_pos_ = end_pos; |
| 57 ClearScriptTable(); | 56 ClearScriptTable(); |
| 58 if (IsReportRequested(kProfile)) { | 57 if (IsReportRequested(kProfile)) { |
| 59 // Build the profile. | 58 // Build the profile. |
| 60 SampleFilter samplesForIsolate(thread_->isolate(), | 59 SampleFilter samplesForIsolate(thread_->isolate(), Thread::kMutatorTask, -1, |
| 61 Thread::kMutatorTask, | 60 -1); |
| 62 -1, -1); | |
| 63 profile_.Build(thread, &samplesForIsolate, Profile::kNoTags); | 61 profile_.Build(thread, &samplesForIsolate, Profile::kNoTags); |
| 64 } | 62 } |
| 65 } | 63 } |
| 66 | 64 |
| 67 | 65 |
| 68 bool SourceReport::IsReportRequested(ReportKind report_kind) { | 66 bool SourceReport::IsReportRequested(ReportKind report_kind) { |
| 69 return (report_set_ & report_kind) != 0; | 67 return (report_set_ & report_kind) != 0; |
| 70 } | 68 } |
| 71 | 69 |
| 72 | 70 |
| (...skipping 15 matching lines...) Expand all Loading... |
| 88 switch (func.kind()) { | 86 switch (func.kind()) { |
| 89 case RawFunction::kRegularFunction: | 87 case RawFunction::kRegularFunction: |
| 90 case RawFunction::kClosureFunction: | 88 case RawFunction::kClosureFunction: |
| 91 case RawFunction::kGetterFunction: | 89 case RawFunction::kGetterFunction: |
| 92 case RawFunction::kSetterFunction: | 90 case RawFunction::kSetterFunction: |
| 93 case RawFunction::kConstructor: | 91 case RawFunction::kConstructor: |
| 94 break; | 92 break; |
| 95 default: | 93 default: |
| 96 return true; | 94 return true; |
| 97 } | 95 } |
| 98 if (func.is_abstract() || | 96 if (func.is_abstract() || func.IsImplicitConstructor() || |
| 99 func.IsImplicitConstructor() || | |
| 100 func.IsRedirectingFactory()) { | 97 func.IsRedirectingFactory()) { |
| 101 return true; | 98 return true; |
| 102 } | 99 } |
| 103 if (func.IsNonImplicitClosureFunction() && | 100 if (func.IsNonImplicitClosureFunction() && |
| 104 (func.context_scope() == ContextScope::null())) { | 101 (func.context_scope() == ContextScope::null())) { |
| 105 // TODO(iposva): This can arise if we attempt to compile an inner function | 102 // TODO(iposva): This can arise if we attempt to compile an inner function |
| 106 // before we have compiled its enclosing function or if the enclosing | 103 // before we have compiled its enclosing function or if the enclosing |
| 107 // function failed to compile. | 104 // function failed to compile. |
| 108 return true; | 105 return true; |
| 109 } | 106 } |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 159 } | 156 } |
| 160 | 157 |
| 161 | 158 |
| 162 void SourceReport::PrintCallSitesData(JSONObject* jsobj, | 159 void SourceReport::PrintCallSitesData(JSONObject* jsobj, |
| 163 const Function& function, | 160 const Function& function, |
| 164 const Code& code) { | 161 const Code& code) { |
| 165 const TokenPosition begin_pos = function.token_pos(); | 162 const TokenPosition begin_pos = function.token_pos(); |
| 166 const TokenPosition end_pos = function.end_token_pos(); | 163 const TokenPosition end_pos = function.end_token_pos(); |
| 167 | 164 |
| 168 ZoneGrowableArray<const ICData*>* ic_data_array = | 165 ZoneGrowableArray<const ICData*>* ic_data_array = |
| 169 new(zone()) ZoneGrowableArray<const ICData*>(); | 166 new (zone()) ZoneGrowableArray<const ICData*>(); |
| 170 function.RestoreICDataMap(ic_data_array, false /* clone ic-data */); | 167 function.RestoreICDataMap(ic_data_array, false /* clone ic-data */); |
| 171 const PcDescriptors& descriptors = PcDescriptors::Handle( | 168 const PcDescriptors& descriptors = |
| 172 zone(), code.pc_descriptors()); | 169 PcDescriptors::Handle(zone(), code.pc_descriptors()); |
| 173 | 170 |
| 174 JSONArray sites(jsobj, "callSites"); | 171 JSONArray sites(jsobj, "callSites"); |
| 175 | 172 |
| 176 PcDescriptors::Iterator iter( | 173 PcDescriptors::Iterator iter( |
| 177 descriptors, | 174 descriptors, |
| 178 RawPcDescriptors::kIcCall | RawPcDescriptors::kUnoptStaticCall); | 175 RawPcDescriptors::kIcCall | RawPcDescriptors::kUnoptStaticCall); |
| 179 while (iter.MoveNext()) { | 176 while (iter.MoveNext()) { |
| 180 HANDLESCOPE(thread()); | 177 HANDLESCOPE(thread()); |
| 181 // TODO(zra): Remove this bailout once DBC has reliable ICData. | 178 // TODO(zra): Remove this bailout once DBC has reliable ICData. |
| 182 #if defined(TARGET_ARCH_DBC) | 179 #if defined(TARGET_ARCH_DBC) |
| 183 if (iter.DeoptId() >= ic_data_array->length()) { | 180 if (iter.DeoptId() >= ic_data_array->length()) { |
| 184 continue; | 181 continue; |
| 185 } | 182 } |
| 186 #else | 183 #else |
| 187 ASSERT(iter.DeoptId() < ic_data_array->length()); | 184 ASSERT(iter.DeoptId() < ic_data_array->length()); |
| 188 #endif | 185 #endif |
| 189 const ICData* ic_data = (*ic_data_array)[iter.DeoptId()]; | 186 const ICData* ic_data = (*ic_data_array)[iter.DeoptId()]; |
| 190 if (ic_data != NULL) { | 187 if (ic_data != NULL) { |
| 191 const TokenPosition token_pos = iter.TokenPos(); | 188 const TokenPosition token_pos = iter.TokenPos(); |
| 192 if ((token_pos < begin_pos) || (token_pos > end_pos)) { | 189 if ((token_pos < begin_pos) || (token_pos > end_pos)) { |
| 193 // Does not correspond to a valid source position. | 190 // Does not correspond to a valid source position. |
| 194 continue; | 191 continue; |
| 195 } | 192 } |
| 196 ic_data->PrintToJSONArray(sites, token_pos); | 193 ic_data->PrintToJSONArray(sites, token_pos); |
| 197 } | 194 } |
| 198 } | 195 } |
| 199 } | 196 } |
| 200 | 197 |
| 201 | 198 |
| 202 void SourceReport::PrintCoverageData(JSONObject* jsobj, | 199 void SourceReport::PrintCoverageData(JSONObject* jsobj, |
| 203 const Function& function, | 200 const Function& function, |
| 204 const Code& code) { | 201 const Code& code) { |
| 205 const TokenPosition begin_pos = function.token_pos(); | 202 const TokenPosition begin_pos = function.token_pos(); |
| 206 const TokenPosition end_pos = function.end_token_pos(); | 203 const TokenPosition end_pos = function.end_token_pos(); |
| 207 | 204 |
| 208 ZoneGrowableArray<const ICData*>* ic_data_array = | 205 ZoneGrowableArray<const ICData*>* ic_data_array = |
| 209 new(zone()) ZoneGrowableArray<const ICData*>(); | 206 new (zone()) ZoneGrowableArray<const ICData*>(); |
| 210 function.RestoreICDataMap(ic_data_array, false /* clone ic-data */); | 207 function.RestoreICDataMap(ic_data_array, false /* clone ic-data */); |
| 211 const PcDescriptors& descriptors = PcDescriptors::Handle( | 208 const PcDescriptors& descriptors = |
| 212 zone(), code.pc_descriptors()); | 209 PcDescriptors::Handle(zone(), code.pc_descriptors()); |
| 213 | 210 |
| 214 const int kCoverageNone = 0; | 211 const int kCoverageNone = 0; |
| 215 const int kCoverageMiss = 1; | 212 const int kCoverageMiss = 1; |
| 216 const int kCoverageHit = 2; | 213 const int kCoverageHit = 2; |
| 217 | 214 |
| 218 intptr_t func_length = (end_pos.Pos() - begin_pos.Pos()) + 1; | 215 intptr_t func_length = (end_pos.Pos() - begin_pos.Pos()) + 1; |
| 219 GrowableArray<char> coverage(func_length); | 216 GrowableArray<char> coverage(func_length); |
| 220 coverage.SetLength(func_length); | 217 coverage.SetLength(func_length); |
| 221 for (int i = 0; i < func_length; i++) { | 218 for (int i = 0; i < func_length; i++) { |
| 222 coverage[i] = kCoverageNone; | 219 coverage[i] = kCoverageNone; |
| 223 } | 220 } |
| 224 | 221 |
| 225 PcDescriptors::Iterator iter( | 222 PcDescriptors::Iterator iter( |
| 226 descriptors, | 223 descriptors, |
| 227 RawPcDescriptors::kIcCall | RawPcDescriptors::kUnoptStaticCall); | 224 RawPcDescriptors::kIcCall | RawPcDescriptors::kUnoptStaticCall); |
| 228 while (iter.MoveNext()) { | 225 while (iter.MoveNext()) { |
| 229 HANDLESCOPE(thread()); | 226 HANDLESCOPE(thread()); |
| 230 // TODO(zra): Remove this bailout once DBC has reliable ICData. | 227 // TODO(zra): Remove this bailout once DBC has reliable ICData. |
| 231 #if defined(TARGET_ARCH_DBC) | 228 #if defined(TARGET_ARCH_DBC) |
| 232 if (iter.DeoptId() >= ic_data_array->length()) { | 229 if (iter.DeoptId() >= ic_data_array->length()) { |
| 233 continue; | 230 continue; |
| 234 } | 231 } |
| 235 #else | 232 #else |
| 236 ASSERT(iter.DeoptId() < ic_data_array->length()); | 233 ASSERT(iter.DeoptId() < ic_data_array->length()); |
| 237 #endif | 234 #endif |
| 238 const ICData* ic_data = (*ic_data_array)[iter.DeoptId()]; | 235 const ICData* ic_data = (*ic_data_array)[iter.DeoptId()]; |
| 239 if (ic_data != NULL) { | 236 if (ic_data != NULL) { |
| 240 const TokenPosition token_pos = iter.TokenPos(); | 237 const TokenPosition token_pos = iter.TokenPos(); |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 272 misses.AddValue(begin_pos.Pos() + i); | 269 misses.AddValue(begin_pos.Pos() + i); |
| 273 } | 270 } |
| 274 } | 271 } |
| 275 } | 272 } |
| 276 } | 273 } |
| 277 | 274 |
| 278 | 275 |
| 279 void SourceReport::PrintPossibleBreakpointsData(JSONObject* jsobj, | 276 void SourceReport::PrintPossibleBreakpointsData(JSONObject* jsobj, |
| 280 const Function& func, | 277 const Function& func, |
| 281 const Code& code) { | 278 const Code& code) { |
| 282 const uint8_t kSafepointKind = (RawPcDescriptors::kIcCall | | 279 const uint8_t kSafepointKind = |
| 283 RawPcDescriptors::kUnoptStaticCall | | 280 (RawPcDescriptors::kIcCall | RawPcDescriptors::kUnoptStaticCall | |
| 284 RawPcDescriptors::kRuntimeCall); | 281 RawPcDescriptors::kRuntimeCall); |
| 285 const TokenPosition begin_pos = func.token_pos(); | 282 const TokenPosition begin_pos = func.token_pos(); |
| 286 const TokenPosition end_pos = func.end_token_pos(); | 283 const TokenPosition end_pos = func.end_token_pos(); |
| 287 | 284 |
| 288 const PcDescriptors& descriptors = PcDescriptors::Handle( | 285 const PcDescriptors& descriptors = |
| 289 zone(), code.pc_descriptors()); | 286 PcDescriptors::Handle(zone(), code.pc_descriptors()); |
| 290 | 287 |
| 291 intptr_t func_length = (end_pos.Pos() - begin_pos.Pos()) + 1; | 288 intptr_t func_length = (end_pos.Pos() - begin_pos.Pos()) + 1; |
| 292 GrowableArray<char> possible(func_length); | 289 GrowableArray<char> possible(func_length); |
| 293 possible.SetLength(func_length); | 290 possible.SetLength(func_length); |
| 294 for (int i = 0; i < func_length; i++) { | 291 for (int i = 0; i < func_length; i++) { |
| 295 possible[i] = false; | 292 possible[i] = false; |
| 296 } | 293 } |
| 297 | 294 |
| 298 PcDescriptors::Iterator iter(descriptors, kSafepointKind); | 295 PcDescriptors::Iterator iter(descriptors, kSafepointKind); |
| 299 while (iter.MoveNext()) { | 296 while (iter.MoveNext()) { |
| (...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 409 range.AddProperty("endPos", end_pos); | 406 range.AddProperty("endPos", end_pos); |
| 410 range.AddProperty("compiled", false); | 407 range.AddProperty("compiled", false); |
| 411 return; | 408 return; |
| 412 } | 409 } |
| 413 } | 410 } |
| 414 ASSERT(!code.IsNull()); | 411 ASSERT(!code.IsNull()); |
| 415 | 412 |
| 416 // We skip compiled async functions. Once an async function has | 413 // We skip compiled async functions. Once an async function has |
| 417 // been compiled, there is another function with the same range which | 414 // been compiled, there is another function with the same range which |
| 418 // actually contains the user code. | 415 // actually contains the user code. |
| 419 if (func.IsAsyncFunction() || | 416 if (func.IsAsyncFunction() || func.IsAsyncGenerator() || |
| 420 func.IsAsyncGenerator() || | |
| 421 func.IsSyncGenerator()) { | 417 func.IsSyncGenerator()) { |
| 422 return; | 418 return; |
| 423 } | 419 } |
| 424 | 420 |
| 425 JSONObject range(jsarr); | 421 JSONObject range(jsarr); |
| 426 range.AddProperty("scriptIndex", GetScriptIndex(script)); | 422 range.AddProperty("scriptIndex", GetScriptIndex(script)); |
| 427 range.AddProperty("startPos", begin_pos); | 423 range.AddProperty("startPos", begin_pos); |
| 428 range.AddProperty("endPos", end_pos); | 424 range.AddProperty("endPos", end_pos); |
| 429 range.AddProperty("compiled", true); | 425 range.AddProperty("compiled", true); |
| 430 | 426 |
| (...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 530 // Visit all closures for this isolate. | 526 // Visit all closures for this isolate. |
| 531 VisitClosures(&ranges); | 527 VisitClosures(&ranges); |
| 532 } | 528 } |
| 533 | 529 |
| 534 // Print the script table. | 530 // Print the script table. |
| 535 JSONArray scripts(&report, "scripts"); | 531 JSONArray scripts(&report, "scripts"); |
| 536 PrintScriptTable(&scripts); | 532 PrintScriptTable(&scripts); |
| 537 } | 533 } |
| 538 | 534 |
| 539 } // namespace dart | 535 } // namespace dart |
| OLD | NEW |