| 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 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 |
| OLD | NEW |