Commit a7577ede 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-Commit-Position: refs/heads/master@{#44079}
parent b123ee34
......@@ -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;
......
......@@ -17,16 +17,6 @@ Running test: testPreciseCountBaseline
}
]
}
[1] : {
functionName : is_optimized
ranges : [
[0] : {
count : 0
endOffset : 175
startOffset : 74
}
]
}
]
scriptId : <scriptId>
url : testPreciseCountBaseline
......@@ -38,32 +28,6 @@ Running test: testPreciseCountBaseline
id : <messageId>
result : {
result : [
[0] : {
functions : [
[0] : {
functionName : fib
ranges : [
[0] : {
count : 0
endOffset : 73
startOffset : 1
}
]
}
[1] : {
functionName : is_optimized
ranges : [
[0] : {
count : 0
endOffset : 175
startOffset : 74
}
]
}
]
scriptId : <scriptId>
url : testPreciseCountBaseline
}
]
}
}
......@@ -72,6 +36,11 @@ Running test: testPreciseCountCoverage
{
id : <messageId>
result : {
result : {
description : 8
type : number
value : 8
}
}
}
{
......@@ -147,68 +116,6 @@ Running test: testPreciseCountCoverage
id : <messageId>
result : {
result : [
[0] : {
functions : [
[0] : {
functionName :
ranges : [
[0] : {
count : 0
endOffset : 221
startOffset : 0
}
]
}
[1] : {
functionName : fib
ranges : [
[0] : {
count : 0
endOffset : 73
startOffset : 1
}
]
}
[2] : {
functionName : is_optimized
ranges : [
[0] : {
count : 0
endOffset : 175
startOffset : 74
}
]
}
[3] : {
functionName : iife
ranges : [
[0] : {
count : 0
endOffset : 208
startOffset : 177
}
]
}
]
scriptId : <scriptId>
url : testPreciseCountCoverage
}
[1] : {
functions : [
[0] : {
functionName :
ranges : [
[0] : {
count : 0
endOffset : 38
startOffset : 0
}
]
}
]
scriptId : <scriptId>
url :
}
]
}
}
......@@ -734,75 +641,196 @@ Running test: testPreciseBinaryCoverage
result : {
result : [
[0] : {
functions : [
[0] : {
functionName : is_optimized
ranges : [
[0] : {
count : 1
endOffset : 175
startOffset : 74
}
]
}
]
scriptId : <scriptId>
url : testPreciseBinaryCoverage
}
[1] : {
functions : [
[0] : {
functionName :
ranges : [
[0] : {
count : 0
endOffset : 221
count : 1
endOffset : 17
startOffset : 0
}
]
}
]
scriptId : <scriptId>
url :
}
[2] : {
functions : [
[0] : {
functionName :
ranges : [
[0] : {
count : 1
endOffset : 7
startOffset : 0
}
]
}
]
scriptId : <scriptId>
url :
}
]
}
}
Running test: testPreciseEmptyScriptCoverageEntries
{
id : <messageId>
result : {
result : [
]
}
}
Running test: testPreciseCountCoveragePartial
{
id : <messageId>
result : {
result : {
type : undefined
}
}
}
{
id : <messageId>
result : {
result : [
[0] : {
functions : [
[0] : {
functionName :
ranges : [
[0] : {
count : 1
endOffset : 238
startOffset : 0
}
]
}
[1] : {
functionName : fib
functionName : outer
ranges : [
[0] : {
count : 0
endOffset : 73
startOffset : 1
count : 1
endOffset : 224
startOffset : 10
}
]
}
[2] : {
functionName : is_optimized
functionName : nested_0
ranges : [
[0] : {
count : 1
endOffset : 175
startOffset : 74
endOffset : 176
startOffset : 31
}
]
}
[3] : {
functionName : iife
functionName : nested_1
ranges : [
[0] : {
count : 1
endOffset : 172
startOffset : 64
}
]
}
[4] : {
functionName : nested_2
ranges : [
[0] : {
count : 1
endOffset : 166
startOffset : 99
}
]
}
[5] : {
functionName : nested_3
ranges : [
[0] : {
count : 1
endOffset : 158
startOffset : 136
}
]
}
[6] : {
functionName : nested_4
ranges : [
[0] : {
count : 0
endOffset : 208
startOffset : 177
endOffset : 201
startOffset : 179
}
]
}
]
scriptId : <scriptId>
url : testPreciseBinaryCoverage
url : testPreciseCountCoveragePartial
}
[1] : {
]
}
}
{
id : <messageId>
result : {
result : [
[0] : {
functions : [
[0] : {
functionName :
functionName : nested_1
ranges : [
[0] : {
count : 1
endOffset : 17
startOffset : 0
endOffset : 172
startOffset : 64
}
]
}
[1] : {
functionName : nested_2
ranges : [
[0] : {
count : 0
endOffset : 166
startOffset : 99
}
]
}
]
scriptId : <scriptId>
url :
url : testPreciseCountCoveragePartial
}
[2] : {
[1] : {
functions : [
[0] : {
functionName :
ranges : [
[0] : {
count : 1
endOffset : 7
endOffset : 3
startOffset : 0
}
]
......
......@@ -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