Index: src/debug/debug-coverage.cc |
diff --git a/src/debug/debug-coverage.cc b/src/debug/debug-coverage.cc |
index c94bf191ac568f5ea04e7dedae2e556be2c05b4e..47f51661a137c103e451fc8b5aa4acc500dad1bb 100644 |
--- a/src/debug/debug-coverage.cc |
+++ b/src/debug/debug-coverage.cc |
@@ -43,9 +43,25 @@ class SharedToCounterMap |
DisallowHeapAllocation no_gc; |
}; |
+namespace { |
+int StartPosition(SharedFunctionInfo* info) { |
+ int start = info->function_token_position(); |
+ if (start == kNoSourcePosition) start = info->start_position(); |
+ return start; |
+} |
+ |
+bool CompareSharedFunctionInfo(SharedFunctionInfo* a, SharedFunctionInfo* b) { |
+ int a_start = StartPosition(a); |
+ int b_start = StartPosition(b); |
+ if (a_start == b_start) return a->end_position() > b->end_position(); |
+ return a_start < b_start; |
+} |
+} // anonymous namespace |
+ |
std::vector<Coverage::ScriptData> Coverage::Collect(Isolate* isolate) { |
SharedToCounterMap counter_map; |
+ // Feed invocation count into the counter map. |
if (isolate->IsCodeCoverageEnabled()) { |
// Feedback vectors are already listed to prevent losing them to GC. |
Handle<ArrayList> list = |
@@ -61,9 +77,6 @@ std::vector<Coverage::ScriptData> Coverage::Collect(Isolate* isolate) { |
// Iterate the heap to find all feedback vectors and accumulate the |
// invocation counts into the map for each shared function info. |
HeapIterator heap_iterator(isolate->heap()); |
- // Initializing the heap iterator might have triggered a GC, which |
- // invalidates entries in the counter_map. |
- DCHECK_EQ(0, counter_map.occupancy()); |
while (HeapObject* current_obj = heap_iterator.next()) { |
if (!current_obj->IsFeedbackVector()) continue; |
FeedbackVector* vector = FeedbackVector::cast(current_obj); |
@@ -74,11 +87,6 @@ std::vector<Coverage::ScriptData> Coverage::Collect(Isolate* isolate) { |
} |
} |
- // Make sure entries in the counter map is not invalidated by GC. |
- DisallowHeapAllocation no_gc; |
- |
- std::vector<Range*> stack; |
- |
// Iterate shared function infos of every script and build a mapping |
// between source ranges and invocation counts. |
std::vector<Coverage::ScriptData> result; |
@@ -86,17 +94,29 @@ std::vector<Coverage::ScriptData> Coverage::Collect(Isolate* isolate) { |
while (Script* script = scripts.Next()) { |
// Dismiss non-user scripts. |
if (script->type() != Script::TYPE_NORMAL) continue; |
- DCHECK(stack.empty()); |
+ |
+ // Create and add new script data. |
int source_length = String::cast(script->source())->length(); |
result.emplace_back(Handle<Script>(script, isolate), source_length); |
+ |
+ std::vector<SharedFunctionInfo*> sorted; |
+ |
+ { |
+ // Collect a list of shared function infos sorted by start position. |
+ // Shared function infos are usually already sorted. Except for classes. |
+ // If the start position is the same, sort from outer to inner function. |
+ HandleScope scope(isolate); |
+ SharedFunctionInfo::ScriptIterator infos(Handle<Script>(script, isolate)); |
+ while (SharedFunctionInfo* info = infos.Next()) sorted.push_back(info); |
+ std::sort(sorted.begin(), sorted.end(), CompareSharedFunctionInfo); |
+ } |
+ |
+ std::vector<Range*> stack; |
stack.push_back(&result.back().toplevel); |
- // Iterate through the list of shared function infos, reconstruct the |
- // nesting, and compute the ranges covering different invocation counts. |
- HandleScope scope(isolate); |
- SharedFunctionInfo::ScriptIterator infos(Handle<Script>(script, isolate)); |
- while (SharedFunctionInfo* info = infos.Next()) { |
- int start = info->function_token_position(); |
- if (start == kNoSourcePosition) start = info->start_position(); |
+ |
+ // Use sorted list to reconstruct function nesting. |
+ for (SharedFunctionInfo* info : sorted) { |
+ int start = StartPosition(info); |
int end = info->end_position(); |
uint32_t count = counter_map.Get(info); |
if (info->is_toplevel()) { |
@@ -109,7 +129,7 @@ std::vector<Coverage::ScriptData> Coverage::Collect(Isolate* isolate) { |
// The shared function infos are sorted by start. |
DCHECK_LE(stack.back()->start, start); |
// Drop the stack to the outer function. |
- while (start > stack.back()->end) stack.pop_back(); |
+ while (start >= stack.back()->end) stack.pop_back(); |
Range* outer = stack.back(); |
// New nested function. |
DCHECK_LE(end, outer->end); |
@@ -121,7 +141,6 @@ std::vector<Coverage::ScriptData> Coverage::Collect(Isolate* isolate) { |
stack.push_back(&nested); |
} |
} |
- stack.clear(); |
} |
return result; |
} |