summaryrefslogtreecommitdiff
path: root/include/gc/gc_typed.h
blob: a9a829311c3304cf9983ecb36ae64eb63999b728 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
/*
 * Copyright 1988, 1989 Hans-J. Boehm, Alan J. Demers
 * Copyright (c) 1991-1994 by Xerox Corporation.  All rights reserved.
 * Copyright 1996 Silicon Graphics.  All rights reserved.
 *
 * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
 * OR IMPLIED.  ANY USE IS AT YOUR OWN RISK.
 *
 * Permission is hereby granted to use or copy this program
 * for any purpose, provided the above notices are retained on all copies.
 * Permission to modify the code and to distribute modified code is granted,
 * provided the above notices are retained, and a notice that the code was
 * modified is included with the above copyright notice.
 */

/*
 * Some simple primitives for allocation with explicit type information.
 * Facilities for dynamic type inference may be added later.
 * Should be used only for extremely performance critical applications,
 * or if conservative collector leakage is otherwise a problem (unlikely).
 * Note that this is implemented completely separately from the rest
 * of the collector, and is not linked in unless referenced.
 * This does not currently support GC_DEBUG in any interesting way.
 */

#ifndef GC_TYPED_H
#define GC_TYPED_H

#ifndef GC_H
# include "gc.h"
#endif

#ifdef __cplusplus
  extern "C" {
#endif

typedef GC_word * GC_bitmap;
        /* The least significant bit of the first word is one if        */
        /* the first word in the object may be a pointer.               */

#define GC_WORDSZ (8 * sizeof(GC_word))
#define GC_get_bit(bm, index) \
            (((bm)[(index) / GC_WORDSZ] >> ((index) % GC_WORDSZ)) & 1)
#define GC_set_bit(bm, index) \
            ((bm)[(index) / GC_WORDSZ] |= (GC_word)1 << ((index) % GC_WORDSZ))
#define GC_WORD_OFFSET(t, f) (offsetof(t,f) / sizeof(GC_word))
#define GC_WORD_LEN(t) (sizeof(t) / sizeof(GC_word))
#define GC_BITMAP_SIZE(t) ((GC_WORD_LEN(t) + GC_WORDSZ - 1) / GC_WORDSZ)

typedef GC_word GC_descr;

GC_API GC_descr GC_CALL GC_make_descriptor(const GC_word * /* GC_bitmap bm */,
                                size_t /* len (number_of_bits_in_bitmap) */);
                /* Return a type descriptor for the object whose layout */
                /* is described by the argument.                        */
                /* The least significant bit of the first word is one   */
                /* if the first word in the object may be a pointer.    */
                /* The second argument specifies the number of          */
                /* meaningful bits in the bitmap.  The actual object    */
                /* may be larger (but not smaller).  Any additional     */
                /* words in the object are assumed not to contain       */
                /* pointers.                                            */
                /* Returns a conservative approximation in the          */
                /* (unlikely) case of insufficient memory to build      */
                /* the descriptor.  Calls to GC_make_descriptor         */
                /* may consume some amount of a finite resource.  This  */
                /* is intended to be called once per type, not once     */
                /* per allocation.                                      */

/* It is possible to generate a descriptor for a C type T with  */
/* word aligned pointer fields f1, f2, ... as follows:                  */
/*                                                                      */
/* GC_descr T_descr;                                                    */
/* GC_word T_bitmap[GC_BITMAP_SIZE(T)] = {0};                           */
/* GC_set_bit(T_bitmap, GC_WORD_OFFSET(T,f1));                          */
/* GC_set_bit(T_bitmap, GC_WORD_OFFSET(T,f2));                          */
/* ...                                                                  */
/* T_descr = GC_make_descriptor(T_bitmap, GC_WORD_LEN(T));              */

GC_API GC_ATTR_MALLOC GC_ATTR_ALLOC_SIZE(1) void * GC_CALL
        GC_malloc_explicitly_typed(size_t /* size_in_bytes */,
                                   GC_descr /* d */);
                /* Allocate an object whose layout is described by d.   */
                /* The size may NOT be less than the number of          */
                /* meaningful bits in the bitmap of d multiplied by     */
                /* sizeof GC_word.  The returned object is cleared.     */
                /* The returned object may NOT be passed to GC_realloc. */

GC_API GC_ATTR_MALLOC GC_ATTR_ALLOC_SIZE(1) void * GC_CALL
        GC_malloc_explicitly_typed_ignore_off_page(size_t /* size_in_bytes */,
                                                   GC_descr /* d */);

GC_API GC_ATTR_MALLOC GC_ATTR_CALLOC_SIZE(1, 2) void * GC_CALL
        GC_calloc_explicitly_typed(size_t /* nelements */,
                                   size_t /* element_size_in_bytes */,
                                   GC_descr /* d */);
        /* Allocate an array of nelements elements, each of the */
        /* given size, and with the given descriptor.           */
        /* The element size must be a multiple of the byte      */
        /* alignment required for pointers.  E.g. on a 32-bit   */
        /* machine with 16-bit aligned pointers, size_in_bytes  */
        /* must be a multiple of 2.  The element size may NOT   */
        /* be less than the number of meaningful bits in the    */
        /* bitmap of d multiplied by sizeof GC_word.            */
        /* Returned object is cleared.                          */

#define GC_CALLOC_TYPED_DESCR_WORDS 8

#ifdef GC_BUILD
  struct GC_calloc_typed_descr_s;
#else
  struct GC_calloc_typed_descr_s {
    GC_word opaque[GC_CALLOC_TYPED_DESCR_WORDS];
  };
#endif

GC_API int GC_CALL GC_calloc_prepare_explicitly_typed(
                        struct GC_calloc_typed_descr_s * /* pctd */,
                        size_t /* sizeof_ctd */, size_t /* nelements */,
                        size_t /* element_size_in_bytes */, GC_descr);
        /* This is same as GC_calloc_explicitly_typed but more optimal  */
        /* in terms of the performance and memory usage if the client   */
        /* needs to allocate multiple typed object arrays with the      */
        /* same layout and number of elements.  The client should call  */
        /* it to be prepared for the subsequent allocations by          */
        /* GC_calloc_do_explicitly_typed, one or many.  The result of   */
        /* the preparation is stored to *pctd, even in case of          */
        /* a failure.  The prepared structure could be just dropped     */
        /* when no longer needed.  Returns 0 on failure, 1 on success;  */
        /* the result could be ignored (as it is also stored to *pctd   */
        /* and checked later by GC_calloc_do_explicitly_typed).         */

GC_API GC_ATTR_MALLOC void * GC_CALL GC_calloc_do_explicitly_typed(
                        const struct GC_calloc_typed_descr_s * /* pctd */,
                        size_t /* sizeof_ctd */);
        /* The actual object allocation for the prepared description.   */

#ifdef GC_DEBUG
# define GC_MALLOC_EXPLICITLY_TYPED(bytes, d) ((void)(d), GC_MALLOC(bytes))
# define GC_MALLOC_EXPLICITLY_TYPED_IGNORE_OFF_PAGE(bytes, d) \
                        GC_MALLOC_EXPLICITLY_TYPED(bytes, d)
# define GC_CALLOC_EXPLICITLY_TYPED(n, bytes, d) \
                        ((void)(d), GC_MALLOC((n) * (bytes)))
#else
# define GC_MALLOC_EXPLICITLY_TYPED(bytes, d) \
                        GC_malloc_explicitly_typed(bytes, d)
# define GC_MALLOC_EXPLICITLY_TYPED_IGNORE_OFF_PAGE(bytes, d) \
                        GC_malloc_explicitly_typed_ignore_off_page(bytes, d)
# define GC_CALLOC_EXPLICITLY_TYPED(n, bytes, d) \
                        GC_calloc_explicitly_typed(n, bytes, d)
#endif

#ifdef __cplusplus
  } /* extern "C" */
#endif

#endif /* GC_TYPED_H */