Chromium Code Reviews| 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 |