1// Copyright 2014 the V8 project authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "src/base/utils/random-number-generator.h"
6#include "src/compiler/zone-pool.h"
7#include "test/unittests/test-utils.h"
8
9namespace v8 {
10namespace internal {
11namespace compiler {
12
13class ZonePoolTest : public TestWithIsolate {
14 public:
15  ZonePoolTest() : zone_pool_(&allocator_) {}
16
17 protected:
18  ZonePool* zone_pool() { return &zone_pool_; }
19
20  void ExpectForPool(size_t current, size_t max, size_t total) {
21    ASSERT_EQ(current, zone_pool()->GetCurrentAllocatedBytes());
22    ASSERT_EQ(max, zone_pool()->GetMaxAllocatedBytes());
23    ASSERT_EQ(total, zone_pool()->GetTotalAllocatedBytes());
24  }
25
26  void Expect(ZonePool::StatsScope* stats, size_t current, size_t max,
27              size_t total) {
28    ASSERT_EQ(current, stats->GetCurrentAllocatedBytes());
29    ASSERT_EQ(max, stats->GetMaxAllocatedBytes());
30    ASSERT_EQ(total, stats->GetTotalAllocatedBytes());
31  }
32
33  size_t Allocate(Zone* zone) {
34    size_t bytes = rng.NextInt(25) + 7;
35    size_t size_before = zone->allocation_size();
36    zone->New(bytes);
37    return zone->allocation_size() - size_before;
38  }
39
40 private:
41  base::AccountingAllocator allocator_;
42  ZonePool zone_pool_;
43  base::RandomNumberGenerator rng;
44};
45
46
47TEST_F(ZonePoolTest, Empty) {
48  ExpectForPool(0, 0, 0);
49  {
50    ZonePool::StatsScope stats(zone_pool());
51    Expect(&stats, 0, 0, 0);
52  }
53  ExpectForPool(0, 0, 0);
54  {
55    ZonePool::Scope scope(zone_pool());
56    scope.zone();
57  }
58  ExpectForPool(0, 0, 0);
59}
60
61
62TEST_F(ZonePoolTest, MultipleZonesWithDeletion) {
63  static const size_t kArraySize = 10;
64
65  ZonePool::Scope* scopes[kArraySize];
66
67  // Initialize.
68  size_t before_stats = 0;
69  for (size_t i = 0; i < kArraySize; ++i) {
70    scopes[i] = new ZonePool::Scope(zone_pool());
71    before_stats += Allocate(scopes[i]->zone());  // Add some stuff.
72  }
73
74  ExpectForPool(before_stats, before_stats, before_stats);
75
76  ZonePool::StatsScope stats(zone_pool());
77
78  size_t before_deletion = 0;
79  for (size_t i = 0; i < kArraySize; ++i) {
80    before_deletion += Allocate(scopes[i]->zone());  // Add some stuff.
81  }
82
83  Expect(&stats, before_deletion, before_deletion, before_deletion);
84  ExpectForPool(before_stats + before_deletion, before_stats + before_deletion,
85                before_stats + before_deletion);
86
87  // Delete the scopes and create new ones.
88  for (size_t i = 0; i < kArraySize; ++i) {
89    delete scopes[i];
90    scopes[i] = new ZonePool::Scope(zone_pool());
91  }
92
93  Expect(&stats, 0, before_deletion, before_deletion);
94  ExpectForPool(0, before_stats + before_deletion,
95                before_stats + before_deletion);
96
97  size_t after_deletion = 0;
98  for (size_t i = 0; i < kArraySize; ++i) {
99    after_deletion += Allocate(scopes[i]->zone());  // Add some stuff.
100  }
101
102  Expect(&stats, after_deletion, std::max(after_deletion, before_deletion),
103         before_deletion + after_deletion);
104  ExpectForPool(after_deletion,
105                std::max(after_deletion, before_stats + before_deletion),
106                before_stats + before_deletion + after_deletion);
107
108  // Cleanup.
109  for (size_t i = 0; i < kArraySize; ++i) {
110    delete scopes[i];
111  }
112
113  Expect(&stats, 0, std::max(after_deletion, before_deletion),
114         before_deletion + after_deletion);
115  ExpectForPool(0, std::max(after_deletion, before_stats + before_deletion),
116                before_stats + before_deletion + after_deletion);
117}
118
119
120TEST_F(ZonePoolTest, SimpleAllocationLoop) {
121  int runs = 20;
122  size_t total_allocated = 0;
123  size_t max_loop_allocation = 0;
124  ZonePool::StatsScope outer_stats(zone_pool());
125  {
126    ZonePool::Scope outer_scope(zone_pool());
127    size_t outer_allocated = 0;
128    for (int i = 0; i < runs; ++i) {
129      {
130        size_t bytes = Allocate(outer_scope.zone());
131        outer_allocated += bytes;
132        total_allocated += bytes;
133      }
134      ZonePool::StatsScope inner_stats(zone_pool());
135      size_t allocated = 0;
136      {
137        ZonePool::Scope inner_scope(zone_pool());
138        for (int j = 0; j < 20; ++j) {
139          size_t bytes = Allocate(inner_scope.zone());
140          allocated += bytes;
141          total_allocated += bytes;
142          max_loop_allocation =
143              std::max(max_loop_allocation, outer_allocated + allocated);
144          Expect(&inner_stats, allocated, allocated, allocated);
145          Expect(&outer_stats, outer_allocated + allocated, max_loop_allocation,
146                 total_allocated);
147          ExpectForPool(outer_allocated + allocated, max_loop_allocation,
148                        total_allocated);
149        }
150      }
151      Expect(&inner_stats, 0, allocated, allocated);
152      Expect(&outer_stats, outer_allocated, max_loop_allocation,
153             total_allocated);
154      ExpectForPool(outer_allocated, max_loop_allocation, total_allocated);
155    }
156  }
157  Expect(&outer_stats, 0, max_loop_allocation, total_allocated);
158  ExpectForPool(0, max_loop_allocation, total_allocated);
159}
160
161}  // namespace compiler
162}  // namespace internal
163}  // namespace v8
164