Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(71)

Side by Side Diff: base/trace_event/heap_profiler_allocation_register_unittest.cc

Issue 1859143003: Handle zero-size allocations properly in heap profiler (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 4 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698