Commit 64a563c9 authored by kozyatinskiy's avatar kozyatinskiy Committed by Commit bot

[inspector] move coverage related methods to profiler

R=dgozman@chromium.org, pfeldman@chromium.org
BUG=v8:5808

Review-Url: https://codereview.chromium.org/2715833003
Cr-Commit-Position: refs/heads/master@{#43426}
parent 6b7650f0
...@@ -204,38 +204,6 @@ ...@@ -204,38 +204,6 @@
{ "name": "parent", "$ref": "StackTrace", "optional": true, "description": "Asynchronous JavaScript stack trace that preceded this stack, if available." }, { "name": "parent", "$ref": "StackTrace", "optional": true, "description": "Asynchronous JavaScript stack trace that preceded this stack, if available." },
{ "name": "promiseCreationFrame", "$ref": "CallFrame", "optional": true, "experimental": true, "description": "Creation frame of the Promise which produced the next synchronous trace when resolved, if available." } { "name": "promiseCreationFrame", "$ref": "CallFrame", "optional": true, "experimental": true, "description": "Creation frame of the Promise which produced the next synchronous trace when resolved, if available." }
] ]
},
{ "id": "CoverageRange",
"type": "object",
"description": "Coverage data for a source range.",
"properties": [
{ "name": "startLineNumber", "type": "integer", "description": "JavaScript script line number (0-based) for the range start." },
{ "name": "startColumnNumber", "type": "integer", "description": "JavaScript script column number (0-based) for the range start." },
{ "name": "endLineNumber", "type": "integer", "description": "JavaScript script line number (0-based) for the range end." },
{ "name": "endColumnNumber", "type": "integer", "description": "JavaScript script column number (0-based) for the range end." },
{ "name": "count", "type": "integer", "description": "Collected execution count of the source range." }
],
"experimental": "true"
},
{ "id": "FunctionCoverage",
"type": "object",
"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." }
],
"experimental": "true"
},
{
"id": "ScriptCoverage",
"type": "object",
"description": "Coverage data for a JavaScript script.",
"properties": [
{ "name": "scriptId", "$ref": "ScriptId", "description": "JavaScript script id." },
{ "name": "url", "type": "string", "description": "JavaScript script name or url." },
{ "name": "functions", "type": "array", "items": { "$ref": "FunctionCoverage" }, "description": "Functions contained in the script that has coverage data." }
],
"experimental": "true"
} }
], ],
"commands": [ "commands": [
...@@ -375,32 +343,6 @@ ...@@ -375,32 +343,6 @@
{ "name": "exceptionDetails", "$ref": "ExceptionDetails", "optional": true, "description": "Exception details."} { "name": "exceptionDetails", "$ref": "ExceptionDetails", "optional": true, "description": "Exception details."}
], ],
"description": "Runs script with given id in a given context." "description": "Runs script with given id in a given context."
},
{
"name": "startPreciseCoverage",
"description": "Enable precise code coverage. Coverage data for JavaScript executed before enabling precise code coverage may be incomplete. Enabling prevents running optimized code and resets execution counters.",
"experimental": true
},
{
"name": "stopPreciseCoverage",
"description": "Disable precise code coverage. Disabling releases unnecessary execution count records and allows executing optimized code.",
"experimental": true
},
{
"name": "takePreciseCoverage",
"returns": [
{ "name": "result", "type": "array", "items": { "$ref": "ScriptCoverage" }, "description": "Coverage data for the current isolate." }
],
"description": "Collect coverage data for the current isolate, and resets execution counters. Precise code coverage needs to have started.",
"experimental": true
},
{
"name": "getBestEffortCoverage",
"returns": [
{ "name": "result", "type": "array", "items": { "$ref": "ScriptCoverage" }, "description": "Coverage data for the current isolate." }
],
"description": "Collect coverage data for the current isolate. The coverage data may be incomplete due to garbage collection.",
"experimental": true
} }
], ],
"events": [ "events": [
...@@ -882,6 +824,38 @@ ...@@ -882,6 +824,38 @@
{ "name": "line", "type": "integer", "description": "Source line number (1-based)." }, { "name": "line", "type": "integer", "description": "Source line number (1-based)." },
{ "name": "ticks", "type": "integer", "description": "Number of samples attributed to the source line." } { "name": "ticks", "type": "integer", "description": "Number of samples attributed to the source line." }
] ]
},
{ "id": "CoverageRange",
"type": "object",
"description": "Coverage data for a source range.",
"properties": [
{ "name": "startLineNumber", "type": "integer", "description": "JavaScript script line number (0-based) for the range start." },
{ "name": "startColumnNumber", "type": "integer", "description": "JavaScript script column number (0-based) for the range start." },
{ "name": "endLineNumber", "type": "integer", "description": "JavaScript script line number (0-based) for the range end." },
{ "name": "endColumnNumber", "type": "integer", "description": "JavaScript script column number (0-based) for the range end." },
{ "name": "count", "type": "integer", "description": "Collected execution count of the source range." }
],
"experimental": true
},
{ "id": "FunctionCoverage",
"type": "object",
"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." }
],
"experimental": true
},
{
"id": "ScriptCoverage",
"type": "object",
"description": "Coverage data for a JavaScript script.",
"properties": [
{ "name": "scriptId", "$ref": "Runtime.ScriptId", "description": "JavaScript script id." },
{ "name": "url", "type": "string", "description": "JavaScript script name or url." },
{ "name": "functions", "type": "array", "items": { "$ref": "FunctionCoverage" }, "description": "Functions contained in the script that has coverage data." }
],
"experimental": true
} }
], ],
"commands": [ "commands": [
...@@ -906,6 +880,32 @@ ...@@ -906,6 +880,32 @@
"returns": [ "returns": [
{ "name": "profile", "$ref": "Profile", "description": "Recorded profile." } { "name": "profile", "$ref": "Profile", "description": "Recorded profile." }
] ]
},
{
"name": "startPreciseCoverage",
"description": "Enable precise code coverage. Coverage data for JavaScript executed before enabling precise code coverage may be incomplete. Enabling prevents running optimized code and resets execution counters.",
"experimental": true
},
{
"name": "stopPreciseCoverage",
"description": "Disable precise code coverage. Disabling releases unnecessary execution count records and allows executing optimized code.",
"experimental": true
},
{
"name": "takePreciseCoverage",
"returns": [
{ "name": "result", "type": "array", "items": { "$ref": "ScriptCoverage" }, "description": "Coverage data for the current isolate." }
],
"description": "Collect coverage data for the current isolate, and resets execution counters. Precise code coverage needs to have started.",
"experimental": true
},
{
"name": "getBestEffortCoverage",
"returns": [
{ "name": "result", "type": "array", "items": { "$ref": "ScriptCoverage" }, "description": "Coverage data for the current isolate." }
],
"description": "Collect coverage data for the current isolate. The coverage data may be incomplete due to garbage collection.",
"experimental": true
} }
], ],
"events": [ "events": [
......
...@@ -22,6 +22,7 @@ namespace ProfilerAgentState { ...@@ -22,6 +22,7 @@ namespace ProfilerAgentState {
static const char samplingInterval[] = "samplingInterval"; static const char samplingInterval[] = "samplingInterval";
static const char userInitiatedProfiling[] = "userInitiatedProfiling"; static const char userInitiatedProfiling[] = "userInitiatedProfiling";
static const char profilerEnabled[] = "profilerEnabled"; static const char profilerEnabled[] = "profilerEnabled";
static const char preciseCoverageStarted[] = "preciseCoverageStarted";
} }
namespace { namespace {
...@@ -152,11 +153,8 @@ V8ProfilerAgentImpl::V8ProfilerAgentImpl( ...@@ -152,11 +153,8 @@ V8ProfilerAgentImpl::V8ProfilerAgentImpl(
protocol::DictionaryValue* state) protocol::DictionaryValue* state)
: m_session(session), : m_session(session),
m_isolate(m_session->inspector()->isolate()), m_isolate(m_session->inspector()->isolate()),
m_profiler(nullptr),
m_state(state), m_state(state),
m_frontend(frontendChannel), m_frontend(frontendChannel) {}
m_enabled(false),
m_recordingCPUProfile(false) {}
V8ProfilerAgentImpl::~V8ProfilerAgentImpl() { V8ProfilerAgentImpl::~V8ProfilerAgentImpl() {
if (m_profiler) m_profiler->Dispose(); if (m_profiler) m_profiler->Dispose();
...@@ -204,8 +202,6 @@ void V8ProfilerAgentImpl::consoleProfileEnd(const String16& title) { ...@@ -204,8 +202,6 @@ void V8ProfilerAgentImpl::consoleProfileEnd(const String16& title) {
Response V8ProfilerAgentImpl::enable() { Response V8ProfilerAgentImpl::enable() {
if (m_enabled) return Response::OK(); if (m_enabled) return Response::OK();
m_enabled = true; m_enabled = true;
DCHECK(!m_profiler);
m_profiler = v8::CpuProfiler::New(m_isolate);
m_state->setBoolean(ProfilerAgentState::profilerEnabled, true); m_state->setBoolean(ProfilerAgentState::profilerEnabled, true);
return Response::OK(); return Response::OK();
} }
...@@ -216,18 +212,18 @@ Response V8ProfilerAgentImpl::disable() { ...@@ -216,18 +212,18 @@ Response V8ProfilerAgentImpl::disable() {
stopProfiling(m_startedProfiles[i - 1].m_id, false); stopProfiling(m_startedProfiles[i - 1].m_id, false);
m_startedProfiles.clear(); m_startedProfiles.clear();
stop(nullptr); stop(nullptr);
m_profiler->Dispose(); stopPreciseCoverage();
m_profiler = nullptr; DCHECK(!m_profiler);
m_enabled = false; m_enabled = false;
m_state->setBoolean(ProfilerAgentState::profilerEnabled, false); m_state->setBoolean(ProfilerAgentState::profilerEnabled, false);
return Response::OK(); return Response::OK();
} }
Response V8ProfilerAgentImpl::setSamplingInterval(int interval) { Response V8ProfilerAgentImpl::setSamplingInterval(int interval) {
if (m_recordingCPUProfile) if (m_profiler) {
return Response::Error("Cannot change sampling interval when profiling."); return Response::Error("Cannot change sampling interval when profiling.");
}
m_state->setInteger(ProfilerAgentState::samplingInterval, interval); m_state->setInteger(ProfilerAgentState::samplingInterval, interval);
m_profiler->SetSamplingInterval(interval);
return Response::OK(); return Response::OK();
} }
...@@ -237,14 +233,14 @@ void V8ProfilerAgentImpl::restore() { ...@@ -237,14 +233,14 @@ void V8ProfilerAgentImpl::restore() {
return; return;
m_enabled = true; m_enabled = true;
DCHECK(!m_profiler); DCHECK(!m_profiler);
m_profiler = v8::CpuProfiler::New(m_isolate);
int interval = 0;
m_state->getInteger(ProfilerAgentState::samplingInterval, &interval);
if (interval) m_profiler->SetSamplingInterval(interval);
if (m_state->booleanProperty(ProfilerAgentState::userInitiatedProfiling, if (m_state->booleanProperty(ProfilerAgentState::userInitiatedProfiling,
false)) { false)) {
start(); start();
} }
if (m_state->booleanProperty(ProfilerAgentState::preciseCoverageStarted,
false)) {
startPreciseCoverage();
}
} }
Response V8ProfilerAgentImpl::start() { Response V8ProfilerAgentImpl::start() {
...@@ -259,8 +255,9 @@ Response V8ProfilerAgentImpl::start() { ...@@ -259,8 +255,9 @@ Response V8ProfilerAgentImpl::start() {
Response V8ProfilerAgentImpl::stop( Response V8ProfilerAgentImpl::stop(
std::unique_ptr<protocol::Profiler::Profile>* profile) { std::unique_ptr<protocol::Profiler::Profile>* profile) {
if (!m_recordingCPUProfile) if (!m_recordingCPUProfile) {
return Response::Error("No recording profiles found"); return Response::Error("No recording profiles found");
}
m_recordingCPUProfile = false; m_recordingCPUProfile = false;
std::unique_ptr<protocol::Profiler::Profile> cpuProfile = std::unique_ptr<protocol::Profiler::Profile> cpuProfile =
stopProfiling(m_frontendInitiatedProfileId, !!profile); stopProfiling(m_frontendInitiatedProfileId, !!profile);
...@@ -273,6 +270,90 @@ Response V8ProfilerAgentImpl::stop( ...@@ -273,6 +270,90 @@ Response V8ProfilerAgentImpl::stop(
return Response::OK(); return Response::OK();
} }
Response V8ProfilerAgentImpl::startPreciseCoverage() {
if (!m_enabled) return Response::Error("Profiler is not enabled");
m_state->setBoolean(ProfilerAgentState::preciseCoverageStarted, true);
v8::debug::Coverage::TogglePrecise(m_isolate, true);
return Response::OK();
}
Response V8ProfilerAgentImpl::stopPreciseCoverage() {
if (!m_enabled) return Response::Error("Profiler is not enabled");
m_state->setBoolean(ProfilerAgentState::preciseCoverageStarted, false);
v8::debug::Coverage::TogglePrecise(m_isolate, false);
return Response::OK();
}
namespace {
Response takeCoverage(
v8::Isolate* isolate, bool reset_count,
std::unique_ptr<protocol::Array<protocol::Profiler::ScriptCoverage>>*
out_result) {
std::unique_ptr<protocol::Array<protocol::Profiler::ScriptCoverage>> result =
protocol::Array<protocol::Profiler::ScriptCoverage>::create();
v8::HandleScope handle_scope(isolate);
v8::debug::Coverage coverage =
v8::debug::Coverage::Collect(isolate, reset_count);
for (size_t i = 0; i < coverage.ScriptCount(); i++) {
v8::debug::Coverage::ScriptData script_data = coverage.GetScriptData(i);
v8::Local<v8::debug::Script> script = script_data.GetScript();
std::unique_ptr<protocol::Array<protocol::Profiler::FunctionCoverage>>
functions =
protocol::Array<protocol::Profiler::FunctionCoverage>::create();
for (size_t j = 0; j < script_data.FunctionCount(); j++) {
v8::debug::Coverage::FunctionData function_data =
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()
.setStartLineNumber(function_data.Start().GetLineNumber())
.setStartColumnNumber(function_data.Start().GetColumnNumber())
.setEndLineNumber(function_data.End().GetLineNumber())
.setEndColumnNumber(function_data.End().GetColumnNumber())
.setCount(function_data.Count())
.build());
functions->addItem(
protocol::Profiler::FunctionCoverage::create()
.setFunctionName(toProtocolString(
function_data.Name().FromMaybe(v8::Local<v8::String>())))
.setRanges(std::move(ranges))
.build());
}
String16 url;
v8::Local<v8::String> name;
if (script->Name().ToLocal(&name) || script->SourceURL().ToLocal(&name)) {
url = toProtocolString(name);
}
result->addItem(protocol::Profiler::ScriptCoverage::create()
.setScriptId(String16::fromInteger(script->Id()))
.setUrl(url)
.setFunctions(std::move(functions))
.build());
}
*out_result = std::move(result);
return Response::OK();
}
} // anonymous namespace
Response V8ProfilerAgentImpl::takePreciseCoverage(
std::unique_ptr<protocol::Array<protocol::Profiler::ScriptCoverage>>*
out_result) {
if (!m_state->booleanProperty(ProfilerAgentState::preciseCoverageStarted,
false)) {
return Response::Error("Precise coverage has not been started.");
}
return takeCoverage(m_isolate, true, out_result);
}
Response V8ProfilerAgentImpl::getBestEffortCoverage(
std::unique_ptr<protocol::Array<protocol::Profiler::ScriptCoverage>>*
out_result) {
return takeCoverage(m_isolate, false, out_result);
}
String16 V8ProfilerAgentImpl::nextProfileId() { String16 V8ProfilerAgentImpl::nextProfileId() {
return String16::fromInteger( return String16::fromInteger(
v8::base::NoBarrier_AtomicIncrement(&s_lastProfileId, 1)); v8::base::NoBarrier_AtomicIncrement(&s_lastProfileId, 1));
...@@ -280,6 +361,15 @@ String16 V8ProfilerAgentImpl::nextProfileId() { ...@@ -280,6 +361,15 @@ String16 V8ProfilerAgentImpl::nextProfileId() {
void V8ProfilerAgentImpl::startProfiling(const String16& title) { void V8ProfilerAgentImpl::startProfiling(const String16& title) {
v8::HandleScope handleScope(m_isolate); v8::HandleScope handleScope(m_isolate);
if (!m_startedProfilesCount) {
DCHECK(!m_profiler);
m_profiler = v8::CpuProfiler::New(m_isolate);
m_profiler->SetIdle(m_idle);
int interval =
m_state->integerProperty(ProfilerAgentState::samplingInterval, 0);
if (interval) m_profiler->SetSamplingInterval(interval);
}
++m_startedProfilesCount;
m_profiler->StartProfiling(toV8String(m_isolate, title), true); m_profiler->StartProfiling(toV8String(m_isolate, title), true);
} }
...@@ -288,24 +378,28 @@ std::unique_ptr<protocol::Profiler::Profile> V8ProfilerAgentImpl::stopProfiling( ...@@ -288,24 +378,28 @@ std::unique_ptr<protocol::Profiler::Profile> V8ProfilerAgentImpl::stopProfiling(
v8::HandleScope handleScope(m_isolate); v8::HandleScope handleScope(m_isolate);
v8::CpuProfile* profile = v8::CpuProfile* profile =
m_profiler->StopProfiling(toV8String(m_isolate, title)); m_profiler->StopProfiling(toV8String(m_isolate, title));
if (!profile) return nullptr;
std::unique_ptr<protocol::Profiler::Profile> result; std::unique_ptr<protocol::Profiler::Profile> result;
if (serialize) result = createCPUProfile(m_isolate, profile); if (profile) {
profile->Delete(); if (serialize) result = createCPUProfile(m_isolate, profile);
profile->Delete();
}
--m_startedProfilesCount;
if (!m_startedProfilesCount) {
m_profiler->Dispose();
m_profiler = nullptr;
}
return result; return result;
} }
bool V8ProfilerAgentImpl::isRecording() const {
return m_recordingCPUProfile || !m_startedProfiles.empty();
}
bool V8ProfilerAgentImpl::idleStarted() { bool V8ProfilerAgentImpl::idleStarted() {
if (m_profiler) m_profiler->SetIdle(true); m_idle = true;
if (m_profiler) m_profiler->SetIdle(m_idle);
return m_profiler; return m_profiler;
} }
bool V8ProfilerAgentImpl::idleFinished() { bool V8ProfilerAgentImpl::idleFinished() {
if (m_profiler) m_profiler->SetIdle(false); m_idle = false;
if (m_profiler) m_profiler->SetIdle(m_idle);
return m_profiler; return m_profiler;
} }
......
...@@ -37,6 +37,15 @@ class V8ProfilerAgentImpl : public protocol::Profiler::Backend { ...@@ -37,6 +37,15 @@ class V8ProfilerAgentImpl : public protocol::Profiler::Backend {
Response start() override; Response start() override;
Response stop(std::unique_ptr<protocol::Profiler::Profile>*) override; Response stop(std::unique_ptr<protocol::Profiler::Profile>*) override;
Response startPreciseCoverage() override;
Response stopPreciseCoverage() override;
Response takePreciseCoverage(
std::unique_ptr<protocol::Array<protocol::Profiler::ScriptCoverage>>*
out_result) override;
Response getBestEffortCoverage(
std::unique_ptr<protocol::Array<protocol::Profiler::ScriptCoverage>>*
out_result) override;
void consoleProfile(const String16& title); void consoleProfile(const String16& title);
void consoleProfileEnd(const String16& title); void consoleProfileEnd(const String16& title);
...@@ -50,18 +59,18 @@ class V8ProfilerAgentImpl : public protocol::Profiler::Backend { ...@@ -50,18 +59,18 @@ class V8ProfilerAgentImpl : public protocol::Profiler::Backend {
std::unique_ptr<protocol::Profiler::Profile> stopProfiling( std::unique_ptr<protocol::Profiler::Profile> stopProfiling(
const String16& title, bool serialize); const String16& title, bool serialize);
bool isRecording() const;
V8InspectorSessionImpl* m_session; V8InspectorSessionImpl* m_session;
v8::Isolate* m_isolate; v8::Isolate* m_isolate;
v8::CpuProfiler* m_profiler; v8::CpuProfiler* m_profiler = nullptr;
protocol::DictionaryValue* m_state; protocol::DictionaryValue* m_state;
protocol::Profiler::Frontend m_frontend; protocol::Profiler::Frontend m_frontend;
bool m_enabled; bool m_enabled = false;
bool m_recordingCPUProfile; bool m_recordingCPUProfile = false;
class ProfileDescriptor; class ProfileDescriptor;
std::vector<ProfileDescriptor> m_startedProfiles; std::vector<ProfileDescriptor> m_startedProfiles;
String16 m_frontendInitiatedProfileId; String16 m_frontendInitiatedProfileId;
bool m_idle = false;
int m_startedProfilesCount = 0;
DISALLOW_COPY_AND_ASSIGN(V8ProfilerAgentImpl); DISALLOW_COPY_AND_ASSIGN(V8ProfilerAgentImpl);
}; };
......
...@@ -52,7 +52,6 @@ namespace V8RuntimeAgentImplState { ...@@ -52,7 +52,6 @@ namespace V8RuntimeAgentImplState {
static const char customObjectFormatterEnabled[] = static const char customObjectFormatterEnabled[] =
"customObjectFormatterEnabled"; "customObjectFormatterEnabled";
static const char runtimeEnabled[] = "runtimeEnabled"; static const char runtimeEnabled[] = "runtimeEnabled";
static const char preciseCoverageStarted[] = "preciseCoverageStarted";
}; };
using protocol::Runtime::RemoteObject; using protocol::Runtime::RemoteObject;
...@@ -647,88 +646,6 @@ void V8RuntimeAgentImpl::runScript( ...@@ -647,88 +646,6 @@ void V8RuntimeAgentImpl::runScript(
std::move(callback)); std::move(callback));
} }
Response V8RuntimeAgentImpl::startPreciseCoverage() {
m_state->setBoolean(V8RuntimeAgentImplState::preciseCoverageStarted, true);
v8::debug::Coverage::TogglePrecise(m_inspector->isolate(), true);
return Response::OK();
}
Response V8RuntimeAgentImpl::stopPreciseCoverage() {
m_state->setBoolean(V8RuntimeAgentImplState::preciseCoverageStarted, false);
v8::debug::Coverage::TogglePrecise(m_inspector->isolate(), false);
return Response::OK();
}
namespace {
Response takeCoverage(
v8::Isolate* isolate, bool reset_count,
std::unique_ptr<protocol::Array<protocol::Runtime::ScriptCoverage>>*
out_result) {
std::unique_ptr<protocol::Array<protocol::Runtime::ScriptCoverage>> result =
protocol::Array<protocol::Runtime::ScriptCoverage>::create();
v8::HandleScope handle_scope(isolate);
v8::debug::Coverage coverage =
v8::debug::Coverage::Collect(isolate, reset_count);
for (size_t i = 0; i < coverage.ScriptCount(); i++) {
v8::debug::Coverage::ScriptData script_data = coverage.GetScriptData(i);
v8::Local<v8::debug::Script> script = script_data.GetScript();
std::unique_ptr<protocol::Array<protocol::Runtime::FunctionCoverage>>
functions =
protocol::Array<protocol::Runtime::FunctionCoverage>::create();
for (size_t j = 0; j < script_data.FunctionCount(); j++) {
v8::debug::Coverage::FunctionData function_data =
script_data.GetFunctionData(j);
std::unique_ptr<protocol::Array<protocol::Runtime::CoverageRange>>
ranges = protocol::Array<protocol::Runtime::CoverageRange>::create();
// At this point we only have per-function coverage data, so there is
// only one range per function.
ranges->addItem(
protocol::Runtime::CoverageRange::create()
.setStartLineNumber(function_data.Start().GetLineNumber())
.setStartColumnNumber(function_data.Start().GetColumnNumber())
.setEndLineNumber(function_data.End().GetLineNumber())
.setEndColumnNumber(function_data.End().GetColumnNumber())
.setCount(function_data.Count())
.build());
functions->addItem(
protocol::Runtime::FunctionCoverage::create()
.setFunctionName(toProtocolString(
function_data.Name().FromMaybe(v8::Local<v8::String>())))
.setRanges(std::move(ranges))
.build());
}
String16 url;
v8::Local<v8::String> name;
if (script->Name().ToLocal(&name) || script->SourceURL().ToLocal(&name)) {
url = toProtocolString(name);
}
result->addItem(protocol::Runtime::ScriptCoverage::create()
.setScriptId(String16::fromInteger(script->Id()))
.setUrl(url)
.setFunctions(std::move(functions))
.build());
}
*out_result = std::move(result);
return Response::OK();
}
} // anonymous namespace
Response V8RuntimeAgentImpl::takePreciseCoverage(
std::unique_ptr<protocol::Array<protocol::Runtime::ScriptCoverage>>*
out_result) {
if (!m_state->booleanProperty(V8RuntimeAgentImplState::preciseCoverageStarted,
false)) {
return Response::Error("Precise coverage has not been started.");
}
return takeCoverage(m_inspector->isolate(), true, out_result);
}
Response V8RuntimeAgentImpl::getBestEffortCoverage(
std::unique_ptr<protocol::Array<protocol::Runtime::ScriptCoverage>>*
out_result) {
return takeCoverage(m_inspector->isolate(), false, out_result);
}
void V8RuntimeAgentImpl::restore() { void V8RuntimeAgentImpl::restore() {
if (!m_state->booleanProperty(V8RuntimeAgentImplState::runtimeEnabled, false)) if (!m_state->booleanProperty(V8RuntimeAgentImplState::runtimeEnabled, false))
return; return;
...@@ -737,9 +654,6 @@ void V8RuntimeAgentImpl::restore() { ...@@ -737,9 +654,6 @@ void V8RuntimeAgentImpl::restore() {
if (m_state->booleanProperty( if (m_state->booleanProperty(
V8RuntimeAgentImplState::customObjectFormatterEnabled, false)) V8RuntimeAgentImplState::customObjectFormatterEnabled, false))
m_session->setCustomObjectFormatterEnabled(true); m_session->setCustomObjectFormatterEnabled(true);
if (m_state->booleanProperty(V8RuntimeAgentImplState::preciseCoverageStarted,
false))
startPreciseCoverage();
} }
Response V8RuntimeAgentImpl::enable() { Response V8RuntimeAgentImpl::enable() {
...@@ -767,7 +681,6 @@ Response V8RuntimeAgentImpl::disable() { ...@@ -767,7 +681,6 @@ Response V8RuntimeAgentImpl::disable() {
reset(); reset();
m_inspector->client()->endEnsureAllContextsInGroup( m_inspector->client()->endEnsureAllContextsInGroup(
m_session->contextGroupId()); m_session->contextGroupId());
stopPreciseCoverage();
return Response::OK(); return Response::OK();
} }
......
...@@ -97,14 +97,6 @@ class V8RuntimeAgentImpl : public protocol::Runtime::Backend { ...@@ -97,14 +97,6 @@ class V8RuntimeAgentImpl : public protocol::Runtime::Backend {
Maybe<bool> includeCommandLineAPI, Maybe<bool> returnByValue, Maybe<bool> includeCommandLineAPI, Maybe<bool> returnByValue,
Maybe<bool> generatePreview, Maybe<bool> awaitPromise, Maybe<bool> generatePreview, Maybe<bool> awaitPromise,
std::unique_ptr<RunScriptCallback>) override; std::unique_ptr<RunScriptCallback>) override;
Response startPreciseCoverage() override;
Response stopPreciseCoverage() override;
Response takePreciseCoverage(
std::unique_ptr<protocol::Array<protocol::Runtime::ScriptCoverage>>*
out_result) override;
Response getBestEffortCoverage(
std::unique_ptr<protocol::Array<protocol::Runtime::ScriptCoverage>>*
out_result) override;
void reset(); void reset();
void reportExecutionContextCreated(InspectedContext*); void reportExecutionContextCreated(InspectedContext*);
......
Test collecting code coverage data with Runtime.collectCoverage. Test collecting code coverage data with Profiler.collectCoverage.
Running test: testPreciseCoverage Running test: testPreciseCoverage
{ {
......
...@@ -14,7 +14,7 @@ function fib(x) { ...@@ -14,7 +14,7 @@ function fib(x) {
fib(5); fib(5);
`; `;
print("Test collecting code coverage data with Runtime.collectCoverage."); print("Test collecting code coverage data with Profiler.collectCoverage.");
function ClearAndGC() { function ClearAndGC() {
return Protocol.Runtime.evaluate({ expression: "fib = null;" }) return Protocol.Runtime.evaluate({ expression: "fib = null;" })
...@@ -32,30 +32,34 @@ InspectorTest.runTestSuite([ ...@@ -32,30 +32,34 @@ InspectorTest.runTestSuite([
function testPreciseCoverage(next) function testPreciseCoverage(next)
{ {
Protocol.Runtime.enable() Protocol.Runtime.enable()
.then(Protocol.Runtime.startPreciseCoverage) .then(Protocol.Profiler.enable)
.then(Protocol.Profiler.startPreciseCoverage)
.then(() => Protocol.Runtime.compileScript({ expression: source, sourceURL: "1", persistScript: true })) .then(() => Protocol.Runtime.compileScript({ expression: source, sourceURL: "1", persistScript: true }))
.then((result) => Protocol.Runtime.runScript({ scriptId: result.result.scriptId })) .then((result) => Protocol.Runtime.runScript({ scriptId: result.result.scriptId }))
.then(ClearAndGC) .then(ClearAndGC)
.then(InspectorTest.logMessage) .then(InspectorTest.logMessage)
.then(Protocol.Runtime.takePreciseCoverage) .then(Protocol.Profiler.takePreciseCoverage)
.then(LogSorted) .then(LogSorted)
.then(Protocol.Runtime.takePreciseCoverage) .then(Protocol.Profiler.takePreciseCoverage)
.then(LogSorted) .then(LogSorted)
.then(ClearAndGC) .then(ClearAndGC)
.then(Protocol.Runtime.stopPreciseCoverage) .then(Protocol.Profiler.stopPreciseCoverage)
.then(Protocol.Profiler.disable)
.then(Protocol.Runtime.disable) .then(Protocol.Runtime.disable)
.then(next); .then(next);
}, },
function testPreciseCoverageFail(next) function testPreciseCoverageFail(next)
{ {
Protocol.Runtime.enable() Protocol.Runtime.enable()
.then(Protocol.Profiler.enable)
.then(() => Protocol.Runtime.compileScript({ expression: source, sourceURL: "2", persistScript: true })) .then(() => Protocol.Runtime.compileScript({ expression: source, sourceURL: "2", persistScript: true }))
.then((result) => Protocol.Runtime.runScript({ scriptId: result.result.scriptId })) .then((result) => Protocol.Runtime.runScript({ scriptId: result.result.scriptId }))
.then(InspectorTest.logMessage) .then(InspectorTest.logMessage)
.then(ClearAndGC) .then(ClearAndGC)
.then(Protocol.Runtime.takePreciseCoverage) .then(Protocol.Profiler.takePreciseCoverage)
.then(InspectorTest.logMessage) .then(InspectorTest.logMessage)
.then(ClearAndGC) .then(ClearAndGC)
.then(Protocol.Profiler.disable)
.then(Protocol.Runtime.disable) .then(Protocol.Runtime.disable)
.then(next); .then(next);
}, },
...@@ -66,9 +70,9 @@ InspectorTest.runTestSuite([ ...@@ -66,9 +70,9 @@ InspectorTest.runTestSuite([
.then((result) => Protocol.Runtime.runScript({ scriptId: result.result.scriptId })) .then((result) => Protocol.Runtime.runScript({ scriptId: result.result.scriptId }))
.then(InspectorTest.logMessage) .then(InspectorTest.logMessage)
.then(ClearAndGC) .then(ClearAndGC)
.then(Protocol.Runtime.getBestEffortCoverage) .then(Protocol.Profiler.getBestEffortCoverage)
.then(LogSorted) .then(LogSorted)
.then(Protocol.Runtime.getBestEffortCoverage) .then(Protocol.Profiler.getBestEffortCoverage)
.then(LogSorted) .then(LogSorted)
.then(ClearAndGC) .then(ClearAndGC)
.then(Protocol.Runtime.disable) .then(Protocol.Runtime.disable)
...@@ -77,17 +81,19 @@ InspectorTest.runTestSuite([ ...@@ -77,17 +81,19 @@ InspectorTest.runTestSuite([
function testBestEffortCoveragePrecise(next) function testBestEffortCoveragePrecise(next)
{ {
Protocol.Runtime.enable() Protocol.Runtime.enable()
.then(Protocol.Runtime.startPreciseCoverage) .then(Protocol.Profiler.enable)
.then(Protocol.Profiler.startPreciseCoverage)
.then(() => Protocol.Runtime.compileScript({ expression: source, sourceURL: "4", persistScript: true })) .then(() => Protocol.Runtime.compileScript({ expression: source, sourceURL: "4", persistScript: true }))
.then((result) => Protocol.Runtime.runScript({ scriptId: result.result.scriptId })) .then((result) => Protocol.Runtime.runScript({ scriptId: result.result.scriptId }))
.then(InspectorTest.logMessage) .then(InspectorTest.logMessage)
.then(ClearAndGC) .then(ClearAndGC)
.then(Protocol.Runtime.getBestEffortCoverage) .then(Protocol.Profiler.getBestEffortCoverage)
.then(LogSorted) .then(LogSorted)
.then(Protocol.Runtime.getBestEffortCoverage) .then(Protocol.Profiler.getBestEffortCoverage)
.then(LogSorted) .then(LogSorted)
.then(ClearAndGC) .then(ClearAndGC)
.then(Protocol.Runtime.stopPreciseCoverage) .then(Protocol.Profiler.stopPreciseCoverage)
.then(Protocol.Profiler.disable)
.then(Protocol.Runtime.disable) .then(Protocol.Runtime.disable)
.then(next); .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