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: 57.5% 23 / 0 / 40

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 508 static inline void CheckGuards(void* ptr)
20 {
21 #ifndef NDEBUG
22 508 size_t lower_guard = (size_t)(((void**)ptr)[-5]);
23
1/2
✗ Branch 2 → 3 not taken.
✓ Branch 2 → 4 taken 508 times.
508 assert(lower_guard == BUFFER_GUARD_VALUE);
24 508 size_t upper_guard = (size_t)(((void**)ptr)[-1]);
25
1/2
✗ Branch 4 → 5 not taken.
✓ Branch 4 → 6 taken 508 times.
508 assert(upper_guard == BUFFER_GUARD_VALUE);
26 #endif
27 508 }
28
29 254 static inline void* GetUserData(void* ptr)
30 {
31 254 return ((void**)ptr)[-4];
32 }
33
34 254 static inline size_t GetRealSize(void* ptr)
35 {
36 254 return (size_t)(((void**)ptr)[-3]);
37 }
38
39 254 static inline void* GetRealPtr(void* ptr)
40 {
41 254 return ((void**)ptr)[-2];
42 }
43
44 254 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 254 const int NUM_EXTRA_FIELDS = 5;
55
56 254 alignment = max(alignment, sizeof(void*));
57
2/4
✓ Branch 3 → 4 taken 254 times.
✗ Branch 3 → 5 not taken.
✗ Branch 4 → 5 not taken.
✓ Branch 4 → 6 taken 254 times.
254 if (!IS_POWER2(alignment))
58 return NULL;
59
60 254 size_t offset = NUM_EXTRA_FIELDS * sizeof(void*) + alignment - 1;
61 254 nBytes += offset;
62
63 254 void *orig = malloc(nBytes);
64
1/2
✗ Branch 6 → 7 not taken.
✓ Branch 6 → 8 taken 254 times.
254 if (orig == NULL)
65 return NULL;
66
67 254 void **aligned = (void**)(((uintptr_t)orig + (uintptr_t)offset) & (~(uintptr_t)(alignment-1)));
68 254 aligned[-5] = (void*)BUFFER_GUARD_VALUE;
69 254 aligned[-4] = user;
70 254 aligned[-3] = (void*)nBytes;
71 254 aligned[-2] = orig;
72 254 aligned[-1] = (void*)BUFFER_GUARD_VALUE;
73
74 254 Env->AdjustMemoryConsumption(nBytes, false);
75 254 return aligned;
76 }
77
78 254 void BufferPool::PrivateFree(void* buffer)
79 {
80 254 CheckGuards(buffer);
81 254 Env->AdjustMemoryConsumption(GetRealSize(buffer), true);
82 254 free(GetRealPtr(buffer));
83 254 }
84
85
86 2265 BufferPool::BufferPool(InternalEnvironment* env) :
87 2265 Env(env)
88 {
89 2263 }
90
91 2261 BufferPool::~BufferPool()
92 {
93 2261 const MapType::iterator end_it = Map.end();
94 2245 for (
95 2229 MapType::iterator it = Map.begin();
96
2/2
✓ Branch 11 → 5 taken 4 times.
✓ Branch 11 → 12 taken 2241 times.
2249 it != end_it;
97 4 ++it)
98 {
99 4 BufferDesc* desc = it->second;
100 4 PrivateFree(desc->ptr);
101
1/2
✓ Branch 7 → 8 taken 4 times.
✗ Branch 7 → 9 not taken.
4 delete desc;
102 }
103 2241 }
104
105 254 void* BufferPool::Allocate(size_t nBytes, size_t alignment, bool pool)
106 {
107
2/2
✓ Branch 2 → 3 taken 4 times.
✓ Branch 2 → 24 taken 250 times.
254 if (pool)
108 {
109 // First, check if we can return a buffer from the pool
110 4 const MapType::iterator end_it = Map.end();
111 4 for (
112
1/2
✓ Branch 4 → 5 taken 4 times.
✗ Branch 4 → 27 not taken.
4 MapType::iterator it = Map.lower_bound(nBytes);
113
2/2
✓ Branch 12 → 6 taken 2 times.
✓ Branch 12 → 13 taken 4 times.
6 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 4 times.
✗ Branch 13 → 28 not taken.
✗ Branch 14 → 15 not taken.
✓ Branch 14 → 16 taken 4 times.
4 BufferDesc* desc = new BufferDesc();
128
129
1/2
✓ Branch 16 → 17 taken 4 times.
✗ Branch 16 → 28 not taken.
4 void* ptr = PrivateAlloc(nBytes, alignment, reinterpret_cast<void*>(desc));
130
1/2
✗ Branch 17 → 18 not taken.
✓ Branch 17 → 21 taken 4 times.
4 if (ptr == NULL)
131 {
132 delete desc;
133 return NULL;
134 }
135
136 4 desc->alignment = alignment;
137 4 desc->in_use = true;
138 4 desc->ptr = ptr;
139 4 desc->size = nBytes;
140
1/2
✓ Branch 21 → 22 taken 4 times.
✗ Branch 21 → 28 not taken.
4 Map.emplace(nBytes, desc);
141 4 return ptr;
142 }
143 else
144 {
145 250 return PrivateAlloc(nBytes, alignment, NULL);
146 }
147 }
148
149 614 void BufferPool::Free(void* ptr)
150 {
151 // Mirroring free()'s semantic requires us to accept NULLs
152
2/2
✓ Branch 2 → 3 taken 360 times.
✓ Branch 2 → 4 taken 254 times.
614 if (ptr == NULL)
153 360 return;
154
155 254 CheckGuards(ptr);
156
157 254 BufferDesc* data = reinterpret_cast<BufferDesc*>(GetUserData(ptr));
158
159
2/2
✓ Branch 6 → 7 taken 4 times.
✓ Branch 6 → 8 taken 250 times.
254 if (data != NULL)
160 { // Getting into this branch means this buffer is pooled
161 4 data->in_use = false;
162 }
163 else
164 {
165 250 PrivateFree(ptr);
166 }
167 }
168