v8/test/unittests/heap/cppgc/stats-collector-scopes-unittest.cc
Omer Katz 760e67973a cppgc: Remove StatsCollector dependency on HeapBase
Bug: chromium:1056170
Change-Id: I561166a7f1be658c5c35aa1caf8dbbbd2d720ab3
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2692815
Commit-Queue: Omer Katz <omerkatz@chromium.org>
Auto-Submit: Omer Katz <omerkatz@chromium.org>
Reviewed-by: Michael Lippautz <mlippautz@chromium.org>
Cr-Commit-Position: refs/heads/master@{#72754}
2021-02-15 17:16:35 +00:00

314 lines
11 KiB
C++

// 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.
#if CPPGC_IS_STANDALONE
#include "src/heap/cppgc/stats-collector.h"
#include "test/unittests/heap/cppgc/tests.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace cppgc {
namespace internal {
namespace {
class DelegatingTracingControllerImpl : public TracingController {
public:
virtual uint64_t AddTraceEvent(
char phase, const uint8_t* category_enabled_flag, const char* name,
const char* scope, uint64_t id, uint64_t bind_id, int32_t num_args,
const char** arg_names, const uint8_t* arg_types,
const uint64_t* arg_values,
std::unique_ptr<ConvertableToTraceFormat>* arg_convertables,
unsigned int flags) {
if (!check_expectations) return 0;
static char phases[2] = {'B', 'E'};
EXPECT_EQ(phases[AddTraceEvent_callcount], phase);
EXPECT_TRUE(*category_enabled_flag);
if (expected_name) {
EXPECT_EQ(0, strcmp(expected_name, name));
}
stored_num_args += num_args;
for (int i = 0; i < num_args; ++i) {
stored_arg_names.push_back(arg_names[i]);
stored_arg_types.push_back(arg_types[i]);
stored_arg_values.push_back(arg_values[i]);
}
AddTraceEvent_callcount++;
return 0;
}
static bool check_expectations;
static size_t AddTraceEvent_callcount;
static const char* expected_name;
static int32_t stored_num_args;
static std::vector<std::string> stored_arg_names;
static std::vector<uint8_t> stored_arg_types;
static std::vector<uint64_t> stored_arg_values;
};
bool DelegatingTracingControllerImpl::check_expectations = false;
size_t DelegatingTracingControllerImpl::AddTraceEvent_callcount = 0u;
const char* DelegatingTracingControllerImpl::expected_name = nullptr;
int32_t DelegatingTracingControllerImpl::stored_num_args = 0;
std::vector<std::string> DelegatingTracingControllerImpl::stored_arg_names;
std::vector<uint8_t> DelegatingTracingControllerImpl::stored_arg_types;
std::vector<uint64_t> DelegatingTracingControllerImpl::stored_arg_values;
class V8_NODISCARD CppgcTracingScopesTest : public testing::TestWithHeap {
using Config = Marker::MarkingConfig;
public:
CppgcTracingScopesTest() {
SetTracingController(std::make_unique<DelegatingTracingControllerImpl>());
}
void StartGC() {
Config config = {Config::CollectionType::kMajor,
Config::StackState::kNoHeapPointers,
Config::MarkingType::kIncremental};
GetMarkerRef() = MarkerFactory::CreateAndStartMarking<Marker>(
Heap::From(GetHeap())->AsBase(), GetPlatformHandle().get(), config);
DelegatingTracingControllerImpl::check_expectations = true;
}
void EndGC() {
DelegatingTracingControllerImpl::check_expectations = false;
GetMarkerRef()->FinishMarking(Config::StackState::kNoHeapPointers);
GetMarkerRef().reset();
Heap::From(GetHeap())->stats_collector()->NotifySweepingCompleted();
}
void ResetDelegatingTracingController(const char* expected_name = nullptr) {
DelegatingTracingControllerImpl::AddTraceEvent_callcount = 0u;
DelegatingTracingControllerImpl::stored_num_args = 0;
DelegatingTracingControllerImpl::stored_arg_names.clear();
DelegatingTracingControllerImpl::stored_arg_types.clear();
DelegatingTracingControllerImpl::stored_arg_values.clear();
DelegatingTracingControllerImpl::expected_name = expected_name;
}
void FindArgument(std::string name, uint8_t type, uint64_t value) {
int i = 0;
for (; i < DelegatingTracingControllerImpl::stored_num_args; ++i) {
if (name.compare(DelegatingTracingControllerImpl::stored_arg_names[i]) ==
0)
break;
}
EXPECT_LT(i, DelegatingTracingControllerImpl::stored_num_args);
EXPECT_EQ(type, DelegatingTracingControllerImpl::stored_arg_types[i]);
EXPECT_EQ(value, DelegatingTracingControllerImpl::stored_arg_values[i]);
}
};
} // namespace
TEST_F(CppgcTracingScopesTest, DisabledScope) {
StartGC();
ResetDelegatingTracingController();
{
StatsCollector::DisabledScope scope(
Heap::From(GetHeap())->stats_collector(),
StatsCollector::kMarkProcessMarkingWorklist);
}
EXPECT_EQ(0u, DelegatingTracingControllerImpl::AddTraceEvent_callcount);
EndGC();
}
TEST_F(CppgcTracingScopesTest, EnabledScope) {
{
StartGC();
ResetDelegatingTracingController("CppGC.MarkProcessMarkingWorklist");
{
StatsCollector::EnabledScope scope(
Heap::From(GetHeap())->stats_collector(),
StatsCollector::kMarkProcessMarkingWorklist);
}
EXPECT_EQ(2u, DelegatingTracingControllerImpl::AddTraceEvent_callcount);
EndGC();
}
{
StartGC();
ResetDelegatingTracingController("CppGC.MarkProcessWriteBarrierWorklist");
{
StatsCollector::EnabledScope scope(
Heap::From(GetHeap())->stats_collector(),
StatsCollector::kMarkProcessWriteBarrierWorklist);
}
EXPECT_EQ(2u, DelegatingTracingControllerImpl::AddTraceEvent_callcount);
EndGC();
}
}
TEST_F(CppgcTracingScopesTest, EnabledScopeWithArgs) {
// Scopes always add 2 arguments: epoch and is_forced_gc.
{
StartGC();
ResetDelegatingTracingController();
{
StatsCollector::EnabledScope scope(
Heap::From(GetHeap())->stats_collector(),
StatsCollector::kMarkProcessMarkingWorklist);
}
EXPECT_EQ(2, DelegatingTracingControllerImpl::stored_num_args);
EndGC();
}
{
StartGC();
ResetDelegatingTracingController();
{
StatsCollector::EnabledScope scope(
Heap::From(GetHeap())->stats_collector(),
StatsCollector::kMarkProcessMarkingWorklist, "arg1", 1);
}
EXPECT_EQ(3, DelegatingTracingControllerImpl::stored_num_args);
EndGC();
}
{
StartGC();
ResetDelegatingTracingController();
{
StatsCollector::EnabledScope scope(
Heap::From(GetHeap())->stats_collector(),
StatsCollector::kMarkProcessMarkingWorklist, "arg1", 1, "arg2", 2);
}
EXPECT_EQ(4, DelegatingTracingControllerImpl::stored_num_args);
EndGC();
}
}
TEST_F(CppgcTracingScopesTest, CheckScopeArgs) {
{
StartGC();
ResetDelegatingTracingController();
{
StatsCollector::EnabledScope scope(
Heap::From(GetHeap())->stats_collector(),
StatsCollector::kMarkProcessMarkingWorklist, "uint_arg", 13u,
"bool_arg", false);
}
FindArgument("uint_arg", TRACE_VALUE_TYPE_UINT, 13);
FindArgument("bool_arg", TRACE_VALUE_TYPE_BOOL, false);
EndGC();
}
{
StartGC();
ResetDelegatingTracingController();
{
StatsCollector::EnabledScope scope(
Heap::From(GetHeap())->stats_collector(),
StatsCollector::kMarkProcessMarkingWorklist, "neg_int_arg", -5,
"pos_int_arg", 7);
}
FindArgument("neg_int_arg", TRACE_VALUE_TYPE_INT, -5);
FindArgument("pos_int_arg", TRACE_VALUE_TYPE_INT, 7);
EndGC();
}
{
StartGC();
ResetDelegatingTracingController();
double double_value = 1.2;
const char* string_value = "test";
{
StatsCollector::EnabledScope scope(
Heap::From(GetHeap())->stats_collector(),
StatsCollector::kMarkProcessMarkingWorklist, "string_arg",
string_value, "double_arg", double_value);
}
FindArgument("string_arg", TRACE_VALUE_TYPE_STRING,
reinterpret_cast<uint64_t>(string_value));
FindArgument("double_arg", TRACE_VALUE_TYPE_DOUBLE,
*reinterpret_cast<uint64_t*>(&double_value));
EndGC();
}
}
TEST_F(CppgcTracingScopesTest, InitalScopesAreZero) {
StatsCollector* stats_collector = Heap::From(GetHeap())->stats_collector();
stats_collector->NotifyMarkingStarted(
GarbageCollector::Config::CollectionType::kMajor,
GarbageCollector::Config::IsForcedGC::kNotForced);
stats_collector->NotifyMarkingCompleted(0);
stats_collector->NotifySweepingCompleted();
const StatsCollector::Event& event =
stats_collector->GetPreviousEventForTesting();
for (int i = 0; i < StatsCollector::kNumHistogramScopeIds; ++i) {
EXPECT_TRUE(event.scope_data[i].IsZero());
}
for (int i = 0; i < StatsCollector::kNumHistogramConcurrentScopeIds; ++i) {
EXPECT_EQ(0, event.concurrent_scope_data[i]);
}
}
TEST_F(CppgcTracingScopesTest, TestIndividualScopes) {
for (int scope_id = 0; scope_id < StatsCollector::kNumHistogramScopeIds;
++scope_id) {
StatsCollector* stats_collector = Heap::From(GetHeap())->stats_collector();
stats_collector->NotifyMarkingStarted(
GarbageCollector::Config::CollectionType::kMajor,
GarbageCollector::Config::IsForcedGC::kNotForced);
DelegatingTracingControllerImpl::check_expectations = false;
{
StatsCollector::EnabledScope scope(
Heap::From(GetHeap())->stats_collector(),
static_cast<StatsCollector::ScopeId>(scope_id));
v8::base::TimeTicks time = v8::base::TimeTicks::Now();
while (time == v8::base::TimeTicks::Now()) {
// Force time to progress before destroying scope.
}
}
stats_collector->NotifyMarkingCompleted(0);
stats_collector->NotifySweepingCompleted();
const StatsCollector::Event& event =
stats_collector->GetPreviousEventForTesting();
for (int i = 0; i < StatsCollector::kNumHistogramScopeIds; ++i) {
if (i == scope_id)
EXPECT_LT(v8::base::TimeDelta(), event.scope_data[i]);
else
EXPECT_TRUE(event.scope_data[i].IsZero());
}
for (int i = 0; i < StatsCollector::kNumHistogramConcurrentScopeIds; ++i) {
EXPECT_EQ(0, event.concurrent_scope_data[i]);
}
}
}
TEST_F(CppgcTracingScopesTest, TestIndividualConcurrentScopes) {
for (int scope_id = 0;
scope_id < StatsCollector::kNumHistogramConcurrentScopeIds; ++scope_id) {
StatsCollector* stats_collector = Heap::From(GetHeap())->stats_collector();
stats_collector->NotifyMarkingStarted(
GarbageCollector::Config::CollectionType::kMajor,
GarbageCollector::Config::IsForcedGC::kNotForced);
DelegatingTracingControllerImpl::check_expectations = false;
{
StatsCollector::EnabledConcurrentScope scope(
Heap::From(GetHeap())->stats_collector(),
static_cast<StatsCollector::ConcurrentScopeId>(scope_id));
v8::base::TimeTicks time = v8::base::TimeTicks::Now();
while (time == v8::base::TimeTicks::Now()) {
// Force time to progress before destroying scope.
}
}
stats_collector->NotifyMarkingCompleted(0);
stats_collector->NotifySweepingCompleted();
const StatsCollector::Event& event =
stats_collector->GetPreviousEventForTesting();
for (int i = 0; i < StatsCollector::kNumHistogramScopeIds; ++i) {
EXPECT_TRUE(event.scope_data[i].IsZero());
}
for (int i = 0; i < StatsCollector::kNumHistogramConcurrentScopeIds; ++i) {
if (i == scope_id)
EXPECT_LT(0, event.concurrent_scope_data[i]);
else
EXPECT_EQ(0, event.concurrent_scope_data[i]);
}
}
}
} // namespace internal
} // namespace cppgc
#endif // CPPGC_IS_STANDALONE