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 |