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" |
| 9 #include "src/isolate.h" |
8 #include "src/objects-inl.h" | 10 #include "src/objects-inl.h" |
9 #include "src/objects.h" | 11 #include "src/objects.h" |
10 | 12 |
11 namespace v8 { | 13 namespace v8 { |
12 namespace internal { | 14 namespace internal { |
13 | 15 |
14 class SharedToCounterMap | 16 class SharedToCounterMap |
15 : public base::TemplateHashMapImpl<SharedFunctionInfo*, uint32_t, | 17 : public base::TemplateHashMapImpl<SharedFunctionInfo*, uint32_t, |
16 base::KeyEqualityMatcher<void*>, | 18 base::KeyEqualityMatcher<void*>, |
17 base::DefaultAllocationPolicy> { | 19 base::DefaultAllocationPolicy> { |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
58 std::swap(result, entries_); | 60 std::swap(result, entries_); |
59 return result; | 61 return result; |
60 } | 62 } |
61 | 63 |
62 private: | 64 private: |
63 std::vector<Coverage::RangeEntry> entries_; | 65 std::vector<Coverage::RangeEntry> entries_; |
64 }; | 66 }; |
65 | 67 |
66 std::vector<Coverage::ScriptData> Coverage::Collect(Isolate* isolate) { | 68 std::vector<Coverage::ScriptData> Coverage::Collect(Isolate* isolate) { |
67 SharedToCounterMap counter_map; | 69 SharedToCounterMap counter_map; |
68 // Iterate the heap to find all feedback vectors and accumulate the | 70 |
69 // invocation counts into the map for each shared function info. | 71 if (isolate->IsCodeCoverageEnabled()) { |
70 HeapIterator heap_iterator(isolate->heap()); | 72 // Feedback vectors are already listed to prevent losing them to GC. |
71 HeapObject* current_obj; | 73 Handle<ArrayList> list = |
72 while ((current_obj = heap_iterator.next())) { | 74 Handle<ArrayList>::cast(isolate->factory()->code_coverage_list()); |
73 if (!current_obj->IsFeedbackVector()) continue; | 75 for (int i = 0; i < list->Length(); i++) { |
74 FeedbackVector* vector = FeedbackVector::cast(current_obj); | 76 FeedbackVector* vector = FeedbackVector::cast(list->Get(i)); |
75 SharedFunctionInfo* shared = vector->shared_function_info(); | 77 SharedFunctionInfo* shared = vector->shared_function_info(); |
76 if (!shared->IsSubjectToDebugging()) continue; | 78 DCHECK(shared->IsSubjectToDebugging()); |
77 uint32_t count = static_cast<uint32_t>(vector->invocation_count()); | 79 uint32_t count = static_cast<uint32_t>(vector->invocation_count()); |
78 counter_map.Add(shared, count); | 80 counter_map.Add(shared, count); |
| 81 } |
| 82 } else { |
| 83 // Iterate the heap to find all feedback vectors and accumulate the |
| 84 // invocation counts into the map for each shared function info. |
| 85 HeapIterator heap_iterator(isolate->heap()); |
| 86 // Initializing the heap iterator might have triggered a GC, which |
| 87 // invalidates entries in the counter_map. |
| 88 DCHECK_EQ(0, counter_map.occupancy()); |
| 89 while (HeapObject* current_obj = heap_iterator.next()) { |
| 90 if (!current_obj->IsFeedbackVector()) continue; |
| 91 FeedbackVector* vector = FeedbackVector::cast(current_obj); |
| 92 SharedFunctionInfo* shared = vector->shared_function_info(); |
| 93 if (!shared->IsSubjectToDebugging()) continue; |
| 94 uint32_t count = static_cast<uint32_t>(vector->invocation_count()); |
| 95 counter_map.Add(shared, count); |
| 96 } |
79 } | 97 } |
80 | 98 |
81 // Make sure entries in the counter map is not invalidated by GC. | 99 // Make sure entries in the counter map is not invalidated by GC. |
82 DisallowHeapAllocation no_gc; | 100 DisallowHeapAllocation no_gc; |
83 | 101 |
84 // Stack to track nested functions. | 102 // Stack to track nested functions. |
85 struct FunctionNode { | 103 struct FunctionNode { |
86 FunctionNode(int s, int e, uint32_t c) : start(s), end(e), count(c) {} | 104 FunctionNode(int s, int e, uint32_t c) : start(s), end(e), count(c) {} |
87 int start; | 105 int start; |
88 int end; | 106 int end; |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
133 while (!stack.empty()) { | 151 while (!stack.empty()) { |
134 // Write out rest of function being dropped. | 152 // Write out rest of function being dropped. |
135 builder.Add(stack.back().end, stack.back().count); | 153 builder.Add(stack.back().end, stack.back().count); |
136 stack.pop_back(); | 154 stack.pop_back(); |
137 } | 155 } |
138 result.emplace_back(script->id(), builder.Finish()); | 156 result.emplace_back(script->id(), builder.Finish()); |
139 } | 157 } |
140 return result; | 158 return result; |
141 } | 159 } |
142 | 160 |
| 161 void Coverage::EnablePrecise(Isolate* isolate) { |
| 162 HandleScope scope(isolate); |
| 163 // Remove all optimized function. Optimized and inlined functions do not |
| 164 // increment invocation count. |
| 165 Deoptimizer::DeoptimizeAll(isolate); |
| 166 // Collect existing feedback vectors. |
| 167 std::vector<Handle<FeedbackVector>> vectors; |
| 168 { |
| 169 HeapIterator heap_iterator(isolate->heap()); |
| 170 while (HeapObject* current_obj = heap_iterator.next()) { |
| 171 if (!current_obj->IsFeedbackVector()) continue; |
| 172 FeedbackVector* vector = FeedbackVector::cast(current_obj); |
| 173 SharedFunctionInfo* shared = vector->shared_function_info(); |
| 174 if (!shared->IsSubjectToDebugging()) continue; |
| 175 vector->clear_invocation_count(); |
| 176 vectors.emplace_back(vector, isolate); |
| 177 } |
| 178 } |
| 179 // Add collected feedback vectors to the root list lest we lose them to GC. |
| 180 Handle<ArrayList> list = |
| 181 ArrayList::New(isolate, static_cast<int>(vectors.size())); |
| 182 for (const auto& vector : vectors) list = ArrayList::Add(list, vector); |
| 183 isolate->SetCodeCoverageList(*list); |
| 184 } |
| 185 |
| 186 void Coverage::DisablePrecise(Isolate* isolate) { |
| 187 isolate->SetCodeCoverageList(isolate->heap()->undefined_value()); |
| 188 } |
| 189 |
143 } // namespace internal | 190 } // namespace internal |
144 } // namespace v8 | 191 } // namespace v8 |
OLD | NEW |