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/memory_profiler_allocation_register.h" | 5 #include "base/trace_event/memory_profiler_allocation_register.h" |
6 | 6 |
7 #include "base/process/process_metrics.h" | 7 #include "base/process/process_metrics.h" |
8 #include "testing/gtest/include/gtest/gtest.h" | 8 #include "testing/gtest/include/gtest/gtest.h" |
9 | 9 |
10 namespace base { | 10 namespace base { |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
43 size_t sum = 0; | 43 size_t sum = 0; |
44 | 44 |
45 for (auto i : reg) | 45 for (auto i : reg) |
46 sum += i.size; | 46 sum += i.size; |
47 | 47 |
48 return sum; | 48 return sum; |
49 } | 49 } |
50 | 50 |
51 TEST_F(AllocationRegisterTest, InsertRemove) { | 51 TEST_F(AllocationRegisterTest, InsertRemove) { |
52 AllocationRegister reg; | 52 AllocationRegister reg; |
53 AllocationContext ctx; | 53 AllocationContext ctx = {}; |
54 | 54 |
55 EXPECT_EQ(0u, OrAllAddresses(reg)); | 55 EXPECT_EQ(0u, OrAllAddresses(reg)); |
56 | 56 |
57 reg.Insert(reinterpret_cast<void*>(1), 0, ctx); | 57 reg.Insert(reinterpret_cast<void*>(1), 0, ctx); |
58 | 58 |
59 EXPECT_EQ(1u, OrAllAddresses(reg)); | 59 EXPECT_EQ(1u, OrAllAddresses(reg)); |
60 | 60 |
61 reg.Insert(reinterpret_cast<void*>(2), 0, ctx); | 61 reg.Insert(reinterpret_cast<void*>(2), 0, ctx); |
62 | 62 |
63 EXPECT_EQ(3u, OrAllAddresses(reg)); | 63 EXPECT_EQ(3u, OrAllAddresses(reg)); |
(...skipping 10 matching lines...) Expand all Loading... |
74 | 74 |
75 EXPECT_EQ(1u, OrAllAddresses(reg)); | 75 EXPECT_EQ(1u, OrAllAddresses(reg)); |
76 | 76 |
77 reg.Remove(reinterpret_cast<void*>(1)); | 77 reg.Remove(reinterpret_cast<void*>(1)); |
78 | 78 |
79 EXPECT_EQ(0u, OrAllAddresses(reg)); | 79 EXPECT_EQ(0u, OrAllAddresses(reg)); |
80 } | 80 } |
81 | 81 |
82 TEST_F(AllocationRegisterTest, DoubleFreeIsAllowed) { | 82 TEST_F(AllocationRegisterTest, DoubleFreeIsAllowed) { |
83 AllocationRegister reg; | 83 AllocationRegister reg; |
84 AllocationContext ctx; | 84 AllocationContext ctx = {}; |
85 | 85 |
86 reg.Insert(reinterpret_cast<void*>(1), 0, ctx); | 86 reg.Insert(reinterpret_cast<void*>(1), 0, ctx); |
87 reg.Insert(reinterpret_cast<void*>(2), 0, ctx); | 87 reg.Insert(reinterpret_cast<void*>(2), 0, ctx); |
88 reg.Remove(reinterpret_cast<void*>(1)); | 88 reg.Remove(reinterpret_cast<void*>(1)); |
89 reg.Remove(reinterpret_cast<void*>(1)); // Remove for the second time. | 89 reg.Remove(reinterpret_cast<void*>(1)); // Remove for the second time. |
90 reg.Remove(reinterpret_cast<void*>(4)); // Remove never inserted address. | 90 reg.Remove(reinterpret_cast<void*>(4)); // Remove never inserted address. |
91 | 91 |
92 EXPECT_EQ(2u, OrAllAddresses(reg)); | 92 EXPECT_EQ(2u, OrAllAddresses(reg)); |
93 } | 93 } |
94 | 94 |
95 TEST_F(AllocationRegisterTest, DoubleInsertOverwrites) { | 95 TEST_F(AllocationRegisterTest, DoubleInsertOverwrites) { |
96 // TODO(ruuda): Although double insert happens in practice, it should not. | 96 // TODO(ruuda): Although double insert happens in practice, it should not. |
97 // Find out the cause and ban double insert if possible. | 97 // Find out the cause and ban double insert if possible. |
98 AllocationRegister reg; | 98 AllocationRegister reg; |
99 AllocationContext ctx; | 99 AllocationContext ctx = {}; |
100 StackFrame frame1 = "Foo"; | 100 StackFrame frame1 = "Foo"; |
101 StackFrame frame2 = "Bar"; | 101 StackFrame frame2 = "Bar"; |
102 | 102 |
103 ctx.backtrace.frames[0] = frame1; | 103 ctx.backtrace.frames[0] = frame1; |
104 reg.Insert(reinterpret_cast<void*>(1), 11, ctx); | 104 reg.Insert(reinterpret_cast<void*>(1), 11, ctx); |
105 | 105 |
106 auto elem = *reg.begin(); | 106 auto elem = *reg.begin(); |
107 | 107 |
108 EXPECT_EQ(frame1, elem.context.backtrace.frames[0]); | 108 EXPECT_EQ(frame1, elem.context.backtrace.frames[0]); |
109 EXPECT_EQ(11u, elem.size); | 109 EXPECT_EQ(11u, elem.size); |
110 EXPECT_EQ(reinterpret_cast<void*>(1), elem.address); | 110 EXPECT_EQ(reinterpret_cast<void*>(1), elem.address); |
111 | 111 |
112 ctx.backtrace.frames[0] = frame2; | 112 ctx.backtrace.frames[0] = frame2; |
113 reg.Insert(reinterpret_cast<void*>(1), 13, ctx); | 113 reg.Insert(reinterpret_cast<void*>(1), 13, ctx); |
114 | 114 |
115 elem = *reg.begin(); | 115 elem = *reg.begin(); |
116 | 116 |
117 EXPECT_EQ(frame2, elem.context.backtrace.frames[0]); | 117 EXPECT_EQ(frame2, elem.context.backtrace.frames[0]); |
118 EXPECT_EQ(13u, elem.size); | 118 EXPECT_EQ(13u, elem.size); |
119 EXPECT_EQ(reinterpret_cast<void*>(1), elem.address); | 119 EXPECT_EQ(reinterpret_cast<void*>(1), elem.address); |
120 } | 120 } |
121 | 121 |
122 // Check that even if more entries than the number of buckets are inserted, the | 122 // Check that even if more entries than the number of buckets are inserted, the |
123 // register still behaves correctly. | 123 // register still behaves correctly. |
124 TEST_F(AllocationRegisterTest, InsertRemoveCollisions) { | 124 TEST_F(AllocationRegisterTest, InsertRemoveCollisions) { |
125 size_t expected_sum = 0; | 125 size_t expected_sum = 0; |
126 AllocationRegister reg; | 126 AllocationRegister reg; |
127 AllocationContext ctx; | 127 AllocationContext ctx = {}; |
128 | 128 |
129 // By inserting 100 more entries than the number of buckets, there will be at | 129 // By inserting 100 more entries than the number of buckets, there will be at |
130 // least 100 collisions. | 130 // least 100 collisions. |
131 for (uintptr_t i = 1; i <= kNumBuckets + 100; i++) { | 131 for (uintptr_t i = 1; i <= kNumBuckets + 100; i++) { |
132 size_t size = i % 31; | 132 size_t size = i % 31; |
133 expected_sum += size; | 133 expected_sum += size; |
134 reg.Insert(reinterpret_cast<void*>(i), size, ctx); | 134 reg.Insert(reinterpret_cast<void*>(i), size, ctx); |
135 | 135 |
136 // Don't check the sum on every iteration to keep the test fast. | 136 // Don't check the sum on every iteration to keep the test fast. |
137 if (i % (1 << 14) == 0) | 137 if (i % (1 << 14) == 0) |
(...skipping 16 matching lines...) Expand all Loading... |
154 | 154 |
155 // The previous tests are not particularly good for testing iterators, because | 155 // The previous tests are not particularly good for testing iterators, because |
156 // elements are removed and inserted in the same order, meaning that the cells | 156 // elements are removed and inserted in the same order, meaning that the cells |
157 // fill up from low to high index, and are then freed from low to high index. | 157 // fill up from low to high index, and are then freed from low to high index. |
158 // This test removes entries in a different order, to ensure that the iterator | 158 // This test removes entries in a different order, to ensure that the iterator |
159 // skips over the freed cells properly. Then insert again to ensure that the | 159 // skips over the freed cells properly. Then insert again to ensure that the |
160 // free list is utilised properly. | 160 // free list is utilised properly. |
161 TEST_F(AllocationRegisterTest, InsertRemoveRandomOrder) { | 161 TEST_F(AllocationRegisterTest, InsertRemoveRandomOrder) { |
162 size_t expected_sum = 0; | 162 size_t expected_sum = 0; |
163 AllocationRegister reg; | 163 AllocationRegister reg; |
164 AllocationContext ctx; | 164 AllocationContext ctx = {}; |
165 | 165 |
166 uintptr_t generator = 3; | 166 uintptr_t generator = 3; |
167 uintptr_t prime = 1013; | 167 uintptr_t prime = 1013; |
168 uint32_t initial_water_mark = GetHighWaterMark(reg); | 168 uint32_t initial_water_mark = GetHighWaterMark(reg); |
169 | 169 |
170 for (uintptr_t i = 2; i < prime; i++) { | 170 for (uintptr_t i = 2; i < prime; i++) { |
171 size_t size = i % 31; | 171 size_t size = i % 31; |
172 expected_sum += size; | 172 expected_sum += size; |
173 reg.Insert(reinterpret_cast<void*>(i), size, ctx); | 173 reg.Insert(reinterpret_cast<void*>(i), size, ctx); |
174 } | 174 } |
(...skipping 21 matching lines...) Expand all Loading... |
196 // Inserting one more entry should use a fresh cell again. | 196 // Inserting one more entry should use a fresh cell again. |
197 reg.Insert(reinterpret_cast<void*>(prime), 0, ctx); | 197 reg.Insert(reinterpret_cast<void*>(prime), 0, ctx); |
198 ASSERT_EQ(prime - 1, GetHighWaterMark(reg) - initial_water_mark); | 198 ASSERT_EQ(prime - 1, GetHighWaterMark(reg) - initial_water_mark); |
199 } | 199 } |
200 | 200 |
201 // Check that the process aborts due to hitting the guard page when inserting | 201 // Check that the process aborts due to hitting the guard page when inserting |
202 // too many elements. | 202 // too many elements. |
203 #if GTEST_HAS_DEATH_TEST | 203 #if GTEST_HAS_DEATH_TEST |
204 TEST_F(AllocationRegisterTest, OverflowDeathTest) { | 204 TEST_F(AllocationRegisterTest, OverflowDeathTest) { |
205 AllocationRegister reg; | 205 AllocationRegister reg; |
206 AllocationContext ctx; | 206 AllocationContext ctx = {}; |
207 uintptr_t i; | 207 uintptr_t i; |
208 | 208 |
209 // Fill up all of the memory allocated for the register. |kNumCells| minus 1 | 209 // Fill up all of the memory allocated for the register. |kNumCells| minus 1 |
210 // elements are inserted, because cell 0 is unused, so this should fill up | 210 // elements are inserted, because cell 0 is unused, so this should fill up |
211 // the available cells exactly. | 211 // the available cells exactly. |
212 for (i = 1; i < kNumCells; i++) { | 212 for (i = 1; i < kNumCells; i++) { |
213 reg.Insert(reinterpret_cast<void*>(i), 0, ctx); | 213 reg.Insert(reinterpret_cast<void*>(i), 0, ctx); |
214 } | 214 } |
215 | 215 |
216 // Adding just one extra element might still work because the allocated memory | 216 // Adding just one extra element might still work because the allocated memory |
217 // is rounded up to the page size. Adding a page full of elements should cause | 217 // is rounded up to the page size. Adding a page full of elements should cause |
218 // overflow. | 218 // overflow. |
219 const size_t cells_per_page = GetNumCellsPerPage(); | 219 const size_t cells_per_page = GetNumCellsPerPage(); |
220 | 220 |
221 ASSERT_DEATH(for (size_t j = 0; j < cells_per_page; j++) { | 221 ASSERT_DEATH(for (size_t j = 0; j < cells_per_page; j++) { |
222 reg.Insert(reinterpret_cast<void*>(i + j), 0, ctx); | 222 reg.Insert(reinterpret_cast<void*>(i + j), 0, ctx); |
223 }, ""); | 223 }, ""); |
224 } | 224 } |
225 #endif | 225 #endif |
226 | 226 |
227 } // namespace trace_event | 227 } // namespace trace_event |
228 } // namespace base | 228 } // namespace base |
OLD | NEW |