Mercurial > hg > xemacs-beta
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 |