[coverage] Expose block coverage through inspector

This piggy-backs on top of existing precise and best-effort coverage to expose
block coverage through the inspector protocol.

Coverage collection now implicitly reports block-granularity coverage when
available.  A new 'isBlockCoverage' property on Inspector's FunctionCoverage
type specifies the granularity of reported coverage.

For now, only count-based block coverage is supported, but binary block
coverage should follow soon.

Support is still gated behind the --block-coverage flag.

Bug: v8:6000
Cq-Include-Trybots: master.tryserver.chromium.linux:linux_chromium_rel_ng
Change-Id: I9c4d64e1d2a098e66178b3a68dcee800de0081af
Reviewed-on: https://chromium-review.googlesource.com/532975
Commit-Queue: Jakob Gruber <jgruber@chromium.org>
Reviewed-by: Aleksey Kozyatinskiy <kozyatinskiy@chromium.org>
Reviewed-by: Dmitry Gozman <dgozman@chromium.org>
Cr-Commit-Position: refs/heads/master@{#46157}
This commit is contained in:
jgruber 2017-06-22 15:29:35 +02:00 committed by Commit Bot
parent 116363258d
commit 1541f422a7
13 changed files with 1309 additions and 16 deletions

View File

@ -9908,6 +9908,10 @@ size_t debug::Coverage::FunctionData::BlockCount() const {
return function_->blocks.size();
}
bool debug::Coverage::FunctionData::HasBlockCoverage() const {
return function_->has_block_coverage;
}
debug::Coverage::BlockData debug::Coverage::FunctionData::GetBlockData(
size_t i) const {
return BlockData(&function_->blocks.at(i));

View File

@ -131,6 +131,18 @@ std::vector<CoverageBlock> GetSortedBlockData(Isolate* isolate,
return result;
}
void ResetAllBlockCounts(SharedFunctionInfo* shared) {
DCHECK(FLAG_block_coverage);
DCHECK(shared->HasCoverageInfo());
CoverageInfo* coverage_info =
CoverageInfo::cast(shared->GetDebugInfo()->coverage_info());
for (int i = 0; i < coverage_info->SlotCount(); i++) {
coverage_info->ResetBlockCount(i);
}
}
// Rewrite position singletons (produced by unconditional control flow
// like return statements, and by continuation counters) into source
// ranges that end at the next sibling range or the end of the parent
@ -191,11 +203,12 @@ Coverage* Coverage::Collect(Isolate* isolate,
v8::debug::Coverage::Mode collectionMode) {
SharedToCounterMap counter_map;
const bool reset_count = collectionMode != v8::debug::Coverage::kBestEffort;
switch (isolate->code_coverage_mode()) {
case v8::debug::Coverage::kBlockCount:
case v8::debug::Coverage::kPreciseBinary:
case v8::debug::Coverage::kPreciseCount: {
bool reset_count = collectionMode != v8::debug::Coverage::kBestEffort;
// Feedback vectors are already listed to prevent losing them to GC.
DCHECK(isolate->factory()->code_coverage_list()->IsArrayList());
Handle<ArrayList> list =
@ -285,8 +298,12 @@ Coverage* Coverage::Collect(Isolate* isolate,
if (FLAG_block_coverage && info->HasCoverageInfo()) {
CoverageFunction* function = &functions->back();
function->has_block_coverage = true;
function->blocks = GetSortedBlockData(isolate, info);
RewritePositionSingletonsToRanges(function);
// TODO(jgruber): Filter empty block ranges with empty parent ranges.
// We should probably unify handling of function & block ranges.
if (reset_count) ResetAllBlockCounts(info);
}
}
}

View File

@ -26,13 +26,14 @@ struct CoverageBlock {
struct CoverageFunction {
CoverageFunction(int s, int e, uint32_t c, Handle<String> n)
: start(s), end(e), count(c), name(n) {}
: start(s), end(e), count(c), name(n), has_block_coverage(false) {}
int start;
int end;
uint32_t count;
Handle<String> name;
// Blocks are sorted by start position, from outer to inner blocks.
std::vector<CoverageBlock> blocks;
bool has_block_coverage;
};
struct CoverageScript {

View File

@ -276,6 +276,7 @@ class V8_EXPORT_PRIVATE Coverage {
uint32_t Count() const;
MaybeLocal<String> Name() const;
size_t BlockCount() const;
bool HasBlockCoverage() const;
BlockData GetBlockData(size_t i) const;
private:

View File

@ -6,6 +6,7 @@ include_rules = [
"+src/base/logging.h",
"+src/base/platform/platform.h",
"+src/conversions.h",
"+src/flags.h",
"+src/unicode-cache.h",
"+src/inspector",
"+src/tracing",

View File

@ -863,7 +863,8 @@
"description": "Coverage data for a JavaScript function.",
"properties": [
{ "name": "functionName", "type": "string", "description": "JavaScript function name." },
{ "name": "ranges", "type": "array", "items": { "$ref": "CoverageRange" }, "description": "Source ranges inside the function with coverage data." }
{ "name": "ranges", "type": "array", "items": { "$ref": "CoverageRange" }, "description": "Source ranges inside the function with coverage data." },
{ "name": "isBlockCoverage", "type": "boolean", "description": "Whether coverage data for this function has block granularity." }
],
"experimental": true
},

View File

@ -7,6 +7,7 @@
#include <vector>
#include "src/base/atomicops.h"
#include "src/flags.h" // TODO(jgruber): Remove include and DEPS entry.
#include "src/inspector/protocol/Protocol.h"
#include "src/inspector/string-util.h"
#include "src/inspector/v8-debugger.h"
@ -279,9 +280,17 @@ Response V8ProfilerAgentImpl::startPreciseCoverage(Maybe<bool> callCount) {
m_state->setBoolean(ProfilerAgentState::preciseCoverageStarted, true);
m_state->setBoolean(ProfilerAgentState::preciseCoverageCallCount,
callCountValue);
v8::debug::Coverage::SelectMode(
m_isolate, callCountValue ? v8::debug::Coverage::kPreciseCount
: v8::debug::Coverage::kPreciseBinary);
// BlockCount is a superset of PreciseCount. It includes block-granularity
// coverage data if it exists (at the time of writing, that's the case for
// each function recompiled after the BlockCount mode has been set); and
// function-granularity coverage data otherwise.
// TODO(jgruber): Implement block binary coverage.
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::SelectMode(m_isolate,
callCountValue ? count_mode : binary_mode);
return Response::OK();
}
@ -294,6 +303,15 @@ Response V8ProfilerAgentImpl::stopPreciseCoverage() {
}
namespace {
std::unique_ptr<protocol::Profiler::CoverageRange> createCoverageRange(
int start, int end, int count) {
return protocol::Profiler::CoverageRange::create()
.setStartOffset(start)
.setEndOffset(end)
.setCount(count)
.build();
}
Response coverageToProtocol(
v8::Isolate* isolate, const v8::debug::Coverage& coverage,
std::unique_ptr<protocol::Array<protocol::Profiler::ScriptCoverage>>*
@ -311,18 +329,27 @@ Response coverageToProtocol(
script_data.GetFunctionData(j);
std::unique_ptr<protocol::Array<protocol::Profiler::CoverageRange>>
ranges = protocol::Array<protocol::Profiler::CoverageRange>::create();
// At this point we only have per-function coverage data, so there is
// only one range per function.
ranges->addItem(protocol::Profiler::CoverageRange::create()
.setStartOffset(function_data.StartOffset())
.setEndOffset(function_data.EndOffset())
.setCount(function_data.Count())
.build());
// Add function range.
ranges->addItem(createCoverageRange(function_data.StartOffset(),
function_data.EndOffset(),
function_data.Count()));
// Process inner blocks.
for (size_t k = 0; k < function_data.BlockCount(); k++) {
v8::debug::Coverage::BlockData block_data =
function_data.GetBlockData(k);
ranges->addItem(createCoverageRange(block_data.StartOffset(),
block_data.EndOffset(),
block_data.Count()));
}
functions->addItem(
protocol::Profiler::FunctionCoverage::create()
.setFunctionName(toProtocolString(
function_data.Name().FromMaybe(v8::Local<v8::String>())))
.setRanges(std::move(ranges))
.setIsBlockCoverage(function_data.HasBlockCoverage())
.build());
}
String16 url;

View File

@ -326,5 +326,12 @@ void CoverageInfo::IncrementBlockCount(int slot_index) {
set(slot_start + kSlotBlockCountIndex, Smi::FromInt(old_count + 1));
}
void CoverageInfo::ResetBlockCount(int slot_index) {
DCHECK(FLAG_block_coverage);
DCHECK_LT(slot_index, SlotCount());
const int slot_start = CoverageInfo::FirstIndexForSlot(slot_index);
set(slot_start + kSlotBlockCountIndex, Smi::kZero);
}
} // namespace internal
} // namespace v8

View File

@ -154,6 +154,7 @@ class CoverageInfo : public FixedArray {
void InitializeSlot(int slot_index, int start_pos, int end_pos);
void IncrementBlockCount(int slot_index);
void ResetBlockCount(int slot_index);
static int FixedArrayLengthForSlotCount(int slot_count) {
return slot_count * kSlotIndexCount + kFirstSlotIndex;

View File

@ -0,0 +1,922 @@
Test collecting code coverage data with Profiler.collectCoverage.
Running test: testPreciseCountBaseline
{
id : <messageId>
result : {
result : [
[0] : {
functions : [
[0] : {
functionName : fib
isBlockCoverage : false
ranges : [
[0] : {
count : 15
endOffset : 73
startOffset : 1
}
]
}
]
scriptId : <scriptId>
url : testPreciseCountBaseline
}
]
}
}
{
id : <messageId>
result : {
result : [
]
}
}
Running test: testPreciseCountCoverage
{
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 : 73
startOffset : 41
}
]
}
[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
}
]
}
]
scriptId : <scriptId>
url : testPreciseCountCoverage
}
[1] : {
functions : [
[0] : {
functionName :
isBlockCoverage : true
ranges : [
[0] : {
count : 1
endOffset : 38
startOffset : 0
}
]
}
]
scriptId : <scriptId>
url :
}
]
}
}
{
id : <messageId>
result : {
result : [
]
}
}
Running test: testPreciseCoverageFail
{
id : <messageId>
result : {
result : {
description : 8
type : number
value : 8
}
}
}
{
error : {
code : -32000
message : Precise coverage has not been started.
}
id : <messageId>
}
Running test: testBestEffortCoverage
{
id : <messageId>
result : {
result : {
description : 8
type : number
value : 8
}
}
}
{
id : <messageId>
result : {
result : [
]
}
}
{
id : <messageId>
result : {
result : [
]
}
}
Running test: testBestEffortCoverageWithPreciseBinaryEnabled
{
id : <messageId>
result : {
result : {
description : 8
type : number
value : 8
}
}
}
{
id : <messageId>
result : {
result : [
[0] : {
functions : [
[0] : {
functionName :
isBlockCoverage : false
ranges : [
[0] : {
count : 1
endOffset : 221
startOffset : 0
}
]
}
[1] : {
functionName : fib
isBlockCoverage : false
ranges : [
[0] : {
count : 1
endOffset : 73
startOffset : 1
}
]
}
[2] : {
functionName : is_optimized
isBlockCoverage : false
ranges : [
[0] : {
count : 0
endOffset : 175
startOffset : 74
}
]
}
[3] : {
functionName : iife
isBlockCoverage : false
ranges : [
[0] : {
count : 1
endOffset : 208
startOffset : 177
}
]
}
]
scriptId : <scriptId>
url : testBestEffortCoverageWithPreciseBinaryEnabled
}
[1] : {
functions : [
[0] : {
functionName :
isBlockCoverage : false
ranges : [
[0] : {
count : 1
endOffset : 38
startOffset : 0
}
]
}
]
scriptId : <scriptId>
url :
}
]
}
}
{
id : <messageId>
result : {
result : [
[0] : {
functions : [
[0] : {
functionName :
isBlockCoverage : false
ranges : [
[0] : {
count : 1
endOffset : 221
startOffset : 0
}
]
}
[1] : {
functionName : fib
isBlockCoverage : false
ranges : [
[0] : {
count : 1
endOffset : 73
startOffset : 1
}
]
}
[2] : {
functionName : is_optimized
isBlockCoverage : false
ranges : [
[0] : {
count : 0
endOffset : 175
startOffset : 74
}
]
}
[3] : {
functionName : iife
isBlockCoverage : false
ranges : [
[0] : {
count : 1
endOffset : 208
startOffset : 177
}
]
}
]
scriptId : <scriptId>
url : testBestEffortCoverageWithPreciseBinaryEnabled
}
[1] : {
functions : [
[0] : {
functionName :
isBlockCoverage : false
ranges : [
[0] : {
count : 1
endOffset : 38
startOffset : 0
}
]
}
]
scriptId : <scriptId>
url :
}
]
}
}
Running test: testBestEffortCoverageWithPreciseCountEnabled
{
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 : 1
endOffset : 73
startOffset : 1
}
[1] : {
count : 8
endOffset : 41
startOffset : 32
}
[2] : {
count : 7
endOffset : 73
startOffset : 41
}
]
}
[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
}
]
}
]
scriptId : <scriptId>
url : testBestEffortCoverageWithPreciseCountEnabled
}
[1] : {
functions : [
[0] : {
functionName :
isBlockCoverage : true
ranges : [
[0] : {
count : 1
endOffset : 38
startOffset : 0
}
]
}
]
scriptId : <scriptId>
url :
}
]
}
}
{
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 : 1
endOffset : 73
startOffset : 1
}
[1] : {
count : 8
endOffset : 41
startOffset : 32
}
[2] : {
count : 7
endOffset : 73
startOffset : 41
}
]
}
[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
}
]
}
]
scriptId : <scriptId>
url : testBestEffortCoverageWithPreciseCountEnabled
}
[1] : {
functions : [
[0] : {
functionName :
isBlockCoverage : true
ranges : [
[0] : {
count : 1
endOffset : 38
startOffset : 0
}
]
}
]
scriptId : <scriptId>
url :
}
]
}
}
Running test: testEnablePreciseCountCoverageAtPause
{
id : <messageId>
result : {
result : {
type : undefined
}
}
}
{
id : <messageId>
result : {
result : [
[0] : {
functions : [
[0] : {
functionName :
isBlockCoverage : false
ranges : [
[0] : {
count : 1
endOffset : 114
startOffset : 0
}
]
}
[1] : {
functionName : g
isBlockCoverage : false
ranges : [
[0] : {
count : 1
endOffset : 29
startOffset : 1
}
]
}
[2] : {
functionName : f
isBlockCoverage : false
ranges : [
[0] : {
count : 4
endOffset : 83
startOffset : 30
}
]
}
[3] : {
functionName : h
isBlockCoverage : false
ranges : [
[0] : {
count : 0
endOffset : 107
startOffset : 84
}
]
}
]
scriptId : <scriptId>
url : testEnablePreciseCountCoverageAtPause
}
[1] : {
functions : [
[0] : {
functionName :
isBlockCoverage : true
ranges : [
[0] : {
count : 1
endOffset : 38
startOffset : 0
}
]
}
]
scriptId : <scriptId>
url :
}
]
}
}
Running test: testPreciseBinaryCoverage
{
id : <messageId>
result : {
result : {
description : 8
type : number
value : 8
}
}
}
{
id : <messageId>
result : {
result : [
[0] : {
functions : [
[0] : {
functionName :
isBlockCoverage : false
ranges : [
[0] : {
count : 1
endOffset : 221
startOffset : 0
}
]
}
[1] : {
functionName : fib
isBlockCoverage : false
ranges : [
[0] : {
count : 1
endOffset : 73
startOffset : 1
}
]
}
[2] : {
functionName : is_optimized
isBlockCoverage : false
ranges : [
[0] : {
count : 0
endOffset : 175
startOffset : 74
}
]
}
[3] : {
functionName : iife
isBlockCoverage : false
ranges : [
[0] : {
count : 1
endOffset : 208
startOffset : 177
}
]
}
]
scriptId : <scriptId>
url : testPreciseBinaryCoverage
}
]
}
}
{
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 : optimized
}
}
}
{
id : <messageId>
result : {
result : [
[0] : {
functions : [
[0] : {
functionName : is_optimized
isBlockCoverage : false
ranges : [
[0] : {
count : 1
endOffset : 175
startOffset : 74
}
]
}
]
scriptId : <scriptId>
url : testPreciseBinaryCoverage
}
[1] : {
functions : [
[0] : {
functionName :
isBlockCoverage : false
ranges : [
[0] : {
count : 1
endOffset : 17
startOffset : 0
}
]
}
]
scriptId : <scriptId>
url :
}
[2] : {
functions : [
[0] : {
functionName :
isBlockCoverage : false
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 :
isBlockCoverage : true
ranges : [
[0] : {
count : 1
endOffset : 238
startOffset : 0
}
]
}
[1] : {
functionName : outer
isBlockCoverage : true
ranges : [
[0] : {
count : 1
endOffset : 224
startOffset : 10
}
]
}
[2] : {
functionName : nested_0
isBlockCoverage : true
ranges : [
[0] : {
count : 1
endOffset : 176
startOffset : 31
}
]
}
[3] : {
functionName : nested_1
isBlockCoverage : true
ranges : [
[0] : {
count : 1
endOffset : 172
startOffset : 64
}
]
}
[4] : {
functionName : nested_2
isBlockCoverage : true
ranges : [
[0] : {
count : 1
endOffset : 166
startOffset : 99
}
]
}
[5] : {
functionName : nested_3
isBlockCoverage : true
ranges : [
[0] : {
count : 1
endOffset : 158
startOffset : 136
}
]
}
[6] : {
functionName : nested_4
isBlockCoverage : false
ranges : [
[0] : {
count : 0
endOffset : 201
startOffset : 179
}
]
}
]
scriptId : <scriptId>
url : testPreciseCountCoveragePartial
}
]
}
}
{
id : <messageId>
result : {
result : [
[0] : {
functions : [
[0] : {
functionName : nested_1
isBlockCoverage : true
ranges : [
[0] : {
count : 1
endOffset : 172
startOffset : 64
}
]
}
[1] : {
functionName : nested_2
isBlockCoverage : true
ranges : [
[0] : {
count : 0
endOffset : 166
startOffset : 99
}
]
}
]
scriptId : <scriptId>
url : testPreciseCountCoveragePartial
}
[1] : {
functions : [
[0] : {
functionName :
isBlockCoverage : true
ranges : [
[0] : {
count : 1
endOffset : 3
startOffset : 0
}
]
}
]
scriptId : <scriptId>
url :
}
]
}
}

View File

@ -0,0 +1,265 @@
// Copyright 2017 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Flags: --allow-natives-syntax --no-always-opt --opt --block-coverage
var source =
`
function fib(x) {
if (x < 2) return 1;
return fib(x-1) + fib(x-2);
}
function is_optimized(f) {
return (%GetOptimizationStatus(f) & 16) ? "optimized" : "unoptimized";
}
(function iife() {
return 1;
})();
fib(5);
`;
var break_source =
`
function g() {
debugger;
}
function f(x) {
if (x == 0) g();
else f(x - 1);
}
function h() {
g();
}
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()()();
`;
let {session, contextGroup, Protocol} = InspectorTest.start("Test collecting code coverage data with Profiler.collectCoverage.");
function ClearAndGC() {
return Protocol.Runtime.evaluate({ expression: "fib = g = f = h = is_optimized = null;" })
.then(GC);
}
function GC() {
return Protocol.HeapProfiler.collectGarbage();
}
function LogSorted(message) {
message.result.result.sort((a, b) => parseInt(a.scriptId) - parseInt(b.scriptId));
return InspectorTest.logMessage(message);
}
InspectorTest.runTestSuite([
function testPreciseCountBaseline(next)
{
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(GC)
.then(Protocol.Profiler.enable)
.then(() => Protocol.Profiler.startPreciseCoverage({callCount: true}))
.then(Protocol.Profiler.takePreciseCoverage)
.then(LogSorted)
.then(Protocol.Profiler.takePreciseCoverage)
.then(LogSorted)
.then(Protocol.Profiler.stopPreciseCoverage)
.then(Protocol.Profiler.disable)
.then(Protocol.Runtime.disable)
.then(ClearAndGC)
.then(next);
},
function testPreciseCountCoverage(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(ClearAndGC)
.then(Protocol.Profiler.takePreciseCoverage)
.then(LogSorted)
.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()
.then(Protocol.Profiler.enable)
.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(ClearAndGC)
.then(Protocol.Profiler.takePreciseCoverage)
.then(InspectorTest.logMessage)
.then(Protocol.Profiler.disable)
.then(Protocol.Runtime.disable)
.then(ClearAndGC)
.then(next);
},
function testBestEffortCoverage(next)
{
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(InspectorTest.logMessage)
.then(ClearAndGC)
.then(Protocol.Profiler.getBestEffortCoverage)
.then(LogSorted)
.then(Protocol.Profiler.getBestEffortCoverage)
.then(LogSorted)
.then(Protocol.Runtime.disable)
.then(ClearAndGC)
.then(next);
},
function testBestEffortCoverageWithPreciseBinaryEnabled(next)
{
Protocol.Runtime.enable()
.then(Protocol.Profiler.enable)
.then(Protocol.Profiler.startPreciseCoverage)
.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(ClearAndGC)
.then(Protocol.Profiler.getBestEffortCoverage)
.then(LogSorted)
.then(Protocol.Profiler.getBestEffortCoverage)
.then(LogSorted)
.then(ClearAndGC)
.then(Protocol.Profiler.stopPreciseCoverage)
.then(Protocol.Profiler.disable)
.then(Protocol.Runtime.disable)
.then(ClearAndGC)
.then(next);
},
function testBestEffortCoverageWithPreciseCountEnabled(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(ClearAndGC)
.then(Protocol.Profiler.getBestEffortCoverage)
.then(LogSorted)
.then(Protocol.Profiler.getBestEffortCoverage)
.then(LogSorted)
.then(ClearAndGC)
.then(Protocol.Profiler.stopPreciseCoverage)
.then(Protocol.Profiler.disable)
.then(Protocol.Runtime.disable)
.then(ClearAndGC)
.then(next);
},
function testEnablePreciseCountCoverageAtPause(next)
{
function handleDebuggerPause() {
Protocol.Profiler.enable()
.then(() => Protocol.Profiler.startPreciseCoverage({callCount: true}))
.then(Protocol.Debugger.resume)
}
Protocol.Debugger.enable();
Protocol.Debugger.oncePaused().then(handleDebuggerPause);
Protocol.Runtime.enable()
.then(() => Protocol.Runtime.compileScript({ expression: break_source, sourceURL: arguments.callee.name, persistScript: true }))
.then((result) => Protocol.Runtime.runScript({ scriptId: result.result.scriptId }))
.then(InspectorTest.logMessage)
.then(ClearAndGC)
.then(Protocol.Profiler.takePreciseCoverage)
.then(LogSorted)
.then(ClearAndGC)
.then(Protocol.Profiler.stopPreciseCoverage)
.then(Protocol.Profiler.disable)
.then(Protocol.Runtime.disable)
.then(Protocol.Debugger.disable)
.then(ClearAndGC)
.then(next);
},
function testPreciseBinaryCoverage(next)
{
Protocol.Runtime.enable()
.then(Protocol.Profiler.enable)
.then(Protocol.Profiler.startPreciseCoverage)
.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 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);
},
]);

View File

@ -9,6 +9,7 @@ Running test: testPreciseCountBaseline
functions : [
[0] : {
functionName : fib
isBlockCoverage : false
ranges : [
[0] : {
count : 15
@ -51,6 +52,7 @@ Running test: testPreciseCountCoverage
functions : [
[0] : {
functionName :
isBlockCoverage : false
ranges : [
[0] : {
count : 1
@ -61,6 +63,7 @@ Running test: testPreciseCountCoverage
}
[1] : {
functionName : fib
isBlockCoverage : false
ranges : [
[0] : {
count : 15
@ -71,6 +74,7 @@ Running test: testPreciseCountCoverage
}
[2] : {
functionName : is_optimized
isBlockCoverage : false
ranges : [
[0] : {
count : 0
@ -81,6 +85,7 @@ Running test: testPreciseCountCoverage
}
[3] : {
functionName : iife
isBlockCoverage : false
ranges : [
[0] : {
count : 1
@ -97,6 +102,7 @@ Running test: testPreciseCountCoverage
functions : [
[0] : {
functionName :
isBlockCoverage : false
ranges : [
[0] : {
count : 1
@ -184,6 +190,7 @@ Running test: testBestEffortCoverageWithPreciseBinaryEnabled
functions : [
[0] : {
functionName :
isBlockCoverage : false
ranges : [
[0] : {
count : 1
@ -194,6 +201,7 @@ Running test: testBestEffortCoverageWithPreciseBinaryEnabled
}
[1] : {
functionName : fib
isBlockCoverage : false
ranges : [
[0] : {
count : 1
@ -204,6 +212,7 @@ Running test: testBestEffortCoverageWithPreciseBinaryEnabled
}
[2] : {
functionName : is_optimized
isBlockCoverage : false
ranges : [
[0] : {
count : 0
@ -214,6 +223,7 @@ Running test: testBestEffortCoverageWithPreciseBinaryEnabled
}
[3] : {
functionName : iife
isBlockCoverage : false
ranges : [
[0] : {
count : 1
@ -230,6 +240,7 @@ Running test: testBestEffortCoverageWithPreciseBinaryEnabled
functions : [
[0] : {
functionName :
isBlockCoverage : false
ranges : [
[0] : {
count : 1
@ -253,6 +264,7 @@ Running test: testBestEffortCoverageWithPreciseBinaryEnabled
functions : [
[0] : {
functionName :
isBlockCoverage : false
ranges : [
[0] : {
count : 1
@ -263,6 +275,7 @@ Running test: testBestEffortCoverageWithPreciseBinaryEnabled
}
[1] : {
functionName : fib
isBlockCoverage : false
ranges : [
[0] : {
count : 1
@ -273,6 +286,7 @@ Running test: testBestEffortCoverageWithPreciseBinaryEnabled
}
[2] : {
functionName : is_optimized
isBlockCoverage : false
ranges : [
[0] : {
count : 0
@ -283,6 +297,7 @@ Running test: testBestEffortCoverageWithPreciseBinaryEnabled
}
[3] : {
functionName : iife
isBlockCoverage : false
ranges : [
[0] : {
count : 1
@ -299,6 +314,7 @@ Running test: testBestEffortCoverageWithPreciseBinaryEnabled
functions : [
[0] : {
functionName :
isBlockCoverage : false
ranges : [
[0] : {
count : 1
@ -334,6 +350,7 @@ Running test: testBestEffortCoverageWithPreciseCountEnabled
functions : [
[0] : {
functionName :
isBlockCoverage : false
ranges : [
[0] : {
count : 1
@ -344,6 +361,7 @@ Running test: testBestEffortCoverageWithPreciseCountEnabled
}
[1] : {
functionName : fib
isBlockCoverage : false
ranges : [
[0] : {
count : 1
@ -354,6 +372,7 @@ Running test: testBestEffortCoverageWithPreciseCountEnabled
}
[2] : {
functionName : is_optimized
isBlockCoverage : false
ranges : [
[0] : {
count : 0
@ -364,6 +383,7 @@ Running test: testBestEffortCoverageWithPreciseCountEnabled
}
[3] : {
functionName : iife
isBlockCoverage : false
ranges : [
[0] : {
count : 1
@ -380,6 +400,7 @@ Running test: testBestEffortCoverageWithPreciseCountEnabled
functions : [
[0] : {
functionName :
isBlockCoverage : false
ranges : [
[0] : {
count : 1
@ -403,6 +424,7 @@ Running test: testBestEffortCoverageWithPreciseCountEnabled
functions : [
[0] : {
functionName :
isBlockCoverage : false
ranges : [
[0] : {
count : 1
@ -413,6 +435,7 @@ Running test: testBestEffortCoverageWithPreciseCountEnabled
}
[1] : {
functionName : fib
isBlockCoverage : false
ranges : [
[0] : {
count : 1
@ -423,6 +446,7 @@ Running test: testBestEffortCoverageWithPreciseCountEnabled
}
[2] : {
functionName : is_optimized
isBlockCoverage : false
ranges : [
[0] : {
count : 0
@ -433,6 +457,7 @@ Running test: testBestEffortCoverageWithPreciseCountEnabled
}
[3] : {
functionName : iife
isBlockCoverage : false
ranges : [
[0] : {
count : 1
@ -449,6 +474,7 @@ Running test: testBestEffortCoverageWithPreciseCountEnabled
functions : [
[0] : {
functionName :
isBlockCoverage : false
ranges : [
[0] : {
count : 1
@ -482,6 +508,7 @@ Running test: testEnablePreciseCountCoverageAtPause
functions : [
[0] : {
functionName :
isBlockCoverage : false
ranges : [
[0] : {
count : 1
@ -492,6 +519,7 @@ Running test: testEnablePreciseCountCoverageAtPause
}
[1] : {
functionName : g
isBlockCoverage : false
ranges : [
[0] : {
count : 1
@ -502,6 +530,7 @@ Running test: testEnablePreciseCountCoverageAtPause
}
[2] : {
functionName : f
isBlockCoverage : false
ranges : [
[0] : {
count : 4
@ -512,6 +541,7 @@ Running test: testEnablePreciseCountCoverageAtPause
}
[3] : {
functionName : h
isBlockCoverage : false
ranges : [
[0] : {
count : 0
@ -528,6 +558,7 @@ Running test: testEnablePreciseCountCoverageAtPause
functions : [
[0] : {
functionName :
isBlockCoverage : false
ranges : [
[0] : {
count : 1
@ -563,6 +594,7 @@ Running test: testPreciseBinaryCoverage
functions : [
[0] : {
functionName :
isBlockCoverage : false
ranges : [
[0] : {
count : 1
@ -573,6 +605,7 @@ Running test: testPreciseBinaryCoverage
}
[1] : {
functionName : fib
isBlockCoverage : false
ranges : [
[0] : {
count : 1
@ -583,6 +616,7 @@ Running test: testPreciseBinaryCoverage
}
[2] : {
functionName : is_optimized
isBlockCoverage : false
ranges : [
[0] : {
count : 0
@ -593,6 +627,7 @@ Running test: testPreciseBinaryCoverage
}
[3] : {
functionName : iife
isBlockCoverage : false
ranges : [
[0] : {
count : 1
@ -644,6 +679,7 @@ Running test: testPreciseBinaryCoverage
functions : [
[0] : {
functionName : is_optimized
isBlockCoverage : false
ranges : [
[0] : {
count : 1
@ -660,6 +696,7 @@ Running test: testPreciseBinaryCoverage
functions : [
[0] : {
functionName :
isBlockCoverage : false
ranges : [
[0] : {
count : 1
@ -676,6 +713,7 @@ Running test: testPreciseBinaryCoverage
functions : [
[0] : {
functionName :
isBlockCoverage : false
ranges : [
[0] : {
count : 1
@ -718,6 +756,7 @@ Running test: testPreciseCountCoveragePartial
functions : [
[0] : {
functionName :
isBlockCoverage : false
ranges : [
[0] : {
count : 1
@ -728,6 +767,7 @@ Running test: testPreciseCountCoveragePartial
}
[1] : {
functionName : outer
isBlockCoverage : false
ranges : [
[0] : {
count : 1
@ -738,6 +778,7 @@ Running test: testPreciseCountCoveragePartial
}
[2] : {
functionName : nested_0
isBlockCoverage : false
ranges : [
[0] : {
count : 1
@ -748,6 +789,7 @@ Running test: testPreciseCountCoveragePartial
}
[3] : {
functionName : nested_1
isBlockCoverage : false
ranges : [
[0] : {
count : 1
@ -758,6 +800,7 @@ Running test: testPreciseCountCoveragePartial
}
[4] : {
functionName : nested_2
isBlockCoverage : false
ranges : [
[0] : {
count : 1
@ -768,6 +811,7 @@ Running test: testPreciseCountCoveragePartial
}
[5] : {
functionName : nested_3
isBlockCoverage : false
ranges : [
[0] : {
count : 1
@ -778,6 +822,7 @@ Running test: testPreciseCountCoveragePartial
}
[6] : {
functionName : nested_4
isBlockCoverage : false
ranges : [
[0] : {
count : 0
@ -801,6 +846,7 @@ Running test: testPreciseCountCoveragePartial
functions : [
[0] : {
functionName : nested_1
isBlockCoverage : false
ranges : [
[0] : {
count : 1
@ -811,6 +857,7 @@ Running test: testPreciseCountCoveragePartial
}
[1] : {
functionName : nested_2
isBlockCoverage : false
ranges : [
[0] : {
count : 0
@ -827,6 +874,7 @@ Running test: testPreciseCountCoveragePartial
functions : [
[0] : {
functionName :
isBlockCoverage : false
ranges : [
[0] : {
count : 1

View File

@ -58,9 +58,7 @@ function ClearAndGC() {
}
function GC() {
return Protocol.HeapProfiler.enable()
.then(() => Protocol.HeapProfiler.collectGarbage())
.then(() => Protocol.HeapProfiler.disable());
return Protocol.HeapProfiler.collectGarbage();
}
function LogSorted(message) {