OLD | NEW |
---|---|
1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "base/trace_event/heap_profiler_allocation_register.h" | 5 #include "base/trace_event/heap_profiler_allocation_register.h" |
6 | 6 |
7 #include <stddef.h> | 7 #include <stddef.h> |
8 #include <stdint.h> | 8 #include <stdint.h> |
9 | 9 |
10 #include "base/process/process_metrics.h" | 10 #include "base/process/process_metrics.h" |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
48 // the sizes of the entries. | 48 // the sizes of the entries. |
49 size_t SumAllSizes(const AllocationRegister& reg) { | 49 size_t SumAllSizes(const AllocationRegister& reg) { |
50 size_t sum = 0; | 50 size_t sum = 0; |
51 | 51 |
52 for (auto i : reg) | 52 for (auto i : reg) |
53 sum += i.size; | 53 sum += i.size; |
54 | 54 |
55 return sum; | 55 return sum; |
56 } | 56 } |
57 | 57 |
58 TEST_F(AllocationRegisterTest, NoZeroSizeInsert) { | |
59 AllocationRegister reg; | |
60 AllocationContext ctx = AllocationContext::Empty(); | |
61 | |
62 reg.Insert(reinterpret_cast<void*>(1), 0, ctx); | |
Primiano Tucci (use gerrit)
2016/04/06 08:20:44
I think this (and line 64) can be moved to the Ins
| |
63 | |
64 EXPECT_EQ(0u, OrAllAddresses(reg)); | |
65 } | |
66 | |
58 TEST_F(AllocationRegisterTest, InsertRemove) { | 67 TEST_F(AllocationRegisterTest, InsertRemove) { |
59 AllocationRegister reg; | 68 AllocationRegister reg; |
60 AllocationContext ctx = AllocationContext::Empty(); | 69 AllocationContext ctx = AllocationContext::Empty(); |
61 | 70 |
62 EXPECT_EQ(0u, OrAllAddresses(reg)); | 71 EXPECT_EQ(0u, OrAllAddresses(reg)); |
63 | 72 |
64 reg.Insert(reinterpret_cast<void*>(1), 0, ctx); | 73 reg.Insert(reinterpret_cast<void*>(1), 1, ctx); |
65 | 74 |
66 EXPECT_EQ(1u, OrAllAddresses(reg)); | 75 EXPECT_EQ(1u, OrAllAddresses(reg)); |
67 | 76 |
68 reg.Insert(reinterpret_cast<void*>(2), 0, ctx); | 77 reg.Insert(reinterpret_cast<void*>(2), 1, ctx); |
69 | 78 |
70 EXPECT_EQ(3u, OrAllAddresses(reg)); | 79 EXPECT_EQ(3u, OrAllAddresses(reg)); |
71 | 80 |
72 reg.Insert(reinterpret_cast<void*>(4), 0, ctx); | 81 reg.Insert(reinterpret_cast<void*>(4), 1, ctx); |
73 | 82 |
74 EXPECT_EQ(7u, OrAllAddresses(reg)); | 83 EXPECT_EQ(7u, OrAllAddresses(reg)); |
75 | 84 |
76 reg.Remove(reinterpret_cast<void*>(2)); | 85 reg.Remove(reinterpret_cast<void*>(2)); |
77 | 86 |
78 EXPECT_EQ(5u, OrAllAddresses(reg)); | 87 EXPECT_EQ(5u, OrAllAddresses(reg)); |
79 | 88 |
80 reg.Remove(reinterpret_cast<void*>(4)); | 89 reg.Remove(reinterpret_cast<void*>(4)); |
81 | 90 |
82 EXPECT_EQ(1u, OrAllAddresses(reg)); | 91 EXPECT_EQ(1u, OrAllAddresses(reg)); |
83 | 92 |
84 reg.Remove(reinterpret_cast<void*>(1)); | 93 reg.Remove(reinterpret_cast<void*>(1)); |
85 | 94 |
86 EXPECT_EQ(0u, OrAllAddresses(reg)); | 95 EXPECT_EQ(0u, OrAllAddresses(reg)); |
87 } | 96 } |
88 | 97 |
89 TEST_F(AllocationRegisterTest, DoubleFreeIsAllowed) { | 98 TEST_F(AllocationRegisterTest, DoubleFreeIsAllowed) { |
90 AllocationRegister reg; | 99 AllocationRegister reg; |
91 AllocationContext ctx = AllocationContext::Empty(); | 100 AllocationContext ctx = AllocationContext::Empty(); |
92 | 101 |
93 reg.Insert(reinterpret_cast<void*>(1), 0, ctx); | 102 reg.Insert(reinterpret_cast<void*>(1), 1, ctx); |
94 reg.Insert(reinterpret_cast<void*>(2), 0, ctx); | 103 reg.Insert(reinterpret_cast<void*>(2), 1, ctx); |
95 reg.Remove(reinterpret_cast<void*>(1)); | 104 reg.Remove(reinterpret_cast<void*>(1)); |
96 reg.Remove(reinterpret_cast<void*>(1)); // Remove for the second time. | 105 reg.Remove(reinterpret_cast<void*>(1)); // Remove for the second time. |
97 reg.Remove(reinterpret_cast<void*>(4)); // Remove never inserted address. | 106 reg.Remove(reinterpret_cast<void*>(4)); // Remove never inserted address. |
98 | 107 |
99 EXPECT_EQ(2u, OrAllAddresses(reg)); | 108 EXPECT_EQ(2u, OrAllAddresses(reg)); |
100 } | 109 } |
101 | 110 |
102 TEST_F(AllocationRegisterTest, DoubleInsertOverwrites) { | 111 TEST_F(AllocationRegisterTest, DoubleInsertOverwrites) { |
103 // TODO(ruuda): Although double insert happens in practice, it should not. | 112 // TODO(ruuda): Although double insert happens in practice, it should not. |
104 // Find out the cause and ban double insert if possible. | 113 // Find out the cause and ban double insert if possible. |
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
172 TEST_F(AllocationRegisterTest, InsertRemoveRandomOrder) { | 181 TEST_F(AllocationRegisterTest, InsertRemoveRandomOrder) { |
173 size_t expected_sum = 0; | 182 size_t expected_sum = 0; |
174 AllocationRegister reg; | 183 AllocationRegister reg; |
175 AllocationContext ctx = AllocationContext::Empty(); | 184 AllocationContext ctx = AllocationContext::Empty(); |
176 | 185 |
177 uintptr_t generator = 3; | 186 uintptr_t generator = 3; |
178 uintptr_t prime = 1013; | 187 uintptr_t prime = 1013; |
179 uint32_t initial_water_mark = GetHighWaterMark(reg); | 188 uint32_t initial_water_mark = GetHighWaterMark(reg); |
180 | 189 |
181 for (uintptr_t i = 2; i < prime; i++) { | 190 for (uintptr_t i = 2; i < prime; i++) { |
182 size_t size = i % 31; | 191 size_t size = i % 31 + 1; |
183 expected_sum += size; | 192 expected_sum += size; |
184 reg.Insert(reinterpret_cast<void*>(i), size, ctx); | 193 reg.Insert(reinterpret_cast<void*>(i), size, ctx); |
185 } | 194 } |
186 | 195 |
187 // This should have used a fresh slot for each of the |prime - 2| inserts. | 196 // This should have used a fresh slot for each of the |prime - 2| inserts. |
188 ASSERT_EQ(prime - 2, GetHighWaterMark(reg) - initial_water_mark); | 197 ASSERT_EQ(prime - 2, GetHighWaterMark(reg) - initial_water_mark); |
189 | 198 |
190 // Iterate the numbers 2, 3, ..., prime - 1 in pseudorandom order. | 199 // Iterate the numbers 2, 3, ..., prime - 1 in pseudorandom order. |
191 for (uintptr_t i = generator; i != 1; i = (i * generator) % prime) { | 200 for (uintptr_t i = generator; i != 1; i = (i * generator) % prime) { |
192 size_t size = i % 31; | 201 size_t size = i % 31 + 1; |
193 expected_sum -= size; | 202 expected_sum -= size; |
194 reg.Remove(reinterpret_cast<void*>(i)); | 203 reg.Remove(reinterpret_cast<void*>(i)); |
195 EXPECT_EQ(expected_sum, SumAllSizes(reg)); | 204 EXPECT_EQ(expected_sum, SumAllSizes(reg)); |
196 } | 205 } |
197 | 206 |
198 ASSERT_EQ(0u, expected_sum); | 207 ASSERT_EQ(0u, expected_sum); |
199 | 208 |
200 // Insert |prime - 2| entries again. This should use cells from the free list, | 209 // Insert |prime - 2| entries again. This should use cells from the free list, |
201 // so the |next_unused_cell_| index should not change. | 210 // so the |next_unused_cell_| index should not change. |
202 for (uintptr_t i = 2; i < prime; i++) | 211 for (uintptr_t i = 2; i < prime; i++) |
203 reg.Insert(reinterpret_cast<void*>(i), 0, ctx); | 212 reg.Insert(reinterpret_cast<void*>(i), 1, ctx); |
204 | 213 |
205 ASSERT_EQ(prime - 2, GetHighWaterMark(reg) - initial_water_mark); | 214 ASSERT_EQ(prime - 2, GetHighWaterMark(reg) - initial_water_mark); |
206 | 215 |
207 // Inserting one more entry should use a fresh cell again. | 216 // Inserting one more entry should use a fresh cell again. |
208 reg.Insert(reinterpret_cast<void*>(prime), 0, ctx); | 217 reg.Insert(reinterpret_cast<void*>(prime), 1, ctx); |
209 ASSERT_EQ(prime - 1, GetHighWaterMark(reg) - initial_water_mark); | 218 ASSERT_EQ(prime - 1, GetHighWaterMark(reg) - initial_water_mark); |
210 } | 219 } |
211 | 220 |
212 TEST_F(AllocationRegisterTest, ChangeContextAfterInsertion) { | 221 TEST_F(AllocationRegisterTest, ChangeContextAfterInsertion) { |
213 using Allocation = AllocationRegister::Allocation; | 222 using Allocation = AllocationRegister::Allocation; |
214 const char kStdString[] = "std::string"; | 223 const char kStdString[] = "std::string"; |
215 AllocationRegister reg; | 224 AllocationRegister reg; |
216 AllocationContext ctx = AllocationContext::Empty(); | 225 AllocationContext ctx = AllocationContext::Empty(); |
217 | 226 |
218 reg.Insert(reinterpret_cast<void*>(17), 1, ctx); | 227 reg.Insert(reinterpret_cast<void*>(17), 1, ctx); |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
261 TEST_F(AllocationRegisterTest, OverflowDeathTest) { | 270 TEST_F(AllocationRegisterTest, OverflowDeathTest) { |
262 // Use a smaller register to prevent OOM errors on low-end devices. | 271 // Use a smaller register to prevent OOM errors on low-end devices. |
263 AllocationRegister reg(static_cast<uint32_t>(GetNumCellsPerPage())); | 272 AllocationRegister reg(static_cast<uint32_t>(GetNumCellsPerPage())); |
264 AllocationContext ctx = AllocationContext::Empty(); | 273 AllocationContext ctx = AllocationContext::Empty(); |
265 uintptr_t i; | 274 uintptr_t i; |
266 | 275 |
267 // Fill up all of the memory allocated for the register. |GetNumCells(reg)| | 276 // Fill up all of the memory allocated for the register. |GetNumCells(reg)| |
268 // minus 1 elements are inserted, because cell 0 is unused, so this should | 277 // minus 1 elements are inserted, because cell 0 is unused, so this should |
269 // fill up the available cells exactly. | 278 // fill up the available cells exactly. |
270 for (i = 1; i < GetNumCells(reg); i++) { | 279 for (i = 1; i < GetNumCells(reg); i++) { |
271 reg.Insert(reinterpret_cast<void*>(i), 0, ctx); | 280 reg.Insert(reinterpret_cast<void*>(i), 1, ctx); |
272 } | 281 } |
273 | 282 |
274 // Adding just one extra element might still work because the allocated memory | 283 // Adding just one extra element might still work because the allocated memory |
275 // is rounded up to the page size. Adding a page full of elements should cause | 284 // is rounded up to the page size. Adding a page full of elements should cause |
276 // overflow. | 285 // overflow. |
277 const size_t cells_per_page = GetNumCellsPerPage(); | 286 const size_t cells_per_page = GetNumCellsPerPage(); |
278 | 287 |
279 ASSERT_DEATH(for (size_t j = 0; j < cells_per_page; j++) { | 288 ASSERT_DEATH(for (size_t j = 0; j < cells_per_page; j++) { |
280 reg.Insert(reinterpret_cast<void*>(i + j), 0, ctx); | 289 reg.Insert(reinterpret_cast<void*>(i + j), 1, ctx); |
281 }, ""); | 290 }, ""); |
282 } | 291 } |
283 #endif | 292 #endif |
284 | 293 |
285 } // namespace trace_event | 294 } // namespace trace_event |
286 } // namespace base | 295 } // namespace base |
OLD | NEW |