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

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

Issue 2700743002: [inspector] extend protocol for code coverage. (Closed)
Patch Set: fix 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/debug/debug-interface.h » ('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 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
51 } 51 }
52 52
53 bool CompareSharedFunctionInfo(SharedFunctionInfo* a, SharedFunctionInfo* b) { 53 bool CompareSharedFunctionInfo(SharedFunctionInfo* a, SharedFunctionInfo* b) {
54 int a_start = StartPosition(a); 54 int a_start = StartPosition(a);
55 int b_start = StartPosition(b); 55 int b_start = StartPosition(b);
56 if (a_start == b_start) return a->end_position() > b->end_position(); 56 if (a_start == b_start) return a->end_position() > b->end_position();
57 return a_start < b_start; 57 return a_start < b_start;
58 } 58 }
59 } // anonymous namespace 59 } // anonymous namespace
60 60
61 CoverageScript::CoverageScript(Isolate* isolate, Handle<Script> s, 61 Coverage* Coverage::Collect(Isolate* isolate, bool reset_count) {
62 int source_length)
63 : script(s),
64 toplevel(0, source_length, 1, isolate->factory()->empty_string()) {}
65
66 Coverage* Coverage::Collect(Isolate* isolate) {
67 SharedToCounterMap counter_map; 62 SharedToCounterMap counter_map;
68 63
69 // Feed invocation count into the counter map. 64 // Feed invocation count into the counter map.
70 if (isolate->IsCodeCoverageEnabled()) { 65 if (isolate->IsCodeCoverageEnabled()) {
71 // Feedback vectors are already listed to prevent losing them to GC. 66 // Feedback vectors are already listed to prevent losing them to GC.
72 Handle<ArrayList> list = 67 Handle<ArrayList> list =
73 Handle<ArrayList>::cast(isolate->factory()->code_coverage_list()); 68 Handle<ArrayList>::cast(isolate->factory()->code_coverage_list());
74 for (int i = 0; i < list->Length(); i++) { 69 for (int i = 0; i < list->Length(); i++) {
75 FeedbackVector* vector = FeedbackVector::cast(list->Get(i)); 70 FeedbackVector* vector = FeedbackVector::cast(list->Get(i));
76 SharedFunctionInfo* shared = vector->shared_function_info(); 71 SharedFunctionInfo* shared = vector->shared_function_info();
77 DCHECK(shared->IsSubjectToDebugging()); 72 DCHECK(shared->IsSubjectToDebugging());
78 uint32_t count = static_cast<uint32_t>(vector->invocation_count()); 73 uint32_t count = static_cast<uint32_t>(vector->invocation_count());
74 if (reset_count) vector->clear_invocation_count();
79 counter_map.Add(shared, count); 75 counter_map.Add(shared, count);
80 } 76 }
81 } else { 77 } else {
82 // Iterate the heap to find all feedback vectors and accumulate the 78 // Iterate the heap to find all feedback vectors and accumulate the
83 // invocation counts into the map for each shared function info. 79 // invocation counts into the map for each shared function info.
84 HeapIterator heap_iterator(isolate->heap()); 80 HeapIterator heap_iterator(isolate->heap());
85 while (HeapObject* current_obj = heap_iterator.next()) { 81 while (HeapObject* current_obj = heap_iterator.next()) {
86 if (!current_obj->IsFeedbackVector()) continue; 82 if (!current_obj->IsFeedbackVector()) continue;
87 FeedbackVector* vector = FeedbackVector::cast(current_obj); 83 FeedbackVector* vector = FeedbackVector::cast(current_obj);
88 SharedFunctionInfo* shared = vector->shared_function_info(); 84 SharedFunctionInfo* shared = vector->shared_function_info();
89 if (!shared->IsSubjectToDebugging()) continue; 85 if (!shared->IsSubjectToDebugging()) continue;
90 uint32_t count = static_cast<uint32_t>(vector->invocation_count()); 86 uint32_t count = static_cast<uint32_t>(vector->invocation_count());
87 if (reset_count) vector->clear_invocation_count();
91 counter_map.Add(shared, count); 88 counter_map.Add(shared, count);
92 } 89 }
93 } 90 }
94 91
95 // Iterate shared function infos of every script and build a mapping 92 // Iterate shared function infos of every script and build a mapping
96 // between source ranges and invocation counts. 93 // between source ranges and invocation counts.
97 Coverage* result = new Coverage(); 94 Coverage* result = new Coverage();
98 Script::Iterator scripts(isolate); 95 Script::Iterator scripts(isolate);
99 while (Script* script = scripts.Next()) { 96 while (Script* script = scripts.Next()) {
100 // Dismiss non-user scripts. 97 // Dismiss non-user scripts.
101 if (script->type() != Script::TYPE_NORMAL) continue; 98 if (script->type() != Script::TYPE_NORMAL) continue;
102 99
103 // Create and add new script data. 100 // Create and add new script data.
104 int source_end = String::cast(script->source())->length();
105 Handle<Script> script_handle(script, isolate); 101 Handle<Script> script_handle(script, isolate);
106 result->emplace_back(isolate, script_handle, source_end); 102 result->emplace_back(isolate, script_handle);
103 std::vector<CoverageFunction>* functions = &result->back().functions;
107 104
108 std::vector<SharedFunctionInfo*> sorted; 105 std::vector<SharedFunctionInfo*> sorted;
106 bool has_toplevel = false;
109 107
110 { 108 {
111 // Collect a list of shared function infos sorted by start position. 109 // Sort functions by start position, from outer to inner functions.
112 // Shared function infos are usually already sorted. Except for classes.
113 // If the start position is the same, sort from outer to inner function.
114 SharedFunctionInfo::ScriptIterator infos(script_handle); 110 SharedFunctionInfo::ScriptIterator infos(script_handle);
115 while (SharedFunctionInfo* info = infos.Next()) sorted.push_back(info); 111 while (SharedFunctionInfo* info = infos.Next()) {
112 has_toplevel |= info->is_toplevel();
113 sorted.push_back(info);
114 }
116 std::sort(sorted.begin(), sorted.end(), CompareSharedFunctionInfo); 115 std::sort(sorted.begin(), sorted.end(), CompareSharedFunctionInfo);
117 } 116 }
118 117
119 std::vector<CoverageRange*> stack; 118 functions->reserve(sorted.size() + (has_toplevel ? 0 : 1));
120 stack.push_back(&result->back().toplevel); 119
120 if (!has_toplevel) {
121 // Add a replacement toplevel function if it does not exist.
122 int source_end = String::cast(script->source())->length();
123 functions->emplace_back(0, source_end, 1u,
124 isolate->factory()->empty_string());
125 }
121 126
122 // Use sorted list to reconstruct function nesting. 127 // Use sorted list to reconstruct function nesting.
123 for (SharedFunctionInfo* info : sorted) { 128 for (SharedFunctionInfo* info : sorted) {
124 int start = StartPosition(info); 129 int start = StartPosition(info);
125 int end = info->end_position(); 130 int end = info->end_position();
126 uint32_t count = counter_map.Get(info); 131 uint32_t count = counter_map.Get(info);
127 if (info->is_toplevel()) { 132 Handle<String> name(info->DebugName(), isolate);
128 // Top-level function is available. 133 functions->emplace_back(start, end, count, name);
129 DCHECK_EQ(1, stack.size());
130 result->back().toplevel.start = start;
131 result->back().toplevel.end = end;
132 result->back().toplevel.count = count;
133 } else {
134 // The shared function infos are sorted by start.
135 DCHECK_LE(stack.back()->start, start);
136 // Drop the stack to the outer function.
137 while (start >= stack.back()->end) stack.pop_back();
138 CoverageRange* outer = stack.back();
139 // New nested function.
140 DCHECK_LE(end, outer->end);
141 Handle<String> name(info->DebugName(), isolate);
142 outer->inner.emplace_back(start, end, count, name);
143 stack.push_back(&outer->inner.back());
144 }
145 } 134 }
146 } 135 }
147 return result; 136 return result;
148 } 137 }
149 138
150 void Coverage::TogglePrecise(Isolate* isolate, bool enable) { 139 void Coverage::TogglePrecise(Isolate* isolate, bool enable) {
151 if (enable) { 140 if (enable) {
152 HandleScope scope(isolate); 141 HandleScope scope(isolate);
153 // Remove all optimized function. Optimized and inlined functions do not 142 // Remove all optimized function. Optimized and inlined functions do not
154 // increment invocation count. 143 // increment invocation count.
(...skipping 16 matching lines...) Expand all
171 ArrayList::New(isolate, static_cast<int>(vectors.size())); 160 ArrayList::New(isolate, static_cast<int>(vectors.size()));
172 for (const auto& vector : vectors) list = ArrayList::Add(list, vector); 161 for (const auto& vector : vectors) list = ArrayList::Add(list, vector);
173 isolate->SetCodeCoverageList(*list); 162 isolate->SetCodeCoverageList(*list);
174 } else { 163 } else {
175 isolate->SetCodeCoverageList(isolate->heap()->undefined_value()); 164 isolate->SetCodeCoverageList(isolate->heap()->undefined_value());
176 } 165 }
177 } 166 }
178 167
179 } // namespace internal 168 } // namespace internal
180 } // namespace v8 169 } // namespace v8
OLDNEW
« no previous file with comments | « src/debug/debug-coverage.h ('k') | src/debug/debug-interface.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698