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

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 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
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, InsertRemove) { 58 TEST_F(AllocationRegisterTest, InsertRemove) {
59 AllocationRegister reg; 59 AllocationRegister reg;
60 AllocationContext ctx = AllocationContext::Empty(); 60 AllocationContext ctx = AllocationContext::Empty();
61 61
62 // Zero-sized allocations should be discarded.
63 reg.Insert(reinterpret_cast<void*>(1), 0, ctx);
64
62 EXPECT_EQ(0u, OrAllAddresses(reg)); 65 EXPECT_EQ(0u, OrAllAddresses(reg));
63 66
64 reg.Insert(reinterpret_cast<void*>(1), 0, ctx); 67 reg.Insert(reinterpret_cast<void*>(1), 1, ctx);
65 68
66 EXPECT_EQ(1u, OrAllAddresses(reg)); 69 EXPECT_EQ(1u, OrAllAddresses(reg));
67 70
68 reg.Insert(reinterpret_cast<void*>(2), 0, ctx); 71 reg.Insert(reinterpret_cast<void*>(2), 1, ctx);
69 72
70 EXPECT_EQ(3u, OrAllAddresses(reg)); 73 EXPECT_EQ(3u, OrAllAddresses(reg));
71 74
72 reg.Insert(reinterpret_cast<void*>(4), 0, ctx); 75 reg.Insert(reinterpret_cast<void*>(4), 1, ctx);
73 76
74 EXPECT_EQ(7u, OrAllAddresses(reg)); 77 EXPECT_EQ(7u, OrAllAddresses(reg));
75 78
76 reg.Remove(reinterpret_cast<void*>(2)); 79 reg.Remove(reinterpret_cast<void*>(2));
77 80
78 EXPECT_EQ(5u, OrAllAddresses(reg)); 81 EXPECT_EQ(5u, OrAllAddresses(reg));
79 82
80 reg.Remove(reinterpret_cast<void*>(4)); 83 reg.Remove(reinterpret_cast<void*>(4));
81 84
82 EXPECT_EQ(1u, OrAllAddresses(reg)); 85 EXPECT_EQ(1u, OrAllAddresses(reg));
83 86
84 reg.Remove(reinterpret_cast<void*>(1)); 87 reg.Remove(reinterpret_cast<void*>(1));
85 88
86 EXPECT_EQ(0u, OrAllAddresses(reg)); 89 EXPECT_EQ(0u, OrAllAddresses(reg));
87 } 90 }
88 91
89 TEST_F(AllocationRegisterTest, DoubleFreeIsAllowed) { 92 TEST_F(AllocationRegisterTest, DoubleFreeIsAllowed) {
90 AllocationRegister reg; 93 AllocationRegister reg;
91 AllocationContext ctx = AllocationContext::Empty(); 94 AllocationContext ctx = AllocationContext::Empty();
92 95
93 reg.Insert(reinterpret_cast<void*>(1), 0, ctx); 96 reg.Insert(reinterpret_cast<void*>(1), 1, ctx);
94 reg.Insert(reinterpret_cast<void*>(2), 0, ctx); 97 reg.Insert(reinterpret_cast<void*>(2), 1, ctx);
95 reg.Remove(reinterpret_cast<void*>(1)); 98 reg.Remove(reinterpret_cast<void*>(1));
96 reg.Remove(reinterpret_cast<void*>(1)); // Remove for the second time. 99 reg.Remove(reinterpret_cast<void*>(1)); // Remove for the second time.
97 reg.Remove(reinterpret_cast<void*>(4)); // Remove never inserted address. 100 reg.Remove(reinterpret_cast<void*>(4)); // Remove never inserted address.
98 101
99 EXPECT_EQ(2u, OrAllAddresses(reg)); 102 EXPECT_EQ(2u, OrAllAddresses(reg));
100 } 103 }
101 104
102 TEST_F(AllocationRegisterTest, DoubleInsertOverwrites) { 105 TEST_F(AllocationRegisterTest, DoubleInsertOverwrites) {
103 // TODO(ruuda): Although double insert happens in practice, it should not. 106 // TODO(ruuda): Although double insert happens in practice, it should not.
104 // Find out the cause and ban double insert if possible. 107 // 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) { 175 TEST_F(AllocationRegisterTest, InsertRemoveRandomOrder) {
173 size_t expected_sum = 0; 176 size_t expected_sum = 0;
174 AllocationRegister reg; 177 AllocationRegister reg;
175 AllocationContext ctx = AllocationContext::Empty(); 178 AllocationContext ctx = AllocationContext::Empty();
176 179
177 uintptr_t generator = 3; 180 uintptr_t generator = 3;
178 uintptr_t prime = 1013; 181 uintptr_t prime = 1013;
179 uint32_t initial_water_mark = GetHighWaterMark(reg); 182 uint32_t initial_water_mark = GetHighWaterMark(reg);
180 183
181 for (uintptr_t i = 2; i < prime; i++) { 184 for (uintptr_t i = 2; i < prime; i++) {
182 size_t size = i % 31; 185 size_t size = i % 31 + 1;
183 expected_sum += size; 186 expected_sum += size;
184 reg.Insert(reinterpret_cast<void*>(i), size, ctx); 187 reg.Insert(reinterpret_cast<void*>(i), size, ctx);
185 } 188 }
186 189
187 // This should have used a fresh slot for each of the |prime - 2| inserts. 190 // This should have used a fresh slot for each of the |prime - 2| inserts.
188 ASSERT_EQ(prime - 2, GetHighWaterMark(reg) - initial_water_mark); 191 ASSERT_EQ(prime - 2, GetHighWaterMark(reg) - initial_water_mark);
189 192
190 // Iterate the numbers 2, 3, ..., prime - 1 in pseudorandom order. 193 // Iterate the numbers 2, 3, ..., prime - 1 in pseudorandom order.
191 for (uintptr_t i = generator; i != 1; i = (i * generator) % prime) { 194 for (uintptr_t i = generator; i != 1; i = (i * generator) % prime) {
192 size_t size = i % 31; 195 size_t size = i % 31 + 1;
193 expected_sum -= size; 196 expected_sum -= size;
194 reg.Remove(reinterpret_cast<void*>(i)); 197 reg.Remove(reinterpret_cast<void*>(i));
195 EXPECT_EQ(expected_sum, SumAllSizes(reg)); 198 EXPECT_EQ(expected_sum, SumAllSizes(reg));
196 } 199 }
197 200
198 ASSERT_EQ(0u, expected_sum); 201 ASSERT_EQ(0u, expected_sum);
199 202
200 // Insert |prime - 2| entries again. This should use cells from the free list, 203 // Insert |prime - 2| entries again. This should use cells from the free list,
201 // so the |next_unused_cell_| index should not change. 204 // so the |next_unused_cell_| index should not change.
202 for (uintptr_t i = 2; i < prime; i++) 205 for (uintptr_t i = 2; i < prime; i++)
203 reg.Insert(reinterpret_cast<void*>(i), 0, ctx); 206 reg.Insert(reinterpret_cast<void*>(i), 1, ctx);
204 207
205 ASSERT_EQ(prime - 2, GetHighWaterMark(reg) - initial_water_mark); 208 ASSERT_EQ(prime - 2, GetHighWaterMark(reg) - initial_water_mark);
206 209
207 // Inserting one more entry should use a fresh cell again. 210 // Inserting one more entry should use a fresh cell again.
208 reg.Insert(reinterpret_cast<void*>(prime), 0, ctx); 211 reg.Insert(reinterpret_cast<void*>(prime), 1, ctx);
209 ASSERT_EQ(prime - 1, GetHighWaterMark(reg) - initial_water_mark); 212 ASSERT_EQ(prime - 1, GetHighWaterMark(reg) - initial_water_mark);
210 } 213 }
211 214
212 TEST_F(AllocationRegisterTest, ChangeContextAfterInsertion) { 215 TEST_F(AllocationRegisterTest, ChangeContextAfterInsertion) {
213 using Allocation = AllocationRegister::Allocation; 216 using Allocation = AllocationRegister::Allocation;
214 const char kStdString[] = "std::string"; 217 const char kStdString[] = "std::string";
215 AllocationRegister reg; 218 AllocationRegister reg;
216 AllocationContext ctx = AllocationContext::Empty(); 219 AllocationContext ctx = AllocationContext::Empty();
217 220
218 reg.Insert(reinterpret_cast<void*>(17), 1, ctx); 221 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) { 264 TEST_F(AllocationRegisterTest, OverflowDeathTest) {
262 // Use a smaller register to prevent OOM errors on low-end devices. 265 // Use a smaller register to prevent OOM errors on low-end devices.
263 AllocationRegister reg(static_cast<uint32_t>(GetNumCellsPerPage())); 266 AllocationRegister reg(static_cast<uint32_t>(GetNumCellsPerPage()));
264 AllocationContext ctx = AllocationContext::Empty(); 267 AllocationContext ctx = AllocationContext::Empty();
265 uintptr_t i; 268 uintptr_t i;
266 269
267 // Fill up all of the memory allocated for the register. |GetNumCells(reg)| 270 // 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 271 // minus 1 elements are inserted, because cell 0 is unused, so this should
269 // fill up the available cells exactly. 272 // fill up the available cells exactly.
270 for (i = 1; i < GetNumCells(reg); i++) { 273 for (i = 1; i < GetNumCells(reg); i++) {
271 reg.Insert(reinterpret_cast<void*>(i), 0, ctx); 274 reg.Insert(reinterpret_cast<void*>(i), 1, ctx);
272 } 275 }
273 276
274 // Adding just one extra element might still work because the allocated memory 277 // 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 278 // is rounded up to the page size. Adding a page full of elements should cause
276 // overflow. 279 // overflow.
277 const size_t cells_per_page = GetNumCellsPerPage(); 280 const size_t cells_per_page = GetNumCellsPerPage();
278 281
279 ASSERT_DEATH(for (size_t j = 0; j < cells_per_page; j++) { 282 ASSERT_DEATH(for (size_t j = 0; j < cells_per_page; j++) {
280 reg.Insert(reinterpret_cast<void*>(i + j), 0, ctx); 283 reg.Insert(reinterpret_cast<void*>(i + j), 1, ctx);
281 }, ""); 284 }, "");
282 } 285 }
283 #endif 286 #endif
284 287
285 } // namespace trace_event 288 } // namespace trace_event
286 } // namespace base 289 } // namespace base
OLDNEW
« no previous file with comments | « base/trace_event/heap_profiler_allocation_register.cc ('k') | base/trace_event/heap_profiler_heap_dump_writer.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698