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/object.h" | 8 #include "vm/object.h" |
9 #include "vm/object_store.h" | 9 #include "vm/object_store.h" |
10 | 10 |
11 namespace dart { | 11 namespace dart { |
12 | 12 |
13 SourceReport::SourceReport(intptr_t report_set, CompileMode compile_mode) | 13 SourceReport::SourceReport(intptr_t report_set, CompileMode compile_mode) |
14 : report_set_(report_set), | 14 : report_set_(report_set), |
15 compile_mode_(compile_mode), | 15 compile_mode_(compile_mode), |
16 thread_(NULL), | 16 thread_(NULL), |
17 script_(NULL), | 17 script_(NULL), |
18 start_pos_(-1), | 18 start_pos_(TokenPosition::kNoSource), |
19 end_pos_(-1), | 19 end_pos_(TokenPosition::kNoSource), |
20 next_script_index_(0) { | 20 next_script_index_(0) { |
21 } | 21 } |
22 | 22 |
23 | 23 |
24 void SourceReport::Init(Thread* thread, | 24 void SourceReport::Init(Thread* thread, |
25 const Script* script, | 25 const Script* script, |
26 intptr_t start_pos, | 26 TokenPosition start_pos, |
27 intptr_t end_pos) { | 27 TokenPosition end_pos) { |
28 thread_ = thread; | 28 thread_ = thread; |
29 script_ = script; | 29 script_ = script; |
30 start_pos_ = start_pos; | 30 start_pos_ = start_pos; |
31 end_pos_ = end_pos; | 31 end_pos_ = end_pos; |
32 script_table_entries_.Clear(); | 32 script_table_entries_.Clear(); |
33 script_table_.Clear(); | 33 script_table_.Clear(); |
34 next_script_index_ = 0; | 34 next_script_index_ = 0; |
35 } | 35 } |
36 | 36 |
37 | 37 |
38 bool SourceReport::IsReportRequested(ReportKind report_kind) { | 38 bool SourceReport::IsReportRequested(ReportKind report_kind) { |
39 return (report_set_ & report_kind) != 0; | 39 return (report_set_ & report_kind) != 0; |
40 } | 40 } |
41 | 41 |
42 | 42 |
43 bool SourceReport::ShouldSkipFunction(const Function& func) { | 43 bool SourceReport::ShouldSkipFunction(const Function& func) { |
44 if (script_ != NULL && !script_->IsNull()) { | 44 if (script_ != NULL && !script_->IsNull()) { |
45 if (func.script() != script_->raw()) { | 45 if (func.script() != script_->raw()) { |
46 // The function is from the wrong script. | 46 // The function is from the wrong script. |
47 return true; | 47 return true; |
48 } | 48 } |
49 if (((start_pos_ > 0) && (func.end_token_pos() < start_pos_)) || | 49 if (((start_pos_ > TokenPosition::kMinSource) && |
50 ((end_pos_ > 0) && (func.token_pos() > end_pos_))) { | 50 (func.end_token_pos() < start_pos_)) || |
| 51 ((end_pos_ > TokenPosition::kMinSource) && |
| 52 (func.token_pos() > end_pos_))) { |
51 // The function does not intersect with the requested token range. | 53 // The function does not intersect with the requested token range. |
52 return true; | 54 return true; |
53 } | 55 } |
54 } | 56 } |
55 | 57 |
56 switch (func.kind()) { | 58 switch (func.kind()) { |
57 case RawFunction::kRegularFunction: | 59 case RawFunction::kRegularFunction: |
58 case RawFunction::kClosureFunction: | 60 case RawFunction::kClosureFunction: |
59 case RawFunction::kGetterFunction: | 61 case RawFunction::kGetterFunction: |
60 case RawFunction::kSetterFunction: | 62 case RawFunction::kSetterFunction: |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
104 return true; | 106 return true; |
105 } | 107 } |
106 } | 108 } |
107 return false; | 109 return false; |
108 } | 110 } |
109 | 111 |
110 | 112 |
111 void SourceReport::PrintCallSitesData(JSONObject* jsobj, | 113 void SourceReport::PrintCallSitesData(JSONObject* jsobj, |
112 const Function& func, | 114 const Function& func, |
113 const Code& code) { | 115 const Code& code) { |
114 const intptr_t begin_pos = func.token_pos(); | 116 const TokenPosition begin_pos = func.token_pos(); |
115 const intptr_t end_pos = func.end_token_pos(); | 117 const TokenPosition end_pos = func.end_token_pos(); |
116 | 118 |
117 ZoneGrowableArray<const ICData*>* ic_data_array = | 119 ZoneGrowableArray<const ICData*>* ic_data_array = |
118 new(zone()) ZoneGrowableArray<const ICData*>(); | 120 new(zone()) ZoneGrowableArray<const ICData*>(); |
119 func.RestoreICDataMap(ic_data_array, false /* clone descriptors */); | 121 func.RestoreICDataMap(ic_data_array, false /* clone descriptors */); |
120 const PcDescriptors& descriptors = PcDescriptors::Handle( | 122 const PcDescriptors& descriptors = PcDescriptors::Handle( |
121 zone(), code.pc_descriptors()); | 123 zone(), code.pc_descriptors()); |
122 | 124 |
123 JSONArray sites(jsobj, "callSites"); | 125 JSONArray sites(jsobj, "callSites"); |
124 | 126 |
125 PcDescriptors::Iterator iter( | 127 PcDescriptors::Iterator iter( |
126 descriptors, | 128 descriptors, |
127 RawPcDescriptors::kIcCall | RawPcDescriptors::kUnoptStaticCall); | 129 RawPcDescriptors::kIcCall | RawPcDescriptors::kUnoptStaticCall); |
128 while (iter.MoveNext()) { | 130 while (iter.MoveNext()) { |
129 HANDLESCOPE(thread()); | 131 HANDLESCOPE(thread()); |
130 const ICData* ic_data = (*ic_data_array)[iter.DeoptId()]; | 132 const ICData* ic_data = (*ic_data_array)[iter.DeoptId()]; |
131 if (!ic_data->IsNull()) { | 133 if (!ic_data->IsNull()) { |
132 const intptr_t token_pos = iter.TokenPos(); | 134 const TokenPosition token_pos = iter.TokenPos(); |
133 if ((token_pos < begin_pos) || (token_pos > end_pos)) { | 135 if ((token_pos < begin_pos) || (token_pos > end_pos)) { |
134 // Does not correspond to a valid source position. | 136 // Does not correspond to a valid source position. |
135 continue; | 137 continue; |
136 } | 138 } |
137 bool is_static_call = iter.Kind() == RawPcDescriptors::kUnoptStaticCall; | 139 bool is_static_call = iter.Kind() == RawPcDescriptors::kUnoptStaticCall; |
138 ic_data->PrintToJSONArrayNew(sites, token_pos, is_static_call); | 140 ic_data->PrintToJSONArrayNew(sites, token_pos, is_static_call); |
139 } | 141 } |
140 } | 142 } |
141 } | 143 } |
142 | 144 |
143 void SourceReport::PrintCoverageData(JSONObject* jsobj, | 145 void SourceReport::PrintCoverageData(JSONObject* jsobj, |
144 const Function& func, | 146 const Function& func, |
145 const Code& code) { | 147 const Code& code) { |
146 const intptr_t begin_pos = func.token_pos(); | 148 const TokenPosition begin_pos = func.token_pos(); |
147 const intptr_t end_pos = func.end_token_pos(); | 149 const TokenPosition end_pos = func.end_token_pos(); |
148 | 150 |
149 ZoneGrowableArray<const ICData*>* ic_data_array = | 151 ZoneGrowableArray<const ICData*>* ic_data_array = |
150 new(zone()) ZoneGrowableArray<const ICData*>(); | 152 new(zone()) ZoneGrowableArray<const ICData*>(); |
151 func.RestoreICDataMap(ic_data_array, false /* clone descriptors */); | 153 func.RestoreICDataMap(ic_data_array, false /* clone descriptors */); |
152 const PcDescriptors& descriptors = PcDescriptors::Handle( | 154 const PcDescriptors& descriptors = PcDescriptors::Handle( |
153 zone(), code.pc_descriptors()); | 155 zone(), code.pc_descriptors()); |
154 | 156 |
155 const int kCoverageNone = 0; | 157 const int kCoverageNone = 0; |
156 const int kCoverageMiss = 1; | 158 const int kCoverageMiss = 1; |
157 const int kCoverageHit = 2; | 159 const int kCoverageHit = 2; |
158 | 160 |
159 intptr_t func_length = (end_pos - begin_pos) + 1; | 161 intptr_t func_length = (end_pos.Pos() - begin_pos.Pos()) + 1; |
160 GrowableArray<char> coverage(func_length); | 162 GrowableArray<char> coverage(func_length); |
161 coverage.SetLength(func_length); | 163 coverage.SetLength(func_length); |
162 for (int i = 0; i < func_length; i++) { | 164 for (int i = 0; i < func_length; i++) { |
163 coverage[i] = kCoverageNone; | 165 coverage[i] = kCoverageNone; |
164 } | 166 } |
165 | 167 |
166 PcDescriptors::Iterator iter( | 168 PcDescriptors::Iterator iter( |
167 descriptors, | 169 descriptors, |
168 RawPcDescriptors::kIcCall | RawPcDescriptors::kUnoptStaticCall); | 170 RawPcDescriptors::kIcCall | RawPcDescriptors::kUnoptStaticCall); |
169 while (iter.MoveNext()) { | 171 while (iter.MoveNext()) { |
170 HANDLESCOPE(thread()); | 172 HANDLESCOPE(thread()); |
171 const ICData* ic_data = (*ic_data_array)[iter.DeoptId()]; | 173 const ICData* ic_data = (*ic_data_array)[iter.DeoptId()]; |
172 if (!ic_data->IsNull()) { | 174 if (!ic_data->IsNull()) { |
173 const intptr_t token_pos = iter.TokenPos(); | 175 const TokenPosition token_pos = iter.TokenPos(); |
174 if ((token_pos < begin_pos) || (token_pos > end_pos)) { | 176 if ((token_pos < begin_pos) || (token_pos > end_pos)) { |
175 // Does not correspond to a valid source position. | 177 // Does not correspond to a valid source position. |
176 continue; | 178 continue; |
177 } | 179 } |
178 intptr_t count = ic_data->AggregateCount(); | 180 intptr_t count = ic_data->AggregateCount(); |
179 intptr_t token_offset = token_pos - begin_pos; | 181 intptr_t token_offset = token_pos.Pos() - begin_pos.Pos(); |
180 if (count > 0) { | 182 if (count > 0) { |
181 coverage[token_offset] = kCoverageHit; | 183 coverage[token_offset] = kCoverageHit; |
182 } else { | 184 } else { |
183 if (coverage[token_offset] == kCoverageNone) { | 185 if (coverage[token_offset] == kCoverageNone) { |
184 coverage[token_offset] = kCoverageMiss; | 186 coverage[token_offset] = kCoverageMiss; |
185 } | 187 } |
186 } | 188 } |
187 } | 189 } |
188 } | 190 } |
189 | 191 |
190 JSONObject cov(jsobj, "coverage"); | 192 JSONObject cov(jsobj, "coverage"); |
191 { | 193 { |
192 JSONArray hits(&cov, "hits"); | 194 JSONArray hits(&cov, "hits"); |
193 for (int i = 0; i < func_length; i++) { | 195 for (int i = 0; i < func_length; i++) { |
194 if (coverage[i] == kCoverageHit) { | 196 if (coverage[i] == kCoverageHit) { |
195 hits.AddValue(begin_pos + i); // Add the token position of the hit. | 197 // Add the token position of the hit. |
| 198 hits.AddValue(begin_pos.Pos() + i); |
196 } | 199 } |
197 } | 200 } |
198 } | 201 } |
199 { | 202 { |
200 JSONArray misses(&cov, "misses"); | 203 JSONArray misses(&cov, "misses"); |
201 for (int i = 0; i < func_length; i++) { | 204 for (int i = 0; i < func_length; i++) { |
202 if (coverage[i] == kCoverageMiss) { | 205 if (coverage[i] == kCoverageMiss) { |
203 misses.AddValue(begin_pos + i); // Add the token position of the miss. | 206 // Add the token position of the miss. |
| 207 misses.AddValue(begin_pos.Pos() + i); |
204 } | 208 } |
205 } | 209 } |
206 } | 210 } |
207 } | 211 } |
208 | 212 |
209 void SourceReport::PrintPossibleBreakpointsData(JSONObject* jsobj, | 213 void SourceReport::PrintPossibleBreakpointsData(JSONObject* jsobj, |
210 const Function& func, | 214 const Function& func, |
211 const Code& code) { | 215 const Code& code) { |
212 const uint8_t kSafepointKind = (RawPcDescriptors::kIcCall | | 216 const uint8_t kSafepointKind = (RawPcDescriptors::kIcCall | |
213 RawPcDescriptors::kUnoptStaticCall | | 217 RawPcDescriptors::kUnoptStaticCall | |
214 RawPcDescriptors::kRuntimeCall); | 218 RawPcDescriptors::kRuntimeCall); |
215 const intptr_t begin_pos = func.token_pos(); | 219 const TokenPosition begin_pos = func.token_pos(); |
216 const intptr_t end_pos = func.end_token_pos(); | 220 const TokenPosition end_pos = func.end_token_pos(); |
217 | 221 |
218 const PcDescriptors& descriptors = PcDescriptors::Handle( | 222 const PcDescriptors& descriptors = PcDescriptors::Handle( |
219 zone(), code.pc_descriptors()); | 223 zone(), code.pc_descriptors()); |
220 | 224 |
221 intptr_t func_length = (end_pos - begin_pos) + 1; | 225 intptr_t func_length = (end_pos.Pos() - begin_pos.Pos()) + 1; |
222 GrowableArray<char> possible(func_length); | 226 GrowableArray<char> possible(func_length); |
223 possible.SetLength(func_length); | 227 possible.SetLength(func_length); |
224 for (int i = 0; i < func_length; i++) { | 228 for (int i = 0; i < func_length; i++) { |
225 possible[i] = false; | 229 possible[i] = false; |
226 } | 230 } |
227 | 231 |
228 PcDescriptors::Iterator iter(descriptors, kSafepointKind); | 232 PcDescriptors::Iterator iter(descriptors, kSafepointKind); |
229 while (iter.MoveNext()) { | 233 while (iter.MoveNext()) { |
230 const intptr_t token_pos = iter.TokenPos(); | 234 const TokenPosition token_pos = iter.TokenPos(); |
231 if ((token_pos < begin_pos) || (token_pos > end_pos)) { | 235 if ((token_pos < begin_pos) || (token_pos > end_pos)) { |
232 // Does not correspond to a valid source position. | 236 // Does not correspond to a valid source position. |
233 continue; | 237 continue; |
234 } | 238 } |
235 intptr_t token_offset = token_pos - begin_pos; | 239 intptr_t token_offset = token_pos.Pos() - begin_pos.Pos(); |
236 possible[token_offset] = true; | 240 possible[token_offset] = true; |
237 } | 241 } |
238 | 242 |
239 JSONArray bpts(jsobj, "possibleBreakpoints"); | 243 JSONArray bpts(jsobj, "possibleBreakpoints"); |
240 for (int i = 0; i < func_length; i++) { | 244 for (int i = 0; i < func_length; i++) { |
241 if (possible[i]) { | 245 if (possible[i]) { |
242 bpts.AddValue(begin_pos + i); // Add the token position. | 246 // Add the token position. |
| 247 bpts.AddValue(begin_pos.Pos() + i); |
243 } | 248 } |
244 } | 249 } |
245 } | 250 } |
246 | 251 |
247 | 252 |
248 void SourceReport::PrintScriptTable(JSONArray* scripts) { | 253 void SourceReport::PrintScriptTable(JSONArray* scripts) { |
249 for (int i = 0; i < script_table_entries_.length(); i++) { | 254 for (int i = 0; i < script_table_entries_.length(); i++) { |
250 const Script* script = script_table_entries_[i].script; | 255 const Script* script = script_table_entries_[i].script; |
251 scripts->AddValue(*script); | 256 scripts->AddValue(*script); |
252 } | 257 } |
253 } | 258 } |
254 | 259 |
255 | 260 |
256 void SourceReport::VisitFunction(JSONArray* jsarr, const Function& func) { | 261 void SourceReport::VisitFunction(JSONArray* jsarr, const Function& func) { |
257 if (ShouldSkipFunction(func)) { | 262 if (ShouldSkipFunction(func)) { |
258 return; | 263 return; |
259 } | 264 } |
260 | 265 |
261 const Script& script = Script::Handle(zone(), func.script()); | 266 const Script& script = Script::Handle(zone(), func.script()); |
262 const intptr_t begin_pos = func.token_pos(); | 267 const TokenPosition begin_pos = func.token_pos(); |
263 const intptr_t end_pos = func.end_token_pos(); | 268 const TokenPosition end_pos = func.end_token_pos(); |
264 | 269 |
265 Code& code = Code::Handle(zone(), func.unoptimized_code()); | 270 Code& code = Code::Handle(zone(), func.unoptimized_code()); |
266 if (code.IsNull()) { | 271 if (code.IsNull()) { |
267 if (func.HasCode() || (compile_mode_ == kForceCompile)) { | 272 if (func.HasCode() || (compile_mode_ == kForceCompile)) { |
268 if (Compiler::EnsureUnoptimizedCode(thread(), func) != Error::null()) { | 273 if (Compiler::EnsureUnoptimizedCode(thread(), func) != Error::null()) { |
269 // Ignore the error and this function entirely. | 274 // Ignore the error and this function entirely. |
270 return; | 275 return; |
271 } | 276 } |
272 code = func.unoptimized_code(); | 277 code = func.unoptimized_code(); |
273 } else { | 278 } else { |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
334 Function& func = Function::Handle(zone()); | 339 Function& func = Function::Handle(zone()); |
335 for (int i = 0; i < closures.Length(); i++) { | 340 for (int i = 0; i < closures.Length(); i++) { |
336 func ^= closures.At(i); | 341 func ^= closures.At(i); |
337 VisitFunction(jsarr, func); | 342 VisitFunction(jsarr, func); |
338 } | 343 } |
339 } | 344 } |
340 | 345 |
341 | 346 |
342 void SourceReport::PrintJSON(JSONStream* js, | 347 void SourceReport::PrintJSON(JSONStream* js, |
343 const Script& script, | 348 const Script& script, |
344 intptr_t start_pos, intptr_t end_pos) { | 349 TokenPosition start_pos, |
| 350 TokenPosition end_pos) { |
345 Init(Thread::Current(), &script, start_pos, end_pos); | 351 Init(Thread::Current(), &script, start_pos, end_pos); |
346 | 352 |
347 JSONObject report(js); | 353 JSONObject report(js); |
348 report.AddProperty("type", "SourceReport"); | 354 report.AddProperty("type", "SourceReport"); |
349 { | 355 { |
350 JSONArray ranges(&report, "ranges"); | 356 JSONArray ranges(&report, "ranges"); |
351 | 357 |
352 const GrowableObjectArray& libs = GrowableObjectArray::Handle( | 358 const GrowableObjectArray& libs = GrowableObjectArray::Handle( |
353 zone(), thread()->isolate()->object_store()->libraries()); | 359 zone(), thread()->isolate()->object_store()->libraries()); |
354 | 360 |
(...skipping 10 matching lines...) Expand all Loading... |
365 VisitClosures(&ranges); | 371 VisitClosures(&ranges); |
366 } | 372 } |
367 | 373 |
368 // Print the script table. | 374 // Print the script table. |
369 JSONArray scripts(&report, "scripts"); | 375 JSONArray scripts(&report, "scripts"); |
370 PrintScriptTable(&scripts); | 376 PrintScriptTable(&scripts); |
371 } | 377 } |
372 | 378 |
373 | 379 |
374 } // namespace dart | 380 } // namespace dart |
OLD | NEW |