~ubuntu-branches/ubuntu/oneiric/ghostscript/oneiric

« back to all changes in this revision

Viewing changes to psi/igcref.c

  • Committer: Bazaar Package Importer
  • Author(s): Till Kamppeter
  • Date: 2011-07-15 16:49:55 UTC
  • mfrom: (1.1.23 upstream)
  • Revision ID: james.westby@ubuntu.com-20110715164955-uga6qibao6kez05c
Tags: 9.04~dfsg~20110715-0ubuntu1
* New upstream release
   - GIT snapshot from Jult, 12 2011.
* debian/patches/020110406~a54df2d.patch,
  debian/patches/020110408~0791cc8.patch,
  debian/patches/020110408~507cbee.patch,
  debian/patches/020110411~4509a49.patch,
  debian/patches/020110412~78bb9a6.patch,
  debian/patches/020110418~a05ab8a.patch,
  debian/patches/020110420~20b6c78.patch,
  debian/patches/020110420~4ddefa2.patch: Removed upstream patches.
* debian/rules: Generate ABI version number (variable "abi") correctly,
  cutting off repackaging and pre-release parts.
* debian/rules: Added ./lcms2/ directory to DEB_UPSTREAM_REPACKAGE_EXCLUDES.
* debian/copyright: Added lcms2/* to the list of excluded files.
* debian/symbols.common: Updated for new upstream source. Applied patch
  which dpkg-gensymbols generated for debian/libgs9.symbols to this file.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/* Copyright (C) 2001-2006 Artifex Software, Inc.
2
2
   All Rights Reserved.
3
 
  
 
3
 
4
4
   This software is provided AS-IS with no warranty, either express or
5
5
   implied.
6
6
 
11
11
   San Rafael, CA  94903, U.S.A., +1(415)492-9861, for further information.
12
12
*/
13
13
 
14
 
/* $Id: igcref.c 9043 2008-08-28 22:48:19Z giles $ */
 
14
/* $Id$ */
15
15
/* ref garbage collector for Ghostscript */
16
16
#include "memory_.h"
17
17
#include "ghost.h"
65
65
    ref *end = (ref *) ((char *)vptr + size);
66
66
 
67
67
    for (; pref < end; pref++)
68
 
        r_clear_attrs(pref, l_mark);
 
68
        r_clear_attrs(pref, l_mark);
69
69
}
70
70
ENUM_PTRS_BEGIN_PROC(ref_struct_enum_ptrs)
71
71
{
72
72
    if (index >= size / sizeof(ref))
73
 
        return 0;
 
73
        return 0;
74
74
    pep->ptr = (const ref *)vptr + index;
75
75
    return ptr_ref_type;
76
76
    ENUM_PTRS_END_PROC
96
96
    ref_packed *rpp = (ref_packed *)pep->ptr;
97
97
 
98
98
    if (r_is_packed(rpp))
99
 
        r_clear_pmark(rpp);
 
99
        r_clear_pmark(rpp);
100
100
    else
101
 
        r_clear_attrs((ref *)rpp, l_mark);
 
101
        r_clear_attrs((ref *)rpp, l_mark);
102
102
}
103
103
 
104
104
/* Unmarking routine for ref objects. */
105
105
static void
106
 
refs_clear_marks(const gs_memory_t *cmem, 
107
 
                 void /*obj_header_t */ *vptr, uint size,
108
 
                 const gs_memory_struct_type_t * pstype)
 
106
refs_clear_marks(const gs_memory_t *cmem,
 
107
                 void /*obj_header_t */ *vptr, uint size,
 
108
                 const gs_memory_struct_type_t * pstype)
109
109
{
110
110
    ref_packed *rp = (ref_packed *) vptr;
111
111
    ref_packed *end = (ref_packed *) ((byte *) vptr + size);
113
113
    /* Since the last ref is full-size, we only need to check for */
114
114
    /* the end of the block when we see one of those. */
115
115
    for (;;) {
116
 
        if (r_is_packed(rp)) {
 
116
        if (r_is_packed(rp)) {
117
117
#ifdef DEBUG
118
 
            if (gs_debug_c('8')) {
119
 
                dlprintf1("  [8]unmark packed 0x%lx ", (ulong) rp);
120
 
                debug_print_ref(cmem, (const ref *)rp);
121
 
                dputs("\n");
122
 
            }
 
118
            if (gs_debug_c('8')) {
 
119
                dlprintf1("  [8]unmark packed 0x%lx ", (ulong) rp);
 
120
                debug_print_ref(cmem, (const ref *)rp);
 
121
                dputs("\n");
 
122
            }
123
123
#endif
124
 
            r_clear_pmark(rp);
125
 
            rp++;
126
 
        } else {                /* full-size ref */
127
 
            ref *const pref = (ref *)rp;
 
124
            r_clear_pmark(rp);
 
125
            rp++;
 
126
        } else {                /* full-size ref */
 
127
            ref *const pref = (ref *)rp;
128
128
 
129
129
#ifdef DEBUG
130
 
            if (gs_debug_c('8')) {
131
 
                dlprintf1("  [8]unmark ref 0x%lx ", (ulong) rp);
132
 
                debug_print_ref(cmem, pref);
133
 
                dputs("\n");
134
 
            }
 
130
            if (gs_debug_c('8')) {
 
131
                dlprintf1("  [8]unmark ref 0x%lx ", (ulong) rp);
 
132
                debug_print_ref(cmem, pref);
 
133
                dputs("\n");
 
134
            }
135
135
#endif
136
 
            r_clear_attrs(pref, l_mark);
137
 
            rp += packed_per_ref;
138
 
            if (rp >= (ref_packed *) end)
139
 
                break;
140
 
        }
 
136
            r_clear_attrs(pref, l_mark);
 
137
            rp += packed_per_ref;
 
138
            if (rp >= (ref_packed *) end)
 
139
                break;
 
140
        }
141
141
    }
142
142
}
143
143
 
150
150
    ref_packed *rpp = (void *)pep->ptr;
151
151
 
152
152
    if (r_is_packed(rpp)) {
153
 
        if (r_has_pmark(rpp))
154
 
            return false;
155
 
        r_set_pmark(rpp);
 
153
        if (r_has_pmark(rpp))
 
154
            return false;
 
155
        r_set_pmark(rpp);
156
156
    } else {
157
 
        ref *const pref = (ref *)rpp;
 
157
        ref *const pref = (ref *)rpp;
158
158
 
159
 
        if (r_has_attr(pref, l_mark))
160
 
            return false;
161
 
        r_set_attrs(pref, l_mark);
 
159
        if (r_has_attr(pref, l_mark))
 
160
            return false;
 
161
        r_set_attrs(pref, l_mark);
162
162
    }
163
163
    return true;
164
164
}
181
181
    ref_packed *end = (ref_packed *) ((byte *) rp + size);
182
182
 
183
183
    while (rp < end) {
184
 
        if (r_is_packed(rp))
185
 
            rp++;
186
 
        else {
187
 
            /* Full-size ref.  Store the relocation here if possible. */
188
 
            ref *const pref = (ref *)rp;
 
184
        if (r_is_packed(rp))
 
185
            rp++;
 
186
        else {
 
187
            /* Full-size ref.  Store the relocation here if possible. */
 
188
            ref *const pref = (ref *)rp;
189
189
 
190
 
            if (!ref_type_uses_size_or_null(r_type(pref))) {
191
 
                if_debug1('8', "  [8]clearing reloc at 0x%lx\n", (ulong) rp);
192
 
                r_set_size(pref, 0);
193
 
            }
194
 
            rp += packed_per_ref;
195
 
        }
 
190
            if (!ref_type_uses_size_or_null(r_type(pref))) {
 
191
                if_debug1('8', "  [8]clearing reloc at 0x%lx\n", (ulong) rp);
 
192
                r_set_size(pref, 0);
 
193
            }
 
194
            rp += packed_per_ref;
 
195
        }
196
196
    }
197
197
}
198
198
 
213
213
     * of align_packed_per_ref, so this makes things relatively easy.
214
214
     */
215
215
    while (rp < end) {
216
 
        if (r_is_packed(rp)) {
 
216
        if (r_is_packed(rp)) {
217
217
#if align_packed_per_ref == 1
218
 
            if (r_has_pmark(rp)) {
219
 
                if_debug1('8',
220
 
                          "  [8]packed ref 0x%lx is marked\n",
221
 
                          (ulong) rp);
222
 
                rp++;
223
 
            } else {
 
218
            if (r_has_pmark(rp)) {
 
219
                if_debug1('8',
 
220
                          "  [8]packed ref 0x%lx is marked\n",
 
221
                          (ulong) rp);
 
222
                rp++;
 
223
            } else {
224
224
#else
225
 
            int i;
 
225
            int i;
226
226
 
227
 
            /*
228
 
             * Note: align_packed_per_ref is typically
229
 
             * 2 or 4 for 32-bit processors.
230
 
             */
 
227
            /*
 
228
             * Note: align_packed_per_ref is typically
 
229
             * 2 or 4 for 32-bit processors.
 
230
             */
231
231
#define all_marked (align_packed_per_ref * lp_mark)
232
232
# if align_packed_per_ref == 2
233
233
#  if arch_sizeof_int == arch_sizeof_short * 2
240
240
# else
241
241
#  if align_packed_per_ref == 4
242
242
#    define marked ((*rp & lp_mark) + (rp[1] & lp_mark) +\
243
 
                    (rp[2] & lp_mark) + (rp[3] & lp_mark))
 
243
                    (rp[2] & lp_mark) + (rp[3] & lp_mark))
244
244
#  else
245
 
            /*
246
 
             * The value of marked is logically a uint, not an int:
247
 
             * we declare it as int only to avoid a compiler warning
248
 
             * message about using a non-int value in a switch statement.
249
 
             */
250
 
            int marked = *rp & lp_mark;
 
245
            /*
 
246
             * The value of marked is logically a uint, not an int:
 
247
             * we declare it as int only to avoid a compiler warning
 
248
             * message about using a non-int value in a switch statement.
 
249
             */
 
250
            int marked = *rp & lp_mark;
251
251
 
252
 
            for (i = 1; i < align_packed_per_ref; i++)
253
 
                marked += rp[i] & lp_mark;
 
252
            for (i = 1; i < align_packed_per_ref; i++)
 
253
                marked += rp[i] & lp_mark;
254
254
#  endif
255
255
# endif
256
 
            /*
257
 
             * Now marked is lp_mark * the number of marked
258
 
             * packed refs in the aligned block, except for
259
 
             * a couple of special cases above.
260
 
             */
261
 
            switch (marked) {
262
 
                case all_marked:
263
 
                    if_debug2('8',
264
 
                              "  [8]packed refs 0x%lx..0x%lx are marked\n",
265
 
                              (ulong) rp,
266
 
                              (ulong) (rp + (align_packed_per_ref - 1)));
267
 
                    rp += align_packed_per_ref;
268
 
                    break;
269
 
                default:
270
 
                    /* At least one packed ref in the block */
271
 
                    /* is marked: Keep the whole block. */
272
 
                    for (i = align_packed_per_ref; i--; rp++) {
273
 
                        r_set_pmark(rp);
274
 
                        if_debug1('8',
275
 
                                  "  [8]packed ref 0x%lx is marked\n",
276
 
                                  (ulong) rp);
277
 
                    }
278
 
                    break;
279
 
                case 0:
 
256
            /*
 
257
             * Now marked is lp_mark * the number of marked
 
258
             * packed refs in the aligned block, except for
 
259
             * a couple of special cases above.
 
260
             */
 
261
            switch (marked) {
 
262
                case all_marked:
 
263
                    if_debug2('8',
 
264
                              "  [8]packed refs 0x%lx..0x%lx are marked\n",
 
265
                              (ulong) rp,
 
266
                              (ulong) (rp + (align_packed_per_ref - 1)));
 
267
                    rp += align_packed_per_ref;
 
268
                    break;
 
269
                default:
 
270
                    /* At least one packed ref in the block */
 
271
                    /* is marked: Keep the whole block. */
 
272
                    for (i = align_packed_per_ref; i--; rp++) {
 
273
                        r_set_pmark(rp);
 
274
                        if_debug1('8',
 
275
                                  "  [8]packed ref 0x%lx is marked\n",
 
276
                                  (ulong) rp);
 
277
                    }
 
278
                    break;
 
279
                case 0:
280
280
#endif
281
 
                    if_debug2('8', "  [8]%d packed ref(s) at 0x%lx are unmarked\n",
282
 
                              align_packed_per_ref, (ulong) rp);
283
 
                    {
284
 
                        uint rel = reloc + freed;
285
 
 
286
 
                        /* Change this to an integer so we can */
287
 
                        /* store the relocation here. */
288
 
                        *rp = pt_tag(pt_integer) +
289
 
                            min(rel, packed_max_value);
290
 
                    }
291
 
                    rp += align_packed_per_ref;
292
 
                    freed += sizeof(ref_packed) * align_packed_per_ref;
293
 
            }
294
 
        } else {                /* full-size ref */
295
 
            uint rel = reloc + freed;
296
 
 
297
 
            /* The following assignment is logically */
298
 
            /* unnecessary; we do it only for convenience */
299
 
            /* in debugging. */
300
 
            ref *pref = (ref *) rp;
301
 
 
302
 
            if (!r_has_attr(pref, l_mark)) {
303
 
                if_debug1('8', "  [8]ref 0x%lx is unmarked\n",
304
 
                          (ulong) pref);
305
 
                /* Change this to a mark so we can */
306
 
                /* store the relocation. */
307
 
                r_set_type(pref, t_mark);
308
 
                r_set_size(pref, rel);
309
 
                freed += sizeof(ref);
310
 
            } else {
311
 
                if_debug1('8', "  [8]ref 0x%lx is marked\n",
312
 
                          (ulong) pref);
313
 
                /* Store the relocation here if possible. */
314
 
                if (!ref_type_uses_size_or_null(r_type(pref))) {
315
 
                    if_debug2('8', "  [8]storing reloc %u at 0x%lx\n",
316
 
                              rel, (ulong) pref);
317
 
                    r_set_size(pref, rel);
318
 
                }
319
 
            }
320
 
            rp += packed_per_ref;
321
 
        }
 
281
                    if_debug2('8', "  [8]%d packed ref(s) at 0x%lx are unmarked\n",
 
282
                              align_packed_per_ref, (ulong) rp);
 
283
                    {
 
284
                        uint rel = reloc + freed;
 
285
 
 
286
                        /* Change this to an integer so we can */
 
287
                        /* store the relocation here. */
 
288
                        *rp = pt_tag(pt_integer) +
 
289
                            min(rel, packed_max_value);
 
290
                    }
 
291
                    rp += align_packed_per_ref;
 
292
                    freed += sizeof(ref_packed) * align_packed_per_ref;
 
293
            }
 
294
        } else {                /* full-size ref */
 
295
            uint rel = reloc + freed;
 
296
 
 
297
            /* The following assignment is logically */
 
298
            /* unnecessary; we do it only for convenience */
 
299
            /* in debugging. */
 
300
            ref *pref = (ref *) rp;
 
301
 
 
302
            if (!r_has_attr(pref, l_mark)) {
 
303
                if_debug1('8', "  [8]ref 0x%lx is unmarked\n",
 
304
                          (ulong) pref);
 
305
                /* Change this to a mark so we can */
 
306
                /* store the relocation. */
 
307
                r_set_type(pref, t_mark);
 
308
                r_set_size(pref, rel);
 
309
                freed += sizeof(ref);
 
310
            } else {
 
311
                if_debug1('8', "  [8]ref 0x%lx is marked\n",
 
312
                          (ulong) pref);
 
313
                /* Store the relocation here if possible. */
 
314
                if (!ref_type_uses_size_or_null(r_type(pref))) {
 
315
                    if_debug2('8', "  [8]storing reloc %u at 0x%lx\n",
 
316
                              rel, (ulong) pref);
 
317
                    r_set_size(pref, rel);
 
318
                }
 
319
            }
 
320
            rp += packed_per_ref;
 
321
        }
322
322
    }
323
323
    if_debug3('7', " [7]at end of refs 0x%lx, size = %u, freed = %u\n",
324
 
              (ulong) (hdr + 1), size, freed);
 
324
              (ulong) (hdr + 1), size, freed);
325
325
    if (freed == size)
326
 
        return false;
 
326
        return false;
327
327
#if arch_sizeof_int > arch_sizeof_short
328
328
    /*
329
329
     * If the final relocation can't fit in the r_size field
333
333
     * references to any ref in it.
334
334
     */
335
335
    if (freed <= max_ushort)
336
 
        return true;
 
336
        return true;
337
337
    /*
338
338
     * We have to mark all surviving refs, but we also must
339
339
     * overwrite any non-surviving refs with something that
341
341
     */
342
342
    rp = (ref_packed *) (hdr + 1);
343
343
    while (rp < end) {
344
 
        if (r_is_packed(rp)) {
345
 
            if (!r_has_pmark(rp))
346
 
                *rp = pt_tag(pt_integer) | lp_mark;
347
 
            ++rp;
348
 
        } else {                /* The following assignment is logically */
349
 
            /* unnecessary; we do it only for convenience */
350
 
            /* in debugging. */
351
 
            ref *pref = (ref *) rp;
 
344
        if (r_is_packed(rp)) {
 
345
            if (!r_has_pmark(rp))
 
346
                *rp = pt_tag(pt_integer) | lp_mark;
 
347
            ++rp;
 
348
        } else {                /* The following assignment is logically */
 
349
            /* unnecessary; we do it only for convenience */
 
350
            /* in debugging. */
 
351
            ref *pref = (ref *) rp;
352
352
 
353
 
            if (!r_has_attr(pref, l_mark)) {
354
 
                r_set_type_attrs(pref, t_mark, l_mark);
355
 
                r_set_size(pref, reloc);
356
 
            } else {
357
 
                if (!ref_type_uses_size_or_null(r_type(pref)))
358
 
                    r_set_size(pref, reloc);
359
 
            }
360
 
            rp += packed_per_ref;
361
 
        }
 
353
            if (!r_has_attr(pref, l_mark)) {
 
354
                r_set_type_attrs(pref, t_mark, l_mark);
 
355
                r_set_size(pref, reloc);
 
356
            } else {
 
357
                if (!ref_type_uses_size_or_null(r_type(pref)))
 
358
                    r_set_size(pref, reloc);
 
359
            }
 
360
            rp += packed_per_ref;
 
361
        }
362
362
    }
363
363
    /* The last ref has to remain unmarked. */
364
364
    r_clear_attrs((ref *) rp - 1, l_mark);
371
371
/* Relocate all the pointers in a block of refs. */
372
372
static void
373
373
refs_do_reloc(void /*obj_header_t */ *vptr, uint size,
374
 
              const gs_memory_struct_type_t * pstype, gc_state_t * gcst)
 
374
              const gs_memory_struct_type_t * pstype, gc_state_t * gcst)
375
375
{
376
376
    igc_reloc_refs((ref_packed *) vptr,
377
 
                   (ref_packed *) ((char *)vptr + size),
378
 
                   gcst);
 
377
                   (ref_packed *) ((char *)vptr + size),
 
378
                   gcst);
379
379
}
380
380
/* Relocate the contents of a block of refs. */
381
381
/* If gcst->relocating_untraced is true, we are relocating pointers from an */
385
385
{
386
386
    int min_trace = gcst->min_collect;
387
387
    ref_packed *rp = from;
388
 
    bool do_all = gcst->relocating_untraced; 
 
388
    bool do_all = gcst->relocating_untraced;
389
389
 
390
390
    vm_spaces spaces = gcst->spaces;
391
391
    const gs_memory_t *cmem = space_system->stable_memory;
392
392
 
393
393
    while (rp < to) {
394
 
        ref *pref;
 
394
        ref *pref;
395
395
#ifdef DEBUG
396
 
        const void *before = 0;
397
 
        const void *after = 0;
 
396
        const void *before = 0;
 
397
        const void *after = 0;
398
398
# define DO_RELOC(var, stat)\
399
399
    BEGIN before = (var); stat; after = (var); END
400
400
# define SET_RELOC(var, expr)\
404
404
# define SET_RELOC(var, expr) var = expr
405
405
#endif
406
406
 
407
 
        if (r_is_packed(rp)) {
408
 
            rp++;
409
 
            continue;
410
 
        }
411
 
        /* The following assignment is logically unnecessary; */
412
 
        /* we do it only for convenience in debugging. */
413
 
        pref = (ref *) rp;
414
 
        if_debug3('8', "  [8]relocating %s %d ref at 0x%lx\n",
415
 
                  (r_has_attr(pref, l_mark) ? "marked" : "unmarked"),
416
 
                  r_btype(pref), (ulong) pref);
417
 
        if ((r_has_attr(pref, l_mark) || do_all) &&
418
 
            r_space(pref) >= min_trace
419
 
            ) {
420
 
            switch (r_type(pref)) {
421
 
                    /* Struct cases */
422
 
                case t_file:
423
 
                    DO_RELOC(pref->value.pfile, RELOC_VAR(pref->value.pfile));
424
 
                    break;
425
 
                case t_device:
426
 
                    DO_RELOC(pref->value.pdevice,
427
 
                             RELOC_VAR(pref->value.pdevice));
428
 
                    break;
429
 
                case t_fontID:
430
 
                case t_struct:
431
 
                case t_astruct:
432
 
                    DO_RELOC(pref->value.pstruct,
433
 
                             RELOC_VAR(pref->value.pstruct));
434
 
                    break;
435
 
                    /* Non-trivial non-struct cases */
436
 
                case t_dictionary:
437
 
                    rputc('d');
438
 
                    SET_RELOC(pref->value.pdict,
439
 
                              (dict *)igc_reloc_ref_ptr((ref_packed *)pref->value.pdict, gcst));
440
 
                    break;
441
 
                case t_array:
442
 
                    {
443
 
                        uint size = r_size(pref);
444
 
 
445
 
                        if (size != 0) {        /* value.refs might be NULL */
446
 
 
447
 
                            /*
448
 
                             * If the array is large, we allocated it in its
449
 
                             * own object (at least originally -- this might
450
 
                             * be a pointer to a subarray.)  In this case,
451
 
                             * we know it is the only object in its
452
 
                             * containing st_refs object, so we know that
453
 
                             * the mark containing the relocation appears
454
 
                             * just after it.
455
 
                             */
456
 
                            if (size < max_size_st_refs / sizeof(ref)) {
457
 
                                rputc('a');
458
 
                                SET_RELOC(pref->value.refs,
459
 
                                    (ref *) igc_reloc_ref_ptr(
460
 
                                     (ref_packed *) pref->value.refs, gcst));
461
 
                            } else {
462
 
                                rputc('A');
463
 
                                /*
464
 
                                 * See the t_shortarray case below for why we
465
 
                                 * decrement size.
466
 
                                 */
467
 
                                --size;
468
 
                                SET_RELOC(pref->value.refs,
469
 
                                    (ref *) igc_reloc_ref_ptr(
470
 
                                   (ref_packed *) (pref->value.refs + size),
471
 
                                                               gcst) - size);
472
 
                            }
473
 
                        }
474
 
                    }
475
 
                    break;
476
 
                case t_mixedarray:
477
 
                    if (r_size(pref) != 0) {    /* value.refs might be NULL */
478
 
                        rputc('m');
479
 
                        SET_RELOC(pref->value.packed,
480
 
                                  igc_reloc_ref_ptr(pref->value.packed, gcst));
481
 
                    }
482
 
                    break;
483
 
                case t_shortarray:
484
 
                    {
485
 
                        uint size = r_size(pref);
486
 
 
487
 
                        /*
488
 
                         * Since we know that igc_reloc_ref_ptr works by
489
 
                         * scanning forward, and we know that all the
490
 
                         * elements of this array itself are marked, we can
491
 
                         * save some scanning time by relocating the pointer
492
 
                         * to the end of the array rather than the
493
 
                         * beginning.
494
 
                         */
495
 
                        if (size != 0) {        /* value.refs might be NULL */
496
 
                            rputc('s');
497
 
                            /*
498
 
                             * igc_reloc_ref_ptr has to be able to determine
499
 
                             * whether the pointer points into a space that
500
 
                             * isn't being collected.  It does this by
501
 
                             * checking whether the referent of the pointer
502
 
                             * is marked.  For this reason, we have to pass
503
 
                             * a pointer to the last real element of the
504
 
                             * array, rather than just beyond it.
505
 
                             */
506
 
                            --size;
507
 
                            SET_RELOC(pref->value.packed,
508
 
                                igc_reloc_ref_ptr(pref->value.packed + size,
509
 
                                                  gcst) - size);
510
 
                        }
511
 
                    }
512
 
                    break;
513
 
                case t_name:
514
 
                    {
515
 
                        void *psub = name_ref_sub_table(cmem, pref);
516
 
                        void *rsub = RELOC_OBJ(psub); /* gcst implicit */
517
 
 
518
 
                        SET_RELOC(pref->value.pname,
519
 
                                  (name *)
520
 
                                  ((char *)rsub + ((char *)pref->value.pname -
521
 
                                                   (char *)psub)));
522
 
                    } break;
523
 
                case t_string:
524
 
                    {
525
 
                        gs_string str;
526
 
 
527
 
                        str.data = pref->value.bytes;
528
 
                        str.size = r_size(pref);
529
 
 
530
 
                        DO_RELOC(str.data, RELOC_STRING_VAR(str));
531
 
                        pref->value.bytes = str.data;
532
 
                    }
533
 
                    break;
534
 
                case t_oparray:
535
 
                    rputc('o');
536
 
                    SET_RELOC(pref->value.const_refs,
537
 
                        (const ref *)igc_reloc_ref_ptr((const ref_packed *)pref->value.const_refs, gcst));
538
 
                    break;
539
 
                default:
540
 
                    goto no_reloc; /* don't print trace message */
541
 
            }
542
 
            if_debug2('8', "  [8]relocated 0x%lx => 0x%lx\n",
543
 
                      (ulong)before, (ulong)after);
544
 
        }
 
407
        if (r_is_packed(rp)) {
 
408
            rp++;
 
409
            continue;
 
410
        }
 
411
        /* The following assignment is logically unnecessary; */
 
412
        /* we do it only for convenience in debugging. */
 
413
        pref = (ref *) rp;
 
414
        if_debug3('8', "  [8]relocating %s %d ref at 0x%lx\n",
 
415
                  (r_has_attr(pref, l_mark) ? "marked" : "unmarked"),
 
416
                  r_btype(pref), (ulong) pref);
 
417
        if ((r_has_attr(pref, l_mark) || do_all) &&
 
418
            r_space(pref) >= min_trace
 
419
            ) {
 
420
            switch (r_type(pref)) {
 
421
                    /* Struct cases */
 
422
                case t_file:
 
423
                    DO_RELOC(pref->value.pfile, RELOC_VAR(pref->value.pfile));
 
424
                    break;
 
425
                case t_device:
 
426
                    DO_RELOC(pref->value.pdevice,
 
427
                             RELOC_VAR(pref->value.pdevice));
 
428
                    break;
 
429
                case t_fontID:
 
430
                case t_struct:
 
431
                case t_astruct:
 
432
                    DO_RELOC(pref->value.pstruct,
 
433
                             RELOC_VAR(pref->value.pstruct));
 
434
                    break;
 
435
                    /* Non-trivial non-struct cases */
 
436
                case t_dictionary:
 
437
                    rputc('d');
 
438
                    SET_RELOC(pref->value.pdict,
 
439
                              (dict *)igc_reloc_ref_ptr((ref_packed *)pref->value.pdict, gcst));
 
440
                    break;
 
441
                case t_array:
 
442
                    {
 
443
                        uint size = r_size(pref);
 
444
 
 
445
                        if (size != 0) {        /* value.refs might be NULL */
 
446
 
 
447
                            /*
 
448
                             * If the array is large, we allocated it in its
 
449
                             * own object (at least originally -- this might
 
450
                             * be a pointer to a subarray.)  In this case,
 
451
                             * we know it is the only object in its
 
452
                             * containing st_refs object, so we know that
 
453
                             * the mark containing the relocation appears
 
454
                             * just after it.
 
455
                             */
 
456
                            if (size < max_size_st_refs / sizeof(ref)) {
 
457
                                rputc('a');
 
458
                                SET_RELOC(pref->value.refs,
 
459
                                    (ref *) igc_reloc_ref_ptr(
 
460
                                     (ref_packed *) pref->value.refs, gcst));
 
461
                            } else {
 
462
                                rputc('A');
 
463
                                /*
 
464
                                 * See the t_shortarray case below for why we
 
465
                                 * decrement size.
 
466
                                 */
 
467
                                --size;
 
468
                                SET_RELOC(pref->value.refs,
 
469
                                    (ref *) igc_reloc_ref_ptr(
 
470
                                   (ref_packed *) (pref->value.refs + size),
 
471
                                                               gcst) - size);
 
472
                            }
 
473
                        }
 
474
                    }
 
475
                    break;
 
476
                case t_mixedarray:
 
477
                    if (r_size(pref) != 0) {    /* value.refs might be NULL */
 
478
                        rputc('m');
 
479
                        SET_RELOC(pref->value.packed,
 
480
                                  igc_reloc_ref_ptr(pref->value.packed, gcst));
 
481
                    }
 
482
                    break;
 
483
                case t_shortarray:
 
484
                    {
 
485
                        uint size = r_size(pref);
 
486
 
 
487
                        /*
 
488
                         * Since we know that igc_reloc_ref_ptr works by
 
489
                         * scanning forward, and we know that all the
 
490
                         * elements of this array itself are marked, we can
 
491
                         * save some scanning time by relocating the pointer
 
492
                         * to the end of the array rather than the
 
493
                         * beginning.
 
494
                         */
 
495
                        if (size != 0) {        /* value.refs might be NULL */
 
496
                            rputc('s');
 
497
                            /*
 
498
                             * igc_reloc_ref_ptr has to be able to determine
 
499
                             * whether the pointer points into a space that
 
500
                             * isn't being collected.  It does this by
 
501
                             * checking whether the referent of the pointer
 
502
                             * is marked.  For this reason, we have to pass
 
503
                             * a pointer to the last real element of the
 
504
                             * array, rather than just beyond it.
 
505
                             */
 
506
                            --size;
 
507
                            SET_RELOC(pref->value.packed,
 
508
                                igc_reloc_ref_ptr(pref->value.packed + size,
 
509
                                                  gcst) - size);
 
510
                        }
 
511
                    }
 
512
                    break;
 
513
                case t_name:
 
514
                    {
 
515
                        void *psub = name_ref_sub_table(cmem, pref);
 
516
                        void *rsub = RELOC_OBJ(psub); /* gcst implicit */
 
517
 
 
518
                        SET_RELOC(pref->value.pname,
 
519
                                  (name *)
 
520
                                  ((char *)rsub + ((char *)pref->value.pname -
 
521
                                                   (char *)psub)));
 
522
                    } break;
 
523
                case t_string:
 
524
                    {
 
525
                        gs_string str;
 
526
 
 
527
                        str.data = pref->value.bytes;
 
528
                        str.size = r_size(pref);
 
529
 
 
530
                        DO_RELOC(str.data, RELOC_STRING_VAR(str));
 
531
                        pref->value.bytes = str.data;
 
532
                    }
 
533
                    break;
 
534
                case t_oparray:
 
535
                    rputc('o');
 
536
                    SET_RELOC(pref->value.const_refs,
 
537
                        (const ref *)igc_reloc_ref_ptr((const ref_packed *)pref->value.const_refs, gcst));
 
538
                    break;
 
539
                default:
 
540
                    goto no_reloc; /* don't print trace message */
 
541
            }
 
542
            if_debug2('8', "  [8]relocated 0x%lx => 0x%lx\n",
 
543
                      (ulong)before, (ulong)after);
 
544
        }
545
545
no_reloc:
546
 
        rp += packed_per_ref;
 
546
        rp += packed_per_ref;
547
547
    }
548
548
}
549
549
 
566
566
#endif
567
567
    for (;;) {
568
568
 
569
 
        if (r_is_packed(rp)) {
570
 
            /*
571
 
             * Normally, an unmarked packed ref will be an
572
 
             * integer whose value is the amount of relocation.
573
 
             * However, the relocation value might have been
574
 
             * too large to fit.  If this is the case, for
575
 
             * each such unmarked packed ref we pass over,
576
 
             * we have to decrement the final relocation.
577
 
             */
578
 
            rputc((*rp & lp_mark ? '1' : '0'));
579
 
            if (!(*rp & lp_mark)) {
580
 
                if (*rp != pt_tag(pt_integer) + packed_max_value) {
581
 
                    /* This is a stored relocation value. */
582
 
                    rputc('\n');
583
 
                    rp = print_reloc(prp, "ref",
584
 
                                     (const ref_packed *)
585
 
                                     ((const char *)prp -
586
 
                                      (*rp & packed_value_mask) + dec));
587
 
                    break;
588
 
                }
589
 
                /*
590
 
                 * We know this is the first of an aligned block
591
 
                 * of packed refs.  Skip over the entire block,
592
 
                 * decrementing the final relocation.
593
 
                 */
594
 
                dec += sizeof(ref_packed) * align_packed_per_ref;
595
 
                rp += align_packed_per_ref;
596
 
            } else
597
 
                rp++;
598
 
            continue;
599
 
        }
600
 
        if (!ref_type_uses_size_or_null(r_type(RP_REF(rp)))) {
601
 
            /* reloc is in r_size */
602
 
            rputc('\n');
603
 
            rp = print_reloc(prp, "ref",
604
 
                             (const ref_packed *)
605
 
                             (r_size(RP_REF(rp)) == 0 ? prp :
606
 
                              (const ref_packed *)((const char *)prp -
607
 
                                                   r_size(RP_REF(rp)) + dec)));
608
 
            break;
609
 
        }
610
 
        rputc('u');
611
 
        rp += packed_per_ref;
 
569
        if (r_is_packed(rp)) {
 
570
            /*
 
571
             * Normally, an unmarked packed ref will be an
 
572
             * integer whose value is the amount of relocation.
 
573
             * However, the relocation value might have been
 
574
             * too large to fit.  If this is the case, for
 
575
             * each such unmarked packed ref we pass over,
 
576
             * we have to decrement the final relocation.
 
577
             */
 
578
            rputc((*rp & lp_mark ? '1' : '0'));
 
579
            if (!(*rp & lp_mark)) {
 
580
                if (*rp != pt_tag(pt_integer) + packed_max_value) {
 
581
                    /* This is a stored relocation value. */
 
582
                    rputc('\n');
 
583
                    rp = print_reloc(prp, "ref",
 
584
                                     (const ref_packed *)
 
585
                                     ((const char *)prp -
 
586
                                      (*rp & packed_value_mask) + dec));
 
587
                    break;
 
588
                }
 
589
                /*
 
590
                 * We know this is the first of an aligned block
 
591
                 * of packed refs.  Skip over the entire block,
 
592
                 * decrementing the final relocation.
 
593
                 */
 
594
                dec += sizeof(ref_packed) * align_packed_per_ref;
 
595
                rp += align_packed_per_ref;
 
596
            } else
 
597
                rp++;
 
598
            continue;
 
599
        }
 
600
        if (!ref_type_uses_size_or_null(r_type(RP_REF(rp)))) {
 
601
            /* reloc is in r_size */
 
602
            rputc('\n');
 
603
            rp = print_reloc(prp, "ref",
 
604
                             (const ref_packed *)
 
605
                             (r_size(RP_REF(rp)) == 0 ? prp :
 
606
                              (const ref_packed *)((const char *)prp -
 
607
                                                   r_size(RP_REF(rp)) + dec)));
 
608
            break;
 
609
        }
 
610
        rputc('u');
 
611
        rp += packed_per_ref;
612
612
    }
613
613
    /* Use a severely deprecated pun to remove the const property. */
614
614
    {
615
 
        union { const ref_packed *r; ref_packed *w; } u;
 
615
        union { const ref_packed *r; ref_packed *w; } u;
616
616
 
617
 
        u.r = rp;
618
 
        return u.w;
 
617
        u.r = rp;
 
618
        return u.w;
619
619
    }
620
620
#undef RP_REF
621
621
}
639
639
     * do any relocation.  Check for this first.
640
640
     */
641
641
    if (r_is_packed(rp)) {
642
 
        if (!r_has_pmark(rp))
643
 
            goto ret_rp;
 
642
        if (!r_has_pmark(rp))
 
643
            goto ret_rp;
644
644
    } else {
645
 
        if (!r_has_attr(RP_REF(rp), l_mark))
646
 
            goto ret_rp;
 
645
        if (!r_has_attr(RP_REF(rp), l_mark))
 
646
            goto ret_rp;
647
647
    }
648
648
    return igc_reloc_ref_ptr_nocheck(prp, gcst);
649
649
ret_rp:
650
650
    /* Use a severely deprecated pun to remove the const property. */
651
651
    {
652
 
        union { const ref_packed *r; ref_packed *w; } u;
 
652
        union { const ref_packed *r; ref_packed *w; } u;
653
653
 
654
 
        u.r = rp;
655
 
        return u.w;
 
654
        u.r = rp;
 
655
        return u.w;
656
656
    }
657
657
}
658
658
 
668
668
    ref_packed *end;
669
669
    uint new_size;
670
670
 
671
 
   /* The next switch controls an optimization 
 
671
   /* The next switch controls an optimization
672
672
      for the loop termination condition.
673
673
      It was useful during the development,
674
674
      when some assumptions were temporary wrong.
682
682
     * of the block when we see one of those.
683
683
     */
684
684
    if (dpre == pre)            /* Loop while we don't need to copy. */
685
 
        for (;;) {
686
 
            if (r_is_packed(src)) {
687
 
                if (!r_has_pmark(src))
688
 
                    break;
689
 
                if_debug1('8', "  [8]packed ref 0x%lx \"copied\"\n",
690
 
                          (ulong) src);
691
 
                *src &= ~lp_mark;
692
 
                src++;
693
 
            } else {            /* full-size ref */
694
 
                ref *const pref = (ref *)src;
 
685
        for (;;) {
 
686
            if (r_is_packed(src)) {
 
687
                if (!r_has_pmark(src))
 
688
                    break;
 
689
                if_debug1('8', "  [8]packed ref 0x%lx \"copied\"\n",
 
690
                          (ulong) src);
 
691
                *src &= ~lp_mark;
 
692
                src++;
 
693
            } else {            /* full-size ref */
 
694
                ref *const pref = (ref *)src;
695
695
 
696
 
                if (!r_has_attr(pref, l_mark))
697
 
                    break;
698
 
                if_debug1('8', "  [8]ref 0x%lx \"copied\"\n", (ulong) src);
699
 
                r_clear_attrs(pref, l_mark);
700
 
                src += packed_per_ref;
701
 
            }
 
696
                if (!r_has_attr(pref, l_mark))
 
697
                    break;
 
698
                if_debug1('8', "  [8]ref 0x%lx \"copied\"\n", (ulong) src);
 
699
                r_clear_attrs(pref, l_mark);
 
700
                src += packed_per_ref;
 
701
            }
702
702
    } else
703
 
        *dpre = *pre;
 
703
        *dpre = *pre;
704
704
    dest = (ref_packed *) ((char *)dpre + ((char *)src - (char *)pre));
705
705
    for (;;) {
706
 
        if (r_is_packed(src)) {
707
 
            if (r_has_pmark(src)) {
708
 
                if_debug2('8', "  [8]packed ref 0x%lx copied to 0x%lx\n",
709
 
                          (ulong) src, (ulong) dest);
710
 
                *dest++ = *src & ~lp_mark;
711
 
            }
712
 
            src++;
713
 
        } else {                /* full-size ref */
714
 
            if (r_has_attr((ref *) src, l_mark)) {
715
 
                ref rtemp;
 
706
        if (r_is_packed(src)) {
 
707
            if (r_has_pmark(src)) {
 
708
                if_debug2('8', "  [8]packed ref 0x%lx copied to 0x%lx\n",
 
709
                          (ulong) src, (ulong) dest);
 
710
                *dest++ = *src & ~lp_mark;
 
711
            }
 
712
            src++;
 
713
        } else {                /* full-size ref */
 
714
            if (r_has_attr((ref *) src, l_mark)) {
 
715
                ref rtemp;
716
716
 
717
 
                if_debug2('8', "  [8]ref 0x%lx copied to 0x%lx\n",
718
 
                          (ulong) src, (ulong) dest);
719
 
                /* We can't just use ref_assign_inline, */
720
 
                /* because the source and destination */
721
 
                /* might overlap! */
722
 
                ref_assign_inline(&rtemp, (ref *) src);
723
 
                r_clear_attrs(&rtemp, l_mark);
724
 
                ref_assign_inline((ref *) dest, &rtemp);
725
 
                src += packed_per_ref;
726
 
                dest += packed_per_ref;
727
 
            } else {            /* check for end of block */
728
 
                src += packed_per_ref;
729
 
                if (src >= end)
730
 
                    break;
731
 
            }
732
 
        }
 
717
                if_debug2('8', "  [8]ref 0x%lx copied to 0x%lx\n",
 
718
                          (ulong) src, (ulong) dest);
 
719
                /* We can't just use ref_assign_inline, */
 
720
                /* because the source and destination */
 
721
                /* might overlap! */
 
722
                ref_assign_inline(&rtemp, (ref *) src);
 
723
                r_clear_attrs(&rtemp, l_mark);
 
724
                ref_assign_inline((ref *) dest, &rtemp);
 
725
                src += packed_per_ref;
 
726
                dest += packed_per_ref;
 
727
            } else {            /* check for end of block */
 
728
                src += packed_per_ref;
 
729
                if (src >= end)
 
730
                    break;
 
731
            }
 
732
        }
733
733
    }
734
734
    new_size = (byte *) dest - (byte *) (dpre + 1) + sizeof(ref);
735
735
#ifdef DEBUG
736
736
    /* Check that the relocation came out OK. */
737
737
    /* NOTE: this check only works within a single chunk. */
738
738
    if ((byte *) src - (byte *) dest != r_size((ref *) src - 1) + sizeof(ref)) {
739
 
        lprintf3("Reloc error for refs 0x%lx: reloc = %lu, stored = %u\n",
740
 
                 (ulong) dpre, (ulong) ((byte *) src - (byte *) dest),
741
 
                 (uint) r_size((ref *) src - 1));
742
 
        gs_abort(mem);
 
739
        lprintf3("Reloc error for refs 0x%lx: reloc = %lu, stored = %u\n",
 
740
                 (ulong) dpre, (ulong) ((byte *) src - (byte *) dest),
 
741
                 (uint) r_size((ref *) src - 1));
 
742
        gs_abort(mem);
743
743
    }
744
744
#endif
745
745
    /* Pad to a multiple of sizeof(ref). */
746
746
    while (new_size & (sizeof(ref) - 1))
747
 
        *dest++ = pt_tag(pt_integer),
748
 
            new_size += sizeof(ref_packed);
 
747
        *dest++ = pt_tag(pt_integer),
 
748
            new_size += sizeof(ref_packed);
749
749
    /* We want to make the newly freed space into a free block, */
750
750
    /* but we can only do this if we have enough room. */
751
751
    if (size - new_size < sizeof(obj_header_t)) {       /* Not enough room.  Pad to original size. */
752
 
        while (new_size < size)
753
 
            *dest++ = pt_tag(pt_integer),
754
 
                new_size += sizeof(ref_packed);
 
752
        while (new_size < size)
 
753
            *dest++ = pt_tag(pt_integer),
 
754
                new_size += sizeof(ref_packed);
755
755
    } else {
756
 
        obj_header_t *pfree = (obj_header_t *) ((ref *) dest + 1);
 
756
        obj_header_t *pfree = (obj_header_t *) ((ref *) dest + 1);
757
757
 
758
 
        pfree->o_alone = 0;
759
 
        pfree->o_size = size - new_size - sizeof(obj_header_t);
760
 
        pfree->o_type = &st_bytes;
 
758
        pfree->o_alone = 0;
 
759
        pfree->o_size = size - new_size - sizeof(obj_header_t);
 
760
        pfree->o_type = &st_bytes;
761
761
    }
762
762
    /* Re-create the final ref. */
763
763
    r_set_type((ref *) dest, t_integer);