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

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

Issue 2689493002: [debugger] implement per-function code coverage. (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.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
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
3 // found in the LICENSE file.
4
5 #include "src/debug/debug-coverage.h"
6
7 #include "src/base/hashmap.h"
8 #include "src/objects-inl.h"
9 #include "src/objects.h"
10
11 namespace v8 {
12 namespace internal {
13
14 class SharedToCounterMap
15 : public base::TemplateHashMapImpl<SharedFunctionInfo*, uint32_t,
16 base::KeyEqualityMatcher<void*>,
17 base::DefaultAllocationPolicy> {
18 public:
19 typedef base::TemplateHashMapEntry<SharedFunctionInfo*, uint32_t> Entry;
20 inline void Add(SharedFunctionInfo* key, uint32_t count) {
21 Entry* entry = LookupOrInsert(key, Hash(key), []() { return 0; });
22 uint32_t old_count = entry->value;
23 if (UINT32_MAX - count < old_count) {
24 entry->value = UINT32_MAX;
25 } else {
26 entry->value = old_count + count;
27 }
28 }
29
30 inline uint32_t Get(SharedFunctionInfo* key) {
31 Entry* entry = Lookup(key, Hash(key));
32 if (entry == nullptr) return 0;
33 return entry->value;
34 }
35
36 private:
37 static uint32_t Hash(SharedFunctionInfo* key) {
38 return static_cast<uint32_t>(reinterpret_cast<intptr_t>(key));
39 }
40 };
41
42 class ScriptDataBuilder {
43 public:
44 void Add(int end_position, uint32_t count) {
45 DCHECK(entries_.empty() || entries_.back().end_position <= end_position);
46 if (entries_.empty()) {
47 if (end_position > 0) entries_.push_back({end_position, count});
48 } else if (entries_.back().count == count) {
49 // Extend last range.
50 entries_.back().end_position = end_position;
51 } else if (entries_.back().end_position < end_position) {
52 // Add new range.
53 entries_.push_back({end_position, count});
54 }
55 }
56 std::vector<Coverage::RangeEntry> Finish() {
57 std::vector<Coverage::RangeEntry> result;
58 std::swap(result, entries_);
59 return result;
60 }
61
62 private:
63 std::vector<Coverage::RangeEntry> entries_;
64 };
65
66 std::vector<Coverage::ScriptData> Coverage::Collect(Isolate* isolate) {
67 SharedToCounterMap counter_map;
68 // Iterate the heap to find all feedback vectors and accumulate the
69 // invocation counts into the map for each shared function info.
70 HeapIterator heap_iterator(isolate->heap());
71 HeapObject* current_obj;
72 while ((current_obj = heap_iterator.next())) {
73 if (!current_obj->IsFeedbackVector()) continue;
74 FeedbackVector* vector = FeedbackVector::cast(current_obj);
75 SharedFunctionInfo* shared = vector->shared_function_info();
76 if (!shared->IsSubjectToDebugging()) continue;
77 uint32_t count = static_cast<uint32_t>(vector->invocation_count());
78 counter_map.Add(shared, count);
79 }
80
81 // Make sure entries in the counter map is not invalidated by GC.
82 DisallowHeapAllocation no_gc;
83
84 // Stack to track nested functions.
85 struct FunctionNode {
86 FunctionNode(int s, int e, uint32_t c) : start(s), end(e), count(c) {}
87 int start;
88 int end;
89 uint32_t count;
90 };
91 std::vector<FunctionNode> stack;
92
93 // Iterate shared function infos of every script and build a mapping
94 // between source ranges and invocation counts.
95 std::vector<Coverage::ScriptData> result;
96 Script::Iterator scripts(isolate);
97 while (Script* script = scripts.Next()) {
98 // Dismiss non-user scripts.
99 if (script->type() != Script::TYPE_NORMAL) continue;
100 DCHECK(stack.empty());
101 int script_end = String::cast(script->source())->length();
102 // If not rooted, the top-level function is likely no longer alive. Set the
103 // outer-most count to 1 to indicate that the script has run at least once.
104 stack.push_back({0, script_end, 1});
105 ScriptDataBuilder builder;
106 // Iterate through the list of shared function infos, reconstruct the
107 // nesting, and compute the ranges covering different invocation counts.
108 HandleScope scope(isolate);
109 SharedFunctionInfo::ScriptIterator infos(Handle<Script>(script, isolate));
110 while (SharedFunctionInfo* info = infos.Next()) {
111 int start = info->function_token_position();
112 if (start == kNoSourcePosition) start = info->start_position();
113 int end = info->end_position();
114 uint32_t count = counter_map.Get(info);
115 // The shared function infos are sorted by start.
116 DCHECK_LE(stack.back().start, start);
117 // If the start are the same, the outer function comes before the inner.
118 DCHECK(stack.back().start < start || stack.back().end >= end);
119 // Drop the stack to the outer function.
120 while (start > stack.back().end) {
121 // Write out rest of function being dropped.
122 builder.Add(stack.back().end, stack.back().count);
123 stack.pop_back();
124 }
125 // Write out outer function up to the start of new function.
126 builder.Add(start, stack.back().count);
127 // New nested function.
128 DCHECK_LE(end, stack.back().end);
129 stack.emplace_back(start, end, count);
130 }
131
132 // Drop the stack to the script level.
133 while (!stack.empty()) {
134 // Write out rest of function being dropped.
135 builder.Add(stack.back().end, stack.back().count);
136 stack.pop_back();
137 }
138 result.emplace_back(script->id(), builder.Finish());
139 }
140 return result;
141 }
142
143 } // namespace internal
144 } // namespace v8
OLDNEW
« no previous file with comments | « src/debug/debug-coverage.h ('k') | src/runtime/runtime.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698