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