OLD | NEW |
---|---|
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, 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/coverage.h" | 5 #include "vm/coverage.h" |
6 | 6 |
7 #include "include/dart_api.h" | |
siva
2013/09/20 19:51:45
Most of our files seem to have a blank line betwee
Ivan Posva
2013/09/20 21:37:07
Done.
| |
7 #include "vm/isolate.h" | 8 #include "vm/isolate.h" |
8 #include "vm/json_stream.h" | 9 #include "vm/json_stream.h" |
9 #include "vm/object.h" | 10 #include "vm/object.h" |
10 #include "vm/object_store.h" | 11 #include "vm/object_store.h" |
11 | 12 |
12 namespace dart { | 13 namespace dart { |
13 | 14 |
14 DEFINE_FLAG(bool, print_coverage, false, "Print code coverage."); | 15 DEFINE_FLAG(charp, coverage_dir, NULL, |
16 "Enable writing coverage data into specified directory."); | |
15 | 17 |
16 void CodeCoverage::PrintClass(const Class& cls, const JSONArray& jsarr) { | 18 void CodeCoverage::PrintClass(const Class& cls, const JSONArray& jsarr) { |
17 const Array& functions = Array::Handle(cls.functions()); | 19 const Array& functions = Array::Handle(cls.functions()); |
18 ASSERT(!functions.IsNull()); | 20 ASSERT(!functions.IsNull()); |
19 Function& function = Function::Handle(); | 21 Function& function = Function::Handle(); |
20 Code& code = Code::Handle(); | 22 Code& code = Code::Handle(); |
21 Script& script = Script::Handle(); | 23 Script& script = Script::Handle(); |
22 String& url = String::Handle(); | 24 String& url = String::Handle(); |
23 String& name = String::Handle(); | 25 String& name = String::Handle(); |
24 PcDescriptors& descriptors = PcDescriptors::Handle(); | 26 PcDescriptors& descriptors = PcDescriptors::Handle(); |
25 Array& ic_array = Array::Handle(); | 27 Array& ic_array = Array::Handle(); |
26 ICData& ic_data = ICData::Handle(); | 28 ICData& ic_data = ICData::Handle(); |
27 for (int i = 0; i < functions.Length(); i++) { | 29 for (int i = 0; i < functions.Length(); i++) { |
28 function ^= functions.At(i); | 30 function ^= functions.At(i); |
31 | |
32 JSONObject jsobj(&jsarr); | |
33 script = function.script(); | |
34 url = script.url(); | |
35 name = function.QualifiedUserVisibleName(); | |
36 jsobj.AddProperty("source", url.ToCString()); | |
37 jsobj.AddProperty("function", name.ToCString()); | |
Michael Lippautz (Google)
2013/09/20 21:24:56
Any reason for keeping the function name? Thought
Ivan Posva
2013/09/20 21:37:07
Redoing the coverage data file will come in a diff
| |
38 | |
39 JSONArray jsarr(&jsobj, "hits"); | |
40 | |
29 if (function.HasCode()) { | 41 if (function.HasCode()) { |
30 JSONObject jsobj(&jsarr); | 42 // Print the hit counts for all IC datas. |
31 | |
32 script = function.script(); | |
33 url = script.url(); | |
34 name = function.QualifiedUserVisibleName(); | |
35 jsobj.AddProperty("source", url.ToCString()); | |
36 jsobj.AddProperty("function", name.ToCString()); | |
37 | |
38 code = function.unoptimized_code(); | 43 code = function.unoptimized_code(); |
39 ic_array = code.ExtractTypeFeedbackArray(); | 44 ic_array = code.ExtractTypeFeedbackArray(); |
40 descriptors = code.pc_descriptors(); | 45 descriptors = code.pc_descriptors(); |
41 | 46 |
42 JSONArray jsarr(&jsobj, "hits"); | |
43 for (int j = 0; j < descriptors.Length(); j++) { | 47 for (int j = 0; j < descriptors.Length(); j++) { |
44 PcDescriptors::Kind kind = descriptors.DescriptorKind(j); | 48 PcDescriptors::Kind kind = descriptors.DescriptorKind(j); |
45 // Only IC based calls have counting. | 49 // Only IC based calls have counting. |
46 if ((kind == PcDescriptors::kIcCall) || | 50 if ((kind == PcDescriptors::kIcCall) || |
47 (kind == PcDescriptors::kUnoptStaticCall)) { | 51 (kind == PcDescriptors::kUnoptStaticCall)) { |
48 intptr_t deopt_id = descriptors.DeoptId(j); | 52 intptr_t deopt_id = descriptors.DeoptId(j); |
49 ic_data ^= ic_array.At(deopt_id); | 53 ic_data ^= ic_array.At(deopt_id); |
50 if (!ic_data.IsNull() && (ic_data.AggregateCount() > 0)) { | 54 if (!ic_data.IsNull()) { |
51 intptr_t token_pos = descriptors.TokenPos(j); | 55 intptr_t token_pos = descriptors.TokenPos(j); |
52 intptr_t line = -1; | 56 intptr_t line = -1; |
53 intptr_t col = -1; | 57 intptr_t col = -1; |
54 script.GetTokenLocation(token_pos, &line, &col); | 58 script.GetTokenLocation(token_pos, &line, &col); |
55 JSONObject ic_info(&jsarr); | 59 JSONObject ic_info(&jsarr); |
56 ic_info.AddProperty("line", line); | 60 ic_info.AddProperty("line", line); |
57 ic_info.AddProperty("col", col); | 61 ic_info.AddProperty("col", col); |
58 ic_info.AddProperty("count", ic_data.AggregateCount()); | 62 ic_info.AddProperty("count", ic_data.AggregateCount()); |
59 } | 63 } |
60 } | 64 } |
61 } | 65 } |
66 } else { | |
67 // The function has no code so it was never executed and thus we add one | |
68 // zero count hit at the first token index. | |
69 intptr_t line = -1; | |
70 intptr_t col = -1; | |
71 script.GetTokenLocation(function.token_pos(), &line, &col); | |
72 JSONObject func_info(&jsarr); | |
73 func_info.AddProperty("line", line); | |
74 func_info.AddProperty("col", col); | |
75 func_info.AddProperty("count", static_cast<intptr_t>(0)); | |
62 } | 76 } |
63 } | 77 } |
64 } | 78 } |
65 | 79 |
66 | 80 |
67 void CodeCoverage::Print(Isolate* isolate) { | 81 void CodeCoverage::Write(Isolate* isolate) { |
82 if (FLAG_coverage_dir == NULL) { | |
83 return; | |
84 } | |
85 | |
86 Dart_FileOpenCallback file_open = Isolate::file_open_callback(); | |
87 Dart_FileWriteCallback file_write = Isolate::file_write_callback(); | |
88 Dart_FileCloseCallback file_close = Isolate::file_close_callback(); | |
89 if ((file_open == NULL) || (file_write == NULL) || (file_close == NULL)) { | |
90 return; | |
91 } | |
92 | |
68 JSONStream stream; | 93 JSONStream stream; |
69 | |
70 { | 94 { |
71 const GrowableObjectArray& libs = GrowableObjectArray::Handle( | 95 const GrowableObjectArray& libs = GrowableObjectArray::Handle( |
72 isolate, isolate->object_store()->libraries()); | 96 isolate, isolate->object_store()->libraries()); |
73 Library& lib = Library::Handle(); | 97 Library& lib = Library::Handle(); |
74 Class& cls = Class::Handle(); | 98 Class& cls = Class::Handle(); |
75 JSONArray jsarr(&stream); | 99 JSONArray jsarr(&stream); |
76 for (int i = 0; i < libs.Length(); i++) { | 100 for (int i = 0; i < libs.Length(); i++) { |
77 lib ^= libs.At(i); | 101 lib ^= libs.At(i); |
78 ClassDictionaryIterator it(lib, ClassDictionaryIterator::kIteratePrivate); | 102 ClassDictionaryIterator it(lib, ClassDictionaryIterator::kIteratePrivate); |
79 while (it.HasNext()) { | 103 while (it.HasNext()) { |
80 cls = it.GetNextClass(); | 104 cls = it.GetNextClass(); |
81 if (cls.is_finalized()) { | 105 if (cls.is_finalized()) { |
82 // Only classes that have been finalized do have a meaningful list of | 106 // Only classes that have been finalized do have a meaningful list of |
83 // functions. | 107 // functions. |
84 PrintClass(cls, jsarr); | 108 PrintClass(cls, jsarr); |
85 } | 109 } |
86 } | 110 } |
87 } | 111 } |
88 } | 112 } |
89 | 113 |
90 OS::Print("### COVERAGE DATA ###\n" | 114 const char* format = "%s/dart-cov-%"Pd"-%"Pd".json"; |
91 "%s\n" | 115 intptr_t pid = OS::ProcessId(); |
92 "### END ###\n", stream.ToCString()); | 116 intptr_t len = OS::SNPrint(NULL, 0, format, |
117 FLAG_coverage_dir, pid, isolate->main_port()); | |
118 char* filename = Isolate::Current()->current_zone()->Alloc<char>(len + 1);; | |
siva
2013/09/20 19:51:45
double semi colon
Ivan Posva
2013/09/20 21:37:07
Done.
| |
119 OS::SNPrint(filename, len + 1, format, | |
120 FLAG_coverage_dir, pid, isolate->main_port()); | |
121 void* file = (*file_open)(filename, true); | |
122 if (file == NULL) { | |
123 OS::Print("Failed to write coverage file: %s\n", filename); | |
124 return; | |
125 } | |
126 (*file_write)(stream.buffer()->buf(), stream.buffer()->length(), file); | |
127 (*file_close)(file); | |
93 } | 128 } |
94 | 129 |
95 } // namespace dart | 130 } // namespace dart |
OLD | NEW |