gc_typed.h raw

   1  /*
   2   * Copyright 1988, 1989 Hans-J. Boehm, Alan J. Demers
   3   * Copyright (c) 1991-1994 by Xerox Corporation.  All rights reserved.
   4   * Copyright 1996 Silicon Graphics.  All rights reserved.
   5   *
   6   * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
   7   * OR IMPLIED.  ANY USE IS AT YOUR OWN RISK.
   8   *
   9   * Permission is hereby granted to use or copy this program
  10   * for any purpose, provided the above notices are retained on all copies.
  11   * Permission to modify the code and to distribute modified code is granted,
  12   * provided the above notices are retained, and a notice that the code was
  13   * modified is included with the above copyright notice.
  14   */
  15  
  16  /*
  17   * Some simple primitives for allocation with explicit type information.
  18   * Facilities for dynamic type inference may be added later.
  19   * Should be used only for extremely performance critical applications,
  20   * or if conservative collector leakage is otherwise a problem (unlikely).
  21   * Note that this is implemented completely separately from the rest
  22   * of the collector, and is not linked in unless referenced.
  23   * This does not currently support `GC_DEBUG` in any interesting way.
  24   *
  25   * Note for cris and m68k architectures (and for bcc and wcc compilers):
  26   * this API expects all pointers in the type (`T`) are aligned by the size
  27   * of a pointer (which might differ from `ALIGNMENT`).
  28   */
  29  
  30  #ifndef GC_TYPED_H
  31  #define GC_TYPED_H
  32  
  33  #ifndef GC_H
  34  #  include "gc.h"
  35  #endif
  36  
  37  #ifdef __cplusplus
  38  extern "C" {
  39  #endif
  40  
  41  /** The size of `GC_word` (not a pointer) type in bits. */
  42  #define GC_WORDSZ (8 * sizeof(GC_word))
  43  
  44  /** The size of a type `t` in pointers.  The value is rounded down. */
  45  #define GC_SIZEOF_IN_PTRS(t) (sizeof(t) / sizeof(void *))
  46  
  47  /** The offset of a field in pointers. */
  48  #define GC_OFFSETOF_IN_PTRS(t, f) (offsetof(t, f) / sizeof(void *))
  49  
  50  /**
  51   * The bitmap type.  The least significant bit of the first `GC_word` is one
  52   * if the first "pointer-sized" word in the object may be a pointer.
  53   */
  54  typedef GC_word *GC_bitmap;
  55  
  56  /**
  57   * The number of elements (of `GC_word` type) of a bitmap array to
  58   * create for a given type `t`.  The bitmap is intended to be passed to
  59   * `GC_make_descriptor()`.
  60   */
  61  #define GC_BITMAP_SIZE(t) ((GC_SIZEOF_IN_PTRS(t) + GC_WORDSZ - 1) / GC_WORDSZ)
  62  
  63  /**
  64   * The setter and getter of the bitmap.  The `bm` argument should be of
  65   * `GC_bitmap` type; `i` argument should be of some `unsigned` type and
  66   * should not have side effects.
  67   */
  68  #define GC_set_bit(bm, i) \
  69    ((bm)[(i) / GC_WORDSZ] |= (GC_word)1 << ((i) % GC_WORDSZ))
  70  #define GC_get_bit(bm, i) (((bm)[(i) / GC_WORDSZ] >> ((i) % GC_WORDSZ)) & 1)
  71  
  72  typedef GC_word GC_descr;
  73  
  74  /**
  75   * Return a type descriptor for the object whose layout is described
  76   * by the first argument.  The least significant bit of the first
  77   * `GC_word` is one if the first "pointer-sized" word in the object may
  78   * be a pointer.  The second argument (`number_of_bits_in_bitmap`)
  79   * specifies the number of meaningful bits in the bitmap.
  80   * The actual object may be larger (but not smaller); any additional
  81   * "pointer-sized" words in the object are assumed not to contain
  82   * pointers.  Returns a conservative approximation in the (unlikely)
  83   * case of insufficient memory to build the descriptor.  Calls to
  84   * `GC_make_descriptor()` may consume some amount of a finite resource.
  85   * This is intended to be called once per a type, not once per an
  86   * allocation.
  87   *
  88   * It is possible to generate a descriptor for a client type `T` with
  89   * aligned pointer fields `f1`, `f2`, ... as follows:
  90   * ```
  91   *   GC_descr t_descr;
  92   *   {
  93   *     GC_word bm[GC_BITMAP_SIZE(T)] = { 0 };
  94   *     GC_set_bit(bm, GC_OFFSETOF_IN_PTRS(T, f1));
  95   *     GC_set_bit(bm, GC_OFFSETOF_IN_PTRS(T, f2));
  96   *     ...
  97   *     t_descr = GC_make_descriptor(bm, GC_SIZEOF_IN_PTRS(T));
  98   *   }
  99   * ```
 100   */
 101  GC_API GC_descr GC_CALL
 102  GC_make_descriptor(const GC_word * /* `GC_bitmap` `bm` */,
 103                     size_t /* `number_of_bits_in_bitmap` */);
 104  
 105  /**
 106   * Allocate an object whose layout is described by `d`.  The size
 107   * (`size_in_bytes`) may *not* be less than the number of meaningful
 108   * bits in the bitmap of `d` multiplied by the size of a pointer.
 109   * The returned object is cleared.  The returned object may *not* be
 110   * passed to `GC_realloc()`.
 111   */
 112  GC_API GC_ATTR_MALLOC GC_ATTR_ALLOC_SIZE(1) void *GC_CALL
 113      GC_malloc_explicitly_typed(size_t /* `size_in_bytes` */,
 114                                 GC_descr /* `d` */);
 115  
 116  /** The ignore-off-page variant of `GC_malloc_explicitly_typed()`. */
 117  GC_API GC_ATTR_MALLOC GC_ATTR_ALLOC_SIZE(1) void *GC_CALL
 118      GC_malloc_explicitly_typed_ignore_off_page(size_t /* `size_in_bytes` */,
 119                                                 GC_descr /* `d` */);
 120  
 121  /**
 122   * Allocate an array of `nelements` elements, each of the given size
 123   * (`element_size_in_bytes`), and with the given descriptor (`d`).
 124   * The element size must be a multiple of the byte alignment required
 125   * for pointers.  (E.g. on a 32-bit machine with 16-bit aligned
 126   * pointers, `element_size_in_bytes` must be a multiple of 2.)
 127   * The element size may *not* be less than the number of meaningful
 128   * bits in the bitmap of `d` multiplied by the size of a pointer.
 129   * The returned object is cleared.
 130   */
 131  GC_API GC_ATTR_MALLOC GC_ATTR_CALLOC_SIZE(1, 2) void *GC_CALL
 132      GC_calloc_explicitly_typed(size_t /* `nelements` */,
 133                                 size_t /* `element_size_in_bytes` */,
 134                                 GC_descr /* d */);
 135  
 136  #define GC_CALLOC_TYPED_DESCR_PTRS 1
 137  #define GC_CALLOC_TYPED_DESCR_WORDS 8 /*< includes space for pointers */
 138  
 139  #ifdef GC_BUILD
 140  struct GC_calloc_typed_descr_s;
 141  #  define GC_calloc_typed_descr_s GC_calloc_typed_descr_opaque_s
 142  #endif
 143  
 144  struct GC_calloc_typed_descr_s {
 145    GC_uintptr_t opaque_p[GC_CALLOC_TYPED_DESCR_PTRS];
 146    GC_word opaque[GC_CALLOC_TYPED_DESCR_WORDS - GC_CALLOC_TYPED_DESCR_PTRS];
 147  };
 148  #undef GC_calloc_typed_descr_s
 149  
 150  /**
 151   * This is same as `GC_calloc_explicitly_typed` but more optimal in
 152   * terms of the performance and memory usage if the client needs to
 153   * allocate multiple typed object arrays with the same layout and
 154   * number of elements.  The client should call it to be prepared for
 155   * the subsequent allocations by `GC_calloc_do_explicitly_typed()`, one
 156   * or many.  The result of the preparation is stored to `*pctd`, even
 157   * in case of a failure.  The prepared structure could be just dropped
 158   * when no longer needed.  Returns 0 on failure, 1 on success; the
 159   * result could be ignored (as it is also stored to `*pctd` and checked
 160   * later by `GC_calloc_do_explicitly_typed()`).
 161   */
 162  GC_API int GC_CALL GC_calloc_prepare_explicitly_typed(
 163      struct GC_calloc_typed_descr_s * /* `pctd` */, size_t /* `sizeof_ctd` */,
 164      size_t /* `nelements` */, size_t /* `element_size_in_bytes` */, GC_descr);
 165  
 166  /** The actual object allocation for the prepared description. */
 167  GC_API GC_ATTR_MALLOC void *GC_CALL GC_calloc_do_explicitly_typed(
 168      const struct GC_calloc_typed_descr_s * /* `pctd` */,
 169      size_t /* `sizeof_ctd` */);
 170  
 171  #ifdef GC_DEBUG
 172  #  define GC_MALLOC_EXPLICITLY_TYPED(bytes, d) ((void)(d), GC_MALLOC(bytes))
 173  #  define GC_MALLOC_EXPLICITLY_TYPED_IGNORE_OFF_PAGE(bytes, d) \
 174      GC_MALLOC_EXPLICITLY_TYPED(bytes, d)
 175  #  define GC_CALLOC_EXPLICITLY_TYPED(n, bytes, d) \
 176      ((void)(d), GC_MALLOC((n) * (bytes)))
 177  #else
 178  #  define GC_MALLOC_EXPLICITLY_TYPED(bytes, d) \
 179      GC_malloc_explicitly_typed(bytes, d)
 180  #  define GC_MALLOC_EXPLICITLY_TYPED_IGNORE_OFF_PAGE(bytes, d) \
 181      GC_malloc_explicitly_typed_ignore_off_page(bytes, d)
 182  #  define GC_CALLOC_EXPLICITLY_TYPED(n, bytes, d) \
 183      GC_calloc_explicitly_typed(n, bytes, d)
 184  #endif
 185  
 186  /* Deprecated.  Use `GC_SIZEOF_IN_PTRS()` instead. */
 187  #define GC_WORD_LEN(t) GC_SIZEOF_IN_PTRS(t)
 188  
 189  /* Deprecated.  Use `GC_OFFSETOF_IN_PTRS()` instead. */
 190  #define GC_WORD_OFFSET(t, f) GC_OFFSETOF_IN_PTRS(t, f)
 191  
 192  #ifdef __cplusplus
 193  } /* extern "C" */
 194  #endif
 195  
 196  #endif /* GC_TYPED_H */
 197