Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(276)

Side by Side Diff: src/debug/debug-coverage.cc

Issue 2694623003: [debugger] change coverage format to nested, with function name. (Closed)
Patch Set: address comments Created 3 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/debug/debug-coverage.h ('k') | src/runtime/runtime-debug.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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/isolate.h" 9 #include "src/isolate.h"
10 #include "src/objects-inl.h" 10 #include "src/objects-inl.h"
(...skipping 21 matching lines...) Expand all
32 inline uint32_t Get(SharedFunctionInfo* key) { 32 inline uint32_t Get(SharedFunctionInfo* key) {
33 Entry* entry = Lookup(key, Hash(key)); 33 Entry* entry = Lookup(key, Hash(key));
34 if (entry == nullptr) return 0; 34 if (entry == nullptr) return 0;
35 return entry->value; 35 return entry->value;
36 } 36 }
37 37
38 private: 38 private:
39 static uint32_t Hash(SharedFunctionInfo* key) { 39 static uint32_t Hash(SharedFunctionInfo* key) {
40 return static_cast<uint32_t>(reinterpret_cast<intptr_t>(key)); 40 return static_cast<uint32_t>(reinterpret_cast<intptr_t>(key));
41 } 41 }
42 };
43 42
44 class ScriptDataBuilder { 43 DisallowHeapAllocation no_gc;
45 public:
46 void Add(int end_position, uint32_t count) {
47 DCHECK(entries_.empty() || entries_.back().end_position <= end_position);
48 if (entries_.empty()) {
49 if (end_position > 0) entries_.push_back({end_position, count});
50 } else if (entries_.back().count == count) {
51 // Extend last range.
52 entries_.back().end_position = end_position;
53 } else if (entries_.back().end_position < end_position) {
54 // Add new range.
55 entries_.push_back({end_position, count});
56 }
57 }
58 std::vector<Coverage::RangeEntry> Finish() {
59 std::vector<Coverage::RangeEntry> result;
60 std::swap(result, entries_);
61 return result;
62 }
63
64 private:
65 std::vector<Coverage::RangeEntry> entries_;
66 }; 44 };
67 45
68 std::vector<Coverage::ScriptData> Coverage::Collect(Isolate* isolate) { 46 std::vector<Coverage::ScriptData> Coverage::Collect(Isolate* isolate) {
69 SharedToCounterMap counter_map; 47 SharedToCounterMap counter_map;
70 48
71 if (isolate->IsCodeCoverageEnabled()) { 49 if (isolate->IsCodeCoverageEnabled()) {
72 // Feedback vectors are already listed to prevent losing them to GC. 50 // Feedback vectors are already listed to prevent losing them to GC.
73 Handle<ArrayList> list = 51 Handle<ArrayList> list =
74 Handle<ArrayList>::cast(isolate->factory()->code_coverage_list()); 52 Handle<ArrayList>::cast(isolate->factory()->code_coverage_list());
75 for (int i = 0; i < list->Length(); i++) { 53 for (int i = 0; i < list->Length(); i++) {
(...skipping 16 matching lines...) Expand all
92 SharedFunctionInfo* shared = vector->shared_function_info(); 70 SharedFunctionInfo* shared = vector->shared_function_info();
93 if (!shared->IsSubjectToDebugging()) continue; 71 if (!shared->IsSubjectToDebugging()) continue;
94 uint32_t count = static_cast<uint32_t>(vector->invocation_count()); 72 uint32_t count = static_cast<uint32_t>(vector->invocation_count());
95 counter_map.Add(shared, count); 73 counter_map.Add(shared, count);
96 } 74 }
97 } 75 }
98 76
99 // Make sure entries in the counter map is not invalidated by GC. 77 // Make sure entries in the counter map is not invalidated by GC.
100 DisallowHeapAllocation no_gc; 78 DisallowHeapAllocation no_gc;
101 79
102 // Stack to track nested functions. 80 std::vector<Range*> stack;
103 struct FunctionNode {
104 FunctionNode(int s, int e, uint32_t c) : start(s), end(e), count(c) {}
105 int start;
106 int end;
107 uint32_t count;
108 };
109 std::vector<FunctionNode> stack;
110 81
111 // Iterate shared function infos of every script and build a mapping 82 // Iterate shared function infos of every script and build a mapping
112 // between source ranges and invocation counts. 83 // between source ranges and invocation counts.
113 std::vector<Coverage::ScriptData> result; 84 std::vector<Coverage::ScriptData> result;
114 Script::Iterator scripts(isolate); 85 Script::Iterator scripts(isolate);
115 while (Script* script = scripts.Next()) { 86 while (Script* script = scripts.Next()) {
116 // Dismiss non-user scripts. 87 // Dismiss non-user scripts.
117 if (script->type() != Script::TYPE_NORMAL) continue; 88 if (script->type() != Script::TYPE_NORMAL) continue;
118 DCHECK(stack.empty()); 89 DCHECK(stack.empty());
119 int script_end = String::cast(script->source())->length(); 90 int source_length = String::cast(script->source())->length();
120 // If not rooted, the top-level function is likely no longer alive. Set the 91 result.emplace_back(Handle<Script>(script, isolate), source_length);
121 // outer-most count to 1 to indicate that the script has run at least once. 92 stack.push_back(&result.back().toplevel);
122 stack.push_back({0, script_end, 1});
123 ScriptDataBuilder builder;
124 // Iterate through the list of shared function infos, reconstruct the 93 // Iterate through the list of shared function infos, reconstruct the
125 // nesting, and compute the ranges covering different invocation counts. 94 // nesting, and compute the ranges covering different invocation counts.
126 HandleScope scope(isolate); 95 HandleScope scope(isolate);
127 SharedFunctionInfo::ScriptIterator infos(Handle<Script>(script, isolate)); 96 SharedFunctionInfo::ScriptIterator infos(Handle<Script>(script, isolate));
128 while (SharedFunctionInfo* info = infos.Next()) { 97 while (SharedFunctionInfo* info = infos.Next()) {
129 int start = info->function_token_position(); 98 int start = info->function_token_position();
130 if (start == kNoSourcePosition) start = info->start_position(); 99 if (start == kNoSourcePosition) start = info->start_position();
131 int end = info->end_position(); 100 int end = info->end_position();
132 uint32_t count = counter_map.Get(info); 101 uint32_t count = counter_map.Get(info);
133 // The shared function infos are sorted by start. 102 if (info->is_toplevel()) {
134 DCHECK_LE(stack.back().start, start); 103 // Top-level function is available.
135 // If the start are the same, the outer function comes before the inner. 104 DCHECK_EQ(1, stack.size());
136 DCHECK(stack.back().start < start || stack.back().end >= end); 105 result.back().toplevel.start = start;
137 // Drop the stack to the outer function. 106 result.back().toplevel.end = end;
138 while (start > stack.back().end) { 107 result.back().toplevel.count = count;
139 // Write out rest of function being dropped. 108 } else {
140 builder.Add(stack.back().end, stack.back().count); 109 // The shared function infos are sorted by start.
141 stack.pop_back(); 110 DCHECK_LE(stack.back()->start, start);
111 // Drop the stack to the outer function.
112 while (start > stack.back()->end) stack.pop_back();
113 Range* outer = stack.back();
114 // New nested function.
115 DCHECK_LE(end, outer->end);
116 outer->inner.emplace_back(start, end, count);
117 Range& nested = outer->inner.back();
118 String* name = info->DebugName();
119 nested.name.resize(name->length());
120 String::WriteToFlat(name, nested.name.data(), 0, name->length());
121 stack.push_back(&nested);
142 } 122 }
143 // Write out outer function up to the start of new function.
144 builder.Add(start, stack.back().count);
145 // New nested function.
146 DCHECK_LE(end, stack.back().end);
147 stack.emplace_back(start, end, count);
148 } 123 }
149 124 stack.clear();
150 // Drop the stack to the script level.
151 while (!stack.empty()) {
152 // Write out rest of function being dropped.
153 builder.Add(stack.back().end, stack.back().count);
154 stack.pop_back();
155 }
156 result.emplace_back(script->id(), builder.Finish());
157 } 125 }
158 return result; 126 return result;
159 } 127 }
160 128
161 void Coverage::EnablePrecise(Isolate* isolate) { 129 void Coverage::EnablePrecise(Isolate* isolate) {
162 HandleScope scope(isolate); 130 HandleScope scope(isolate);
163 // Remove all optimized function. Optimized and inlined functions do not 131 // Remove all optimized function. Optimized and inlined functions do not
164 // increment invocation count. 132 // increment invocation count.
165 Deoptimizer::DeoptimizeAll(isolate); 133 Deoptimizer::DeoptimizeAll(isolate);
166 // Collect existing feedback vectors. 134 // Collect existing feedback vectors.
(...skipping 15 matching lines...) Expand all
182 for (const auto& vector : vectors) list = ArrayList::Add(list, vector); 150 for (const auto& vector : vectors) list = ArrayList::Add(list, vector);
183 isolate->SetCodeCoverageList(*list); 151 isolate->SetCodeCoverageList(*list);
184 } 152 }
185 153
186 void Coverage::DisablePrecise(Isolate* isolate) { 154 void Coverage::DisablePrecise(Isolate* isolate) {
187 isolate->SetCodeCoverageList(isolate->heap()->undefined_value()); 155 isolate->SetCodeCoverageList(isolate->heap()->undefined_value());
188 } 156 }
189 157
190 } // namespace internal 158 } // namespace internal
191 } // namespace v8 159 } // namespace v8
OLDNEW
« no previous file with comments | « src/debug/debug-coverage.h ('k') | src/runtime/runtime-debug.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698