1*593dc095SDavid du Colombier /* Copyright (C) 1995, 1996, 1999, 2002 Aladdin Enterprises. All rights reserved. 27dd7cddfSDavid du Colombier 3*593dc095SDavid du Colombier This software is provided AS-IS with no warranty, either express or 4*593dc095SDavid du Colombier implied. 57dd7cddfSDavid du Colombier 6*593dc095SDavid du Colombier This software is distributed under license and may not be copied, 7*593dc095SDavid du Colombier modified or distributed except as expressly authorized under the terms 8*593dc095SDavid du Colombier of the license contained in the file LICENSE in this distribution. 97dd7cddfSDavid du Colombier 10*593dc095SDavid du Colombier For more information about licensing, please refer to 11*593dc095SDavid du Colombier http://www.ghostscript.com/licensing/. For information on 12*593dc095SDavid du Colombier commercial licensing, go to http://www.artifex.com/licensing/ or 13*593dc095SDavid du Colombier contact Artifex Software, Inc., 101 Lucas Valley Road #110, 14*593dc095SDavid du Colombier San Rafael, CA 94903, U.S.A., +1(415)492-9861. 157dd7cddfSDavid du Colombier */ 167dd7cddfSDavid du Colombier 17*593dc095SDavid du Colombier /* $Id: gxobj.h,v 1.7 2005/10/12 10:45:21 leonardo Exp $ */ 187dd7cddfSDavid du Colombier /* Memory manager implementation structures for Ghostscript */ 197dd7cddfSDavid du Colombier 207dd7cddfSDavid du Colombier #ifndef gxobj_INCLUDED 217dd7cddfSDavid du Colombier # define gxobj_INCLUDED 227dd7cddfSDavid du Colombier 237dd7cddfSDavid du Colombier #include "gxbitmap.h" 247dd7cddfSDavid du Colombier 25*593dc095SDavid du Colombier #ifdef DEBUG 26*593dc095SDavid du Colombier #define IGC_PTR_STABILITY_CHECK 0 27*593dc095SDavid du Colombier #else 28*593dc095SDavid du Colombier #define IGC_PTR_STABILITY_CHECK 0 29*593dc095SDavid du Colombier #endif 30*593dc095SDavid du Colombier 317dd7cddfSDavid du Colombier /* ================ Objects ================ */ 327dd7cddfSDavid du Colombier 337dd7cddfSDavid du Colombier /* 347dd7cddfSDavid du Colombier * Object headers have the form: 357dd7cddfSDavid du Colombier -l- -mark/back- 367dd7cddfSDavid du Colombier -size- 377dd7cddfSDavid du Colombier -type/reloc- 387dd7cddfSDavid du Colombier * l (aLone) is a single bit. Mark/back is 1 bit shorter than a uint. We 397dd7cddfSDavid du Colombier * round the header size up to the next multiple of the most severe 407dd7cddfSDavid du Colombier * alignment restriction (4 or 8 bytes). 417dd7cddfSDavid du Colombier * 427dd7cddfSDavid du Colombier * The mark/back field is used for the mark during the marking phase of 437dd7cddfSDavid du Colombier * garbage collection, and for a back pointer value during the compaction 447dd7cddfSDavid du Colombier * phase. Since we want to be able to collect local VM independently of 457dd7cddfSDavid du Colombier * global VM, we need two different distinguished mark values: 467dd7cddfSDavid du Colombier * - For local objects that have not been traced and should be freed 477dd7cddfSDavid du Colombier * (compacted out), we use 1...11 in the mark field (o_unmarked). 487dd7cddfSDavid du Colombier * - For global objects that have not been traced but should be kept, 497dd7cddfSDavid du Colombier * we use 1...10 in the mark field (o_untraced). 507dd7cddfSDavid du Colombier * Note that neither of these values is a possible real relocation value. 517dd7cddfSDavid du Colombier * 527dd7cddfSDavid du Colombier * The back pointer's meaning depends on whether the object is 537dd7cddfSDavid du Colombier * free (unmarked) or in use (marked): 547dd7cddfSDavid du Colombier * - In free objects, the back pointer is an offset from the object 557dd7cddfSDavid du Colombier * header back to a chunk_head_t structure that contains the location 567dd7cddfSDavid du Colombier * to which all the data in this chunk will get moved; the reloc field 577dd7cddfSDavid du Colombier * contains the amount by which the following run of useful objects 587dd7cddfSDavid du Colombier * will be relocated downwards. 597dd7cddfSDavid du Colombier * - In useful objects, the back pointer is an offset from the object 607dd7cddfSDavid du Colombier * back to the previous free object; the reloc field is not used (it 617dd7cddfSDavid du Colombier * overlays the type field). 627dd7cddfSDavid du Colombier * These two cases can be distinguished when scanning a chunk linearly, 637dd7cddfSDavid du Colombier * but when simply examining an object via a pointer, the chunk pointer 647dd7cddfSDavid du Colombier * is also needed. 657dd7cddfSDavid du Colombier */ 667dd7cddfSDavid du Colombier #define obj_flag_bits 1 677dd7cddfSDavid du Colombier #define obj_mb_bits (arch_sizeof_int * 8 - obj_flag_bits) 687dd7cddfSDavid du Colombier #define o_unmarked (((uint)1 << obj_mb_bits) - 1) 697dd7cddfSDavid du Colombier #define o_set_unmarked(pp)\ 707dd7cddfSDavid du Colombier ((pp)->o_smark = o_unmarked) 717dd7cddfSDavid du Colombier #define o_is_unmarked(pp)\ 727dd7cddfSDavid du Colombier ((pp)->o_smark == o_unmarked) 737dd7cddfSDavid du Colombier #define o_untraced (((uint)1 << obj_mb_bits) - 2) 747dd7cddfSDavid du Colombier #define o_set_untraced(pp)\ 757dd7cddfSDavid du Colombier ((pp)->o_smark = o_untraced) 767dd7cddfSDavid du Colombier #define o_is_untraced(pp)\ 777dd7cddfSDavid du Colombier ((pp)->o_smark == o_untraced) 787dd7cddfSDavid du Colombier #define o_marked 0 797dd7cddfSDavid du Colombier #define o_mark(pp)\ 807dd7cddfSDavid du Colombier ((pp)->o_smark = o_marked) 817dd7cddfSDavid du Colombier #define obj_back_shift obj_flag_bits 827dd7cddfSDavid du Colombier #define obj_back_scale (1 << obj_back_shift) 837dd7cddfSDavid du Colombier typedef struct obj_header_data_s { 847dd7cddfSDavid du Colombier union _f { 857dd7cddfSDavid du Colombier struct _h { 867dd7cddfSDavid du Colombier unsigned alone:1; 877dd7cddfSDavid du Colombier } h; 887dd7cddfSDavid du Colombier struct _m { 897dd7cddfSDavid du Colombier unsigned _:1, smark:obj_mb_bits; 907dd7cddfSDavid du Colombier } m; 917dd7cddfSDavid du Colombier struct _b { 927dd7cddfSDavid du Colombier unsigned _:1, back:obj_mb_bits; 937dd7cddfSDavid du Colombier } b; 947dd7cddfSDavid du Colombier } f; 957dd7cddfSDavid du Colombier uint size; 967dd7cddfSDavid du Colombier union _t { 977dd7cddfSDavid du Colombier gs_memory_type_ptr_t type; 987dd7cddfSDavid du Colombier uint reloc; 997dd7cddfSDavid du Colombier } t; 100*593dc095SDavid du Colombier # if IGC_PTR_STABILITY_CHECK 101*593dc095SDavid du Colombier unsigned space_id:3; /* r_space_bits + 1 bit for "instability". */ 102*593dc095SDavid du Colombier # endif 1037dd7cddfSDavid du Colombier } obj_header_data_t; 1047dd7cddfSDavid du Colombier 1057dd7cddfSDavid du Colombier /* 1067dd7cddfSDavid du Colombier * Define the alignment modulus for aligned objects. We assume all 1077dd7cddfSDavid du Colombier * alignment values are powers of 2; we can avoid nested 'max'es that way. 1087dd7cddfSDavid du Colombier * The final | is because back pointer values are divided by obj_back_scale, 1097dd7cddfSDavid du Colombier * so objects must be aligned at least 0 mod obj_back_scale. 110*593dc095SDavid du Colombier * 111*593dc095SDavid du Colombier * Note: OBJECTS ARE NOT GUARANTEED to be aligned any more strictly than 112*593dc095SDavid du Colombier * required by the hardware, regardless of the value of obj_align_mod. 113*593dc095SDavid du Colombier * See gsmemraw.h for more information about this. 1147dd7cddfSDavid du Colombier */ 1157dd7cddfSDavid du Colombier #define obj_align_mod\ 116*593dc095SDavid du Colombier (((arch_align_memory_mod - 1) |\ 117*593dc095SDavid du Colombier (align_bitmap_mod - 1) |\ 1187dd7cddfSDavid du Colombier (obj_back_scale - 1)) + 1) 1197dd7cddfSDavid du Colombier /* The only possible values for obj_align_mod are 4, 8, or 16.... */ 1207dd7cddfSDavid du Colombier #if obj_align_mod == 4 1217dd7cddfSDavid du Colombier # define log2_obj_align_mod 2 1227dd7cddfSDavid du Colombier #else 1237dd7cddfSDavid du Colombier #if obj_align_mod == 8 1247dd7cddfSDavid du Colombier # define log2_obj_align_mod 3 1257dd7cddfSDavid du Colombier #else 1267dd7cddfSDavid du Colombier #if obj_align_mod == 16 1277dd7cddfSDavid du Colombier # define log2_obj_align_mod 4 1287dd7cddfSDavid du Colombier #endif 1297dd7cddfSDavid du Colombier #endif 1307dd7cddfSDavid du Colombier #endif 1317dd7cddfSDavid du Colombier #define obj_align_mask (obj_align_mod-1) 1327dd7cddfSDavid du Colombier #define obj_align_round(siz)\ 1337dd7cddfSDavid du Colombier (uint)(((siz) + obj_align_mask) & -obj_align_mod) 1347dd7cddfSDavid du Colombier #define obj_size_round(siz)\ 1357dd7cddfSDavid du Colombier obj_align_round((siz) + sizeof(obj_header_t)) 1367dd7cddfSDavid du Colombier 1377dd7cddfSDavid du Colombier /* Define the real object header type, taking alignment into account. */ 1387dd7cddfSDavid du Colombier struct obj_header_s { /* must be a struct because of forward reference */ 1397dd7cddfSDavid du Colombier union _d { 1407dd7cddfSDavid du Colombier obj_header_data_t o; 1417dd7cddfSDavid du Colombier byte _pad[ROUND_UP(sizeof(obj_header_data_t), obj_align_mod)]; 1427dd7cddfSDavid du Colombier } 1437dd7cddfSDavid du Colombier d; 1447dd7cddfSDavid du Colombier }; 1457dd7cddfSDavid du Colombier 1467dd7cddfSDavid du Colombier /* Define some reasonable abbreviations for the fields. */ 1477dd7cddfSDavid du Colombier #define o_alone d.o.f.h.alone 1487dd7cddfSDavid du Colombier #define o_back d.o.f.b.back 1497dd7cddfSDavid du Colombier #define o_smark d.o.f.m.smark 1507dd7cddfSDavid du Colombier #define o_size d.o.size 1517dd7cddfSDavid du Colombier #define o_type d.o.t.type 1527dd7cddfSDavid du Colombier #define o_nreloc d.o.t.reloc 1537dd7cddfSDavid du Colombier 1547dd7cddfSDavid du Colombier /* 1557dd7cddfSDavid du Colombier * The macros for getting the sizes of objects all take pointers to 1567dd7cddfSDavid du Colombier * the object header, for use when scanning storage linearly. 1577dd7cddfSDavid du Colombier */ 1587dd7cddfSDavid du Colombier #define pre_obj_contents_size(pp)\ 1597dd7cddfSDavid du Colombier ((pp)->o_size) 1607dd7cddfSDavid du Colombier 1617dd7cddfSDavid du Colombier #define pre_obj_rounded_size(pp)\ 1627dd7cddfSDavid du Colombier obj_size_round(pre_obj_contents_size(pp)) 1637dd7cddfSDavid du Colombier #define pre_obj_next(pp)\ 1647dd7cddfSDavid du Colombier ((obj_header_t *)((byte *)(pp) + obj_align_round(\ 1657dd7cddfSDavid du Colombier pre_obj_contents_size(pp) + sizeof(obj_header_t) ))) 1667dd7cddfSDavid du Colombier 1677dd7cddfSDavid du Colombier /* 1687dd7cddfSDavid du Colombier * Define the header that free objects point back to when relocating. 1697dd7cddfSDavid du Colombier * Every chunk, including inner chunks, has one of these. 1707dd7cddfSDavid du Colombier */ 1717dd7cddfSDavid du Colombier typedef struct chunk_head_s { 1727dd7cddfSDavid du Colombier byte *dest; /* destination for objects */ 1737dd7cddfSDavid du Colombier #if obj_align_mod > arch_sizeof_ptr 1747dd7cddfSDavid du Colombier byte *_pad[obj_align_mod / arch_sizeof_ptr - 1]; 1757dd7cddfSDavid du Colombier #endif 1767dd7cddfSDavid du Colombier obj_header_t free; /* header for a free object, */ 1777dd7cddfSDavid du Colombier /* in case the first real object */ 1787dd7cddfSDavid du Colombier /* is in use */ 1797dd7cddfSDavid du Colombier } chunk_head_t; 1807dd7cddfSDavid du Colombier 1817dd7cddfSDavid du Colombier #endif /* gxobj_INCLUDED */ 182