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/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 Loading... | |
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 std::vector<Coverage::ScriptData> Coverage::Collect(Isolate* isolate) { | 61 CoverageScript::CoverageScript(Isolate* isolate, Handle<Script> s, |
62 int source_length) | |
63 : script(s), | |
64 toplevel(0, source_length, 1, isolate->factory()->empty_string()) {} | |
65 | |
66 Coverage* Coverage::Collect(Isolate* isolate) { | |
62 SharedToCounterMap counter_map; | 67 SharedToCounterMap counter_map; |
63 | 68 |
64 // Feed invocation count into the counter map. | 69 // Feed invocation count into the counter map. |
65 if (isolate->IsCodeCoverageEnabled()) { | 70 if (isolate->IsCodeCoverageEnabled()) { |
66 // Feedback vectors are already listed to prevent losing them to GC. | 71 // Feedback vectors are already listed to prevent losing them to GC. |
67 Handle<ArrayList> list = | 72 Handle<ArrayList> list = |
68 Handle<ArrayList>::cast(isolate->factory()->code_coverage_list()); | 73 Handle<ArrayList>::cast(isolate->factory()->code_coverage_list()); |
69 for (int i = 0; i < list->Length(); i++) { | 74 for (int i = 0; i < list->Length(); i++) { |
70 FeedbackVector* vector = FeedbackVector::cast(list->Get(i)); | 75 FeedbackVector* vector = FeedbackVector::cast(list->Get(i)); |
71 SharedFunctionInfo* shared = vector->shared_function_info(); | 76 SharedFunctionInfo* shared = vector->shared_function_info(); |
(...skipping 10 matching lines...) Expand all Loading... | |
82 FeedbackVector* vector = FeedbackVector::cast(current_obj); | 87 FeedbackVector* vector = FeedbackVector::cast(current_obj); |
83 SharedFunctionInfo* shared = vector->shared_function_info(); | 88 SharedFunctionInfo* shared = vector->shared_function_info(); |
84 if (!shared->IsSubjectToDebugging()) continue; | 89 if (!shared->IsSubjectToDebugging()) continue; |
85 uint32_t count = static_cast<uint32_t>(vector->invocation_count()); | 90 uint32_t count = static_cast<uint32_t>(vector->invocation_count()); |
86 counter_map.Add(shared, count); | 91 counter_map.Add(shared, count); |
87 } | 92 } |
88 } | 93 } |
89 | 94 |
90 // Iterate shared function infos of every script and build a mapping | 95 // Iterate shared function infos of every script and build a mapping |
91 // between source ranges and invocation counts. | 96 // between source ranges and invocation counts. |
92 std::vector<Coverage::ScriptData> result; | 97 Coverage* result = new Coverage(); |
93 Script::Iterator scripts(isolate); | 98 Script::Iterator scripts(isolate); |
94 while (Script* script = scripts.Next()) { | 99 while (Script* script = scripts.Next()) { |
95 // Dismiss non-user scripts. | 100 // Dismiss non-user scripts. |
96 if (script->type() != Script::TYPE_NORMAL) continue; | 101 if (script->type() != Script::TYPE_NORMAL) continue; |
97 | 102 |
98 // Create and add new script data. | 103 // Create and add new script data. |
99 int source_length = String::cast(script->source())->length(); | 104 int source_end = String::cast(script->source())->length(); |
100 result.emplace_back(Handle<Script>(script, isolate), source_length); | 105 Handle<Script> script_handle(script, isolate); |
106 result->emplace_back(isolate, script_handle, source_end); | |
101 | 107 |
102 std::vector<SharedFunctionInfo*> sorted; | 108 std::vector<SharedFunctionInfo*> sorted; |
103 | 109 |
104 { | 110 { |
105 // Collect a list of shared function infos sorted by start position. | 111 // Collect a list of shared function infos sorted by start position. |
106 // Shared function infos are usually already sorted. Except for classes. | 112 // Shared function infos are usually already sorted. Except for classes. |
107 // If the start position is the same, sort from outer to inner function. | 113 // If the start position is the same, sort from outer to inner function. |
108 HandleScope scope(isolate); | 114 SharedFunctionInfo::ScriptIterator infos(script_handle); |
109 SharedFunctionInfo::ScriptIterator infos(Handle<Script>(script, isolate)); | |
110 while (SharedFunctionInfo* info = infos.Next()) sorted.push_back(info); | 115 while (SharedFunctionInfo* info = infos.Next()) sorted.push_back(info); |
111 std::sort(sorted.begin(), sorted.end(), CompareSharedFunctionInfo); | 116 std::sort(sorted.begin(), sorted.end(), CompareSharedFunctionInfo); |
112 } | 117 } |
113 | 118 |
114 std::vector<Range*> stack; | 119 std::vector<CoverageRange*> stack; |
115 stack.push_back(&result.back().toplevel); | 120 stack.push_back(&result->back().toplevel); |
116 | 121 |
117 // Use sorted list to reconstruct function nesting. | 122 // Use sorted list to reconstruct function nesting. |
118 for (SharedFunctionInfo* info : sorted) { | 123 for (SharedFunctionInfo* info : sorted) { |
119 int start = StartPosition(info); | 124 int start = StartPosition(info); |
120 int end = info->end_position(); | 125 int end = info->end_position(); |
121 uint32_t count = counter_map.Get(info); | 126 uint32_t count = counter_map.Get(info); |
122 if (info->is_toplevel()) { | 127 if (info->is_toplevel()) { |
123 // Top-level function is available. | 128 // Top-level function is available. |
124 DCHECK_EQ(1, stack.size()); | 129 DCHECK_EQ(1, stack.size()); |
125 result.back().toplevel.start = start; | 130 result->back().toplevel.start = start; |
126 result.back().toplevel.end = end; | 131 result->back().toplevel.end = end; |
127 result.back().toplevel.count = count; | 132 result->back().toplevel.count = count; |
128 } else { | 133 } else { |
129 // The shared function infos are sorted by start. | 134 // The shared function infos are sorted by start. |
130 DCHECK_LE(stack.back()->start, start); | 135 DCHECK_LE(stack.back()->start, start); |
131 // Drop the stack to the outer function. | 136 // Drop the stack to the outer function. |
132 while (start >= stack.back()->end) stack.pop_back(); | 137 while (start >= stack.back()->end) stack.pop_back(); |
133 Range* outer = stack.back(); | 138 CoverageRange* outer = stack.back(); |
134 // New nested function. | 139 // New nested function. |
135 DCHECK_LE(end, outer->end); | 140 DCHECK_LE(end, outer->end); |
136 outer->inner.emplace_back(start, end, count); | 141 Handle<String> name(info->DebugName(), isolate); |
kozy
2017/02/15 16:33:41
Why GC couldn't happen for example here? Is it saf
Yang
2017/02/15 16:42:41
Yes. No GC can happen. We assert that in the Share
| |
137 Range& nested = outer->inner.back(); | 142 outer->inner.emplace_back(start, end, count, name); |
138 String* name = info->DebugName(); | 143 stack.push_back(&outer->inner.back()); |
139 nested.name.resize(name->length()); | |
140 String::WriteToFlat(name, nested.name.data(), 0, name->length()); | |
141 stack.push_back(&nested); | |
142 } | 144 } |
143 } | 145 } |
144 } | 146 } |
145 return result; | 147 return result; |
146 } | 148 } |
147 | 149 |
148 void Coverage::EnablePrecise(Isolate* isolate) { | 150 void Coverage::TogglePrecise(Isolate* isolate, bool enable) { |
149 HandleScope scope(isolate); | 151 if (enable) { |
150 // Remove all optimized function. Optimized and inlined functions do not | 152 HandleScope scope(isolate); |
151 // increment invocation count. | 153 // Remove all optimized function. Optimized and inlined functions do not |
152 Deoptimizer::DeoptimizeAll(isolate); | 154 // increment invocation count. |
153 // Collect existing feedback vectors. | 155 Deoptimizer::DeoptimizeAll(isolate); |
154 std::vector<Handle<FeedbackVector>> vectors; | 156 // Collect existing feedback vectors. |
155 { | 157 std::vector<Handle<FeedbackVector>> vectors; |
156 HeapIterator heap_iterator(isolate->heap()); | 158 { |
157 while (HeapObject* current_obj = heap_iterator.next()) { | 159 HeapIterator heap_iterator(isolate->heap()); |
158 if (!current_obj->IsFeedbackVector()) continue; | 160 while (HeapObject* current_obj = heap_iterator.next()) { |
159 FeedbackVector* vector = FeedbackVector::cast(current_obj); | 161 if (!current_obj->IsFeedbackVector()) continue; |
160 SharedFunctionInfo* shared = vector->shared_function_info(); | 162 FeedbackVector* vector = FeedbackVector::cast(current_obj); |
161 if (!shared->IsSubjectToDebugging()) continue; | 163 SharedFunctionInfo* shared = vector->shared_function_info(); |
162 vector->clear_invocation_count(); | 164 if (!shared->IsSubjectToDebugging()) continue; |
163 vectors.emplace_back(vector, isolate); | 165 vector->clear_invocation_count(); |
166 vectors.emplace_back(vector, isolate); | |
167 } | |
164 } | 168 } |
169 // Add collected feedback vectors to the root list lest we lose them to GC. | |
170 Handle<ArrayList> list = | |
171 ArrayList::New(isolate, static_cast<int>(vectors.size())); | |
172 for (const auto& vector : vectors) list = ArrayList::Add(list, vector); | |
173 isolate->SetCodeCoverageList(*list); | |
174 } else { | |
175 isolate->SetCodeCoverageList(isolate->heap()->undefined_value()); | |
165 } | 176 } |
166 // Add collected feedback vectors to the root list lest we lose them to GC. | |
167 Handle<ArrayList> list = | |
168 ArrayList::New(isolate, static_cast<int>(vectors.size())); | |
169 for (const auto& vector : vectors) list = ArrayList::Add(list, vector); | |
170 isolate->SetCodeCoverageList(*list); | |
171 } | |
172 | |
173 void Coverage::DisablePrecise(Isolate* isolate) { | |
174 isolate->SetCodeCoverageList(isolate->heap()->undefined_value()); | |
175 } | 177 } |
176 | 178 |
177 } // namespace internal | 179 } // namespace internal |
178 } // namespace v8 | 180 } // namespace v8 |
OLD | NEW |