Coverage Report

Created: 2022-04-16 11:23

/src/ghostpdl/base/gxbcache.c
Line
Count
Source
1
/* Copyright (C) 2001-2022 Artifex Software, Inc.
2
   All Rights Reserved.
3
4
   This software is provided AS-IS with no warranty, either express or
5
   implied.
6
7
   This software is distributed under license and may not be copied,
8
   modified or distributed except as expressly authorized under the terms
9
   of the license contained in the file LICENSE in this distribution.
10
11
   Refer to licensing information at http://www.artifex.com or contact
12
   Artifex Software, Inc.,  1305 Grant Avenue - Suite 200, Novato,
13
   CA 94945, U.S.A., +1(415)492-9861, for further information.
14
*/
15
16
17
/* Bitmap cache implementation */
18
#include "memory_.h"
19
#include "stdint_.h"
20
#include "gx.h"
21
#include "gxobj.h"
22
#include "gsmdebug.h"
23
#include "gxbcache.h"
24
25
/* ------ Entire cache ------ */
26
27
/* Initialize a cache.  The caller must allocate and initialize */
28
/* the first chunk. */
29
void
30
gx_bits_cache_init(gx_bits_cache * bc, gx_bits_cache_chunk * bck)
31
16.0k
{
32
16.0k
    bck->next = bck;
33
16.0k
    bc->chunks = bck;
34
16.0k
    bc->cnext = 0;
35
16.0k
    bc->bsize = 0;
36
16.0k
    bc->csize = 0;
37
16.0k
}
38
39
/* ------ Chunks ------ */
40
41
/* Initialize a chunk.  The caller must allocate it and its data. */
42
void
43
gx_bits_cache_chunk_init(gx_bits_cache_chunk * bck, byte * data, uint size)
44
16.3k
{
45
16.3k
    bck->next = 0;
46
16.3k
    bck->data = data;
47
16.3k
    bck->size = size;
48
16.3k
    bck->allocated = 0;
49
16.3k
    if (data != 0) {
50
15.0k
        gx_cached_bits_head *cbh = (gx_cached_bits_head *) data;
51
52
15.0k
        cbh->size = size;
53
15.0k
        cb_head_set_free(cbh);
54
15.0k
    }
55
16.3k
}
56
57
/* ------ Individual entries ------ */
58
59
/* Attempt to allocate an entry.  If successful, set *pcbh and return 0. */
60
/* If there isn't enough room, set *pcbh to an entry requiring freeing, */
61
/* or to 0 if we are at the end of the chunk, and return -1. */
62
int
63
gx_bits_cache_alloc(gx_bits_cache * bc, ulong lsize0, gx_cached_bits_head ** pcbh)
64
315k
{
65
315k
    ulong lsize = ROUND_UP(lsize0, obj_align_mod);
66
67
2.48M
#define ssize ((uint)lsize)
68
315k
    ulong lsize1 = lsize + sizeof(gx_cached_bits_head);
69
70
1.57M
#define ssize1 ((uint)lsize1)
71
315k
    uint cnext = bc->cnext;
72
315k
    gx_bits_cache_chunk *bck = bc->chunks;
73
315k
    uint left = bck->size - cnext;
74
315k
    gx_cached_bits_head *cbh;
75
315k
    gx_cached_bits_head *cbh_next;
76
315k
    uint fsize = 0;
77
78
315k
    if (lsize1 > bck->size - cnext && lsize != left) { /* Not enough room to allocate in this chunk. */
79
506
        *pcbh = 0;
80
506
        return -1;
81
506
    }
82
    /* Look for and/or free enough space. */
83
314k
    cbh = cbh_next = (gx_cached_bits_head *) (bck->data + cnext);
84
787k
    while (fsize < ssize1 && fsize != ssize) {
85
505k
        if (!cb_head_is_free(cbh_next)) { /* Ask the caller to free the entry. */
86
32.5k
            if (fsize)
87
31.5k
                cbh->size = fsize;
88
32.5k
            *pcbh = cbh_next;
89
32.5k
            return -1;
90
32.5k
        }
91
472k
        fsize += cbh_next->size;
92
472k
        if_debug2('K', "[K]merging free bits "PRI_INTPTR"(%u)\n",
93
472k
                  (intptr_t)cbh_next, cbh_next->size);
94
472k
        cbh_next = (gx_cached_bits_head *) ((byte *) cbh + fsize);
95
472k
    }
96
282k
    if (fsize > ssize) { /* fsize >= ssize1 */
97
281k
        cbh_next = (gx_cached_bits_head *) ((byte *) cbh + ssize);
98
281k
        cbh_next->size = fsize - ssize;
99
281k
        cb_head_set_free(cbh_next);
100
281k
        if_debug2('K', "[K]shortening bits "PRI_INTPTR" by %u (initial)\n",
101
281k
                  (intptr_t)cbh, fsize - ssize);
102
281k
    }
103
282k
    gs_alloc_fill(cbh, gs_alloc_fill_block, ssize);
104
282k
    cbh->size = ssize;
105
282k
    bc->bsize += ssize;
106
282k
    bc->csize++;
107
282k
    bc->cnext += ssize;
108
282k
    bck->allocated += ssize;
109
282k
    *pcbh = cbh;
110
282k
    return 0;
111
314k
#undef ssize
112
314k
#undef ssize1
113
314k
}
114
115
/* Shorten an entry by a given amount. */
116
void
117
gx_bits_cache_shorten(gx_bits_cache * bc, gx_cached_bits_head * cbh,
118
                      uint diff, gx_bits_cache_chunk * bck)
119
133k
{
120
133k
    gx_cached_bits_head *next;
121
122
133k
    if ((byte *) cbh + cbh->size == bck->data + bc->cnext &&
123
133k
        bck == bc->chunks
124
133k
        )
125
133k
        bc->cnext -= diff;
126
133k
    bc->bsize -= diff;
127
133k
    bck->allocated -= diff;
128
133k
    cbh->size -= diff;
129
133k
    next = (gx_cached_bits_head *) ((byte *) cbh + cbh->size);
130
133k
    cb_head_set_free(next);
131
133k
    next->size = diff;
132
133k
}
133
134
/* Free an entry.  The caller is responsible for removing the entry */
135
/* from any other structures (like a hash table). */
136
void
137
gx_bits_cache_free(gx_bits_cache * bc, gx_cached_bits_head * cbh,
138
                   gx_bits_cache_chunk * bck)
139
156k
{
140
156k
    uint size = cbh->size;
141
142
156k
    bc->csize--;
143
156k
    bc->bsize -= size;
144
156k
    bck->allocated -= size;
145
156k
    gs_alloc_fill(cbh, gs_alloc_fill_deleted, size);
146
156k
    cbh->size = size;   /* gs_alloc_fill may have overwritten */
147
156k
    cb_head_set_free(cbh);
148
156k
}
149
150
#ifdef DEBUG
151
/* A useful bit of code to dump the contents of the bitmap cache. Not
152
 * currently called. Current position is indicated with a '>'. */
153
void
154
gx_bits_cache_dump(gx_bits_cache * bc)
155
{
156
    gx_bits_cache_chunk *bck = bc->chunks;
157
    gx_bits_cache_chunk *first = bck;
158
159
    dlprintf2("%d entries making %d bytes\n", bc->csize, bc->bsize);
160
161
    do {
162
        gx_cached_bits_head *cbh;
163
        uint pos = 0;
164
165
        dlprintf2(" chunk of %d bytes (%d allocated)\n", bck->size, bck->allocated);
166
167
        cbh = (gx_cached_bits_head *)bck->data;
168
        while (pos != bck->size) {
169
            dlprintf3(" %csize=%d depth=%d\n",
170
                      pos == bc->cnext && bck == bc->chunks ? '>' : ' ',
171
                      cbh->size, cbh->depth);
172
            pos += cbh->size;
173
            cbh = (gx_cached_bits_head *)(((byte *)cbh) + cbh->size);
174
        }
175
        bck = bck->next;
176
    } while (bck != first);
177
178
    bck=bck;
179
}
180
#endif