[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();
|
MarkAsSourcePositionsEnabled();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (FLAG_block_coverage && isolate->is_block_count_code_coverage() &&
|
if (FLAG_block_coverage && isolate->is_block_code_coverage() &&
|
||||||
parse_info->script()->IsUserJavaScript()) {
|
parse_info->script()->IsUserJavaScript()) {
|
||||||
MarkAsBlockCoverageEnabled();
|
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) {
|
void ResetAllBlockCounts(SharedFunctionInfo* shared) {
|
||||||
DCHECK(FLAG_block_coverage);
|
DCHECK(FLAG_block_coverage);
|
||||||
DCHECK(shared->HasCoverageInfo());
|
DCHECK(shared->HasCoverageInfo());
|
||||||
@ -349,6 +358,9 @@ void CollectBlockCoverage(Isolate* isolate, CoverageFunction* function,
|
|||||||
// Filter out ranges of zero length.
|
// Filter out ranges of zero length.
|
||||||
FilterEmptyRanges(function);
|
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.
|
// Reset all counters on the DebugInfo to zero.
|
||||||
ResetAllBlockCounts(info);
|
ResetAllBlockCounts(info);
|
||||||
}
|
}
|
||||||
@ -357,7 +369,8 @@ void CollectBlockCoverage(Isolate* isolate, CoverageFunction* function,
|
|||||||
Coverage* Coverage::CollectPrecise(Isolate* isolate) {
|
Coverage* Coverage::CollectPrecise(Isolate* isolate) {
|
||||||
DCHECK(!isolate->is_best_effort_code_coverage());
|
DCHECK(!isolate->is_best_effort_code_coverage());
|
||||||
Coverage* result = Collect(isolate, isolate->code_coverage_mode());
|
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
|
// We do not have to hold onto feedback vectors for invocations we already
|
||||||
// reported. So we can reset the list.
|
// reported. So we can reset the list.
|
||||||
isolate->SetCodeCoverageList(*ArrayList::New(isolate, 0));
|
isolate->SetCodeCoverageList(*ArrayList::New(isolate, 0));
|
||||||
@ -376,6 +389,7 @@ Coverage* Coverage::Collect(Isolate* isolate,
|
|||||||
const bool reset_count = collectionMode != v8::debug::Coverage::kBestEffort;
|
const bool reset_count = collectionMode != v8::debug::Coverage::kBestEffort;
|
||||||
|
|
||||||
switch (isolate->code_coverage_mode()) {
|
switch (isolate->code_coverage_mode()) {
|
||||||
|
case v8::debug::Coverage::kBlockBinary:
|
||||||
case v8::debug::Coverage::kBlockCount:
|
case v8::debug::Coverage::kBlockCount:
|
||||||
case v8::debug::Coverage::kPreciseBinary:
|
case v8::debug::Coverage::kPreciseBinary:
|
||||||
case v8::debug::Coverage::kPreciseCount: {
|
case v8::debug::Coverage::kPreciseCount: {
|
||||||
@ -449,6 +463,7 @@ Coverage* Coverage::Collect(Isolate* isolate,
|
|||||||
case v8::debug::Coverage::kBlockCount:
|
case v8::debug::Coverage::kBlockCount:
|
||||||
case v8::debug::Coverage::kPreciseCount:
|
case v8::debug::Coverage::kPreciseCount:
|
||||||
break;
|
break;
|
||||||
|
case v8::debug::Coverage::kBlockBinary:
|
||||||
case v8::debug::Coverage::kPreciseBinary:
|
case v8::debug::Coverage::kPreciseBinary:
|
||||||
count = info->has_reported_binary_coverage() ? 0 : 1;
|
count = info->has_reported_binary_coverage() ? 0 : 1;
|
||||||
info->set_has_reported_binary_coverage(true);
|
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();
|
if (FLAG_block_coverage) isolate->debug()->RemoveAllCoverageInfos();
|
||||||
isolate->SetCodeCoverageList(isolate->heap()->undefined_value());
|
isolate->SetCodeCoverageList(isolate->heap()->undefined_value());
|
||||||
break;
|
break;
|
||||||
|
case debug::Coverage::kBlockBinary:
|
||||||
case debug::Coverage::kBlockCount:
|
case debug::Coverage::kBlockCount:
|
||||||
case debug::Coverage::kPreciseBinary:
|
case debug::Coverage::kPreciseBinary:
|
||||||
case debug::Coverage::kPreciseCount: {
|
case debug::Coverage::kPreciseCount: {
|
||||||
|
@ -250,6 +250,7 @@ class V8_EXPORT_PRIVATE Coverage {
|
|||||||
// Similar to the precise coverage modes but provides coverage at a
|
// Similar to the precise coverage modes but provides coverage at a
|
||||||
// lower granularity. Design doc: goo.gl/lA2swZ.
|
// lower granularity. Design doc: goo.gl/lA2swZ.
|
||||||
kBlockCount,
|
kBlockCount,
|
||||||
|
kBlockBinary,
|
||||||
};
|
};
|
||||||
|
|
||||||
// Forward declarations.
|
// Forward declarations.
|
||||||
|
@ -288,7 +288,9 @@ Response V8ProfilerAgentImpl::startPreciseCoverage(Maybe<bool> callCount) {
|
|||||||
v8::debug::Coverage::Mode count_mode =
|
v8::debug::Coverage::Mode count_mode =
|
||||||
v8::internal::FLAG_block_coverage ? v8::debug::Coverage::kBlockCount
|
v8::internal::FLAG_block_coverage ? v8::debug::Coverage::kBlockCount
|
||||||
: v8::debug::Coverage::kPreciseCount;
|
: 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,
|
v8::debug::Coverage::SelectMode(m_isolate,
|
||||||
callCountValue ? count_mode : binary_mode);
|
callCountValue ? count_mode : binary_mode);
|
||||||
return Response::OK();
|
return Response::OK();
|
||||||
|
@ -1001,6 +1001,14 @@ class Isolate {
|
|||||||
return code_coverage_mode() == debug::Coverage::kBlockCount;
|
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);
|
void SetCodeCoverageList(Object* value);
|
||||||
|
|
||||||
double time_millis_since_init() {
|
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
|
Running test: testPreciseCoverageFail
|
||||||
{
|
{
|
||||||
id : <messageId>
|
id : <messageId>
|
||||||
|
@ -104,6 +104,30 @@ InspectorTest.runTestSuite([
|
|||||||
.then(ClearAndGC)
|
.then(ClearAndGC)
|
||||||
.then(next);
|
.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)
|
function testPreciseCoverageFail(next)
|
||||||
{
|
{
|
||||||
Protocol.Runtime.enable()
|
Protocol.Runtime.enable()
|
||||||
|
Loading…
Reference in New Issue
Block a user