GCC Code Coverage Report


Directory: avs_core/
Coverage: low: ≥ 0% medium: ≥ 75.0% high: ≥ 90.0%
Coverage Exec / Excl / Total
Lines: 91.2% 73 / 0 / 80
Functions: 100.0% 10 / 0 / 10
Branches: 59.5% 25 / 0 / 42

core/BufferPool.cpp
Line Branch Exec Source
1 #include "BufferPool.h"
2 #include <map>
3 #include <avisynth.h>
4 #include <avs/alignment.h>
5 #include <avs/minmax.h>
6 #include "InternalEnvironment.h"
7
8 #define BUFFER_GUARD_VALUE 0x55555555
9
10 struct BufferPool::BufferDesc
11 {
12 void* ptr;
13 size_t size;
14 size_t alignment;
15 bool in_use;
16 };
17
18
19 1440 static inline void CheckGuards(void* ptr)
20 {
21 #ifndef NDEBUG
22 1440 size_t lower_guard = (size_t)(((void**)ptr)[-5]);
23
1/2
✗ Branch 2 → 3 not taken.
✓ Branch 2 → 4 taken 1440 times.
1440 assert(lower_guard == BUFFER_GUARD_VALUE);
24 1440 size_t upper_guard = (size_t)(((void**)ptr)[-1]);
25
1/2
✗ Branch 4 → 5 not taken.
✓ Branch 4 → 6 taken 1440 times.
1440 assert(upper_guard == BUFFER_GUARD_VALUE);
26 #endif
27 1440 }
28
29 720 static inline void* GetUserData(void* ptr)
30 {
31 720 return ((void**)ptr)[-4];
32 }
33
34 720 static inline size_t GetRealSize(void* ptr)
35 {
36 720 return (size_t)(((void**)ptr)[-3]);
37 }
38
39 720 static inline void* GetRealPtr(void* ptr)
40 {
41 720 return ((void**)ptr)[-2];
42 }
43
44 720 void* BufferPool::PrivateAlloc(size_t nBytes, size_t alignment, void* user)
45 {
46 /* Number of extra data fields to allocate.
47 * Current field assignment:
48 * [-1] = upper guard (size_t)
49 * [-2] = original buffer pointer (void*)
50 * [-3] = original buffer size (size_t)
51 * [-4] = user data (void*)
52 * [-5] = lower guard (size_t)
53 */
54
2/2
✓ Branch 2 → 3 taken 711 times.
✓ Branch 2 → 4 taken 9 times.
720 const int NUM_EXTRA_FIELDS = 5;
55
56 720 alignment = max(alignment, sizeof(void*));
57
2/4
✓ Branch 7 → 8 taken 720 times.
✗ Branch 7 → 9 not taken.
✗ Branch 8 → 9 not taken.
✓ Branch 8 → 10 taken 720 times.
720 if (!IS_POWER2(alignment))
58 return NULL;
59
60 720 size_t offset = NUM_EXTRA_FIELDS * sizeof(void*) + alignment - 1;
61 720 nBytes += offset;
62
63 720 void *orig = malloc(nBytes);
64
1/2
✗ Branch 10 → 11 not taken.
✓ Branch 10 → 12 taken 720 times.
720 if (orig == NULL)
65 return NULL;
66
67 720 void **aligned = (void**)(((uintptr_t)orig + (uintptr_t)offset) & (~(uintptr_t)(alignment-1)));
68 720 aligned[-5] = (void*)BUFFER_GUARD_VALUE;
69 720 aligned[-4] = user;
70 720 aligned[-3] = (void*)nBytes;
71 720 aligned[-2] = orig;
72 720 aligned[-1] = (void*)BUFFER_GUARD_VALUE;
73
74 720 Env->AdjustMemoryConsumption(nBytes, false);
75 720 return aligned;
76 }
77
78 720 void BufferPool::PrivateFree(void* buffer)
79 {
80 720 CheckGuards(buffer);
81 720 Env->AdjustMemoryConsumption(GetRealSize(buffer), true);
82 720 free(GetRealPtr(buffer));
83 720 }
84
85
86 3209 BufferPool::BufferPool(InternalEnvironment* env) :
87 3209 Env(env)
88 {
89 3209 }
90
91 3202 BufferPool::~BufferPool()
92 {
93 3202 const MapType::iterator end_it = Map.end();
94 3174 for (
95 3166 MapType::iterator it = Map.begin();
96
2/2
✓ Branch 11 → 5 taken 7 times.
✓ Branch 11 → 12 taken 3164 times.
3181 it != end_it;
97 7 ++it)
98 {
99 7 BufferDesc* desc = it->second;
100 7 PrivateFree(desc->ptr);
101
1/2
✓ Branch 7 → 8 taken 7 times.
✗ Branch 7 → 9 not taken.
7 delete desc;
102 }
103 3164 }
104
105 720 void* BufferPool::Allocate(size_t nBytes, size_t alignment, bool pool)
106 {
107
2/2
✓ Branch 2 → 3 taken 7 times.
✓ Branch 2 → 24 taken 713 times.
720 if (pool)
108 {
109 // First, check if we can return a buffer from the pool
110 7 const MapType::iterator end_it = Map.end();
111 7 for (
112
1/2
✓ Branch 4 → 5 taken 7 times.
✗ Branch 4 → 27 not taken.
7 MapType::iterator it = Map.lower_bound(nBytes);
113
2/2
✓ Branch 12 → 6 taken 2 times.
✓ Branch 12 → 13 taken 7 times.
9 it != end_it;
114 2 ++it)
115 {
116 2 BufferDesc* desc = it->second;
117
1/2
✗ Branch 7 → 8 not taken.
✓ Branch 7 → 10 taken 2 times.
2 if ( !desc->in_use
118 && (desc->alignment >= alignment)
119 )
120 {
121 desc->in_use = true;
122 return desc->ptr;
123 }
124 }
125
126 // None found, allocate new one
127
2/4
✓ Branch 13 → 14 taken 7 times.
✗ Branch 13 → 28 not taken.
✗ Branch 14 → 15 not taken.
✓ Branch 14 → 16 taken 7 times.
7 BufferDesc* desc = new BufferDesc();
128
129
1/2
✓ Branch 16 → 17 taken 7 times.
✗ Branch 16 → 28 not taken.
7 void* ptr = PrivateAlloc(nBytes, alignment, reinterpret_cast<void*>(desc));
130
1/2
✗ Branch 17 → 18 not taken.
✓ Branch 17 → 21 taken 7 times.
7 if (ptr == NULL)
131 {
132 delete desc;
133 return NULL;
134 }
135
136 7 desc->alignment = alignment;
137 7 desc->in_use = true;
138 7 desc->ptr = ptr;
139 7 desc->size = nBytes;
140
1/2
✓ Branch 21 → 22 taken 7 times.
✗ Branch 21 → 28 not taken.
7 Map.emplace(nBytes, desc);
141 7 return ptr;
142 }
143 else
144 {
145 713 return PrivateAlloc(nBytes, alignment, NULL);
146 }
147 }
148
149 1470 void BufferPool::Free(void* ptr)
150 {
151 // Mirroring free()'s semantic requires us to accept NULLs
152
2/2
✓ Branch 2 → 3 taken 750 times.
✓ Branch 2 → 4 taken 720 times.
1470 if (ptr == NULL)
153 750 return;
154
155 720 CheckGuards(ptr);
156
157 720 BufferDesc* data = reinterpret_cast<BufferDesc*>(GetUserData(ptr));
158
159
2/2
✓ Branch 6 → 7 taken 7 times.
✓ Branch 6 → 8 taken 713 times.
720 if (data != NULL)
160 { // Getting into this branch means this buffer is pooled
161 7 data->in_use = false;
162 }
163 else
164 {
165 713 PrivateFree(ptr);
166 }
167 }
168