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
1.72M
{
32
1.72M
    bck->next = bck;
33
1.72M
    bc->chunks = bck;
34
1.72M
    bc->cnext = 0;
35
1.72M
    bc->bsize = 0;
36
1.72M
    bc->csize = 0;
37
1.72M
}
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
1.76M
{
45
1.76M
    bck->next = 0;
46
1.76M
    bck->data = data;
47
1.76M
    bck->size = size;
48
1.76M
    bck->allocated = 0;
49
1.76M
    if (data != 0) {
50
1.46M
        gx_cached_bits_head *cbh = (gx_cached_bits_head *) data;
51
52
1.46M
        cbh->size = size;
53
1.46M
        cb_head_set_free(cbh);
54
1.46M
    }
55
1.76M
}
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
12.7M
{
65
12.7M
    ulong lsize = ROUND_UP(lsize0, obj_align_mod);
66
67
99.9M
#define ssize ((uint)lsize)
68
12.7M
    ulong lsize1 = lsize + sizeof(gx_cached_bits_head);
69
70
68.5M
#define ssize1 ((uint)lsize1)
71
12.7M
    uint cnext = bc->cnext;
72
12.7M
    gx_bits_cache_chunk *bck = bc->chunks;
73
12.7M
    uint left = bck->size - cnext;
74
12.7M
    gx_cached_bits_head *cbh;
75
12.7M
    gx_cached_bits_head *cbh_next;
76
12.7M
    uint fsize = 0;
77
78
12.7M
    if (lsize1 > bck->size - cnext && lsize != left) { /* Not enough room to allocate in this chunk. */
79
40.3k
        *pcbh = 0;
80
40.3k
        return -1;
81
40.3k
    }
82
    /* Look for and/or free enough space. */
83
12.7M
    cbh = cbh_next = (gx_cached_bits_head *) (bck->data + cnext);
84
34.2M
    while (fsize < ssize1 && fsize != ssize) {
85
23.2M
        if (!cb_head_is_free(cbh_next)) { /* Ask the caller to free the entry. */
86
1.71M
            if (fsize)
87
1.64M
                cbh->size = fsize;
88
1.71M
            *pcbh = cbh_next;
89
1.71M
            return -1;
90
1.71M
        }
91
21.5M
        fsize += cbh_next->size;
92
21.5M
        if_debug2('K', "[K]merging free bits "PRI_INTPTR"(%u)\n",
93
21.5M
                  (intptr_t)cbh_next, cbh_next->size);
94
21.5M
        cbh_next = (gx_cached_bits_head *) ((byte *) cbh + fsize);
95
21.5M
    }
96
10.9M
    if (fsize > ssize) { /* fsize >= ssize1 */
97
10.7M
        cbh_next = (gx_cached_bits_head *) ((byte *) cbh + ssize);
98
10.7M
        cbh_next->size = fsize - ssize;
99
10.7M
        cb_head_set_free(cbh_next);
100
10.7M
        if_debug2('K', "[K]shortening bits "PRI_INTPTR" by %u (initial)\n",
101
10.7M
                  (intptr_t)cbh, fsize - ssize);
102
10.7M
    }
103
10.9M
    gs_alloc_fill(cbh, gs_alloc_fill_block, ssize);
104
10.9M
    cbh->size = ssize;
105
10.9M
    bc->bsize += ssize;
106
10.9M
    bc->csize++;
107
10.9M
    bc->cnext += ssize;
108
10.9M
    bck->allocated += ssize;
109
10.9M
    *pcbh = cbh;
110
10.9M
    return 0;
111
12.7M
#undef ssize
112
12.7M
#undef ssize1
113
12.7M
}
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
5.78M
{
120
5.78M
    gx_cached_bits_head *next;
121
122
5.78M
    if ((byte *) cbh + cbh->size == bck->data + bc->cnext &&
123
5.78M
        bck == bc->chunks
124
5.78M
        )
125
5.78M
        bc->cnext -= diff;
126
5.78M
    bc->bsize -= diff;
127
5.78M
    bck->allocated -= diff;
128
5.78M
    cbh->size -= diff;
129
5.78M
    next = (gx_cached_bits_head *) ((byte *) cbh + cbh->size);
130
5.78M
    cb_head_set_free(next);
131
5.78M
    next->size = diff;
132
5.78M
}
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
7.41M
{
140
7.41M
    uint size = cbh->size;
141
142
7.41M
    bc->csize--;
143
7.41M
    bc->bsize -= size;
144
7.41M
    bck->allocated -= size;
145
7.41M
    gs_alloc_fill(cbh, gs_alloc_fill_deleted, size);
146
7.41M
    cbh->size = size;   /* gs_alloc_fill may have overwritten */
147
7.41M
    cb_head_set_free(cbh);
148
7.41M
}
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