Branch data Line data Source code
1 : : #include <stdlib.h>
2 : :
3 : : #include "flatcc/flatcc_rtconfig.h"
4 : : #include "flatcc/flatcc_emitter.h"
5 : :
6 : 376418 : static int advance_front(flatcc_emitter_t *E)
7 : : {
8 : : flatcc_emitter_page_t *p = 0;
9 : :
10 [ + + ][ + + ]: 376418 : if (E->front && E->front->prev != E->back) {
11 : 342150 : E->front->prev->page_offset = E->front->page_offset - FLATCC_EMITTER_PAGE_SIZE;
12 : 342150 : E->front = E->front->prev;
13 : 342150 : goto done;
14 : : }
15 [ + - ]: 34268 : if (!(p = FLATCC_EMITTER_ALLOC(sizeof(flatcc_emitter_page_t)))) {
16 : : return -1;
17 : : }
18 : 34268 : E->capacity += FLATCC_EMITTER_PAGE_SIZE;
19 [ + + ]: 34268 : if (E->front) {
20 : 34216 : p->prev = E->back;
21 : 34216 : p->next = E->front;
22 : 34216 : E->front->prev = p;
23 : 34216 : E->back->next = p;
24 : 34216 : E->front = p;
25 : 34216 : goto done;
26 : : }
27 : : /*
28 : : * The first page is shared between front and back to avoid
29 : : * double unecessary extra allocation.
30 : : */
31 : 52 : E->front = p;
32 : 52 : E->back = p;
33 : 52 : p->next = p;
34 : 52 : p->prev = p;
35 : 52 : E->front_cursor = E->front->page + FLATCC_EMITTER_PAGE_SIZE / 2;
36 : 52 : E->back_cursor = E->front_cursor;
37 : 52 : E->front_left = FLATCC_EMITTER_PAGE_SIZE / 2;
38 : 52 : E->back_left = FLATCC_EMITTER_PAGE_SIZE - E->front_left;
39 : 52 : p->page_offset = -(flatbuffers_soffset_t)E->front_left;
40 : 52 : return 0;
41 : : done:
42 : 376366 : E->front_cursor = E->front->page + FLATCC_EMITTER_PAGE_SIZE;
43 : 376366 : E->front_left = FLATCC_EMITTER_PAGE_SIZE;
44 : 376366 : E->front->page_offset = E->front->next->page_offset - FLATCC_EMITTER_PAGE_SIZE;
45 : 376366 : return 0;
46 : : }
47 : :
48 : 1 : static int advance_back(flatcc_emitter_t *E)
49 : : {
50 : : flatcc_emitter_page_t *p = 0;
51 : :
52 [ - + ][ # # ]: 1 : if (E->back && E->back->next != E->front) {
53 : 0 : E->back = E->back->next;
54 : 0 : goto done;
55 : : }
56 [ + - ]: 1 : if (!(p = FLATCC_EMITTER_ALLOC(sizeof(flatcc_emitter_page_t)))) {
57 : : return -1;
58 : : }
59 : 1 : E->capacity += FLATCC_EMITTER_PAGE_SIZE;
60 [ - + ]: 1 : if (E->back) {
61 : 0 : p->prev = E->back;
62 : 0 : p->next = E->front;
63 : 0 : E->front->prev = p;
64 : 0 : E->back->next = p;
65 : 0 : E->back = p;
66 : 0 : goto done;
67 : : }
68 : : /*
69 : : * The first page is shared between front and back to avoid
70 : : * double unecessary extra allocation.
71 : : */
72 : 1 : E->front = p;
73 : 1 : E->back = p;
74 : 1 : p->next = p;
75 : 1 : p->prev = p;
76 : 1 : E->front_cursor = E->front->page + FLATCC_EMITTER_PAGE_SIZE / 2;
77 : 1 : E->back_cursor = E->front_cursor;
78 : 1 : E->front_left = FLATCC_EMITTER_PAGE_SIZE / 2;
79 : 1 : E->back_left = FLATCC_EMITTER_PAGE_SIZE - E->front_left;
80 : 1 : p->page_offset = -(flatbuffers_soffset_t)E->front_left;
81 : 1 : return 0;
82 : : done:
83 : 0 : E->back_cursor = E->back->page;
84 : 0 : E->back_left = FLATCC_EMITTER_PAGE_SIZE;
85 : 0 : E->back->page_offset = E->back->prev->page_offset + FLATCC_EMITTER_PAGE_SIZE;
86 : 0 : return 0;
87 : : }
88 : :
89 : 30198 : static int copy_front(flatcc_emitter_t *E, uint8_t *data, size_t size)
90 : : {
91 : : size_t k;
92 : :
93 : 30198 : data += size;
94 [ + + ]: 813069 : while (size) {
95 : : k = size;
96 [ + + ]: 782871 : if (k > E->front_left) {
97 : : k = E->front_left;
98 [ + + ]: 752673 : if (k == 0) {
99 [ + - ]: 376418 : if (advance_front(E)) {
100 : : return -1;
101 : : }
102 : 376418 : continue;
103 : : }
104 : : }
105 : 406453 : E->front_cursor -= k;
106 : 406453 : E->front_left -= k;
107 : 406453 : data -= k;
108 : 406453 : size -= k;
109 : 782871 : memcpy(E->front_cursor, data, k);
110 : : };
111 : : return 0;
112 : : }
113 : :
114 : 1 : static int copy_back(flatcc_emitter_t *E, uint8_t *data, size_t size)
115 : : {
116 : : size_t k;
117 : :
118 [ + + ]: 3 : while (size) {
119 : : k = size;
120 [ + + ]: 2 : if (k > E->back_left) {
121 : : k = E->back_left;
122 [ + - ]: 1 : if (k == 0) {
123 [ + - ]: 1 : if (advance_back(E)) {
124 : : return -1;
125 : : }
126 : 1 : continue;
127 : : }
128 : : }
129 : 1 : memcpy(E->back_cursor, data, k);
130 : 1 : size -= k;
131 : 1 : data += k;
132 : 1 : E->back_cursor += k;
133 : 2 : E->back_left -= k;
134 : : }
135 : : return 0;
136 : : }
137 : :
138 : 0 : int flatcc_emitter_recycle_page(flatcc_emitter_t *E, flatcc_emitter_page_t *p)
139 : : {
140 [ # # ][ # # ]: 0 : if (p == E->front || p == E->back) {
141 : : return -1;
142 : : }
143 : 0 : p->next->prev = p->prev;
144 : 0 : p->prev->next = p->next;
145 : 0 : p->prev = E->front->prev;
146 : 0 : p->next = E->front;
147 : 0 : p->prev->next = p;
148 : 0 : p->next->prev = p;
149 : 0 : return 0;
150 : : }
151 : :
152 : 31 : void flatcc_emitter_reset(flatcc_emitter_t *E)
153 : : {
154 : 31 : flatcc_emitter_page_t *p = E->front;
155 : :
156 [ + + ]: 31 : if (!E->front) {
157 : : return;
158 : : }
159 : 29 : E->back = E->front;
160 : 29 : E->front_cursor = E->front->page + FLATCC_EMITTER_PAGE_SIZE / 2;
161 : 29 : E->back_cursor = E->front_cursor;
162 : 29 : E->front_left = FLATCC_EMITTER_PAGE_SIZE / 2;
163 : 29 : E->back_left = FLATCC_EMITTER_PAGE_SIZE - FLATCC_EMITTER_PAGE_SIZE / 2;
164 : 29 : E->front->page_offset = -(flatbuffers_soffset_t)E->front_left;
165 : : /* Heuristic to reduce peak allocation over time. */
166 [ + + ]: 29 : if (E->used_average == 0) {
167 : 4 : E->used_average = E->used;
168 : : }
169 : 29 : E->used_average = E->used_average * 3 / 4 + E->used / 4;
170 : 29 : E->used = 0;
171 [ + + ][ - + ]: 29 : while (E->used_average * 2 < E->capacity && E->back->next != E->front) {
172 : : /* We deallocate the page after back since it is less likely to be hot in cache. */
173 : : p = E->back->next;
174 : 0 : E->back->next = p->next;
175 : 0 : p->next->prev = E->back;
176 : 0 : free(p);
177 : 0 : E->capacity -= FLATCC_EMITTER_PAGE_SIZE;
178 : : }
179 : : }
180 : :
181 : 53 : void flatcc_emitter_clear(flatcc_emitter_t *E)
182 : : {
183 : 53 : flatcc_emitter_page_t *p = E->front;
184 : :
185 [ + - ]: 53 : if (!p) {
186 : : return;
187 : : }
188 : 53 : p->prev->next = 0;
189 [ + + ]: 34269 : while (p->next) {
190 : : p = p->next;
191 : 34216 : free(p->prev);
192 : : }
193 : 53 : free(p);
194 : 53 : memset(E, 0, sizeof(*E));
195 : : }
196 : :
197 : 33815 : int flatcc_emitter(void *emit_context,
198 : : const flatcc_iovec_t *iov, int iov_count,
199 : : flatbuffers_soffset_t offset, size_t len)
200 : : {
201 : : flatcc_emitter_t *E = emit_context;
202 : : uint8_t *p;
203 : :
204 : 33815 : E->used += len;
205 [ + + ]: 33815 : if (offset < 0) {
206 [ + + ]: 33666 : if (len <= E->front_left) {
207 : 19918 : E->front_cursor -= len;
208 : 19918 : E->front_left -= len;
209 : : p = E->front_cursor;
210 : 20066 : goto copy;
211 : : }
212 : 13748 : iov += iov_count;
213 [ + + ]: 43946 : while (iov_count--) {
214 : 30198 : --iov;
215 [ + - ]: 30198 : if (copy_front(E, iov->iov_base, iov->iov_len)) {
216 : : return -1;
217 : : }
218 : : }
219 : : } else {
220 [ + + ]: 149 : if (len <= E->back_left) {
221 : 148 : p = E->back_cursor;
222 : 148 : E->back_cursor += len;
223 : 148 : E->back_left -= len;
224 : 148 : goto copy;
225 : : }
226 [ + + ]: 2 : while (iov_count--) {
227 [ + - ]: 1 : if (copy_back(E, iov->iov_base, iov->iov_len)) {
228 : : return -1;
229 : : }
230 : 1 : ++iov;
231 : : }
232 : : }
233 : : return 0;
234 : : copy:
235 [ + + ]: 68702 : while (iov_count--) {
236 : 48636 : memcpy(p, iov->iov_base, iov->iov_len);
237 : 48636 : p += iov->iov_len;
238 : 48636 : ++iov;
239 : : }
240 : : return 0;
241 : : }
242 : :
243 : 69 : void *flatcc_emitter_copy_buffer(flatcc_emitter_t *E, void *buf, size_t size)
244 : : {
245 : : flatcc_emitter_page_t *p;
246 : : size_t len;
247 : :
248 [ + - ]: 69 : if (size < E->used) {
249 : : return 0;
250 : : }
251 [ + - ]: 69 : if (!E->front) {
252 : : return 0;
253 : : }
254 [ + + ]: 69 : if (E->front == E->back) {
255 : 57 : memcpy(buf, E->front_cursor, E->used);
256 : 57 : return buf;
257 : : }
258 : 12 : len = FLATCC_EMITTER_PAGE_SIZE - E->front_left;
259 : 12 : memcpy(buf, E->front_cursor, len);
260 : 12 : buf = (uint8_t *)buf + len;
261 : 12 : p = E->front->next;
262 [ + + ]: 376366 : while (p != E->back) {
263 : 376354 : memcpy(buf, p->page, FLATCC_EMITTER_PAGE_SIZE);
264 : 376354 : buf = (uint8_t *)buf + FLATCC_EMITTER_PAGE_SIZE;
265 : 376354 : p = p->next;
266 : : }
267 : 12 : memcpy(buf, p->page, FLATCC_EMITTER_PAGE_SIZE - E->back_left);
268 : 12 : return buf;
269 : : }
|