| Index: src/debug/debug-coverage.cc
|
| diff --git a/src/debug/debug-coverage.cc b/src/debug/debug-coverage.cc
|
| index dd54d2a616a2e9109e8dde93a28df2eace846d41..c94bf191ac568f5ea04e7dedae2e556be2c05b4e 100644
|
| --- a/src/debug/debug-coverage.cc
|
| +++ b/src/debug/debug-coverage.cc
|
| @@ -39,30 +39,8 @@ class SharedToCounterMap
|
| static uint32_t Hash(SharedFunctionInfo* key) {
|
| return static_cast<uint32_t>(reinterpret_cast<intptr_t>(key));
|
| }
|
| -};
|
| -
|
| -class ScriptDataBuilder {
|
| - public:
|
| - void Add(int end_position, uint32_t count) {
|
| - DCHECK(entries_.empty() || entries_.back().end_position <= end_position);
|
| - if (entries_.empty()) {
|
| - if (end_position > 0) entries_.push_back({end_position, count});
|
| - } else if (entries_.back().count == count) {
|
| - // Extend last range.
|
| - entries_.back().end_position = end_position;
|
| - } else if (entries_.back().end_position < end_position) {
|
| - // Add new range.
|
| - entries_.push_back({end_position, count});
|
| - }
|
| - }
|
| - std::vector<Coverage::RangeEntry> Finish() {
|
| - std::vector<Coverage::RangeEntry> result;
|
| - std::swap(result, entries_);
|
| - return result;
|
| - }
|
|
|
| - private:
|
| - std::vector<Coverage::RangeEntry> entries_;
|
| + DisallowHeapAllocation no_gc;
|
| };
|
|
|
| std::vector<Coverage::ScriptData> Coverage::Collect(Isolate* isolate) {
|
| @@ -99,14 +77,7 @@ std::vector<Coverage::ScriptData> Coverage::Collect(Isolate* isolate) {
|
| // Make sure entries in the counter map is not invalidated by GC.
|
| DisallowHeapAllocation no_gc;
|
|
|
| - // Stack to track nested functions.
|
| - struct FunctionNode {
|
| - FunctionNode(int s, int e, uint32_t c) : start(s), end(e), count(c) {}
|
| - int start;
|
| - int end;
|
| - uint32_t count;
|
| - };
|
| - std::vector<FunctionNode> stack;
|
| + std::vector<Range*> stack;
|
|
|
| // Iterate shared function infos of every script and build a mapping
|
| // between source ranges and invocation counts.
|
| @@ -116,11 +87,9 @@ std::vector<Coverage::ScriptData> Coverage::Collect(Isolate* isolate) {
|
| // Dismiss non-user scripts.
|
| if (script->type() != Script::TYPE_NORMAL) continue;
|
| DCHECK(stack.empty());
|
| - int script_end = String::cast(script->source())->length();
|
| - // If not rooted, the top-level function is likely no longer alive. Set the
|
| - // outer-most count to 1 to indicate that the script has run at least once.
|
| - stack.push_back({0, script_end, 1});
|
| - ScriptDataBuilder builder;
|
| + int source_length = String::cast(script->source())->length();
|
| + result.emplace_back(Handle<Script>(script, isolate), source_length);
|
| + 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);
|
| @@ -130,30 +99,29 @@ std::vector<Coverage::ScriptData> Coverage::Collect(Isolate* isolate) {
|
| if (start == kNoSourcePosition) start = info->start_position();
|
| int end = info->end_position();
|
| uint32_t count = counter_map.Get(info);
|
| - // The shared function infos are sorted by start.
|
| - DCHECK_LE(stack.back().start, start);
|
| - // If the start are the same, the outer function comes before the inner.
|
| - DCHECK(stack.back().start < start || stack.back().end >= end);
|
| - // Drop the stack to the outer function.
|
| - while (start > stack.back().end) {
|
| - // Write out rest of function being dropped.
|
| - builder.Add(stack.back().end, stack.back().count);
|
| - stack.pop_back();
|
| + if (info->is_toplevel()) {
|
| + // Top-level function is available.
|
| + DCHECK_EQ(1, stack.size());
|
| + result.back().toplevel.start = start;
|
| + result.back().toplevel.end = end;
|
| + result.back().toplevel.count = count;
|
| + } else {
|
| + // 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();
|
| + Range* outer = stack.back();
|
| + // New nested function.
|
| + DCHECK_LE(end, outer->end);
|
| + outer->inner.emplace_back(start, end, count);
|
| + Range& nested = outer->inner.back();
|
| + String* name = info->DebugName();
|
| + nested.name.resize(name->length());
|
| + String::WriteToFlat(name, nested.name.data(), 0, name->length());
|
| + stack.push_back(&nested);
|
| }
|
| - // Write out outer function up to the start of new function.
|
| - builder.Add(start, stack.back().count);
|
| - // New nested function.
|
| - DCHECK_LE(end, stack.back().end);
|
| - stack.emplace_back(start, end, count);
|
| - }
|
| -
|
| - // Drop the stack to the script level.
|
| - while (!stack.empty()) {
|
| - // Write out rest of function being dropped.
|
| - builder.Add(stack.back().end, stack.back().count);
|
| - stack.pop_back();
|
| }
|
| - result.emplace_back(script->id(), builder.Finish());
|
| + stack.clear();
|
| }
|
| return result;
|
| }
|
|
|