OLD | NEW |
1 // Copyright 2017 the V8 project authors. All rights reserved. | 1 // Copyright 2017 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "src/debug/debug-coverage.h" | 5 #include "src/debug/debug-coverage.h" |
6 | 6 |
7 #include "src/base/hashmap.h" | 7 #include "src/base/hashmap.h" |
8 #include "src/deoptimizer.h" | 8 #include "src/deoptimizer.h" |
9 #include "src/frames-inl.h" | 9 #include "src/frames-inl.h" |
10 #include "src/isolate.h" | 10 #include "src/isolate.h" |
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
114 | 114 |
115 // Iterate shared function infos of every script and build a mapping | 115 // Iterate shared function infos of every script and build a mapping |
116 // between source ranges and invocation counts. | 116 // between source ranges and invocation counts. |
117 Coverage* result = new Coverage(); | 117 Coverage* result = new Coverage(); |
118 Script::Iterator scripts(isolate); | 118 Script::Iterator scripts(isolate); |
119 while (Script* script = scripts.Next()) { | 119 while (Script* script = scripts.Next()) { |
120 if (!script->IsUserJavaScript()) continue; | 120 if (!script->IsUserJavaScript()) continue; |
121 | 121 |
122 // Create and add new script data. | 122 // Create and add new script data. |
123 Handle<Script> script_handle(script, isolate); | 123 Handle<Script> script_handle(script, isolate); |
124 result->emplace_back(isolate, script_handle); | 124 result->emplace_back(script_handle); |
125 std::vector<CoverageFunction>* functions = &result->back().functions; | 125 std::vector<CoverageFunction>* functions = &result->back().functions; |
126 | 126 |
127 std::vector<SharedFunctionInfo*> sorted; | 127 std::vector<SharedFunctionInfo*> sorted; |
128 | 128 |
129 { | 129 { |
130 // Sort functions by start position, from outer to inner functions. | 130 // Sort functions by start position, from outer to inner functions. |
131 SharedFunctionInfo::ScriptIterator infos(script_handle); | 131 SharedFunctionInfo::ScriptIterator infos(script_handle); |
132 while (SharedFunctionInfo* info = infos.Next()) { | 132 while (SharedFunctionInfo* info = infos.Next()) { |
133 sorted.push_back(info); | 133 sorted.push_back(info); |
134 } | 134 } |
135 std::sort(sorted.begin(), sorted.end(), CompareSharedFunctionInfo); | 135 std::sort(sorted.begin(), sorted.end(), CompareSharedFunctionInfo); |
136 } | 136 } |
137 | 137 |
| 138 // Stack to track nested functions, referring function by index. |
| 139 std::vector<size_t> nesting; |
| 140 |
138 // Use sorted list to reconstruct function nesting. | 141 // Use sorted list to reconstruct function nesting. |
139 for (SharedFunctionInfo* info : sorted) { | 142 for (SharedFunctionInfo* info : sorted) { |
140 int start = StartPosition(info); | 143 int start = StartPosition(info); |
141 int end = info->end_position(); | 144 int end = info->end_position(); |
142 uint32_t count = counter_map.Get(info); | 145 uint32_t count = counter_map.Get(info); |
| 146 // Find the correct outer function based on start position. |
| 147 while (!nesting.empty() && functions->at(nesting.back()).end <= start) { |
| 148 nesting.pop_back(); |
| 149 } |
143 if (count != 0) { | 150 if (count != 0) { |
144 switch (collectionMode) { | 151 switch (collectionMode) { |
145 case v8::debug::Coverage::kPreciseCount: | 152 case v8::debug::Coverage::kPreciseCount: |
146 break; | 153 break; |
147 case v8::debug::Coverage::kPreciseBinary: | 154 case v8::debug::Coverage::kPreciseBinary: |
148 count = info->has_reported_binary_coverage() ? 0 : 1; | 155 count = info->has_reported_binary_coverage() ? 0 : 1; |
149 info->set_has_reported_binary_coverage(true); | 156 info->set_has_reported_binary_coverage(true); |
150 break; | 157 break; |
151 case v8::debug::Coverage::kBestEffort: | 158 case v8::debug::Coverage::kBestEffort: |
152 count = 1; | 159 count = 1; |
153 break; | 160 break; |
154 } | 161 } |
| 162 } else if (nesting.empty() || functions->at(nesting.back()).count == 0) { |
| 163 // Only include a function range if it has a non-0 count, or |
| 164 // if it is directly nested inside a function with non-0 count. |
| 165 continue; |
155 } | 166 } |
156 Handle<String> name(info->DebugName(), isolate); | 167 Handle<String> name(info->DebugName(), isolate); |
| 168 nesting.push_back(functions->size()); |
157 functions->emplace_back(start, end, count, name); | 169 functions->emplace_back(start, end, count, name); |
158 } | 170 } |
| 171 |
| 172 // Remove entries for scripts that have no coverage. |
| 173 if (functions->empty()) result->pop_back(); |
159 } | 174 } |
160 return result; | 175 return result; |
161 } | 176 } |
162 | 177 |
163 void Coverage::SelectMode(Isolate* isolate, debug::Coverage::Mode mode) { | 178 void Coverage::SelectMode(Isolate* isolate, debug::Coverage::Mode mode) { |
164 switch (mode) { | 179 switch (mode) { |
165 case debug::Coverage::kBestEffort: | 180 case debug::Coverage::kBestEffort: |
166 isolate->SetCodeCoverageList(isolate->heap()->undefined_value()); | 181 isolate->SetCodeCoverageList(isolate->heap()->undefined_value()); |
167 break; | 182 break; |
168 case debug::Coverage::kPreciseBinary: | 183 case debug::Coverage::kPreciseBinary: |
(...skipping 25 matching lines...) Expand all Loading... |
194 for (const auto& vector : vectors) list = ArrayList::Add(list, vector); | 209 for (const auto& vector : vectors) list = ArrayList::Add(list, vector); |
195 isolate->SetCodeCoverageList(*list); | 210 isolate->SetCodeCoverageList(*list); |
196 break; | 211 break; |
197 } | 212 } |
198 } | 213 } |
199 isolate->set_code_coverage_mode(mode); | 214 isolate->set_code_coverage_mode(mode); |
200 } | 215 } |
201 | 216 |
202 } // namespace internal | 217 } // namespace internal |
203 } // namespace v8 | 218 } // namespace v8 |
OLD | NEW |