Commit f633c5f3 authored by yangguo's avatar yangguo Committed by Commit bot

[debug] do not report unnecessary coverage data.

Only include function ranges for with non-0 counts or if the immediate outer function has non-0 count.

R=caseq@chromium.org, jgruber@chromium.org
BUG=v8:5808

Review-Url: https://codereview.chromium.org/2764073004
Cr-Original-Commit-Position: refs/heads/master@{#44079}
Committed: https://chromium.googlesource.com/v8/v8/+/a7577ede0b74967727895eba5e06dbe1d01fb56d
Review-Url: https://codereview.chromium.org/2764073004
Cr-Commit-Position: refs/heads/master@{#44120}
parent 5fdb5a14
......@@ -121,7 +121,7 @@ Coverage* Coverage::Collect(Isolate* isolate,
// Create and add new script data.
Handle<Script> script_handle(script, isolate);
result->emplace_back(isolate, script_handle);
result->emplace_back(script_handle);
std::vector<CoverageFunction>* functions = &result->back().functions;
std::vector<SharedFunctionInfo*> sorted;
......@@ -135,11 +135,18 @@ Coverage* Coverage::Collect(Isolate* isolate,
std::sort(sorted.begin(), sorted.end(), CompareSharedFunctionInfo);
}
// Stack to track nested functions, referring function by index.
std::vector<size_t> nesting;
// 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);
// Find the correct outer function based on start position.
while (!nesting.empty() && functions->at(nesting.back()).end <= start) {
nesting.pop_back();
}
if (count != 0) {
switch (collectionMode) {
case v8::debug::Coverage::kPreciseCount:
......@@ -152,10 +159,18 @@ Coverage* Coverage::Collect(Isolate* isolate,
count = 1;
break;
}
} else if (nesting.empty() || functions->at(nesting.back()).count == 0) {
// Only include a function range if it has a non-0 count, or
// if it is directly nested inside a function with non-0 count.
continue;
}
Handle<String> name(info->DebugName(), isolate);
nesting.push_back(functions->size());
functions->emplace_back(start, end, count, name);
}
// Remove entries for scripts that have no coverage.
if (functions->empty()) result->pop_back();
}
return result;
}
......
......@@ -27,7 +27,7 @@ struct CoverageFunction {
struct CoverageScript {
// Initialize top-level function in case it has been garbage-collected.
CoverageScript(Isolate* isolate, Handle<Script> s) : script(s) {}
explicit CoverageScript(Handle<Script> s) : script(s) {}
Handle<Script> script;
// Functions are sorted by start position, from outer to inner function.
std::vector<CoverageFunction> functions;
......
......@@ -34,6 +34,22 @@ function h() {
f(3);
`;
var nested =
`
var f = (function outer() {
function nested_0() {
return function nested_1() {
return function nested_2() {
return function nested_3() {}
}
}
}
function nested_4() {}
return nested_0();
})();
f()()();
`;
InspectorTest.log("Test collecting code coverage data with Profiler.collectCoverage.");
function ClearAndGC() {
......@@ -78,8 +94,8 @@ InspectorTest.runTestSuite([
.then(() => Protocol.Profiler.startPreciseCoverage({callCount: true}))
.then(() => Protocol.Runtime.compileScript({ expression: source, sourceURL: arguments.callee.name, persistScript: true }))
.then((result) => Protocol.Runtime.runScript({ scriptId: result.result.scriptId }))
.then(ClearAndGC)
.then(InspectorTest.logMessage)
.then(ClearAndGC)
.then(Protocol.Profiler.takePreciseCoverage)
.then(LogSorted)
.then(Protocol.Profiler.takePreciseCoverage)
......@@ -208,4 +224,44 @@ InspectorTest.runTestSuite([
.then(ClearAndGC)
.then(next);
},
function testPreciseEmptyScriptCoverageEntries(next)
{
// Enabling the debugger holds onto script objects even though its
// functions can be garbage collected. We would get empty ScriptCoverage
// entires unless we remove them.
Protocol.Debugger.enable()
.then(Protocol.Runtime.enable)
.then(() => Protocol.Runtime.compileScript({ expression: source, sourceURL: arguments.callee.name, persistScript: true }))
.then((result) => Protocol.Runtime.runScript({ scriptId: result.result.scriptId }))
.then(ClearAndGC)
.then(Protocol.Profiler.enable)
.then(Protocol.Profiler.startPreciseCoverage)
.then(Protocol.Profiler.takePreciseCoverage)
.then(LogSorted)
.then(Protocol.Profiler.stopPreciseCoverage)
.then(Protocol.Profiler.disable)
.then(Protocol.Runtime.disable)
.then(Protocol.Debugger.disable)
.then(ClearAndGC)
.then(next);
},
function testPreciseCountCoveragePartial(next)
{
Protocol.Runtime.enable()
.then(Protocol.Profiler.enable)
.then(() => Protocol.Profiler.startPreciseCoverage({callCount: true}))
.then(() => Protocol.Runtime.compileScript({ expression: nested, sourceURL: arguments.callee.name, persistScript: true }))
.then((result) => Protocol.Runtime.runScript({ scriptId: result.result.scriptId }))
.then(InspectorTest.logMessage)
.then(Protocol.Profiler.takePreciseCoverage)
.then(LogSorted)
.then(() => Protocol.Runtime.evaluate({ expression: "f()" }))
.then(Protocol.Profiler.takePreciseCoverage)
.then(LogSorted)
.then(Protocol.Profiler.stopPreciseCoverage)
.then(Protocol.Profiler.disable)
.then(Protocol.Runtime.disable)
.then(ClearAndGC)
.then(next);
},
]);
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment