Commit fa3f8c6f authored by yangguo's avatar yangguo Committed by Commit bot

[debug] refactor code coverage to use enum for mode.

This is in preparation of adding precise binary mode.

BUG=v8:5808

Review-Url: https://codereview.chromium.org/2765813002
Cr-Commit-Position: refs/heads/master@{#43974}
parent 0956e587
......@@ -9625,8 +9625,8 @@ debug::Coverage debug::Coverage::Collect(Isolate* isolate, bool reset_count) {
reset_count));
}
void debug::Coverage::TogglePrecise(Isolate* isolate, bool enable) {
i::Coverage::TogglePrecise(reinterpret_cast<i::Isolate*>(isolate), enable);
void debug::Coverage::SelectMode(Isolate* isolate, debug::Coverage::Mode mode) {
i::Coverage::SelectMode(reinterpret_cast<i::Isolate*>(isolate), mode);
}
const char* CpuProfileNode::GetFunctionNameStr() const {
......
......@@ -2539,7 +2539,9 @@ int Shell::RunMain(Isolate* isolate, int argc, char* argv[], bool last_run) {
options.isolate_sources[i].StartExecuteInThread();
}
{
if (options.lcov_file) debug::Coverage::TogglePrecise(isolate, true);
if (options.lcov_file) {
debug::Coverage::SelectMode(isolate, debug::Coverage::kPreciseCount);
}
HandleScope scope(isolate);
Local<Context> context = CreateEvaluationContext(isolate);
if (last_run && options.use_interactive_shell()) {
......
......@@ -63,30 +63,35 @@ Coverage* Coverage::Collect(Isolate* isolate, bool reset_count) {
SharedToCounterMap counter_map;
// Feed invocation count into the counter map.
if (isolate->IsCodeCoverageEnabled()) {
// Feedback vectors are already listed to prevent losing them to GC.
Handle<ArrayList> list =
Handle<ArrayList>::cast(isolate->factory()->code_coverage_list());
for (int i = 0; i < list->Length(); i++) {
FeedbackVector* vector = FeedbackVector::cast(list->Get(i));
SharedFunctionInfo* shared = vector->shared_function_info();
DCHECK(shared->IsSubjectToDebugging());
uint32_t count = static_cast<uint32_t>(vector->invocation_count());
if (reset_count) vector->clear_invocation_count();
counter_map.Add(shared, count);
switch (isolate->code_coverage_mode()) {
case debug::Coverage::kPreciseCount: {
// Feedback vectors are already listed to prevent losing them to GC.
Handle<ArrayList> list =
Handle<ArrayList>::cast(isolate->factory()->code_coverage_list());
for (int i = 0; i < list->Length(); i++) {
FeedbackVector* vector = FeedbackVector::cast(list->Get(i));
SharedFunctionInfo* shared = vector->shared_function_info();
DCHECK(shared->IsSubjectToDebugging());
uint32_t count = static_cast<uint32_t>(vector->invocation_count());
if (reset_count) vector->clear_invocation_count();
counter_map.Add(shared, count);
}
break;
}
} else {
// Iterate the heap to find all feedback vectors and accumulate the
// invocation counts into the map for each shared function info.
HeapIterator heap_iterator(isolate->heap());
while (HeapObject* current_obj = heap_iterator.next()) {
if (!current_obj->IsFeedbackVector()) continue;
FeedbackVector* vector = FeedbackVector::cast(current_obj);
SharedFunctionInfo* shared = vector->shared_function_info();
if (!shared->IsSubjectToDebugging()) continue;
uint32_t count = static_cast<uint32_t>(vector->invocation_count());
if (reset_count) vector->clear_invocation_count();
counter_map.Add(shared, count);
case debug::Coverage::kBestEffort: {
// Iterate the heap to find all feedback vectors and accumulate the
// invocation counts into the map for each shared function info.
HeapIterator heap_iterator(isolate->heap());
while (HeapObject* current_obj = heap_iterator.next()) {
if (!current_obj->IsFeedbackVector()) continue;
FeedbackVector* vector = FeedbackVector::cast(current_obj);
SharedFunctionInfo* shared = vector->shared_function_info();
if (!shared->IsSubjectToDebugging()) continue;
uint32_t count = static_cast<uint32_t>(vector->invocation_count());
if (reset_count) vector->clear_invocation_count();
counter_map.Add(shared, count);
}
break;
}
}
......@@ -125,32 +130,38 @@ Coverage* Coverage::Collect(Isolate* isolate, bool reset_count) {
return result;
}
void Coverage::TogglePrecise(Isolate* isolate, bool enable) {
if (enable) {
HandleScope scope(isolate);
// Remove all optimized function. Optimized and inlined functions do not
// increment invocation count.
Deoptimizer::DeoptimizeAll(isolate);
// Collect existing feedback vectors.
std::vector<Handle<FeedbackVector>> vectors;
{
HeapIterator heap_iterator(isolate->heap());
while (HeapObject* current_obj = heap_iterator.next()) {
if (!current_obj->IsFeedbackVector()) continue;
FeedbackVector* vector = FeedbackVector::cast(current_obj);
SharedFunctionInfo* shared = vector->shared_function_info();
if (!shared->IsSubjectToDebugging()) continue;
vectors.emplace_back(vector, isolate);
void Coverage::SelectMode(Isolate* isolate, debug::Coverage::Mode mode) {
switch (mode) {
case debug::Coverage::kBestEffort:
isolate->SetCodeCoverageList(isolate->heap()->undefined_value());
break;
case debug::Coverage::kPreciseCount: {
HandleScope scope(isolate);
// Remove all optimized function. Optimized and inlined functions do not
// increment invocation count.
Deoptimizer::DeoptimizeAll(isolate);
// Collect existing feedback vectors.
std::vector<Handle<FeedbackVector>> vectors;
{
HeapIterator heap_iterator(isolate->heap());
while (HeapObject* current_obj = heap_iterator.next()) {
if (!current_obj->IsFeedbackVector()) continue;
FeedbackVector* vector = FeedbackVector::cast(current_obj);
SharedFunctionInfo* shared = vector->shared_function_info();
if (!shared->IsSubjectToDebugging()) continue;
vectors.emplace_back(vector, isolate);
}
}
// Add collected feedback vectors to the root list lest we lose them to
// GC.
Handle<ArrayList> list =
ArrayList::New(isolate, static_cast<int>(vectors.size()));
for (const auto& vector : vectors) list = ArrayList::Add(list, vector);
isolate->SetCodeCoverageList(*list);
break;
}
// Add collected feedback vectors to the root list lest we lose them to GC.
Handle<ArrayList> list =
ArrayList::New(isolate, static_cast<int>(vectors.size()));
for (const auto& vector : vectors) list = ArrayList::Add(list, vector);
isolate->SetCodeCoverageList(*list);
} else {
isolate->SetCodeCoverageList(isolate->heap()->undefined_value());
}
isolate->set_code_coverage_mode(mode);
}
} // namespace internal
......
......@@ -39,9 +39,8 @@ class Coverage : public std::vector<CoverageScript> {
// The ownership is transferred to the caller.
static Coverage* Collect(Isolate* isolate, bool reset_count);
// Enable precise code coverage. This disables optimization and makes sure
// invocation count is not affected by GC.
static void TogglePrecise(Isolate* isolate, bool enable);
// Select code coverage mode.
static void SelectMode(Isolate* isolate, debug::Coverage::Mode mode);
private:
Coverage() {}
......
......@@ -215,6 +215,14 @@ class GeneratorObject {
*/
class V8_EXPORT_PRIVATE Coverage {
public:
enum Mode {
// Make use of existing information in feedback vectors on the heap.
kBestEffort,
// Disable optimization and prevent feedback vectors from being garbage
// collected in order to get precise invocation counts.
kPreciseCount,
};
class ScriptData; // Forward declaration.
class V8_EXPORT_PRIVATE FunctionData {
......@@ -247,7 +255,7 @@ class V8_EXPORT_PRIVATE Coverage {
static Coverage Collect(Isolate* isolate, bool reset_count);
static void TogglePrecise(Isolate* isolate, bool enable);
static void SelectMode(Isolate* isolate, Mode mode);
size_t ScriptCount();
ScriptData GetScriptData(size_t i);
......
......@@ -250,7 +250,9 @@ Handle<FeedbackVector> FeedbackVector::New(Isolate* isolate,
}
Handle<FeedbackVector> result = Handle<FeedbackVector>::cast(array);
if (isolate->IsCodeCoverageEnabled()) AddToCodeCoverageList(isolate, result);
if (!isolate->is_best_effort_code_coverage()) {
AddToCodeCoverageList(isolate, result);
}
return result;
}
......@@ -260,14 +262,16 @@ Handle<FeedbackVector> FeedbackVector::Copy(Isolate* isolate,
Handle<FeedbackVector> result;
result = Handle<FeedbackVector>::cast(
isolate->factory()->CopyFixedArray(Handle<FixedArray>::cast(vector)));
if (isolate->IsCodeCoverageEnabled()) AddToCodeCoverageList(isolate, result);
if (!isolate->is_best_effort_code_coverage()) {
AddToCodeCoverageList(isolate, result);
}
return result;
}
// static
void FeedbackVector::AddToCodeCoverageList(Isolate* isolate,
Handle<FeedbackVector> vector) {
DCHECK(isolate->IsCodeCoverageEnabled());
DCHECK(!isolate->is_best_effort_code_coverage());
if (!vector->shared_function_info()->IsSubjectToDebugging()) return;
Handle<ArrayList> list =
Handle<ArrayList>::cast(isolate->factory()->code_coverage_list());
......
......@@ -273,14 +273,15 @@ Response V8ProfilerAgentImpl::stop(
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);
v8::debug::Coverage::SelectMode(m_isolate,
v8::debug::Coverage::kPreciseCount);
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);
v8::debug::Coverage::SelectMode(m_isolate, v8::debug::Coverage::kBestEffort);
return Response::OK();
}
......
......@@ -2990,7 +2990,7 @@ Map* Isolate::get_initial_js_array_map(ElementsKind kind) {
bool Isolate::use_crankshaft() {
return FLAG_opt && FLAG_crankshaft && !serializer_enabled_ &&
CpuFeatures::SupportsCrankshaft() && !IsCodeCoverageEnabled();
CpuFeatures::SupportsCrankshaft() && !is_precise_count_code_coverage();
}
bool Isolate::NeedsSourcePositionsForProfiling() const {
......@@ -2999,10 +2999,6 @@ bool Isolate::NeedsSourcePositionsForProfiling() const {
debug_->is_active() || logger_->is_logging();
}
bool Isolate::IsCodeCoverageEnabled() {
return heap()->code_coverage_list()->IsArrayList();
}
void Isolate::SetCodeCoverageList(Object* value) {
DCHECK(value->IsUndefined(this) || value->IsArrayList());
heap()->set_code_coverage_list(value);
......
......@@ -14,6 +14,7 @@
#include "src/builtins/builtins.h"
#include "src/contexts.h"
#include "src/date.h"
#include "src/debug/debug-interface.h"
#include "src/execution.h"
#include "src/frames.h"
#include "src/futex-emulation.h"
......@@ -422,6 +423,8 @@ typedef List<HeapObject*> DebugObjectCache;
V(bool, formatting_stack_trace, false) \
/* Perform side effect checks on function call and API callbacks. */ \
V(bool, needs_side_effect_check, false) \
/* Current code coverage mode */ \
V(debug::Coverage::Mode, code_coverage_mode, debug::Coverage::kBestEffort) \
ISOLATE_INIT_SIMULATOR_LIST(V)
#define THREAD_LOCAL_TOP_ACCESSOR(type, name) \
......@@ -975,7 +978,14 @@ class Isolate {
bool NeedsSourcePositionsForProfiling() const;
bool IsCodeCoverageEnabled();
bool is_best_effort_code_coverage() const {
return code_coverage_mode() == debug::Coverage::kBestEffort;
}
bool is_precise_count_code_coverage() const {
return code_coverage_mode() == debug::Coverage::kPreciseCount;
}
void SetCodeCoverageList(Object* value);
double time_millis_since_init() {
......
......@@ -1945,7 +1945,8 @@ RUNTIME_FUNCTION(Runtime_DebugCollectCoverage) {
RUNTIME_FUNCTION(Runtime_DebugTogglePreciseCoverage) {
SealHandleScope shs(isolate);
CONVERT_BOOLEAN_ARG_CHECKED(enable, 0);
Coverage::TogglePrecise(isolate, enable);
Coverage::SelectMode(isolate, enable ? debug::Coverage::kPreciseCount
: debug::Coverage::kBestEffort);
return isolate->heap()->undefined_value();
}
......
......@@ -6613,7 +6613,7 @@ TEST(DebugCoverage) {
LocalContext env;
v8::Isolate* isolate = env->GetIsolate();
v8::HandleScope scope(isolate);
v8::debug::Coverage::TogglePrecise(isolate, true);
v8::debug::Coverage::SelectMode(isolate, v8::debug::Coverage::kPreciseCount);
v8::Local<v8::String> source = v8_str(
"function f() {\n"
"}\n"
......
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