// Copyright 2014 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. #include "src/compiler/zone-stats.h" #include "src/base/utils/random-number-generator.h" #include "test/unittests/test-utils.h" namespace v8 { namespace internal { namespace compiler { class ZoneStatsTest : public ::testing::Test { public: ZoneStatsTest() : zone_stats_(&allocator_) {} protected: ZoneStats* zone_stats() { return &zone_stats_; } void ExpectForPool(size_t current, size_t max, size_t total) { ASSERT_EQ(current, zone_stats()->GetCurrentAllocatedBytes()); ASSERT_EQ(max, zone_stats()->GetMaxAllocatedBytes()); ASSERT_EQ(total, zone_stats()->GetTotalAllocatedBytes()); } void Expect(ZoneStats::StatsScope* stats, size_t current, size_t max, size_t total) { ASSERT_EQ(current, stats->GetCurrentAllocatedBytes()); ASSERT_EQ(max, stats->GetMaxAllocatedBytes()); ASSERT_EQ(total, stats->GetTotalAllocatedBytes()); } size_t Allocate(Zone* zone) { size_t bytes = rng.NextInt(25) + 7; size_t size_before = zone->allocation_size(); zone->New(bytes); return zone->allocation_size() - size_before; } private: v8::internal::AccountingAllocator allocator_; ZoneStats zone_stats_; base::RandomNumberGenerator rng; }; TEST_F(ZoneStatsTest, Empty) { ExpectForPool(0, 0, 0); { ZoneStats::StatsScope stats(zone_stats()); Expect(&stats, 0, 0, 0); } ExpectForPool(0, 0, 0); { ZoneStats::Scope scope(zone_stats(), ZONE_NAME); scope.zone(); } ExpectForPool(0, 0, 0); } TEST_F(ZoneStatsTest, MultipleZonesWithDeletion) { static const size_t kArraySize = 10; ZoneStats::Scope* scopes[kArraySize]; // Initialize. size_t before_stats = 0; for (size_t i = 0; i < kArraySize; ++i) { scopes[i] = new ZoneStats::Scope(zone_stats(), ZONE_NAME); before_stats += Allocate(scopes[i]->zone()); // Add some stuff. } ExpectForPool(before_stats, before_stats, before_stats); ZoneStats::StatsScope stats(zone_stats()); size_t before_deletion = 0; for (size_t i = 0; i < kArraySize; ++i) { before_deletion += Allocate(scopes[i]->zone()); // Add some stuff. } Expect(&stats, before_deletion, before_deletion, before_deletion); ExpectForPool(before_stats + before_deletion, before_stats + before_deletion, before_stats + before_deletion); // Delete the scopes and create new ones. for (size_t i = 0; i < kArraySize; ++i) { delete scopes[i]; scopes[i] = new ZoneStats::Scope(zone_stats(), ZONE_NAME); } Expect(&stats, 0, before_deletion, before_deletion); ExpectForPool(0, before_stats + before_deletion, before_stats + before_deletion); size_t after_deletion = 0; for (size_t i = 0; i < kArraySize; ++i) { after_deletion += Allocate(scopes[i]->zone()); // Add some stuff. } Expect(&stats, after_deletion, std::max(after_deletion, before_deletion), before_deletion + after_deletion); ExpectForPool(after_deletion, std::max(after_deletion, before_stats + before_deletion), before_stats + before_deletion + after_deletion); // Cleanup. for (size_t i = 0; i < kArraySize; ++i) { delete scopes[i]; } Expect(&stats, 0, std::max(after_deletion, before_deletion), before_deletion + after_deletion); ExpectForPool(0, std::max(after_deletion, before_stats + before_deletion), before_stats + before_deletion + after_deletion); } TEST_F(ZoneStatsTest, SimpleAllocationLoop) { int runs = 20; size_t total_allocated = 0; size_t max_loop_allocation = 0; ZoneStats::StatsScope outer_stats(zone_stats()); { ZoneStats::Scope outer_scope(zone_stats(), ZONE_NAME); size_t outer_allocated = 0; for (int i = 0; i < runs; ++i) { { size_t bytes = Allocate(outer_scope.zone()); outer_allocated += bytes; total_allocated += bytes; } ZoneStats::StatsScope inner_stats(zone_stats()); size_t allocated = 0; { ZoneStats::Scope inner_scope(zone_stats(), ZONE_NAME); for (int j = 0; j < 20; ++j) { size_t bytes = Allocate(inner_scope.zone()); allocated += bytes; total_allocated += bytes; max_loop_allocation = std::max(max_loop_allocation, outer_allocated + allocated); Expect(&inner_stats, allocated, allocated, allocated); Expect(&outer_stats, outer_allocated + allocated, max_loop_allocation, total_allocated); ExpectForPool(outer_allocated + allocated, max_loop_allocation, total_allocated); } } Expect(&inner_stats, 0, allocated, allocated); Expect(&outer_stats, outer_allocated, max_loop_allocation, total_allocated); ExpectForPool(outer_allocated, max_loop_allocation, total_allocated); } } Expect(&outer_stats, 0, max_loop_allocation, total_allocated); ExpectForPool(0, max_loop_allocation, total_allocated); } } // namespace compiler } // namespace internal } // namespace v8