Coverage Report

Created: 2025-06-10 07:27

/src/ghostpdl/base/gxbcache.c
Line
Count
Source
1
/* Copyright (C) 2001-2023 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.,  39 Mesa Street, Suite 108A, San Francisco,
13
   CA 94129, USA, 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
166k
{
32
166k
    bck->next = bck;
33
166k
    bc->chunks = bck;
34
166k
    bc->cnext = 0;
35
166k
    bc->bsize = 0;
36
166k
    bc->csize = 0;
37
166k
}
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
169k
{
45
169k
    bck->next = 0;
46
169k
    bck->data = data;
47
169k
    bck->size = size;
48
169k
    bck->allocated = 0;
49
169k
    if (data != 0) {
50
153k
        gx_cached_bits_head *cbh = (gx_cached_bits_head *) data;
51
52
153k
        cbh->size = size;
53
153k
        cb_head_set_free(cbh);
54
153k
    }
55
169k
}
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
1.18M
{
65
1.18M
    ulong lsize = ROUND_UP(lsize0, obj_align_mod);
66
67
9.30M
#define ssize ((uint)lsize)
68
1.18M
    ulong lsize1 = lsize + sizeof(gx_cached_bits_head);
69
70
6.23M
#define ssize1 ((uint)lsize1)
71
1.18M
    uint cnext = bc->cnext;
72
1.18M
    gx_bits_cache_chunk *bck = bc->chunks;
73
1.18M
    uint left = bck->size - cnext;
74
1.18M
    gx_cached_bits_head *cbh;
75
1.18M
    gx_cached_bits_head *cbh_next;
76
1.18M
    uint fsize = 0;
77
78
1.18M
    if (lsize1 > bck->size - cnext && lsize != left) { /* Not enough room to allocate in this chunk. */
79
3.92k
        *pcbh = 0;
80
3.92k
        return -1;
81
3.92k
    }
82
    /* Look for and/or free enough space. */
83
1.17M
    cbh = cbh_next = (gx_cached_bits_head *) (bck->data + cnext);
84
3.11M
    while (fsize < ssize1 && fsize != ssize) {
85
2.08M
        if (!cb_head_is_free(cbh_next)) { /* Ask the caller to free the entry. */
86
142k
            if (fsize)
87
136k
                cbh->size = fsize;
88
142k
            *pcbh = cbh_next;
89
142k
            return -1;
90
142k
        }
91
1.94M
        fsize += cbh_next->size;
92
1.94M
        if_debug2('K', "[K]merging free bits "PRI_INTPTR"(%u)\n",
93
1.94M
                  (intptr_t)cbh_next, cbh_next->size);
94
1.94M
        cbh_next = (gx_cached_bits_head *) ((byte *) cbh + fsize);
95
1.94M
    }
96
1.03M
    if (fsize > ssize) { /* fsize >= ssize1 */
97
1.01M
        cbh_next = (gx_cached_bits_head *) ((byte *) cbh + ssize);
98
1.01M
        cbh_next->size = fsize - ssize;
99
1.01M
        cb_head_set_free(cbh_next);
100
1.01M
        if_debug2('K', "[K]shortening bits "PRI_INTPTR" by %u (initial)\n",
101
1.01M
                  (intptr_t)cbh, fsize - ssize);
102
1.01M
    }
103
1.03M
    gs_alloc_fill(cbh, gs_alloc_fill_block, ssize);
104
1.03M
    cbh->size = ssize;
105
1.03M
    bc->bsize += ssize;
106
1.03M
    bc->csize++;
107
1.03M
    bc->cnext += ssize;
108
1.03M
    bck->allocated += ssize;
109
1.03M
    *pcbh = cbh;
110
1.03M
    return 0;
111
1.17M
#undef ssize
112
1.17M
#undef ssize1
113
1.17M
}
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
535k
{
120
535k
    gx_cached_bits_head *next;
121
122
535k
    if ((byte *) cbh + cbh->size == bck->data + bc->cnext &&
123
535k
        bck == bc->chunks
124
535k
        )
125
534k
        bc->cnext -= diff;
126
535k
    bc->bsize -= diff;
127
535k
    bck->allocated -= diff;
128
535k
    cbh->size -= diff;
129
535k
    next = (gx_cached_bits_head *) ((byte *) cbh + cbh->size);
130
535k
    cb_head_set_free(next);
131
535k
    next->size = diff;
132
535k
}
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
662k
{
140
662k
    uint size = cbh->size;
141
142
662k
    bc->csize--;
143
662k
    bc->bsize -= size;
144
662k
    bck->allocated -= size;
145
662k
    gs_alloc_fill(cbh, gs_alloc_fill_deleted, size);
146
662k
    cbh->size = size;   /* gs_alloc_fill may have overwritten */
147
662k
    cb_head_set_free(cbh);
148
662k
}
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