comparison src/lrecord.h @ 211:78478c60bfcd r20-4b4

Import from CVS: tag r20-4b4
author cvs
date Mon, 13 Aug 2007 10:05:51 +0200
parents e45d5e7c476e
children 78f53ef88e17
comparison
equal deleted inserted replaced
210:49f55ca3ba57 211:78478c60bfcd
27 /* The "lrecord" type of Lisp object is used for all object types 27 /* The "lrecord" type of Lisp object is used for all object types
28 other than a few simple ones. This allows many types to be 28 other than a few simple ones. This allows many types to be
29 implemented but only a few bits required in a Lisp object for 29 implemented but only a few bits required in a Lisp object for
30 type information. (The tradeoff is that each object has its 30 type information. (The tradeoff is that each object has its
31 type marked in it, thereby increasing its size.) The first 31 type marked in it, thereby increasing its size.) The first
32 four bytes of all lrecords is a pointer to a struct 32 four bytes of all lrecords is either a pointer to a struct
33 lrecord_implementation, which contains methods describing 33 lrecord_implementation, which contains methods describing how
34 how to process this object. 34 to process this object, or an index into an array of pointers
35 to struct lrecord_implementations plus some other data bits.
35 36
36 lrecords are of two types: straight lrecords, and lcrecords. 37 lrecords are of two types: straight lrecords, and lcrecords.
37 Straight lrecords are used for those types of objects that 38 Straight lrecords are used for those types of objects that
38 have their own allocation routines (typically allocated out 39 have their own allocation routines (typically allocated out of
39 of 2K chunks of memory). These objects have a 40 2K chunks of memory). These objects have a `struct
40 `struct lrecord_header' at the top, containing only the 41 lrecord_header' at the top, containing only the bits needed to
41 implementation pointer. There are special routines in alloc.c 42 find the lrecord_implementation for the object. There are
42 to deal with each such object type. 43 special routines in alloc.c to deal with each such object
44 type.
43 45
44 Lcrecords are used for less common sorts of objects that don't 46 Lcrecords are used for less common sorts of objects that don't
45 do their own allocation. Each such object is malloc()ed 47 do their own allocation. Each such object is malloc()ed
46 individually, and the objects are chained together through 48 individually, and the objects are chained together through
47 a `next' pointer. Lcrecords have a `struct lcrecord_header' 49 a `next' pointer. Lcrecords have a `struct lcrecord_header'
48 at the top, which contains an implementation pointer and 50 at the top, which contains a `struct lrecord_header' and
49 a `next' pointer, and are allocated using alloc_lcrecord(). 51 a `next' pointer, and are allocated using alloc_lcrecord().
50 52
51 Creating a new lcrecord type is fairly easy; just follow the 53 Creating a new lcrecord type is fairly easy; just follow the
52 lead of some existing type (e.g. hashtables). Note that you 54 lead of some existing type (e.g. hashtables). Note that you
53 do not need to supply all the methods (see below); reasonable 55 do not need to supply all the methods (see below); reasonable
78 read and a comparison against a variable value. (Variable since 80 read and a comparison against a variable value. (Variable since
79 it is a very good idea to assign the indices into the hypothetical 81 it is a very good idea to assign the indices into the hypothetical
80 type-code table dynamically rather that pre-defining them.) 82 type-code table dynamically rather that pre-defining them.)
81 I think I remember that Elk Lisp does something like this. 83 I think I remember that Elk Lisp does something like this.
82 Gee, I wonder if some cretin has patented it? */ 84 Gee, I wonder if some cretin has patented it? */
85
86 /*
87 * If USE_INDEXED_LRECORD_IMPLEMENTATION is defined, we are
88 * implementing the scheme described in the 'It would be better
89 * ...' paragraph above.
90 */
91 #ifdef USE_INDEXED_LRECORD_IMPLEMENTATION
92 /* index into lrecord_implementations_table[] */
93 unsigned type:8;
94 /* 1 if the object is marked during GC, 0 otherwise. */
95 unsigned mark:1;
96 /* 1 if the object was resides in pure (read-only) space */
97 unsigned pure:1;
98 #else
83 CONST struct lrecord_implementation *implementation; 99 CONST struct lrecord_implementation *implementation;
100 #endif
84 }; 101 };
85 #define set_lheader_implementation(header,imp) (header)->implementation=(imp) 102
103 #ifdef USE_INDEXED_LRECORD_IMPLEMENTATION
104 # define set_lheader_implementation(header,imp) \
105 do { (header)->type = lrecord_type_index((imp)) \
106 (header)->mark = 0; \
107 (header)->pure = 0; \
108 } while (0)
109 #else
110 # define set_lheader_implementation(header,imp) (header)->implementation=(imp)
111 #endif
86 112
87 struct lcrecord_header 113 struct lcrecord_header
88 { 114 {
89 struct lrecord_header lheader; 115 struct lrecord_header lheader;
90 /* The "next" field is normally used to chain all lrecords together 116 /* The "next" field is normally used to chain all lrecords together
176 some consistency checking, and that only when error-checking is 202 some consistency checking, and that only when error-checking is
177 enabled. */ 203 enabled. */
178 int basic_p; 204 int basic_p;
179 }; 205 };
180 206
207 extern CONST struct lrecord_implementation *lrecord_implementations_table[];
208
209 #ifdef USE_INDEXED_LRECORD_IMPLEMENTATION
210 # define XRECORD_LHEADER_IMPLEMENTATION(obj) \
211 (lrecord_implementations_table[XRECORD_LHEADER (obj)->type])
212 # define LHEADER_IMPLEMENTATION(lh) (lrecord_implementations_table[(lh)->type])
213 #else
214 # define XRECORD_LHEADER_IMPLEMENTATION(obj) \
215 (XRECORD_LHEADER (obj)->implementation)
216 # define LHEADER_IMPLEMENTATION(lh) ((lh)->implementation)
217 #endif
218
181 extern int gc_in_progress; 219 extern int gc_in_progress;
182 220
183 #define MARKED_RECORD_P(obj) (gc_in_progress && \ 221 #ifdef USE_INDEXED_LRECORD_IMPLEMENTATION
222 # define MARKED_RECORD_P(obj) (gc_in_progress && XRECORD_LHEADER (obj)->mark)
223 #else
224 # define MARKED_RECORD_P(obj) (gc_in_progress && \
184 XRECORD_LHEADER (obj)->implementation->finalizer == \ 225 XRECORD_LHEADER (obj)->implementation->finalizer == \
185 this_marks_a_marked_record) 226 this_marks_a_marked_record)
186 227 #endif
187 228
188 /* moved here from alloc.c so that lisp.h macros can use them. */ 229 #ifdef USE_INDEXED_LRECORD_IMPLEMENTATION
189 #define MARKED_RECORD_HEADER_P(lheader) \ 230
231 # define MARKED_RECORD_HEADER_P(lheader) (lheader)->mark
232 # define MARK_RECORD_HEADER(lheader) (lheader)->mark = 1
233 # define UNMARK_RECORD_HEADER(lheader) (lheader)->mark = 0
234
235 #else /* ! USE_INDEXED_LRECORD_IMPLEMENTATION */
236
237 # define MARKED_RECORD_HEADER_P(lheader) \
190 (((lheader)->implementation->finalizer) == this_marks_a_marked_record) 238 (((lheader)->implementation->finalizer) == this_marks_a_marked_record)
239 # define MARK_RECORD_HEADER(lheader) \
240 do { (((lheader)->implementation)++); } while (0)
241 # define UNMARK_RECORD_HEADER(lheader) \
242 do { (((lheader)->implementation)--); } while (0)
243
244 #endif /* ! USE_INDEXED_LRECORD_IMPLEMENTATION */
245
191 #define UNMARKABLE_RECORD_HEADER_P(lheader) \ 246 #define UNMARKABLE_RECORD_HEADER_P(lheader) \
192 (((lheader)->implementation->marker) == this_one_is_unmarkable) 247 ((LHEADER_IMPLEMENTATION (lheader)->marker) \
193 #define MARK_RECORD_HEADER(lheader) \ 248 == this_one_is_unmarkable)
194 do { (((lheader)->implementation)++); } while (0)
195 #define UNMARK_RECORD_HEADER(lheader) \
196 do { (((lheader)->implementation)--); } while (0)
197
198 249
199 /* Declaring the following structures as const puts them in the 250 /* Declaring the following structures as const puts them in the
200 text (read-only) segment, which makes debugging inconvenient 251 text (read-only) segment, which makes debugging inconvenient
201 because this segment is not mapped when processing a core- 252 because this segment is not mapped when processing a core-
202 dump file */ 253 dump file */
271 &(lrecord_##c_name##_lrecord_type_index), 0 }, \ 322 &(lrecord_##c_name##_lrecord_type_index), 0 }, \
272 { 0, 0, 0, this_marks_a_marked_record, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } } 323 { 0, 0, 0, this_marks_a_marked_record, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } }
273 324
274 #define LRECORDP(a) (XTYPE ((a)) == Lisp_Type_Record) 325 #define LRECORDP(a) (XTYPE ((a)) == Lisp_Type_Record)
275 #define XRECORD_LHEADER(a) ((struct lrecord_header *) XPNTR (a)) 326 #define XRECORD_LHEADER(a) ((struct lrecord_header *) XPNTR (a))
276 #define RECORD_TYPEP(x, ty) \ 327
328 #ifdef USE_INDEXED_LRECORD_IMPLEMENTATION
329 # define RECORD_TYPEP(x, ty) \
330 (LRECORDP (x) && \
331 lrecord_implementations_table[XRECORD_LHEADER (x)->type] == (ty))
332 #else
333 # define RECORD_TYPEP(x, ty) \
277 (LRECORDP (x) && XRECORD_LHEADER (x)->implementation == (ty)) 334 (LRECORDP (x) && XRECORD_LHEADER (x)->implementation == (ty))
335 #endif
278 336
279 /* NOTE: the DECLARE_LRECORD() must come before the associated 337 /* NOTE: the DECLARE_LRECORD() must come before the associated
280 DEFINE_LRECORD_*() or you will get compile errors. 338 DEFINE_LRECORD_*() or you will get compile errors.
281 339
282 Furthermore, you always need to put the DECLARE_LRECORD() in a header 340 Furthermore, you always need to put the DECLARE_LRECORD() in a header