[coverage] Add binary block coverage
This adds a new binary block coverage mode (in addition to the existing count block coverage), as well as a few transformation passes to reduce the number of uselessly reported ranges. Bug: v8:6000 Change-Id: I4fb234ca015990d00aa2f1dccb87f76ba4748994 Reviewed-on: https://chromium-review.googlesource.com/552642 Commit-Queue: Jakob Gruber <jgruber@chromium.org> Reviewed-by: Aleksey Kozyatinskiy <kozyatinskiy@chromium.org> Cr-Commit-Position: refs/heads/master@{#46463}
This commit is contained in:
parent
086fdedb33
commit
bfc0bc8f83
@ -69,7 +69,7 @@ CompilationInfo::CompilationInfo(Zone* zone, ParseInfo* parse_info,
|
||||
MarkAsSourcePositionsEnabled();
|
||||
}
|
||||
|
||||
if (FLAG_block_coverage && isolate->is_block_count_code_coverage() &&
|
||||
if (FLAG_block_coverage && isolate->is_block_code_coverage() &&
|
||||
parse_info->script()->IsUserJavaScript()) {
|
||||
MarkAsBlockCoverageEnabled();
|
||||
}
|
||||
|
@ -302,6 +302,15 @@ void FilterEmptyRanges(CoverageFunction* function) {
|
||||
}
|
||||
}
|
||||
|
||||
void ClampToBinary(CoverageFunction* function) {
|
||||
CoverageBlockIterator iter(function);
|
||||
|
||||
while (iter.Next()) {
|
||||
CoverageBlock& block = iter.GetBlock();
|
||||
if (block.count > 0) block.count = 1;
|
||||
}
|
||||
}
|
||||
|
||||
void ResetAllBlockCounts(SharedFunctionInfo* shared) {
|
||||
DCHECK(FLAG_block_coverage);
|
||||
DCHECK(shared->HasCoverageInfo());
|
||||
@ -349,6 +358,9 @@ void CollectBlockCoverage(Isolate* isolate, CoverageFunction* function,
|
||||
// Filter out ranges of zero length.
|
||||
FilterEmptyRanges(function);
|
||||
|
||||
// If in binary mode, only report counts of 0/1.
|
||||
if (mode == debug::Coverage::kBlockBinary) ClampToBinary(function);
|
||||
|
||||
// Reset all counters on the DebugInfo to zero.
|
||||
ResetAllBlockCounts(info);
|
||||
}
|
||||
@ -357,7 +369,8 @@ void CollectBlockCoverage(Isolate* isolate, CoverageFunction* function,
|
||||
Coverage* Coverage::CollectPrecise(Isolate* isolate) {
|
||||
DCHECK(!isolate->is_best_effort_code_coverage());
|
||||
Coverage* result = Collect(isolate, isolate->code_coverage_mode());
|
||||
if (isolate->is_precise_binary_code_coverage()) {
|
||||
if (isolate->is_precise_binary_code_coverage() ||
|
||||
isolate->is_block_binary_code_coverage()) {
|
||||
// We do not have to hold onto feedback vectors for invocations we already
|
||||
// reported. So we can reset the list.
|
||||
isolate->SetCodeCoverageList(*ArrayList::New(isolate, 0));
|
||||
@ -376,6 +389,7 @@ Coverage* Coverage::Collect(Isolate* isolate,
|
||||
const bool reset_count = collectionMode != v8::debug::Coverage::kBestEffort;
|
||||
|
||||
switch (isolate->code_coverage_mode()) {
|
||||
case v8::debug::Coverage::kBlockBinary:
|
||||
case v8::debug::Coverage::kBlockCount:
|
||||
case v8::debug::Coverage::kPreciseBinary:
|
||||
case v8::debug::Coverage::kPreciseCount: {
|
||||
@ -449,6 +463,7 @@ Coverage* Coverage::Collect(Isolate* isolate,
|
||||
case v8::debug::Coverage::kBlockCount:
|
||||
case v8::debug::Coverage::kPreciseCount:
|
||||
break;
|
||||
case v8::debug::Coverage::kBlockBinary:
|
||||
case v8::debug::Coverage::kPreciseBinary:
|
||||
count = info->has_reported_binary_coverage() ? 0 : 1;
|
||||
info->set_has_reported_binary_coverage(true);
|
||||
@ -490,6 +505,7 @@ void Coverage::SelectMode(Isolate* isolate, debug::Coverage::Mode mode) {
|
||||
if (FLAG_block_coverage) isolate->debug()->RemoveAllCoverageInfos();
|
||||
isolate->SetCodeCoverageList(isolate->heap()->undefined_value());
|
||||
break;
|
||||
case debug::Coverage::kBlockBinary:
|
||||
case debug::Coverage::kBlockCount:
|
||||
case debug::Coverage::kPreciseBinary:
|
||||
case debug::Coverage::kPreciseCount: {
|
||||
|
@ -250,6 +250,7 @@ class V8_EXPORT_PRIVATE Coverage {
|
||||
// Similar to the precise coverage modes but provides coverage at a
|
||||
// lower granularity. Design doc: goo.gl/lA2swZ.
|
||||
kBlockCount,
|
||||
kBlockBinary,
|
||||
};
|
||||
|
||||
// Forward declarations.
|
||||
|
@ -288,7 +288,9 @@ Response V8ProfilerAgentImpl::startPreciseCoverage(Maybe<bool> callCount) {
|
||||
v8::debug::Coverage::Mode count_mode =
|
||||
v8::internal::FLAG_block_coverage ? v8::debug::Coverage::kBlockCount
|
||||
: v8::debug::Coverage::kPreciseCount;
|
||||
v8::debug::Coverage::Mode binary_mode = v8::debug::Coverage::kPreciseBinary;
|
||||
v8::debug::Coverage::Mode binary_mode =
|
||||
v8::internal::FLAG_block_coverage ? v8::debug::Coverage::kBlockBinary
|
||||
: v8::debug::Coverage::kPreciseBinary;
|
||||
v8::debug::Coverage::SelectMode(m_isolate,
|
||||
callCountValue ? count_mode : binary_mode);
|
||||
return Response::OK();
|
||||
|
@ -1001,6 +1001,14 @@ class Isolate {
|
||||
return code_coverage_mode() == debug::Coverage::kBlockCount;
|
||||
}
|
||||
|
||||
bool is_block_binary_code_coverage() const {
|
||||
return code_coverage_mode() == debug::Coverage::kBlockBinary;
|
||||
}
|
||||
|
||||
bool is_block_code_coverage() const {
|
||||
return is_block_count_code_coverage() || is_block_binary_code_coverage();
|
||||
}
|
||||
|
||||
void SetCodeCoverageList(Object* value);
|
||||
|
||||
double time_millis_since_init() {
|
||||
|
@ -146,6 +146,212 @@ Running test: testPreciseCountCoverage
|
||||
}
|
||||
}
|
||||
|
||||
Running test: testPreciseCountCoverageIncremental
|
||||
{
|
||||
id : <messageId>
|
||||
result : {
|
||||
result : {
|
||||
description : 8
|
||||
type : number
|
||||
value : 8
|
||||
}
|
||||
}
|
||||
}
|
||||
{
|
||||
id : <messageId>
|
||||
result : {
|
||||
result : [
|
||||
[0] : {
|
||||
functions : [
|
||||
[0] : {
|
||||
functionName :
|
||||
isBlockCoverage : true
|
||||
ranges : [
|
||||
[0] : {
|
||||
count : 1
|
||||
endOffset : 221
|
||||
startOffset : 0
|
||||
}
|
||||
]
|
||||
}
|
||||
[1] : {
|
||||
functionName : fib
|
||||
isBlockCoverage : true
|
||||
ranges : [
|
||||
[0] : {
|
||||
count : 15
|
||||
endOffset : 73
|
||||
startOffset : 1
|
||||
}
|
||||
[1] : {
|
||||
count : 8
|
||||
endOffset : 41
|
||||
startOffset : 32
|
||||
}
|
||||
[2] : {
|
||||
count : 7
|
||||
endOffset : 71
|
||||
startOffset : 41
|
||||
}
|
||||
[3] : {
|
||||
count : 0
|
||||
endOffset : 73
|
||||
startOffset : 71
|
||||
}
|
||||
]
|
||||
}
|
||||
[2] : {
|
||||
functionName : is_optimized
|
||||
isBlockCoverage : false
|
||||
ranges : [
|
||||
[0] : {
|
||||
count : 0
|
||||
endOffset : 175
|
||||
startOffset : 74
|
||||
}
|
||||
]
|
||||
}
|
||||
[3] : {
|
||||
functionName : iife
|
||||
isBlockCoverage : true
|
||||
ranges : [
|
||||
[0] : {
|
||||
count : 1
|
||||
endOffset : 208
|
||||
startOffset : 177
|
||||
}
|
||||
[1] : {
|
||||
count : 0
|
||||
endOffset : 208
|
||||
startOffset : 206
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
scriptId : <scriptId>
|
||||
url : testPreciseCountCoverageIncremental
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
{
|
||||
id : <messageId>
|
||||
result : {
|
||||
result : {
|
||||
type : string
|
||||
value : unoptimized
|
||||
}
|
||||
}
|
||||
}
|
||||
{
|
||||
id : <messageId>
|
||||
result : {
|
||||
result : {
|
||||
description : 10946
|
||||
type : number
|
||||
value : 10946
|
||||
}
|
||||
}
|
||||
}
|
||||
{
|
||||
id : <messageId>
|
||||
result : {
|
||||
result : {
|
||||
type : string
|
||||
value : unoptimized
|
||||
}
|
||||
}
|
||||
}
|
||||
{
|
||||
id : <messageId>
|
||||
result : {
|
||||
result : [
|
||||
[0] : {
|
||||
functions : [
|
||||
[0] : {
|
||||
functionName : fib
|
||||
isBlockCoverage : true
|
||||
ranges : [
|
||||
[0] : {
|
||||
count : 21891
|
||||
endOffset : 73
|
||||
startOffset : 1
|
||||
}
|
||||
[1] : {
|
||||
count : 10946
|
||||
endOffset : 41
|
||||
startOffset : 32
|
||||
}
|
||||
[2] : {
|
||||
count : 10945
|
||||
endOffset : 71
|
||||
startOffset : 41
|
||||
}
|
||||
[3] : {
|
||||
count : 0
|
||||
endOffset : 73
|
||||
startOffset : 71
|
||||
}
|
||||
]
|
||||
}
|
||||
[1] : {
|
||||
functionName : is_optimized
|
||||
isBlockCoverage : true
|
||||
ranges : [
|
||||
[0] : {
|
||||
count : 2
|
||||
endOffset : 175
|
||||
startOffset : 74
|
||||
}
|
||||
[1] : {
|
||||
count : 0
|
||||
endOffset : 175
|
||||
startOffset : 173
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
scriptId : <scriptId>
|
||||
url : testPreciseCountCoverageIncremental
|
||||
}
|
||||
[1] : {
|
||||
functions : [
|
||||
[0] : {
|
||||
functionName :
|
||||
isBlockCoverage : true
|
||||
ranges : [
|
||||
[0] : {
|
||||
count : 2
|
||||
endOffset : 17
|
||||
startOffset : 0
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
scriptId : <scriptId>
|
||||
url :
|
||||
}
|
||||
[2] : {
|
||||
functions : [
|
||||
[0] : {
|
||||
functionName :
|
||||
isBlockCoverage : true
|
||||
ranges : [
|
||||
[0] : {
|
||||
count : 1
|
||||
endOffset : 7
|
||||
startOffset : 0
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
scriptId : <scriptId>
|
||||
url :
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
Running test: testPreciseCoverageFail
|
||||
{
|
||||
id : <messageId>
|
||||
|
@ -104,6 +104,30 @@ InspectorTest.runTestSuite([
|
||||
.then(ClearAndGC)
|
||||
.then(next);
|
||||
},
|
||||
function testPreciseCountCoverageIncremental(next)
|
||||
{
|
||||
Protocol.Runtime.enable()
|
||||
.then(Protocol.Profiler.enable)
|
||||
.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(InspectorTest.logMessage)
|
||||
.then(Protocol.Profiler.takePreciseCoverage)
|
||||
.then(LogSorted)
|
||||
.then(() => Protocol.Runtime.evaluate({ expression: "is_optimized(fib)" }))
|
||||
.then(message => InspectorTest.logMessage(message))
|
||||
.then(() => Protocol.Runtime.evaluate({ expression: "fib(20)" }))
|
||||
.then(message => InspectorTest.logMessage(message))
|
||||
.then(() => Protocol.Runtime.evaluate({ expression: "is_optimized(fib)" }))
|
||||
.then(message => InspectorTest.logMessage(message))
|
||||
.then(Protocol.Profiler.takePreciseCoverage)
|
||||
.then(LogSorted)
|
||||
.then(Protocol.Profiler.stopPreciseCoverage)
|
||||
.then(Protocol.Profiler.disable)
|
||||
.then(Protocol.Runtime.disable)
|
||||
.then(ClearAndGC)
|
||||
.then(next);
|
||||
},
|
||||
function testPreciseCoverageFail(next)
|
||||
{
|
||||
Protocol.Runtime.enable()
|
||||
|
Loading…
Reference in New Issue
Block a user