LCOV - code coverage report
Current view: top level - src/runtime - emitter.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 127 152 83.6 %
Date: 2016-11-30 13:12:14 Functions: 8 9 88.9 %
Branches: 53 72 73.6 %

           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                 :            : }

Generated by: LCOV version 1.12