home *** CD-ROM | disk | FTP | other *** search
/ PC World Komputer 1996 February / PCWK0296.iso / sharewar / dos / program / gs300sr1 / gs300sr1.exe / IASTRUCT.H < prev    next >
C/C++ Source or Header  |  1994-07-27  |  8KB  |  200 lines

  1. /* Copyright (C) 1993, 1994 Aladdin Enterprises.  All rights reserved.
  2.   
  3.   This file is part of Aladdin Ghostscript.
  4.   
  5.   Aladdin Ghostscript is distributed with NO WARRANTY OF ANY KIND.  No author
  6.   or distributor accepts any responsibility for the consequences of using it,
  7.   or for whether it serves any particular purpose or works at all, unless he
  8.   or she says so in writing.  Refer to the Aladdin Ghostscript Free Public
  9.   License (the "License") for full details.
  10.   
  11.   Every copy of Aladdin Ghostscript must include a copy of the License,
  12.   normally in a plain ASCII text file named PUBLIC.  The License grants you
  13.   the right to copy, modify and redistribute Aladdin Ghostscript, but only
  14.   under certain conditions described in the License.  Among other things, the
  15.   License requires that the copyright notice and this notice be preserved on
  16.   all copies.
  17. */
  18.  
  19. /* iastruct.h */
  20. /* Memory manager implementation structures for Ghostscript */
  21. #include "gxbitmap.h"
  22. #include "ialloc.h"
  23.  
  24. /* ================ Objects ================ */
  25.  
  26. /*
  27.  * Object headers come in a number of different varieties.
  28.  * All arise from the same basic form, which is
  29.     -l- -lmsize/mark/back-
  30.     -size-
  31.     -type/reloc-
  32.  * l (large) is a single bit.  The size of lmsize/mark/back, size, and type
  33.  * varies according to the environment.  On machines with N:16 segmented
  34.  * addressing, 16-bit ints, and no alignment requirement more severe than
  35.  * 2 bytes, we can squeeze an object header into 6 bytes by making these
  36.  * fields 16 bits (using _ds addressing).  On all other machines, we let the
  37.  * lmsize/mark/back field be 1 bit shorter than a uint, and round the header
  38.  * size up to the next multiple of the most severe alignment restriction
  39.  * (4 or 8 bytes).  Miraculously, we can do all this without any case testing.
  40.  *
  41.  * The mark/back field is used for the mark during the marking phase of
  42.  * garbage collection, and for a back pointer value during the compaction
  43.  * phase.  Since we want to be able to collect local VM independently of
  44.  * global VM, we need two different distinguished mark values:
  45.  *    - For local objects that have not been traced and should be freed
  46.  *    (compacted out), we use 1...11 in the mark field (o_unmarked).
  47.  *    - For global objects that have not been traced but should be kept,
  48.  *    we use 1...10 in the mark field (o_untraced).
  49.  * Note that neither of these values is a possible real relocation value.
  50.  *
  51.  * The lmsize field of large objects overlaps mark and back, so we must
  52.  * handle these functions for large objects in some other way.
  53.  * Since large objects cannot be moved or relocated, we don't need the
  54.  * back field for them; we allocate 2 bits for the 3 mark values.
  55.  */
  56. /*
  57.  * The back pointer's meaning depends on whether the object is
  58.  * free (unmarked) or in use (marked):
  59.  *    - In free objects, the back pointer is an offset from the object
  60.  * header back to a chunk_head_t structure that contains the location
  61.  * to which all the data in this chunk will get moved; the reloc field
  62.  * contains the amount by which the following run of useful objects
  63.  * will be relocated downwards.
  64.  *    - In useful objects, the back pointer is an offset from the object
  65.  * back to the previous free object; the reloc field is not used (it
  66.  * overlays the type field).
  67.  * These two cases can be distinguished when scanning a chunk linearly,
  68.  * but when simply examining an object via a pointer, the chunk pointer
  69.  * is also needed.
  70.  */
  71. #define obj_flag_bits 1
  72. #define obj_mb_bits (arch_sizeof_int * 8 - obj_flag_bits)
  73. #define obj_ls_bits (obj_mb_bits - 2)
  74. #define o_unmarked (((uint)1 << obj_mb_bits) - 1)
  75. #define o_l_unmarked (o_unmarked & 3)
  76. #define o_set_unmarked_large(pp) (pp)->o_lmark = o_l_unmarked
  77. #define o_set_unmarked(pp)\
  78.   if ( (pp)->o_large ) o_set_unmarked_large(pp);\
  79.   else (pp)->o_smark = o_unmarked
  80. #define o_is_unmarked_large(pp) ((pp)->o_lmark == o_l_unmarked)
  81. #define o_is_unmarked(pp)\
  82.  ((pp)->o_large ? o_is_unmarked_large(pp) :\
  83.   ((pp)->o_smark == o_unmarked))
  84. #define o_untraced (((uint)1 << obj_mb_bits) - 2)
  85. #define o_l_untraced (o_untraced & 3)
  86. #define o_set_untraced(pp)\
  87.   if ( (pp)->o_large ) (pp)->o_lmark = o_l_untraced;\
  88.   else (pp)->o_smark = o_untraced
  89. #define o_is_untraced(pp)\
  90.  ((pp)->o_large ? (pp)->o_lmark == o_l_untraced :\
  91.   ((pp)->o_smark == o_untraced))
  92. #define o_marked 0
  93. #define o_mark_large(pp) (pp)->o_lmark = o_marked
  94. #define o_mark(pp)\
  95.   if ( (pp)->o_large ) o_mark_large(pp);\
  96.   else (pp)->o_smark = o_marked
  97. #define obj_back_shift obj_flag_bits
  98. #define obj_back_scale (1 << obj_back_shift)
  99. typedef struct obj_header_data_s {
  100.     union _f {
  101.       struct _h { unsigned large : 1; } h;
  102.       struct _l { unsigned _ : 1, lmark : 2, lsize : obj_ls_bits; } l;
  103.       struct _m { unsigned _ : 1, smark : obj_mb_bits; } m;
  104.       struct _b { unsigned _ : 1, back : obj_mb_bits; } b;
  105.     } f;
  106.     uint size;
  107.     union _t {
  108.       gs_memory_type_ptr_t type;
  109.       uint reloc;
  110.     } t;
  111. } obj_header_data_t;
  112.  
  113. /*
  114.  * Define the alignment modulus for aligned objects.  We assume all
  115.  * alignment values are powers of 2; we can avoid nested 'max'es that way.
  116.  * The final | is because back pointer values are divided by obj_back_scale,
  117.  * so objects must be aligned at least 0 mod obj_back_scale.
  118.  */
  119. #define obj_align_mod\
  120.   (((arch_align_long_mod - 1) | (arch_align_ptr_mod - 1) |\
  121.     (arch_align_double_mod - 1) | (align_bitmap_mod - 1) |\
  122.     (obj_back_scale - 1)) + 1)
  123. #define log2_obj_align_mod small_exact_log2(obj_align_mod)
  124. #define obj_align_mask (obj_align_mod-1)
  125. #define obj_align_round(siz)\
  126.   (uint)(((siz) + obj_align_mask) & -obj_align_mod)
  127. #define obj_size_round(siz)\
  128.   obj_align_round((siz) + sizeof(obj_header_t))
  129.  
  130. /* Define the real object header type, taking alignment into account. */
  131. struct obj_header_s {    /* must be a struct because of forward reference */
  132.     union _d {
  133.         obj_header_data_t o;
  134.         byte _pad[round_up(sizeof(obj_header_data_t), obj_align_mod)];
  135.     } d;
  136. };
  137.  
  138. /* Define some reasonable abbreviations for the fields. */
  139. #define o_large d.o.f.h.large
  140. #define o_lsize d.o.f.l.lsize
  141. #define o_lmark d.o.f.l.lmark
  142. #define o_back d.o.f.b.back
  143. #define o_smark d.o.f.m.smark
  144. #define o_size d.o.size
  145. #define o_type d.o.t.type
  146. #define o_nreloc d.o.t.reloc
  147.  
  148. /*
  149.  * The macros for getting the sizes of objects all take pointers to
  150.  * the object header, for use when scanning storage linearly.
  151.  */
  152. #define pre_obj_small_size(pp)\
  153.   ((pp)->o_size)
  154.  
  155. #if arch_sizeof_long > arch_sizeof_int
  156.  
  157.     /* Large objects need to use o_lsize. */
  158.  
  159. #define pre_obj_large_size(pp)\
  160.   (((ulong)(pp)->o_lsize << (arch_sizeof_int * 8)) + (pp)->o_size)
  161. #define pre_obj_set_large_size(pp, lsize)\
  162.   ((pp)->o_lsize = (lsize) >> (arch_sizeof_int * 8),\
  163.    (pp)->o_size = (uint)(lsize))
  164. #define pre_obj_contents_size(pp)\
  165.   ((pp)->o_large ? pre_obj_large_size(pp) : pre_obj_small_size(pp))
  166.  
  167. #else
  168.  
  169.     /* Large objects don't need to use o_lsize. */
  170.  
  171. #define pre_obj_large_size(pp)\
  172.   pre_obj_small_size(pp)
  173. #define pre_obj_set_large_size(pp, lsize)\
  174.   ((pp)->o_lsize = 0,\
  175.    (pp)->o_size = (lsize))
  176. #define pre_obj_contents_size(pp)\
  177.   pre_obj_small_size(pp)
  178.  
  179. #endif
  180.  
  181. #define pre_obj_rounded_size(pp)\
  182.   obj_size_round(pre_obj_contents_size(pp))
  183. #define pre_obj_next(pp)\
  184.   ((obj_header_t *)((byte *)(pp) + obj_align_round(\
  185.     pre_obj_contents_size(pp) + sizeof(obj_header_t) )))
  186.  
  187. /*
  188.  * Define the header that free objects point back to when relocating.
  189.  * Every chunk, including inner chunks, has one of these.
  190.  */
  191. typedef struct chunk_head_s {
  192.     byte *dest;            /* destination for objects */
  193. #if obj_align_mod > arch_sizeof_ptr
  194.     byte *_pad[obj_align_mod / arch_sizeof_ptr - 1];
  195. #endif
  196.     obj_header_t free;        /* header for a free object, */
  197.                     /* in case the first real object */
  198.                     /* is in use */
  199. } chunk_head_t;
  200.