Revert "[DevTools] Implemented DevTools protocol API to retrieve V8 RunTime Call Stats."

This reverts commit 91c8be9599.

RCS should not be exposed through the API or the inspector protocol as
they are meant as an internal debugging feature.
The only regularly tested and supported way is through chrome-tracing.

Given that this was used mostly for an experiment to analyse chrome's
performance, we can use pprof support as a replacement.

Original change's description:
> [DevTools] Implemented DevTools protocol API to retrieve V8 RunTime Call Stats.
>
> The new APIs are:
> enableRuntimeCallStats
> disableRuntimeCallStats
> getRuntimeCallStats
>
> The RunTime Call Stats are collected per isolate.
>
> Change-Id: I7e520e2c866288aa9f9dc74f12572abedf0d3ac8
> Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1881601
> Commit-Queue: Peter Kvitek <kvitekp@chromium.org>
> Reviewed-by: Yang Guo <yangguo@chromium.org>
> Cr-Commit-Position: refs/heads/master@{#64784}

Change-Id: Ia7575436e97d3420dd7e68414d89477e6a86bb05
Bug: v8:11395
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2998585
Reviewed-by: Yang Guo <yangguo@chromium.org>
Commit-Queue: Camillo Bruni <cbruni@chromium.org>
Cr-Commit-Position: refs/heads/master@{#76297}
This commit is contained in:
Camillo Bruni 2021-08-04 11:55:29 +02:00 committed by V8 LUCI CQ
parent e74d6918fb
commit a016cce5fc
20 changed files with 0 additions and 558 deletions

View File

@ -845,24 +845,6 @@ domain Profiler
# Type profile entries for parameters and return values of the functions in the script.
array of TypeProfileEntry entries
# Collected counter information.
experimental type CounterInfo extends object
properties
# Counter name.
string name
# Counter value.
integer value
# Runtime call counter information.
experimental type RuntimeCallCounterInfo extends object
properties
# Counter name.
string name
# Counter value.
number value
# Counter time in seconds.
number time
command disable
command enable
@ -927,30 +909,6 @@ domain Profiler
# Type profile for all scripts since startTypeProfile() was turned on.
array of ScriptTypeProfile result
# Enable counters collection.
experimental command enableCounters
# Disable counters collection.
experimental command disableCounters
# Retrieve counters.
experimental command getCounters
returns
# Collected counters information.
array of CounterInfo result
# Enable run time call stats collection.
experimental command enableRuntimeCallStats
# Disable run time call stats collection.
experimental command disableRuntimeCallStats
# Retrieve run time call stats.
experimental command getRuntimeCallStats
returns
# Collected runtime call counter information.
array of RuntimeCallCounterInfo result
event consoleProfileFinished
parameters
string id

View File

@ -9,7 +9,6 @@
#include <cctype>
#include <memory>
#include <unordered_map>
#include "v8.h" // NOLINT(build/include_directory)
@ -320,24 +319,6 @@ class V8_EXPORT V8Inspector {
virtual std::unique_ptr<V8StackTrace> createStackTrace(
v8::Local<v8::StackTrace>) = 0;
virtual std::unique_ptr<V8StackTrace> captureStackTrace(bool fullStack) = 0;
// Performance counters.
class V8_EXPORT Counters : public std::enable_shared_from_this<Counters> {
public:
explicit Counters(v8::Isolate* isolate);
~Counters();
const std::unordered_map<std::string, int>& getCountersMap() const {
return m_countersMap;
}
private:
static int* getCounterPtr(const char* name);
v8::Isolate* m_isolate;
std::unordered_map<std::string, int> m_countersMap;
};
virtual std::shared_ptr<Counters> enableCounters() = 0;
};
} // namespace v8_inspector

View File

@ -1034,16 +1034,6 @@ int64_t GetNextRandomInt64(v8::Isolate* v8_isolate) {
->NextInt64();
}
void EnumerateRuntimeCallCounters(v8::Isolate* v8_isolate,
RuntimeCallCounterCallback callback) {
#ifdef V8_RUNTIME_CALL_STATS
i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate);
if (isolate->counters()) {
isolate->counters()->runtime_call_stats()->EnumerateCounters(callback);
}
#endif // V8_RUNTIME_CALL_STATS
}
int GetDebuggingId(v8::Local<v8::Function> function) {
i::Handle<i::JSReceiver> callable = v8::Utils::OpenHandle(*function);
if (!callable->IsJSFunction()) return i::DebugInfo::kNoDebuggingId;

View File

@ -9,7 +9,6 @@
#include "include/v8-util.h"
#include "include/v8.h"
#include "src/base/platform/time.h"
#include "src/base/vector.h"
#include "src/common/globals.h"
#include "src/debug/interface-types.h"
@ -515,11 +514,6 @@ enum class NativeAccessorType {
int64_t GetNextRandomInt64(v8::Isolate* isolate);
using RuntimeCallCounterCallback =
std::function<void(const char* name, int64_t count, base::TimeDelta time)>;
void EnumerateRuntimeCallCounters(v8::Isolate* isolate,
RuntimeCallCounterCallback callback);
MaybeLocal<Value> CallFunctionOn(Local<Context> context,
Local<Function> function, Local<Value> recv,
int argc, Local<Value> argv[],

View File

@ -13,7 +13,6 @@ include_rules = [
"+src/base/safe_conversions.h",
"+src/base/template-utils.h",
"+src/base/v8-fallthrough.h",
"+src/logging/tracing-flags.h",
"+src/numbers/conversions.h",
"+src/inspector",
"+src/tracing",

View File

@ -333,39 +333,6 @@ void V8InspectorImpl::allAsyncTasksCanceled() {
m_debugger->allAsyncTasksCanceled();
}
V8Inspector::Counters::Counters(v8::Isolate* isolate) : m_isolate(isolate) {
CHECK(m_isolate);
auto* inspector =
static_cast<V8InspectorImpl*>(v8::debug::GetInspector(m_isolate));
CHECK(inspector);
CHECK(!inspector->m_counters);
inspector->m_counters = this;
m_isolate->SetCounterFunction(&Counters::getCounterPtr);
}
V8Inspector::Counters::~Counters() {
auto* inspector =
static_cast<V8InspectorImpl*>(v8::debug::GetInspector(m_isolate));
CHECK(inspector);
inspector->m_counters = nullptr;
m_isolate->SetCounterFunction(nullptr);
}
int* V8Inspector::Counters::getCounterPtr(const char* name) {
v8::Isolate* isolate = v8::Isolate::GetCurrent();
DCHECK(isolate);
V8Inspector* inspector = v8::debug::GetInspector(isolate);
DCHECK(inspector);
auto* instance = static_cast<V8InspectorImpl*>(inspector)->m_counters;
DCHECK(instance);
return &(instance->m_countersMap[name]);
}
std::shared_ptr<V8Inspector::Counters> V8InspectorImpl::enableCounters() {
if (m_counters) return m_counters->shared_from_this();
return std::make_shared<Counters>(m_isolate);
}
v8::MaybeLocal<v8::Context> V8InspectorImpl::regexContext() {
if (m_regexContext.IsEmpty()) {
m_regexContext.Reset(m_isolate, v8::Context::New(m_isolate));

View File

@ -110,8 +110,6 @@ class V8InspectorImpl : public V8Inspector {
void externalAsyncTaskStarted(const V8StackTraceId& parent) override;
void externalAsyncTaskFinished(const V8StackTraceId& parent) override;
std::shared_ptr<Counters> enableCounters() override;
bool associateExceptionData(v8::Local<v8::Context>,
v8::Local<v8::Value> exception,
v8::Local<v8::Name> key,
@ -157,8 +155,6 @@ class V8InspectorImpl : public V8Inspector {
};
private:
friend class Counters;
v8::Isolate* m_isolate;
V8InspectorClient* m_client;
std::unique_ptr<V8Debugger> m_debugger;
@ -191,8 +187,6 @@ class V8InspectorImpl : public V8Inspector {
std::map<std::pair<int64_t, int64_t>, int> m_uniqueIdToContextId;
std::unique_ptr<V8Console> m_console;
Counters* m_counters = nullptr;
};
} // namespace v8_inspector

View File

@ -16,7 +16,6 @@
#include "src/inspector/v8-inspector-impl.h"
#include "src/inspector/v8-inspector-session-impl.h"
#include "src/inspector/v8-stack-trace-impl.h"
#include "src/logging/tracing-flags.h"
namespace v8_inspector {
@ -30,8 +29,6 @@ static const char preciseCoverageDetailed[] = "preciseCoverageDetailed";
static const char preciseCoverageAllowTriggeredUpdates[] =
"preciseCoverageAllowTriggeredUpdates";
static const char typeProfileStarted[] = "typeProfileStarted";
static const char countersEnabled[] = "countersEnabled";
static const char runtimeCallStatsEnabled[] = "runtimeCallStatsEnabled";
} // namespace ProfilerAgentState
namespace {
@ -243,16 +240,6 @@ Response V8ProfilerAgentImpl::disable() {
m_state->setBoolean(ProfilerAgentState::profilerEnabled, false);
}
if (m_counters) {
disableCounters();
m_state->setBoolean(ProfilerAgentState::countersEnabled, false);
}
if (m_runtime_call_stats_enabled) {
disableRuntimeCallStats();
m_state->setBoolean(ProfilerAgentState::runtimeCallStatsEnabled, false);
}
return Response::Success();
}
@ -287,15 +274,6 @@ void V8ProfilerAgentImpl::restore() {
Maybe<bool>(updatesAllowed), &timestamp);
}
}
if (m_state->booleanProperty(ProfilerAgentState::countersEnabled, false)) {
enableCounters();
}
if (m_state->booleanProperty(ProfilerAgentState::runtimeCallStatsEnabled,
false)) {
enableRuntimeCallStats();
}
}
Response V8ProfilerAgentImpl::start() {
@ -551,104 +529,6 @@ Response V8ProfilerAgentImpl::takeTypeProfile(
return Response::Success();
}
Response V8ProfilerAgentImpl::enableCounters() {
if (m_counters)
return Response::ServerError("Counters collection already enabled.");
if (V8Inspector* inspector = v8::debug::GetInspector(m_isolate))
m_counters = inspector->enableCounters();
else
return Response::ServerError("No inspector found.");
return Response::Success();
}
Response V8ProfilerAgentImpl::disableCounters() {
if (m_counters) m_counters.reset();
return Response::Success();
}
Response V8ProfilerAgentImpl::getCounters(
std::unique_ptr<protocol::Array<protocol::Profiler::CounterInfo>>*
out_result) {
if (!m_counters)
return Response::ServerError("Counters collection is not enabled.");
*out_result =
std::make_unique<protocol::Array<protocol::Profiler::CounterInfo>>();
for (const auto& counter : m_counters->getCountersMap()) {
(*out_result)
->emplace_back(
protocol::Profiler::CounterInfo::create()
.setName(String16(counter.first.data(), counter.first.length()))
.setValue(counter.second)
.build());
}
return Response::Success();
}
Response V8ProfilerAgentImpl::enableRuntimeCallStats() {
if (v8::internal::TracingFlags::runtime_stats.load()) {
return Response::ServerError(
"Runtime Call Stats collection is already enabled.");
}
v8::internal::TracingFlags::runtime_stats.store(true);
m_runtime_call_stats_enabled = true;
return Response::Success();
}
Response V8ProfilerAgentImpl::disableRuntimeCallStats() {
if (!v8::internal::TracingFlags::runtime_stats.load()) {
return Response::ServerError(
"Runtime Call Stats collection is not enabled.");
}
if (!m_runtime_call_stats_enabled) {
return Response::ServerError(
"Runtime Call Stats collection was not enabled by this session.");
}
v8::internal::TracingFlags::runtime_stats.store(false);
m_runtime_call_stats_enabled = false;
return Response::Success();
}
Response V8ProfilerAgentImpl::getRuntimeCallStats(
std::unique_ptr<
protocol::Array<protocol::Profiler::RuntimeCallCounterInfo>>*
out_result) {
if (!m_runtime_call_stats_enabled) {
return Response::ServerError(
"Runtime Call Stats collection is not enabled.");
}
if (!v8::internal::TracingFlags::runtime_stats.load()) {
return Response::ServerError(
"Runtime Call Stats collection was disabled outside of this session.");
}
*out_result = std::make_unique<
protocol::Array<protocol::Profiler::RuntimeCallCounterInfo>>();
v8::debug::EnumerateRuntimeCallCounters(
m_isolate,
[&](const char* name, int64_t count, v8::base::TimeDelta time) {
(*out_result)
->emplace_back(protocol::Profiler::RuntimeCallCounterInfo::create()
.setName(String16(name))
.setValue(static_cast<double>(count))
.setTime(time.InSecondsF())
.build());
});
return Response::Success();
}
String16 V8ProfilerAgentImpl::nextProfileId() {
return String16::fromInteger(
v8::base::Relaxed_AtomicIncrement(&s_lastProfileId, 1));

View File

@ -59,19 +59,6 @@ class V8ProfilerAgentImpl : public protocol::Profiler::Backend {
std::unique_ptr<protocol::Array<protocol::Profiler::ScriptTypeProfile>>*
out_result) override;
Response enableCounters() override;
Response disableCounters() override;
Response getCounters(
std::unique_ptr<protocol::Array<protocol::Profiler::CounterInfo>>*
out_result) override;
Response enableRuntimeCallStats() override;
Response disableRuntimeCallStats() override;
Response getRuntimeCallStats(
std::unique_ptr<
protocol::Array<protocol::Profiler::RuntimeCallCounterInfo>>*
out_result) override;
void consoleProfile(const String16& title);
void consoleProfileEnd(const String16& title);
@ -95,8 +82,6 @@ class V8ProfilerAgentImpl : public protocol::Profiler::Backend {
std::vector<ProfileDescriptor> m_startedProfiles;
String16 m_frontendInitiatedProfileId;
int m_startedProfilesCount = 0;
std::shared_ptr<V8Inspector::Counters> m_counters;
bool m_runtime_call_stats_enabled = false;
};
} // namespace v8_inspector

View File

@ -260,17 +260,6 @@ void RuntimeCallStats::Print(std::ostream& os) {
entries.Print(os);
}
void RuntimeCallStats::EnumerateCounters(
debug::RuntimeCallCounterCallback callback) {
if (current_timer_.Value() != nullptr) {
current_timer_.Value()->Snapshot();
}
for (int i = 0; i < kNumberOfCounters; i++) {
RuntimeCallCounter* counter = GetCounter(i);
callback(counter->name(), counter->count(), counter->time());
}
}
void RuntimeCallStats::Reset() {
if (V8_LIKELY(!TracingFlags::is_runtime_stats_enabled())) return;

View File

@ -597,9 +597,6 @@ class RuntimeCallStats final {
V8_EXPORT_PRIVATE void Print();
V8_NOINLINE void Dump(v8::tracing::TracedValue* value);
V8_EXPORT_PRIVATE void EnumerateCounters(
debug::RuntimeCallCounterCallback callback);
ThreadId thread_id() const { return thread_id_; }
RuntimeCallTimer* current_timer() { return current_timer_.Value(); }
RuntimeCallCounter* current_counter() { return current_counter_.Value(); }

View File

@ -1,2 +0,0 @@
Test Counters collection using Profiler.getCounters.
PASSED

View File

@ -1,83 +0,0 @@
// Copyright 2020 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.
let {session, contextGroup, Protocol} = InspectorTest.start(
'Test Counters collection using Profiler.getCounters.');
var source =
`
function fib(x) {
if (x < 2) return 1;
return fib(x-1) + fib(x-2);
}
fib(5);
`;
function buildCounterMap(result) {
let counterMap = new Map();
let counters = result.result.result;
for (const {name, value} of counters) {
counterMap.set(name, value);
}
return counterMap;
}
function compareCounterMaps(counterMap, counterMap2) {
// Check for counters that are present in the first map but are not found
// in the the second map
for (let counter of counterMap.keys()) {
if (!counterMap2.has(counter)) {
InspectorTest.log(`Counter ${counter} is missing`);
return false;
}
}
// Check for the counter value changes
let counterValueIncreased = false;
for (let [counter, value2] of counterMap2) {
let value = counterMap.get(counter);
if (value !== undefined) {
if (value2 < value) {
InspectorTest.log(`Counter ${counter} value decreased: ${value} -> ${value2}`);
return false;
}
if (value2 > value) {
counterValueIncreased = true;
}
}
}
if (!counterValueIncreased && counterMap.size === counterMap2.size) {
InspectorTest.log(`No counter values has increased or added`);
return false;
}
return true;
}
(async function test() {
await Protocol.Runtime.enable();
await Protocol.Profiler.enableCounters();
let counterMap = buildCounterMap(await Protocol.Profiler.getCounters());
await Protocol.Runtime.evaluate({ expression: source, sourceURL: arguments.callee.name, persistScript: true });
let counterMap2 = buildCounterMap(await Protocol.Profiler.getCounters());
const check1 = compareCounterMaps(counterMap, counterMap2);
await Protocol.Runtime.evaluate({ expression: source, sourceURL: arguments.callee.name, persistScript: true });
let counterMap3 = buildCounterMap(await Protocol.Profiler.getCounters());
const check2 = compareCounterMaps(counterMap2, counterMap3);
await Protocol.Profiler.disableCounters();
await Protocol.Runtime.disable();
InspectorTest.log(check1 && check2 ? 'PASSED' : 'FAILED');
InspectorTest.completeTest();
})().catch(e => InspectorTest.log('caught: ' + e));

View File

@ -1,6 +0,0 @@
Test Counters collection enabling and disabling.
Expected error: "Counters collection is not enabled."
Expected error: "Counters collection already enabled."
Some counters reported
Expected error: "Counters collection is not enabled."
Less counters reported

View File

@ -1,51 +0,0 @@
// Copyright 2020 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.
let {session, contextGroup, Protocol} = InspectorTest.start(
'Test Counters collection enabling and disabling.');
var source =
`
function fib(x) {
if (x < 2) return 1;
return fib(x-1) + fib(x-2);
}
fib(5);
`;
function logErrorMessage(result) {
InspectorTest.log('Expected error: "' + result.error.message + '"');
}
(async function test() {
await Protocol.Runtime.enable();
// This should fail with "not enabled" error.
logErrorMessage(await Protocol.Profiler.getCounters());
// This should fail with "already enabled" error.
await Protocol.Profiler.enableCounters();
logErrorMessage(await Protocol.Profiler.enableCounters());
// The result should not be empty.
await Protocol.Runtime.evaluate({ expression: source, sourceURL: arguments.callee.name, persistScript: true });
const counters = (await Protocol.Profiler.getCounters()).result.result;
if (counters.length > 0)
InspectorTest.log('Some counters reported');
await Protocol.Profiler.disableCounters();
// This should fail with "not enabled" error too.
logErrorMessage(await Protocol.Profiler.getCounters());
// The result should not be empty and have smaller amount of counters than
// the first result.
await Protocol.Profiler.enableCounters();
const counters2 = (await Protocol.Profiler.getCounters()).result.result;
if (counters2.length > 0 && counters2.length < counters.length)
InspectorTest.log('Less counters reported');
await Protocol.Profiler.disableCounters();
await Protocol.Runtime.disable();
InspectorTest.completeTest();
})().catch(e => InspectorTest.log('caught: ' + e));

View File

@ -20,9 +20,6 @@
# loop instead of properly reporting a RangeError for a stack overflow.
'regress/regress-crbug-1080638': [SKIP],
# https://crbug.com/v8/11338
'runtime-call-stats/enable-disable': [SKIP],
# Tests that need to run sequentially (e.g. due to memory consumption).
'runtime/console-messages-limits': [PASS, HEAVY],
'runtime/regression-732717': [PASS, HEAVY],
@ -169,7 +166,6 @@
'debugger/set-breakpoint-at-last-line': [SKIP],
'debugger/set-breakpoint-breaks-on-first-breakable-location': [SKIP],
'heap-profiler/collect-garbage' : [SKIP],
'runtime-call-stats/collection': [SKIP],
'runtime/context-destroyed-on-context-collected': [SKIP],
'runtime/evaluate-async': [SKIP],
'runtime/internal-properties-entries': [SKIP],
@ -192,7 +188,6 @@
'cpu-profiler/coverage': [SKIP],
'cpu-profiler/coverage-block': [SKIP],
'runtime/internal-properties-entries': [SKIP],
'runtime-call-stats/collection': [SKIP],
# Skip tests that might fail with concurrent allocation
'debugger/pause-on-oom-wide': [SKIP],
@ -222,8 +217,6 @@
'regress/regress-crbug-1199919': [SKIP],
'console/destroy-context-during-log': [SKIP],
'console/scoped-variables': [SKIP],
'counters/collection': [SKIP],
'counters/enable-disable': [SKIP],
'cpu-profiler/console-profile': [SKIP],
'cpu-profiler/console-profile-asm-js': [SKIP],
'cpu-profiler/console-profile-end-parameterless-crash': [SKIP],
@ -429,8 +422,6 @@
'print-method-not-found': [SKIP],
'regress/regress-crbug-1147552': [SKIP],
'regress/regress-crbug-1183664': [SKIP],
'runtime-call-stats/collection': [SKIP],
'runtime-call-stats/enable-disable': [SKIP],
'runtime/add-binding': [SKIP],
'runtime/await-promise': [SKIP],
'runtime/call-function-on-async': [SKIP],

View File

@ -1,2 +0,0 @@
Test RunTimeCallStats collection using Profiler.getRuntimeCallStats.
PASSED

View File

@ -1,83 +0,0 @@
// Copyright 2020 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.
let {session, contextGroup, Protocol} = InspectorTest.start(
'Test RunTimeCallStats collection using Profiler.getRuntimeCallStats.');
var source =
`
function fib(x) {
if (x < 2) return 1;
return fib(x-1) + fib(x-2);
}
fib(5);
`;
function buildCounterMap(result) {
let counterMap = new Map();
let counters = result.result.result;
for (const {name, value} of counters) {
counterMap.set(name, value);
}
return counterMap;
}
function compareCounterMaps(counterMap, counterMap2) {
// Check for counters that are present in the first map but are not found
// in the the second map
for (let counter of counterMap.keys()) {
if (!counterMap2.has(counter)) {
InspectorTest.log(`Counter ${counter} is missing`);
return false;
}
}
// Check for the counter value changes
let counterValueIncreased = false;
for (let [counter, value2] of counterMap2) {
let value = counterMap.get(counter);
if (value !== undefined) {
if (value2 < value) {
InspectorTest.log(`Counter ${counter} value decreased: ${value} -> ${value2}`);
return false;
}
if (value2 > value) {
counterValueIncreased = true;
}
}
}
if (!counterValueIncreased && counterMap.size === counterMap2.size) {
InspectorTest.log(`No counter values has increased or added`);
return false;
}
return true;
}
(async function test() {
await Protocol.Runtime.enable();
await Protocol.Profiler.enableRuntimeCallStats();
let counterMap = buildCounterMap(await Protocol.Profiler.getRuntimeCallStats());
await Protocol.Runtime.evaluate({ expression: source, sourceURL: arguments.callee.name, persistScript: true });
let counterMap2 = buildCounterMap(await Protocol.Profiler.getRuntimeCallStats());
const check1 = compareCounterMaps(counterMap, counterMap2);
await Protocol.Runtime.evaluate({ expression: source, sourceURL: arguments.callee.name, persistScript: true });
let counterMap3 = buildCounterMap(await Protocol.Profiler.getRuntimeCallStats());
const check2 = compareCounterMaps(counterMap2, counterMap3);
await Protocol.Profiler.disableRuntimeCallStats();
await Protocol.Runtime.disable();
InspectorTest.log(check1 && check2 ? 'PASSED' : 'FAILED');
InspectorTest.completeTest();
})().catch(e => InspectorTest.log('caught: ' + e));

View File

@ -1,5 +0,0 @@
Test Runtime Call Stats collection enabling and disabling.
Expected error: "Runtime Call Stats collection is not enabled."
Expected error: "Runtime Call Stats collection is already enabled."
Some counters reported
Expected error: "Runtime Call Stats collection is not enabled."

View File

@ -1,51 +0,0 @@
// Copyright 2020 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.
let {session, contextGroup, Protocol} = InspectorTest.start(
'Test Runtime Call Stats collection enabling and disabling.');
var source =
`
function fib(x) {
if (x < 2) return 1;
return fib(x-1) + fib(x-2);
}
fib(5);
`;
function logErrorMessage(result) {
InspectorTest.log('Expected error: "' + result.error.message + '"');
}
(async function test() {
await Protocol.Runtime.enable();
// This should fail with "not enabled" error.
logErrorMessage(await Protocol.Profiler.getRuntimeCallStats());
// This should fail with "already enabled" error.
await Protocol.Profiler.enableRuntimeCallStats();
logErrorMessage(await Protocol.Profiler.enableRuntimeCallStats());
// The result should not be empty.
await Protocol.Runtime.evaluate({ expression: source, sourceURL: arguments.callee.name, persistScript: true });
const counters = (await Protocol.Profiler.getRuntimeCallStats()).result.result;
if (counters.length > 0)
InspectorTest.log('Some counters reported');
await Protocol.Profiler.disableRuntimeCallStats();
// This should fail with "not enabled" error too.
logErrorMessage(await Protocol.Profiler.getRuntimeCallStats());
// The result should not be empty and have smaller amount of counters than
// the first result.
await Protocol.Profiler.enableRuntimeCallStats();
const counters2 = (await Protocol.Profiler.getRuntimeCallStats()).result.result;
if (counters2.length > 0 && counters2.length < counters.length)
InspectorTest.log('Less counters reported');
await Protocol.Profiler.disableRuntimeCallStats();
await Protocol.Runtime.disable();
InspectorTest.completeTest();
})().catch(e => InspectorTest.log('caught: ' + e));