GCC Code Coverage Report


Directory: ../
File: src/util/BlockAllocator.h
Date: 2024-12-24 01:17:15
Exec Total Coverage
Lines: 32 38 84.2%
Functions: 89 91 97.8%
Branches: 19 48 39.6%

Line Branch Exec Source
1 // Copyright (c) 2021-2024 ChilliBits. All rights reserved.
2
3 #pragma once
4
5 #include <vector>
6
7 #include <exception/CompilerError.h>
8 #include <util/CommonUtil.h>
9 #include <util/Memory.h>
10
11 namespace spice::compiler {
12
13 template <typename Base> class BlockAllocator {
14 public:
15 // Constructors
16 393 explicit BlockAllocator(const MemoryManager &memoryManager, size_t blockSize = CommonUtil::getSystemPageSize())
17 393 : memoryManager(memoryManager), blockSize(blockSize) {
18
1/2
✓ Branch 1 taken 393 times.
✗ Branch 2 not taken.
393 allocateNewBlock();
19 393 }
20 393 ~BlockAllocator() {
21 // Destruct all objects
22
2/2
✓ Branch 5 taken 1128806 times.
✓ Branch 6 taken 393 times.
1129199 for (Base *ptr : allocatedObjects)
23 1128806 ptr->~Base();
24 393 allocatedObjects.clear();
25
26 // Free memory
27
2/2
✓ Branch 5 taken 66520 times.
✓ Branch 6 taken 393 times.
66913 for (byte *ptr : memoryBlocks)
28 66520 memoryManager.deallocate(ptr);
29 393 memoryBlocks.clear();
30 393 }
31
32 // Public methods
33 2156605 template <typename T, typename... Args> T *allocate(Args &&...args) {
34 static_assert(std::is_base_of_v<Base, T>, "T must be derived from Base");
35 2156605 constexpr size_t objSize = sizeof(T);
36
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1128807 times.
2156605 assert(objSize <= blockSize && "Object size exceeds block size");
37
38 // Check if we need a new block
39
2/2
✓ Branch 0 taken 66128 times.
✓ Branch 1 taken 1062679 times.
2156605 if (offsetInBlock + objSize >= blockSize)
40 107004 allocateNewBlock();
41
42 // Construct object at the offset address
43 2156604 byte *destAddr = memoryBlocks.back() + offsetInBlock;
44
1/4
✓ Branch 3 taken 152441 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
2156604 T *ptr = new (destAddr) T(std::forward<Args>(args)...);
45
1/2
✓ Branch 1 taken 1128806 times.
✗ Branch 2 not taken.
2156604 allocatedObjects.push_back(ptr);
46
47 #ifndef NDEBUG
48
1/2
✓ Branch 2 taken 1128806 times.
✗ Branch 3 not taken.
2156604 ++allocatedClassStatistic[typeid(T).name()];
49 #endif
50
51 // Update offset to be ready to store the next object
52 2156604 offsetInBlock += objSize;
53 2156604 return ptr;
54 }
55
56 2 [[nodiscard]] size_t getTotalAllocatedSize() const { return memoryBlocks.size() * blockSize; }
57 2 [[nodiscard]] size_t getAllocationCount() const { return allocatedObjects.size(); }
58 #ifndef NDEBUG
59 void printAllocatedClassStatistic() const {
60 std::vector<std::pair<const char *, size_t>> elements(allocatedClassStatistic.begin(), allocatedClassStatistic.end());
61 std::sort(elements.begin(), elements.end(), [](const auto &left, const auto &right) { return left.second > right.second; });
62 for (const auto &[mangledName, count] : elements)
63 std::cout << CommonUtil::demangleTypeName(mangledName) << ": " << count << std::endl;
64 }
65 #endif
66
67 private:
68 // Private members
69 const MemoryManager &memoryManager;
70 std::vector<byte *> memoryBlocks;
71 std::vector<Base *> allocatedObjects;
72 #ifndef NDEBUG
73 std::unordered_map<const char *, size_t> allocatedClassStatistic;
74 #endif
75 size_t blockSize;
76 size_t offsetInBlock = 0;
77
78 // Private methods
79 66521 void allocateNewBlock() {
80 // Allocate new block
81
1/2
✓ Branch 1 taken 66521 times.
✗ Branch 2 not taken.
66521 byte *ptr = memoryManager.allocate(blockSize);
82
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 66520 times.
66521 if (!ptr)
83
4/8
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 1 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 1 times.
✗ Branch 10 not taken.
✓ Branch 12 taken 1 times.
✗ Branch 13 not taken.
1 throw CompilerError(OOM, "Could not allocate memory for BlockAllocator. Already allocated " +
84 std::to_string(memoryBlocks.size()) + " blocks.");
85
86 // Store pointer and reset offset
87
1/2
✓ Branch 1 taken 66520 times.
✗ Branch 2 not taken.
66520 memoryBlocks.push_back(ptr);
88 66520 offsetInBlock = 0;
89 66520 }
90 };
91
92 } // namespace spice::compiler
93