1 | // mycpp/bump_leak_heap.cc: Leaky Bump Allocator
|
2 |
|
3 | #include "mycpp/bump_leak_heap.h"
|
4 |
|
5 | #include <inttypes.h> // PRId64
|
6 | #include <stddef.h>
|
7 | #include <stdio.h>
|
8 | #include <string.h> // memcpy
|
9 | #include <unistd.h> // STDERR_FILENO
|
10 |
|
11 | #include "mycpp/common.h" // aligned
|
12 |
|
13 | // We need this #ifdef because we don't want the global var in other binaries
|
14 |
|
15 | #if defined(BUMP_LEAK) || defined(BUMP_SMALL) || defined(BUMP_BIG)
|
16 |
|
17 | // some benchmarks take more than 1 GiB
|
18 | // but cachegrind can't work with static data of 2 GiB (get mmap() error)
|
19 | char gMemory[MiB(1400)];
|
20 |
|
21 | // This type is for "layout"; it's not instantiated
|
22 | struct LayoutBlock {
|
23 | size_t num_bytes;
|
24 | char data[1]; // flexible array
|
25 | };
|
26 |
|
27 | // offsetof() accounts for possible padding, but it should equal sizeof(size_t)
|
28 | const int kHeaderSize = offsetof(LayoutBlock, data);
|
29 |
|
30 | // Allocate() bumps a pointer
|
31 | void* BumpLeakHeap::Allocate(size_t num_bytes) {
|
32 | char* p = &(gMemory[mem_pos_]);
|
33 | LayoutBlock* block = reinterpret_cast<LayoutBlock*>(p);
|
34 | block->num_bytes = num_bytes; // record size for Reallocate()
|
35 |
|
36 | mem_pos_ += aligned(kHeaderSize + num_bytes);
|
37 |
|
38 | // Update stats
|
39 | num_allocated_++;
|
40 | bytes_allocated_ += num_bytes;
|
41 |
|
42 | // log("Allocate() -> %p", block->data);
|
43 | return block->data; // pointer user can write to
|
44 | }
|
45 |
|
46 | // Reallocate() calls Allocate() and then copies the old data
|
47 | void* BumpLeakHeap::Reallocate(void* old_data, size_t num_bytes) {
|
48 | // log("");
|
49 | // log("Reallocate(%d) got %p", num_bytes, old_data);
|
50 | char* new_data = reinterpret_cast<char*>(Allocate(num_bytes));
|
51 |
|
52 | char* p_old = reinterpret_cast<char*>(old_data) - kHeaderSize;
|
53 | LayoutBlock* old_block = reinterpret_cast<LayoutBlock*>(p_old);
|
54 |
|
55 | memcpy(new_data, old_block->data, old_block->num_bytes);
|
56 |
|
57 | return new_data;
|
58 | }
|
59 |
|
60 | void BumpLeakHeap::PrintStats(int fd) {
|
61 | dprintf(fd, "[BumpLeakHeap]");
|
62 | #ifdef BUMP_ROOT
|
63 | dprintf(fd, " max roots = %10d\n", max_roots_);
|
64 | #endif
|
65 | dprintf(fd, " num allocated = %10d\n", num_allocated_);
|
66 | dprintf(fd, "bytes allocated = %10" PRId64 "\n", bytes_allocated_);
|
67 | dprintf(fd, " mem pos = %10d\n", mem_pos_);
|
68 | }
|
69 |
|
70 | void BumpLeakHeap::CleanProcessExit() {
|
71 | PrintStats(STDERR_FILENO);
|
72 | }
|
73 |
|
74 | void BumpLeakHeap::ProcessExit() {
|
75 | PrintStats(STDERR_FILENO);
|
76 | }
|
77 | #endif
|
78 |
|
79 | #ifdef BUMP_LEAK
|
80 | BumpLeakHeap gHeap;
|
81 | #endif
|