Mercurial > hg > xemacs-beta
comparison src/lrecord.h @ 5178:97eb4942aec8
merge
author | Ben Wing <ben@xemacs.org> |
---|---|
date | Mon, 29 Mar 2010 21:28:13 -0500 |
parents | b785049378e3 5ddbab03b0e6 |
children | 4cd28c29a7a1 |
comparison
equal
deleted
inserted
replaced
5177:b785049378e3 | 5178:97eb4942aec8 |
---|---|
1 /* The "lrecord" structure (header of a compound lisp object). | 1 /* The "lrecord" structure (header of a compound lisp object). |
2 Copyright (C) 1993, 1994, 1995 Free Software Foundation, Inc. | 2 Copyright (C) 1993, 1994, 1995 Free Software Foundation, Inc. |
3 Copyright (C) 1996, 2001, 2002, 2004, 2005, 2010 Ben Wing. | 3 Copyright (C) 1996, 2001, 2002, 2004, 2005, 2009, 2010 Ben Wing. |
4 | 4 |
5 This file is part of XEmacs. | 5 This file is part of XEmacs. |
6 | 6 |
7 XEmacs is free software; you can redistribute it and/or modify it | 7 XEmacs is free software; you can redistribute it and/or modify it |
8 under the terms of the GNU General Public License as published by the | 8 under the terms of the GNU General Public License as published by the |
24 /* This file has been Mule-ized, Ben Wing, 10-13-04. */ | 24 /* This file has been Mule-ized, Ben Wing, 10-13-04. */ |
25 | 25 |
26 #ifndef INCLUDED_lrecord_h_ | 26 #ifndef INCLUDED_lrecord_h_ |
27 #define INCLUDED_lrecord_h_ | 27 #define INCLUDED_lrecord_h_ |
28 | 28 |
29 /* The "lrecord" type of Lisp object is used for all object types other | 29 /* All objects other than char and int are implemented as structures and |
30 than a few simple ones (like char and int). This allows many types to be | 30 passed by reference. Such objects are called "record objects" ("record" |
31 implemented but only a few bits required in a Lisp object for type | 31 is another term for "structure"). The "wrapped" value of such an object |
32 information. (The tradeoff is that each object has its type marked in | 32 (i.e. when stored in a variable of type Lisp_Object) is simply the raw |
33 it, thereby increasing its size.) All lrecords begin with a `struct | 33 pointer coerced to an integral type the same size as the pointer |
34 lrecord_header', which identifies the lisp object type, by providing an | 34 (usually `long'). |
35 index into a table of `struct lrecord_implementation', which describes | 35 |
36 the behavior of the lisp object. It also contains some other data bits. | 36 Under old-GC (i.e. when NEW_GC is not defined), there are two kinds of |
37 | 37 record objects: normal objects (those allocated on their own with |
38 #ifndef NEW_GC | 38 xmalloc()) and frob-block objects (those allocated as pieces of large, |
39 Lrecords are of two types: straight lrecords, and lcrecords. | 39 usually 2K, chunks of memory known as "frob blocks"). Under NEW_GC, |
40 Straight lrecords are used for those types of objects that have | 40 there is only one type of record object. Stuff below that applies to |
41 their own allocation routines (typically allocated out of 2K chunks | 41 frob-block objects is assumed to apply to the same type of object as |
42 of memory called `frob blocks'). These objects have a `struct | 42 normal objects under NEW_GC. |
43 lrecord_header' at the top, containing only the bits needed to find | 43 |
44 the lrecord_implementation for the object. There are special | 44 Record objects have a header at the beginning of their structure, which |
45 routines in alloc.c to create an object of each such type. | 45 is used internally to identify the type of the object (so that an |
46 | 46 object's type can be recovered from its pointer); in addition, it holds |
47 Lcrecords are used for less common sorts of objects that don't do | 47 a few flags and a "UID", which for most objects is shown when it is |
48 their own allocation. Each such object is malloc()ed individually, | 48 printed, and is primarily useful for debugging purposes. The header of |
49 and the objects are chained together through a `next' pointer. | 49 a normal object is declared as NORMAL_LISP_OBJECT_HEADER and that of a |
50 Lcrecords have a `struct old_lcrecord_header' at the top, which | 50 frob-block object FROB_BLOCK_LISP_OBJECT_HEADER. |
51 contains a `struct lrecord_header' and a `next' pointer, and are | 51 |
52 allocated using old_alloc_lcrecord_type() or its variants. | 52 FROB_BLOCK_LISP_OBJECT_HEADER boils down to a `struct lrecord_header'. |
53 #endif | 53 This is a 32-bit value made up of bit fields, where 8 bits are used to |
54 | 54 hold the type, 2 or 3 bits are used for flags associated with the |
55 Creating a new Lisp object type is fairly easy; just follow the | 55 garbage collector, and the remaining 21 or 22 bits hold the UID. |
56 lead of some existing type (e.g. hash tables). Note that you | 56 |
57 do not need to supply all the methods (see below); reasonable | 57 Under NEW_GC, NORMAL_LISP_OBJECT_HEADER also resolves to `struct |
58 defaults are provided for many of them. Alternatively, if you're | 58 lrecord_header'. Under old-GC, however, NORMAL_LISP_OBJECT_HEADER |
59 just looking for a way of encapsulating data (which possibly | 59 resolves to a `struct old_lcrecord_header' (note the `c'), which is a |
60 could contain Lisp_Objects in it), you may well be able to use | 60 larger structure -- on 32-bit machines it occupies 2 machine words |
61 the opaque type. | 61 instead of 1. Such an object is known internally as an "lcrecord". The |
62 first word of `struct old_lcrecord_header' is an embedded `struct | |
63 lrecord_header' with the same information as for frob-block objects; | |
64 that way, all objects can be cast to a `struct lrecord_header' to | |
65 determine their type or other info. The other word is a pointer, used | |
66 to thread all lcrecords together in one big linked list. | |
67 | |
68 Under old-GC, normal objects (i.e. lcrecords) are allocated in | |
69 individual chunks using the underlying allocator (i.e. xmalloc(), which | |
70 is a thin wrapper around malloc()). Frob-block objects are more | |
71 efficient than normal objects, as they have a smaller header and don't | |
72 have the additional memory overhead associated with malloc() -- instead, | |
73 as mentioned above, they are carved out of 2K chunks of memory called | |
74 "frob blocks"). However, it is slightly more tricky to create such | |
75 objects, as they require special routines in alloc.c to create an object | |
76 of each such type and to sweep them during garbage collection. In | |
77 addition, there is currently no mechanism for handling variable-sized | |
78 frob-block objects (e.g. vectors), whereas variable-sized normal objects | |
79 are not a problem. Frob-block objects are typically used for basic | |
80 objects that exist in large numbers, such as `cons' or `string'. | |
81 | |
82 Note that strings are an apparent exception to the statement above that | |
83 variable-sized objects can't be handled. Under old-GC strings work as | |
84 follows. A string consists of two parts -- a fixed-size "string header" | |
85 that is allocated as a standard frob-block object, and a "string-chars" | |
86 structure that is allocated out of special 8K-sized frob blocks that | |
87 have a dedicated garbage-collection handler that compacts the blocks | |
88 during the sweep stage, relocating the string-chars data (but not the | |
89 string headers) to eliminate gaps. Strings larger than 8K are not | |
90 placed in frob blocks, but instead are stored as individually malloc()ed | |
91 blocks of memory. Strings larger than 8K are called "big strings" and | |
92 those smaller than 8K are called "small strings". | |
93 | |
94 Under new-GC, there is no difference between big and small strings, | |
95 just as there is no difference between normal and frob-block objects. | |
96 There is only one allocation method, which is capable of handling | |
97 variable-sized objects. This apparently allocates all objects in | |
98 frob blocks according to the size of the object. | |
99 | |
100 To create a new normal Lisp object, see the toolbar-button example | |
101 below. To create a new frob-block Lisp object, follow the lead of | |
102 one of the existing frob-block objects, such as extents or events. | |
103 Note that you do not need to supply all the methods (see below); | |
104 reasonable defaults are provided for many of them. Alternatively, if | |
105 you're just looking for a way of encapsulating data (which possibly | |
106 could contain Lisp_Objects in it), you may well be able to use the | |
107 opaque type. | |
62 */ | 108 */ |
109 | |
110 /* | |
111 How to declare a Lisp object: | |
112 | |
113 NORMAL_LISP_OBJECT_HEADER: | |
114 Header for normal objects | |
115 | |
116 FROB_BLOCK_LISP_OBJECT_HEADER: | |
117 Header for frob-block objects | |
118 | |
119 How to allocate a Lisp object: | |
120 | |
121 - For normal objects of a fixed size, simply call | |
122 ALLOC_NORMAL_LISP_OBJECT (type), where TYPE is the name of the type | |
123 (e.g. toolbar_button). Such objects can be freed manually using | |
124 free_normal_lisp_object. | |
125 | |
126 - For normal objects whose size can vary (and hence which have a | |
127 size_in_bytes_method rather than a static_size), call | |
128 ALLOC_SIZED_LISP_OBJECT (size, type), where TYPE is the | |
129 name of the type. NOTE: You cannot call free_normal_lisp_object() on such | |
130 on object! (At least when not NEW_GC) | |
131 | |
132 - For frob-block objects, use | |
133 ALLOC_FROB_BLOCK_LISP_OBJECT (type, lisp_type, var, lrec_ptr). | |
134 But these objects need special handling; if you don't understand this, | |
135 just ignore it. | |
136 | |
137 - Some lrecords, which are used totally internally, use the | |
138 noseeum-* functions for debugging reasons. | |
139 | |
140 Other operations: | |
141 | |
142 - copy_lisp_object (dst, src) | |
143 | |
144 - zero_nonsized_lisp_object (obj), zero_sized_lisp_object (obj, size): | |
145 BUT NOTE, it is not necessary to zero out newly allocated Lisp objects. | |
146 This happens automatically. | |
147 | |
148 - lisp_object_size (obj): Return the size of a Lisp object. NOTE: This | |
149 requires that the object is properly initialized. | |
150 | |
151 - lisp_object_storage_size (obj, stats): Return the storage size of a | |
152 Lisp objcet, including malloc or frob-block overhead; also, if STATS | |
153 is non-NULL, accumulate info about the size and overhead into STATS. | |
154 */ | |
63 | 155 |
64 #ifdef NEW_GC | 156 #ifdef NEW_GC |
65 /* | 157 /* |
66 There are some limitations under New-GC that lead to the creation of a | 158 There are some limitations under New-GC that lead to the creation of a |
67 large number of new internal object types. I'm not completely sure what | 159 large number of new internal object types. I'm not completely sure what |
72 It must have something to do with the fact that these substructures | 164 It must have something to do with the fact that these substructures |
73 contain pointers to Lisp objects, but it's not completely clear why -- | 165 contain pointers to Lisp objects, but it's not completely clear why -- |
74 object descriptions exist to indicate the size of these structures and | 166 object descriptions exist to indicate the size of these structures and |
75 the Lisp object pointers within them. | 167 the Lisp object pointers within them. |
76 | 168 |
77 At least one definite issue is that under New-GC dumpable objects cannot | 169 At least one definite issue is that under New-GC dumpable objects cannot |
78 contain any finalizers (see pdump_register_object()). This means that any | 170 contain any finalizers (see pdump_register_object()). This means that |
79 substructures in dumpable objects that are allocated separately and | 171 any substructures in dumpable objects that are allocated separately and |
80 normally freed in a finalizer need instead to be made into actual Lisp | 172 normally freed in a finalizer need instead to be made into actual Lisp |
81 objects. If those structures are Dynarrs, they need to be made into | 173 objects. If those structures are Dynarrs, they need to be made into |
82 Dynarr Lisp objects (e.g. face-cachel-dynarr or glyph-cachel-dynarr), | 174 Dynarr Lisp objects (e.g. face-cachel-dynarr or glyph-cachel-dynarr), |
83 which are created using Dynarr_lisp_new() or Dynarr_new_new2(). | 175 which are created using Dynarr_lisp_new() or Dynarr_new_new2(). |
84 Furthermore, the objects contained in the Dynarr also need to be Lisp | 176 Furthermore, the objects contained in the Dynarr also need to be Lisp |
85 objects (e.g. face-cachel or glyph-cachel). | 177 objects (e.g. face-cachel or glyph-cachel). |
86 | 178 |
87 --ben | 179 --ben |
88 */ | 180 */ |
89 | |
90 #endif | 181 #endif |
91 | 182 |
92 | |
93 | |
94 #ifdef NEW_GC | 183 #ifdef NEW_GC |
95 #define ALLOC_LCRECORD_TYPE alloc_lrecord_type | 184 #define ALLOC_NORMAL_LISP_OBJECT(type) alloc_lrecord (&lrecord_##type) |
96 #define COPY_SIZED_LCRECORD copy_sized_lrecord | 185 #define ALLOC_SIZED_LISP_OBJECT(size, type) \ |
97 #define COPY_LCRECORD copy_lrecord | 186 alloc_sized_lrecord (size, &lrecord_##type) |
98 #define LISPOBJ_STORAGE_SIZE(ptr, size, stats) \ | 187 #define NORMAL_LISP_OBJECT_HEADER struct lrecord_header |
99 mc_alloced_storage_size (size, stats) | 188 #define FROB_BLOCK_LISP_OBJECT_HEADER struct lrecord_header |
100 #define ZERO_LCRECORD zero_lrecord | 189 #define LISP_OBJECT_FROB_BLOCK_P(obj) 0 |
101 #define LCRECORD_HEADER lrecord_header | 190 #define IF_NEW_GC(x) x |
102 #define BASIC_ALLOC_LCRECORD alloc_lrecord | 191 #define IF_OLD_GC(x) 0 |
103 #define FREE_LCRECORD free_lrecord | |
104 #else /* not NEW_GC */ | 192 #else /* not NEW_GC */ |
105 #define ALLOC_LCRECORD_TYPE old_alloc_lcrecord_type | 193 #define ALLOC_NORMAL_LISP_OBJECT(type) alloc_automanaged_lcrecord (&lrecord_##type) |
106 #define COPY_SIZED_LCRECORD old_copy_sized_lcrecord | 194 #define ALLOC_SIZED_LISP_OBJECT(size, type) \ |
107 #define COPY_LCRECORD old_copy_lcrecord | 195 old_alloc_sized_lcrecord (size, &lrecord_##type) |
108 #define LISPOBJ_STORAGE_SIZE malloced_storage_size | 196 #define NORMAL_LISP_OBJECT_HEADER struct old_lcrecord_header |
109 #define ZERO_LCRECORD old_zero_lcrecord | 197 #define FROB_BLOCK_LISP_OBJECT_HEADER struct lrecord_header |
110 #define LCRECORD_HEADER old_lcrecord_header | 198 #define LISP_OBJECT_FROB_BLOCK_P(obj) (XRECORD_LHEADER_IMPLEMENTATION(obj)->frob_block_p) |
111 #define BASIC_ALLOC_LCRECORD old_basic_alloc_lcrecord | 199 #define IF_NEW_GC(x) 0 |
112 #define FREE_LCRECORD old_free_lcrecord | 200 #define IF_OLD_GC(x) x |
113 #endif /* not NEW_GC */ | 201 #endif /* not NEW_GC */ |
202 | |
203 #define LISP_OBJECT_UID(obj) (XRECORD_LHEADER (obj)->uid) | |
114 | 204 |
115 BEGIN_C_DECLS | 205 BEGIN_C_DECLS |
116 | 206 |
117 struct lrecord_header | 207 struct lrecord_header |
118 { | 208 { |
148 unsigned int c_readonly :1; | 238 unsigned int c_readonly :1; |
149 | 239 |
150 /* 1 if the object is readonly from lisp */ | 240 /* 1 if the object is readonly from lisp */ |
151 unsigned int lisp_readonly :1; | 241 unsigned int lisp_readonly :1; |
152 | 242 |
243 /* The `free' field is currently used only for lcrecords under old-GC. | |
244 It is a flag that indicates whether this lcrecord is on a "free list". | |
245 Free lists are used to minimize the number of calls to malloc() when | |
246 we're repeatedly allocating and freeing a number of the same sort of | |
247 lcrecord. Lcrecords on a free list always get marked in a different | |
248 fashion, so we can use this flag as a sanity check to make sure that | |
249 free lists only have freed lcrecords and there are no freed lcrecords | |
250 elsewhere. */ | |
251 unsigned int free :1; | |
252 | |
153 /* The `uid' field is just for debugging/printing convenience. Having | 253 /* The `uid' field is just for debugging/printing convenience. Having |
154 this slot doesn't hurt us spacewise, since the bits are unused | 254 this slot doesn't hurt us spacewise, since the bits are unused |
155 anyway. (The bits are used for strings, though.) */ | 255 anyway. (The bits are used for strings, though.) */ |
156 unsigned int uid :21; | 256 unsigned int uid :20; |
157 | 257 |
158 #endif /* not NEW_GC */ | 258 #endif /* not NEW_GC */ |
159 }; | 259 }; |
160 | 260 |
161 struct lrecord_implementation; | 261 struct lrecord_implementation; |
162 int lrecord_type_index (const struct lrecord_implementation *implementation); | 262 int lrecord_type_index (const struct lrecord_implementation *implementation); |
163 extern int lrecord_uid_counter; | 263 extern int lrecord_uid_counter[]; |
164 | 264 |
165 #ifdef NEW_GC | 265 #ifdef NEW_GC |
166 #define set_lheader_implementation(header,imp) do { \ | 266 #define set_lheader_implementation(header,imp) do { \ |
167 struct lrecord_header* SLI_header = (header); \ | 267 struct lrecord_header* SLI_header = (header); \ |
168 SLI_header->type = (imp)->lrecord_type_index; \ | 268 SLI_header->type = (imp)->lrecord_type_index; \ |
169 SLI_header->lisp_readonly = 0; \ | 269 SLI_header->lisp_readonly = 0; \ |
170 SLI_header->free = 0; \ | 270 SLI_header->free = 0; \ |
171 SLI_header->uid = lrecord_uid_counter++; \ | 271 SLI_header->uid = lrecord_uid_counter[(imp)->lrecord_type_index]++; \ |
172 } while (0) | 272 } while (0) |
173 #else /* not NEW_GC */ | 273 #else /* not NEW_GC */ |
174 #define set_lheader_implementation(header,imp) do { \ | 274 #define set_lheader_implementation(header,imp) do { \ |
175 struct lrecord_header* SLI_header = (header); \ | 275 struct lrecord_header* SLI_header = (header); \ |
176 SLI_header->type = (imp)->lrecord_type_index; \ | 276 SLI_header->type = (imp)->lrecord_type_index; \ |
177 SLI_header->mark = 0; \ | 277 SLI_header->mark = 0; \ |
178 SLI_header->c_readonly = 0; \ | 278 SLI_header->c_readonly = 0; \ |
179 SLI_header->lisp_readonly = 0; \ | 279 SLI_header->lisp_readonly = 0; \ |
180 SLI_header->uid = lrecord_uid_counter++; \ | 280 SLI_header->free = 0; \ |
281 SLI_header->uid = lrecord_uid_counter[(imp)->lrecord_type_index]++; \ | |
181 } while (0) | 282 } while (0) |
182 #endif /* not NEW_GC */ | 283 #endif /* not NEW_GC */ |
183 | 284 |
184 #ifndef NEW_GC | 285 #ifndef NEW_GC |
185 struct old_lcrecord_header | 286 struct old_lcrecord_header |
186 { | 287 { |
187 struct lrecord_header lheader; | 288 struct lrecord_header lheader; |
188 | 289 |
189 /* The `next' field is normally used to chain all lcrecords together | 290 /* The `next' field is normally used to chain all lcrecords together |
190 so that the GC can find (and free) all of them. | 291 so that the GC can find (and free) all of them. |
191 `old_basic_alloc_lcrecord' threads lcrecords together. | 292 `old_alloc_sized_lcrecord' threads lcrecords together. |
192 | 293 |
193 The `next' field may be used for other purposes as long as some | 294 The `next' field may be used for other purposes as long as some |
194 other mechanism is provided for letting the GC do its work. | 295 other mechanism is provided for letting the GC do its work. |
195 | 296 |
196 For example, the event and marker object types allocate members | 297 For example, the event and marker object types allocate members |
197 out of memory chunks, and are able to find all unmarked members | 298 out of memory chunks, and are able to find all unmarked members |
198 by sweeping through the elements of the list of chunks. */ | 299 by sweeping through the elements of the list of chunks. */ |
199 struct old_lcrecord_header *next; | 300 struct old_lcrecord_header *next; |
200 | |
201 /* The `uid' field is just for debugging/printing convenience. | |
202 Having this slot doesn't hurt us much spacewise, since an | |
203 lcrecord already has the above slots plus malloc overhead. */ | |
204 unsigned int uid :31; | |
205 | |
206 /* The `free' field is a flag that indicates whether this lcrecord | |
207 is on a "free list". Free lists are used to minimize the number | |
208 of calls to malloc() when we're repeatedly allocating and freeing | |
209 a number of the same sort of lcrecord. Lcrecords on a free list | |
210 always get marked in a different fashion, so we can use this flag | |
211 as a sanity check to make sure that free lists only have freed | |
212 lcrecords and there are no freed lcrecords elsewhere. */ | |
213 unsigned int free :1; | |
214 }; | 301 }; |
215 | 302 |
216 /* Used for lcrecords in an lcrecord-list. */ | 303 /* Used for lcrecords in an lcrecord-list. */ |
217 struct free_lcrecord_header | 304 struct free_lcrecord_header |
218 { | 305 { |
225 enum lrecord_type | 312 enum lrecord_type |
226 { | 313 { |
227 /* Symbol value magic types come first to make SYMBOL_VALUE_MAGIC_P fast. | 314 /* Symbol value magic types come first to make SYMBOL_VALUE_MAGIC_P fast. |
228 #### This should be replaced by a symbol_value_magic_p flag | 315 #### This should be replaced by a symbol_value_magic_p flag |
229 in the Lisp_Symbol lrecord_header. */ | 316 in the Lisp_Symbol lrecord_header. */ |
230 lrecord_type_symbol_value_forward, /* 0 */ | 317 /* Don't assign any type to 0, so in case we come across zeroed memory |
318 it will be more obvious when printed */ | |
319 lrecord_type_symbol_value_forward = 1, | |
231 lrecord_type_symbol_value_varalias, | 320 lrecord_type_symbol_value_varalias, |
232 lrecord_type_symbol_value_lisp_magic, | 321 lrecord_type_symbol_value_lisp_magic, |
233 lrecord_type_symbol_value_buffer_local, | 322 lrecord_type_symbol_value_buffer_local, |
234 lrecord_type_max_symbol_value_magic = lrecord_type_symbol_value_buffer_local, | 323 lrecord_type_max_symbol_value_magic = lrecord_type_symbol_value_buffer_local, |
235 lrecord_type_symbol, | 324 lrecord_type_symbol, |
279 lrecord_type_console, | 368 lrecord_type_console, |
280 lrecord_type_device, | 369 lrecord_type_device, |
281 lrecord_type_frame, | 370 lrecord_type_frame, |
282 lrecord_type_window, | 371 lrecord_type_window, |
283 lrecord_type_window_mirror, | 372 lrecord_type_window_mirror, |
284 lrecord_type_window_configuration, | |
285 lrecord_type_gui_item, | 373 lrecord_type_gui_item, |
286 lrecord_type_popup_data, | |
287 lrecord_type_toolbar_button, | 374 lrecord_type_toolbar_button, |
288 lrecord_type_scrollbar_instance, | 375 lrecord_type_scrollbar_instance, |
289 lrecord_type_color_instance, | 376 lrecord_type_color_instance, |
290 lrecord_type_font_instance, | 377 lrecord_type_font_instance, |
291 lrecord_type_image_instance, | 378 lrecord_type_image_instance, |
374 description below instead), unless the data description is missing. | 461 description below instead), unless the data description is missing. |
375 Yes, this currently means there is logic duplication. Eventually the | 462 Yes, this currently means there is logic duplication. Eventually the |
376 mark methods will be removed. */ | 463 mark methods will be removed. */ |
377 Lisp_Object (*marker) (Lisp_Object); | 464 Lisp_Object (*marker) (Lisp_Object); |
378 | 465 |
379 /* `printer' converts the object to a printed representation. | 466 /* `printer' converts the object to a printed representation. `printer' |
380 This can be NULL; in this case default_object_printer() will be | 467 should never be NULL (if so, you will get an assertion failure when |
381 used instead. */ | 468 trying to print such an object). Either supply a specific printing |
469 method, or use the default methods internal_object_printer() (for | |
470 internal objects that should not be visible at Lisp level) or | |
471 external_object_printer() (for objects visible at Lisp level). */ | |
382 void (*printer) (Lisp_Object, Lisp_Object printcharfun, int escapeflag); | 472 void (*printer) (Lisp_Object, Lisp_Object printcharfun, int escapeflag); |
383 | 473 |
384 /* `finalizer' is called at GC time when the object is about to be freed, | 474 /* `finalizer' is called at GC time when the object is about to be freed. |
385 and at dump time (FOR_DISKSAVE will be non-zero in this case). It | 475 It should perform any necessary cleanup, such as freeing malloc()ed |
386 should perform any necessary cleanup (e.g. freeing malloc()ed memory | 476 memory or releasing pointers or handles to objects created in external |
387 or releasing objects created in external libraries, such as | 477 libraries, such as window-system windows or file handles. This can be |
388 window-system windows or file handles). This can be NULL, meaning no | 478 NULL, meaning no special finalization is necessary. */ |
389 special finalization is necessary. | 479 void (*finalizer) (Lisp_Object obj); |
390 | |
391 WARNING: remember that `finalizer' is called at dump time even though | |
392 the object is not being freed -- check the FOR_DISKSAVE argument. */ | |
393 void (*finalizer) (void *header, int for_disksave); | |
394 | 480 |
395 /* This can be NULL, meaning compare objects with EQ(). */ | 481 /* This can be NULL, meaning compare objects with EQ(). */ |
396 int (*equal) (Lisp_Object obj1, Lisp_Object obj2, int depth, | 482 int (*equal) (Lisp_Object obj1, Lisp_Object obj2, int depth, |
397 int foldcase); | 483 int foldcase); |
398 | 484 |
406 Hashcode (*hash) (Lisp_Object, int); | 492 Hashcode (*hash) (Lisp_Object, int); |
407 | 493 |
408 /* Data layout description for your object. See long comment below. */ | 494 /* Data layout description for your object. See long comment below. */ |
409 const struct memory_description *description; | 495 const struct memory_description *description; |
410 | 496 |
497 /* Only one of `static_size' and `size_in_bytes_method' is non-0. If | |
498 `static_size' is 0, this type is not instantiable by | |
499 ALLOC_NORMAL_LISP_OBJECT(). If both are 0 (this should never happen), | |
500 this object cannot be instantiated; you will get an abort() if you | |
501 try.*/ | |
502 Bytecount static_size; | |
503 Bytecount (*size_in_bytes_method) (Lisp_Object); | |
504 | |
505 /* The (constant) index into lrecord_implementations_table */ | |
506 enum lrecord_type lrecord_type_index; | |
507 | |
508 #ifndef NEW_GC | |
509 /* A "frob-block" lrecord is any lrecord that's not an lcrecord, i.e. | |
510 one that does not have an old_lcrecord_header at the front and which | |
511 is (usually) allocated in frob blocks. */ | |
512 unsigned int frob_block_p :1; | |
513 #endif /* not NEW_GC */ | |
514 | |
515 /**********************************************************************/ | |
516 /* Remaining stuff is not assignable statically using | |
517 DEFINE_*_LISP_OBJECT, but must be assigned with OBJECT_HAS_METHOD, | |
518 OBJECT_HAS_PROPERTY or the like. */ | |
519 | |
411 /* These functions allow any object type to have builtin property | 520 /* These functions allow any object type to have builtin property |
412 lists that can be manipulated from the lisp level with | 521 lists that can be manipulated from the lisp level with |
413 `get', `put', `remprop', and `object-plist'. */ | 522 `get', `put', `remprop', and `object-plist'. */ |
414 Lisp_Object (*getprop) (Lisp_Object obj, Lisp_Object prop); | 523 Lisp_Object (*getprop) (Lisp_Object obj, Lisp_Object prop); |
415 int (*putprop) (Lisp_Object obj, Lisp_Object prop, Lisp_Object val); | 524 int (*putprop) (Lisp_Object obj, Lisp_Object prop, Lisp_Object val); |
416 int (*remprop) (Lisp_Object obj, Lisp_Object prop); | 525 int (*remprop) (Lisp_Object obj, Lisp_Object prop); |
417 Lisp_Object (*plist) (Lisp_Object obj); | 526 Lisp_Object (*plist) (Lisp_Object obj); |
418 | 527 |
419 #ifdef NEW_GC | 528 /* `disksave' is called at dump time. It is used for objects that |
420 /* Only one of `static_size' and `size_in_bytes_method' is non-0. */ | 529 contain pointers or handles to objects created in external libraries, |
421 #else /* not NEW_GC */ | 530 such as window-system windows or file handles. Such external objects |
422 /* Only one of `static_size' and `size_in_bytes_method' is non-0. | 531 cannot be dumped, so it is necessary to release them at dump time and |
423 If both are 0, this type is not instantiable by | 532 arrange somehow or other for them to be resurrected if necessary later |
424 old_basic_alloc_lcrecord(). */ | 533 on. |
425 #endif /* not NEW_GC */ | 534 |
426 Bytecount static_size; | 535 It seems that even non-dumpable objects may be around at dump time, |
427 Bytecount (*size_in_bytes_method) (const void *header); | 536 and a disksave may be provided. (In fact, the only object currently |
428 | 537 with a disksave, lstream, is non-dumpable.) |
429 /* The (constant) index into lrecord_implementations_table */ | 538 |
430 enum lrecord_type lrecord_type_index; | 539 Objects rarely need to provide this method; most of the time it will |
431 | 540 be NULL. */ |
432 #ifndef NEW_GC | 541 void (*disksave) (Lisp_Object); |
433 /* A "basic" lrecord is any lrecord that's not an lcrecord, i.e. | 542 |
434 one that does not have an old_lcrecord_header at the front and which | 543 #ifdef MEMORY_USAGE_STATS |
435 is (usually) allocated in frob blocks. */ | 544 /* Return memory-usage information about the object in question, stored |
436 unsigned int basic_p :1; | 545 into STATS. |
437 #endif /* not NEW_GC */ | 546 |
547 Two types of information are stored: storage (including overhead) for | |
548 ancillary non-Lisp structures attached to the object, and storage | |
549 (including overhead) for ancillary Lisp objects attached to the | |
550 object. The third type of memory-usage information (storage for the | |
551 object itself) is not noted here, because it's computed automatically | |
552 by the calling function. Also, the computed storage for ancillary | |
553 Lisp objects is the sum of all three source of memory associated with | |
554 the Lisp object: the object itself, ancillary non-Lisp structures and | |
555 ancillary Lisp objects. Note also that the `struct usage_stats u' at | |
556 the beginning of the STATS structure is for ancillary non-Lisp usage | |
557 *ONLY*; do not store any memory into it related to ancillary Lisp | |
558 objects. | |
559 | |
560 Note that it may be subjective which Lisp objects are considered | |
561 "attached" to the object. Some guidelines: | |
562 | |
563 -- Lisp objects which are "internal" to the main object and not | |
564 accessible except through the main object should be included | |
565 -- Objects linked by a weak reference should *NOT* be included | |
566 */ | |
567 void (*memory_usage) (Lisp_Object obj, struct generic_usage_stats *stats); | |
568 | |
569 /* List of tags to be given to the extra statistics, one per statistic. | |
570 Qnil or Qt can be present to separate off different slices. Qnil | |
571 separates different slices within the same group of statistics. | |
572 These represent different ways of partitioning the same memory space. | |
573 Qt separates different groups; these represent different spaces of | |
574 memory. | |
575 | |
576 If Qt is not present, all slices describe extra non-Lisp-Object memory | |
577 associated with a Lisp object. If Qt is present, slices before Qt | |
578 describe non-Lisp-Object memory, as before, and slices after Qt | |
579 describe ancillary Lisp-Object memory logically associated with the | |
580 object. For example, if the object is a table, then ancillary | |
581 Lisp-Object memory might be the entries in the table. This info is | |
582 only advisory since it will duplicate memory described elsewhere and | |
583 since it may not be possible to be completely accurate, e.g. it may | |
584 not be clear what to count in "ancillary objects", and the value may | |
585 be too high if the same object occurs multiple times in the table. */ | |
586 Lisp_Object memusage_stats_list; | |
587 | |
588 /* --------------------------------------------------------------------- */ | |
589 | |
590 /* The following are automatically computed based on the value in | |
591 `memusage_stats_list' (see compute_memusage_stats_length()). */ | |
592 | |
593 /* Total number of additional type-specific statistics related to memory | |
594 usage. */ | |
595 Elemcount num_extra_memusage_stats; | |
596 | |
597 /* Number of additional type-specific statistics belonging to the first | |
598 slice of the group describing non-Lisp-Object memory usage for this | |
599 object. These stats occur starting at offset 0. */ | |
600 Elemcount num_extra_nonlisp_memusage_stats; | |
601 | |
602 /* The offset into the extra statistics at which the Lisp-Object | |
603 memory-usage statistics begin. */ | |
604 Elemcount offset_lisp_ancillary_memusage_stats; | |
605 | |
606 /* Number of additional type-specific statistics belonging to the first | |
607 slice of the group describing Lisp-Object memory usage for this | |
608 object. These stats occur starting at offset | |
609 `offset_lisp_ancillary_memusage_stats'. */ | |
610 Elemcount num_extra_lisp_ancillary_memusage_stats; | |
611 | |
612 #endif /* MEMORY_USAGE_STATS */ | |
438 }; | 613 }; |
439 | 614 |
440 /* All the built-in lisp object types are enumerated in `enum lrecord_type'. | 615 /* All the built-in lisp object types are enumerated in `enum lrecord_type'. |
441 Additional ones may be defined by a module (none yet). We leave some | 616 Additional ones may be defined by a module (none yet). We leave some |
442 room in `lrecord_implementations_table' for such new lisp object types. */ | 617 room in `lrecord_implementations_table' for such new lisp object types. */ |
443 #define MODULE_DEFINABLE_TYPE_COUNT 32 | 618 #define MODULE_DEFINABLE_TYPE_COUNT 32 |
444 | 619 |
445 extern MODULE_API const struct lrecord_implementation * | 620 extern MODULE_API struct lrecord_implementation * |
446 lrecord_implementations_table[lrecord_type_last_built_in_type + MODULE_DEFINABLE_TYPE_COUNT]; | 621 lrecord_implementations_table[lrecord_type_last_built_in_type + MODULE_DEFINABLE_TYPE_COUNT]; |
447 | 622 |
623 /* Given a Lisp object, return its implementation | |
624 (struct lrecord_implementation) */ | |
448 #define XRECORD_LHEADER_IMPLEMENTATION(obj) \ | 625 #define XRECORD_LHEADER_IMPLEMENTATION(obj) \ |
449 LHEADER_IMPLEMENTATION (XRECORD_LHEADER (obj)) | 626 LHEADER_IMPLEMENTATION (XRECORD_LHEADER (obj)) |
450 #define LHEADER_IMPLEMENTATION(lh) lrecord_implementations_table[(lh)->type] | 627 #define LHEADER_IMPLEMENTATION(lh) lrecord_implementations_table[(lh)->type] |
451 | 628 |
452 #include "gc.h" | 629 #include "gc.h" |
479 const struct lrecord_implementation *MCACF_implementation \ | 656 const struct lrecord_implementation *MCACF_implementation \ |
480 = LHEADER_IMPLEMENTATION (MCACF_lheader); \ | 657 = LHEADER_IMPLEMENTATION (MCACF_lheader); \ |
481 if (MCACF_implementation && MCACF_implementation->finalizer) \ | 658 if (MCACF_implementation && MCACF_implementation->finalizer) \ |
482 { \ | 659 { \ |
483 GC_STAT_FINALIZED; \ | 660 GC_STAT_FINALIZED; \ |
484 MCACF_implementation->finalizer (ptr, 0); \ | 661 MCACF_implementation->finalizer (MCACF_obj); \ |
485 } \ | 662 } \ |
486 } \ | 663 } \ |
487 } while (0) | 664 } while (0) |
488 | 665 |
489 /* Tell mc-alloc how to call a finalizer for disksave. */ | 666 /* Tell mc-alloc how to call a finalizer for disksave. */ |
494 if (XRECORD_LHEADER (MCACF_obj) && LRECORDP (MCACF_obj) \ | 671 if (XRECORD_LHEADER (MCACF_obj) && LRECORDP (MCACF_obj) \ |
495 && !LRECORD_FREE_P (MCACF_lheader) ) \ | 672 && !LRECORD_FREE_P (MCACF_lheader) ) \ |
496 { \ | 673 { \ |
497 const struct lrecord_implementation *MCACF_implementation \ | 674 const struct lrecord_implementation *MCACF_implementation \ |
498 = LHEADER_IMPLEMENTATION (MCACF_lheader); \ | 675 = LHEADER_IMPLEMENTATION (MCACF_lheader); \ |
499 if (MCACF_implementation && MCACF_implementation->finalizer) \ | 676 if (MCACF_implementation && MCACF_implementation->disksave) \ |
500 MCACF_implementation->finalizer (ptr, 1); \ | 677 MCACF_implementation->disksave (MCACF_obj); \ |
501 } \ | 678 } \ |
502 } while (0) | 679 } while (0) |
503 | 680 |
504 #define LRECORD_FREE_P(ptr) \ | 681 #define LRECORD_FREE_P(ptr) \ |
505 (((struct lrecord_header *) ptr)->free) | 682 (((struct lrecord_header *) ptr)->free) |
643 some descriptions are written this way. This is dangerous, though, | 820 some descriptions are written this way. This is dangerous, though, |
644 because another use might come along for the data descriptions, that | 821 because another use might come along for the data descriptions, that |
645 doesn't care about the dumper flag and makes use of some of the stuff | 822 doesn't care about the dumper flag and makes use of some of the stuff |
646 normally omitted from the "abbreviated" description -- see above. | 823 normally omitted from the "abbreviated" description -- see above. |
647 | 824 |
648 A memory_description is an array of values. (This is actually | 825 A memory_description is an array of values. The first value of each |
649 misnamed, in that it does not just describe lrecords, but any | 826 line is a type, the second the offset in the lrecord structure. The |
650 blocks of memory.) The first value of each line is a type, the | 827 third and following elements are parameters; their presence, type and |
651 second the offset in the lrecord structure. The third and | 828 number is type-dependent. |
652 following elements are parameters; their presence, type and number | |
653 is type-dependent. | |
654 | 829 |
655 The description ends with an "XD_END" record. | 830 The description ends with an "XD_END" record. |
656 | 831 |
657 The top-level description of an lrecord or lcrecord does not need | 832 The top-level description of an lrecord or lcrecord does not need |
658 to describe every element, just the ones that need to be relocated, | 833 to describe every element, just the ones that need to be relocated, |
752 Lisp_Object value; | 927 Lisp_Object value; |
753 } htentry; | 928 } htentry; |
754 | 929 |
755 struct Lisp_Hash_Table | 930 struct Lisp_Hash_Table |
756 { | 931 { |
757 struct LCRECORD_HEADER header; | 932 NORMAL_LISP_OBJECT_HEADER header; |
758 Elemcount size; | 933 Elemcount size; |
759 Elemcount count; | 934 Elemcount count; |
760 Elemcount rehash_count; | 935 Elemcount rehash_count; |
761 double rehash_size; | 936 double rehash_size; |
762 double rehash_threshold; | 937 double rehash_threshold; |
817 ... | 992 ... |
818 }; | 993 }; |
819 | 994 |
820 struct Lisp_Specifier | 995 struct Lisp_Specifier |
821 { | 996 { |
822 struct LCRECORD_HEADER header; | 997 NORMAL_LISP_OBJECT_HEADER header; |
823 struct specifier_methods *methods; | 998 struct specifier_methods *methods; |
824 | 999 |
825 ... | 1000 ... |
826 // type-specific extra data attached to a specifier | 1001 // type-specific extra data attached to a specifier |
827 max_align_t data[1]; | 1002 max_align_t data[1]; |
842 The existing types : | 1017 The existing types : |
843 | 1018 |
844 | 1019 |
845 XD_LISP_OBJECT | 1020 XD_LISP_OBJECT |
846 | 1021 |
847 A Lisp object. This is also the type to use for pointers to other lrecords | 1022 A Lisp_Object. This is also the type to use for pointers to other lrecords |
848 (e.g. struct frame *). | 1023 (e.g. struct frame *). |
849 | 1024 |
850 XD_LISP_OBJECT_ARRAY | 1025 XD_LISP_OBJECT_ARRAY |
851 | 1026 |
852 An array of Lisp objects or (equivalently) pointers to lrecords. | 1027 An array of Lisp_Objects or (equivalently) pointers to lrecords. |
853 The parameter (i.e. third element) is the count. This would be declared | 1028 The parameter (i.e. third element) is the count. This would be declared |
854 as Lisp_Object foo[666]. For something declared as Lisp_Object *foo, | 1029 as Lisp_Object foo[666]. For something declared as Lisp_Object *foo, |
855 use XD_BLOCK_PTR, whose description parameter is a sized_memory_description | 1030 use XD_BLOCK_PTR, whose description parameter is a sized_memory_description |
856 consisting of only XD_LISP_OBJECT and XD_END. | 1031 consisting of only XD_LISP_OBJECT and XD_END. |
1032 | |
1033 XD_INLINE_LISP_OBJECT_BLOCK_PTR | |
1034 | |
1035 An pointer to a contiguous block of inline Lisp objects -- i.e., the Lisp | |
1036 object itself rather than a Lisp_Object pointer is stored in the block. | |
1037 This is used only under NEW_GC and is useful for increased efficiency when | |
1038 an array of the same kind of object is needed. Examples of the use of this | |
1039 type are Lisp dynarrs, where the array elements are inline Lisp objects | |
1040 rather than non-Lisp structures, as is normally the case; and hash tables, | |
1041 where the key/value pairs are encapsulated as hash-table-entry objects and | |
1042 an array of inline hash-table-entry objects is stored. | |
857 | 1043 |
858 XD_LO_LINK | 1044 XD_LO_LINK |
859 | 1045 |
860 Weak link in a linked list of objects of the same type. This is a | 1046 Weak link in a linked list of objects of the same type. This is a |
861 link that does NOT generate a GC reference. Thus the pdumper will | 1047 link that does NOT generate a GC reference. Thus the pdumper will |
1018 enum memory_description_type | 1204 enum memory_description_type |
1019 { | 1205 { |
1020 XD_LISP_OBJECT_ARRAY, | 1206 XD_LISP_OBJECT_ARRAY, |
1021 XD_LISP_OBJECT, | 1207 XD_LISP_OBJECT, |
1022 #ifdef NEW_GC | 1208 #ifdef NEW_GC |
1023 XD_LISP_OBJECT_BLOCK_PTR, | 1209 XD_INLINE_LISP_OBJECT_BLOCK_PTR, |
1024 #endif /* NEW_GC */ | 1210 #endif /* NEW_GC */ |
1025 XD_LO_LINK, | 1211 XD_LO_LINK, |
1026 XD_OPAQUE_PTR, | 1212 XD_OPAQUE_PTR, |
1027 XD_OPAQUE_PTR_CONVERTIBLE, | 1213 XD_OPAQUE_PTR_CONVERTIBLE, |
1028 XD_OPAQUE_DATA_CONVERTIBLE, | 1214 XD_OPAQUE_DATA_CONVERTIBLE, |
1068 /* Indicates that this is a free Lisp object we're marking. | 1254 /* Indicates that this is a free Lisp object we're marking. |
1069 Only relevant for ERROR_CHECK_GC. This occurs when we're marking | 1255 Only relevant for ERROR_CHECK_GC. This occurs when we're marking |
1070 lcrecord-lists, where the objects have had their type changed to | 1256 lcrecord-lists, where the objects have had their type changed to |
1071 lrecord_type_free and also have had their free bit set, but we mark | 1257 lrecord_type_free and also have had their free bit set, but we mark |
1072 them as normal. */ | 1258 them as normal. */ |
1073 XD_FLAG_FREE_LISP_OBJECT = 8 | 1259 XD_FLAG_FREE_LISP_OBJECT = 8, |
1074 #endif /* not NEW_GC */ | 1260 #endif /* not NEW_GC */ |
1075 #if 0 | 1261 #if 0 |
1076 , | |
1077 /* Suggestions for other possible flags: */ | 1262 /* Suggestions for other possible flags: */ |
1078 | 1263 |
1079 /* Eliminate XD_UNION_DYNAMIC_SIZE and replace it with a flag, like this. */ | 1264 /* Eliminate XD_UNION_DYNAMIC_SIZE and replace it with a flag, like this. */ |
1080 XD_FLAG_UNION_DYNAMIC_SIZE = 16, | 1265 XD_FLAG_UNION_DYNAMIC_SIZE = 16, |
1081 /* Require that everyone who uses a description map has to flag it, so | 1266 /* Require that everyone who uses a description map has to flag it, so |
1083 description maps are and who's using them. This might also become | 1268 description maps are and who's using them. This might also become |
1084 necessary if for some reason the format of the description map is | 1269 necessary if for some reason the format of the description map is |
1085 expanded and we need to stick a pointer in the second slot (although | 1270 expanded and we need to stick a pointer in the second slot (although |
1086 we could still ensure that the second slot in the first entry was NULL | 1271 we could still ensure that the second slot in the first entry was NULL |
1087 or <0). */ | 1272 or <0). */ |
1088 XD_FLAG_DESCRIPTION_MAP = 32 | 1273 XD_FLAG_DESCRIPTION_MAP = 32, |
1089 #endif | 1274 #endif |
1090 }; | 1275 }; |
1091 | 1276 |
1092 union memory_contents_description | 1277 union memory_contents_description |
1093 { | 1278 { |
1126 because they contain pointers. This is called at dump time to | 1311 because they contain pointers. This is called at dump time to |
1127 convert to an opaque, pointer-less representation. | 1312 convert to an opaque, pointer-less representation. |
1128 | 1313 |
1129 This function must put a pointer to the opaque result in *data | 1314 This function must put a pointer to the opaque result in *data |
1130 and its size in *size. */ | 1315 and its size in *size. */ |
1131 void (*convert)(const void *object, void **data, Bytecount *size); | 1316 void (*convert) (const void *object, void **data, Bytecount *size); |
1132 | 1317 |
1133 /* Post-conversion cleanup. Optional (null if not provided). | 1318 /* Post-conversion cleanup. Optional (null if not provided). |
1134 | 1319 |
1135 When provided it will be called post-dumping to free any storage | 1320 When provided it will be called post-dumping to free any storage |
1136 allocated for the conversion results. */ | 1321 allocated for the conversion results. */ |
1137 void (*convert_free)(const void *object, void *data, Bytecount size); | 1322 void (*convert_free) (const void *object, void *data, Bytecount size); |
1138 | 1323 |
1139 /* De-conversion. | 1324 /* De-conversion. |
1140 | 1325 |
1141 At reload time, rebuilds the object from the converted form. | 1326 At reload time, rebuilds the object from the converted form. |
1142 "object" is 0 for the PTR case, return is ignored in the DATA | 1327 "object" is 0 for the PTR case, return is ignored in the DATA |
1143 case. */ | 1328 case. */ |
1144 void *(*deconvert)(void *object, void *data, Bytecount size); | 1329 void *(*deconvert) (void *object, void *data, Bytecount size); |
1145 | 1330 |
1146 }; | 1331 }; |
1147 | 1332 |
1148 extern const struct sized_memory_description lisp_object_description; | 1333 extern const struct sized_memory_description lisp_object_description; |
1149 | 1334 |
1151 | 1336 |
1152 #define XD_IS_INDIRECT(code) ((code) < 0) | 1337 #define XD_IS_INDIRECT(code) ((code) < 0) |
1153 #define XD_INDIRECT_VAL(code) ((-1 - (code)) & 255) | 1338 #define XD_INDIRECT_VAL(code) ((-1 - (code)) & 255) |
1154 #define XD_INDIRECT_DELTA(code) ((-1 - (code)) >> 8) | 1339 #define XD_INDIRECT_DELTA(code) ((-1 - (code)) >> 8) |
1155 | 1340 |
1156 /* DEFINE_LRECORD_IMPLEMENTATION is for objects with constant size. | 1341 /* DEFINE_*_LISP_OBJECT is for objects with constant size. (Either |
1157 DEFINE_LRECORD_SEQUENCE_IMPLEMENTATION is for objects whose size varies. | 1342 DEFINE_DUMPABLE_LISP_OBJECT for objects that can be saved in a dumped |
1343 executable, or DEFINE_NODUMP_LISP_OBJECT for objects that cannot be | |
1344 saved -- e.g. that contain pointers to non-persistent external objects | |
1345 such as window-system windows.) | |
1346 | |
1347 DEFINE_*_SIZABLE_LISP_OBJECT is for objects whose size varies. | |
1348 | |
1349 DEFINE_*_FROB_BLOCK_LISP_OBJECT is for objects that are allocated in | |
1350 large blocks ("frob blocks"), which are parceled up individually. Such | |
1351 objects need special handling in alloc.c. This does not apply to | |
1352 NEW_GC, because it does this automatically. | |
1353 | |
1354 DEFINE_*_INTERNAL_LISP_OBJECT is for "internal" objects that should | |
1355 never be visible on the Lisp level. This is a shorthand for the most | |
1356 common type of internal objects, which have no equal or hash method | |
1357 (since they generally won't appear in hash tables), no finalizer and | |
1358 internal_object_printer() as their print method (which prints that the | |
1359 object is internal and shouldn't be visible externally). For internal | |
1360 objects needing a finalizer, equal or hash method, or wanting to | |
1361 customize the print method, use the normal DEFINE_*_LISP_OBJECT | |
1362 mechanism for defining these objects. | |
1363 | |
1364 DEFINE_MODULE_* is for objects defined in an external module. | |
1365 | |
1366 MAKE_LISP_OBJECT and MAKE_MODULE_LISP_OBJECT are what underlies all of | |
1367 these; they define a structure containing pointers to object methods | |
1368 and other info such as the size of the structure containing the object. | |
1158 */ | 1369 */ |
1159 | 1370 |
1371 /* #### FIXME What's going on here? */ | |
1160 #if defined (ERROR_CHECK_TYPES) | 1372 #if defined (ERROR_CHECK_TYPES) |
1161 # define DECLARE_ERROR_CHECK_TYPES(c_name, structtype) | 1373 # define DECLARE_ERROR_CHECK_TYPES(c_name, structtype) |
1162 #else | 1374 #else |
1163 # define DECLARE_ERROR_CHECK_TYPES(c_name, structtype) | 1375 # define DECLARE_ERROR_CHECK_TYPES(c_name, structtype) |
1164 #endif | 1376 #endif |
1165 | 1377 |
1166 | 1378 /********* The dumpable versions *********** */ |
1167 #define DEFINE_BASIC_LRECORD_IMPLEMENTATION(name,c_name,dumpable,marker,printer,nuker,equal,hash,desc,structtype) \ | 1379 |
1168 DEFINE_BASIC_LRECORD_IMPLEMENTATION_WITH_PROPS(name,c_name,dumpable,marker,printer,nuker,equal,hash,desc,0,0,0,0,structtype) | 1380 #define DEFINE_DUMPABLE_LISP_OBJECT(name,c_name,marker,printer,nuker,equal,hash,desc,structtype) \ |
1169 | 1381 MAKE_LISP_OBJECT(name,c_name,1 /*dumpable*/,marker,printer,nuker,equal,hash,desc,sizeof (structtype),0,0,structtype) |
1170 #define DEFINE_BASIC_LRECORD_IMPLEMENTATION_WITH_PROPS(name,c_name,dumpable,marker,printer,nuker,equal,hash,desc,getprop,putprop,remprop,plist,structtype) \ | 1382 |
1171 MAKE_LRECORD_IMPLEMENTATION(name,c_name,dumpable,marker,printer,nuker,equal,hash,desc,getprop,putprop,remprop,plist,sizeof(structtype),0,1,structtype) | 1383 #define DEFINE_DUMPABLE_SIZABLE_LISP_OBJECT(name,c_name,marker,printer,nuker,equal,hash,desc,sizer,structtype) \ |
1172 | 1384 MAKE_LISP_OBJECT(name,c_name,1 /*dumpable*/,marker,printer,nuker,equal,hash,desc,0,sizer,0,structtype) |
1173 #define DEFINE_LRECORD_IMPLEMENTATION(name,c_name,dumpable,marker,printer,nuker,equal,hash,desc,structtype) \ | 1385 |
1174 DEFINE_LRECORD_IMPLEMENTATION_WITH_PROPS(name,c_name,dumpable,marker,printer,nuker,equal,hash,desc,0,0,0,0,structtype) | 1386 #define DEFINE_DUMPABLE_FROB_BLOCK_LISP_OBJECT(name,c_name,marker,printer,nuker,equal,hash,desc,structtype) \ |
1175 | 1387 MAKE_LISP_OBJECT(name,c_name,1 /*dumpable*/,marker,printer,nuker,equal,hash,desc,sizeof(structtype),0,1,structtype) |
1176 #define DEFINE_LRECORD_IMPLEMENTATION_WITH_PROPS(name,c_name,dumpable,marker,printer,nuker,equal,hash,desc,getprop,putprop,remprop,plist,structtype) \ | 1388 |
1177 MAKE_LRECORD_IMPLEMENTATION(name,c_name,dumpable,marker,printer,nuker,equal,hash,desc,getprop,putprop,remprop,plist,sizeof (structtype),0,0,structtype) | 1389 #define DEFINE_DUMPABLE_FROB_BLOCK_SIZABLE_LISP_OBJECT(name,c_name,marker,printer,nuker,equal,hash,desc,sizer,structtype) \ |
1178 | 1390 MAKE_LISP_OBJECT(name,c_name,1 /*dumpable*/,marker,printer,nuker,equal,hash,desc,0,sizer,1,structtype) |
1179 #define DEFINE_LRECORD_SEQUENCE_IMPLEMENTATION(name,c_name,dumpable,marker,printer,nuker,equal,hash,desc,sizer,structtype) \ | 1391 |
1180 DEFINE_LRECORD_SEQUENCE_IMPLEMENTATION_WITH_PROPS(name,c_name,dumpable,marker,printer,nuker,equal,hash,desc,0,0,0,0,sizer,structtype) | 1392 #define DEFINE_DUMPABLE_INTERNAL_LISP_OBJECT(name,c_name,marker,desc,structtype) \ |
1181 | 1393 DEFINE_DUMPABLE_LISP_OBJECT(name,c_name,marker,internal_object_printer,0,0,0,desc,structtype) |
1182 #define DEFINE_BASIC_LRECORD_SEQUENCE_IMPLEMENTATION(name,c_name,dumpable,marker,printer,nuker,equal,hash,desc,sizer,structtype) \ | 1394 |
1183 MAKE_LRECORD_IMPLEMENTATION(name,c_name,dumpable,marker,printer,nuker,equal,hash,desc,0,0,0,0,0,sizer,1,structtype) | 1395 #define DEFINE_DUMPABLE_SIZABLE_INTERNAL_LISP_OBJECT(name,c_name,marker,desc,sizer,structtype) \ |
1184 | 1396 DEFINE_DUMPABLE_SIZABLE_LISP_OBJECT(name,c_name,marker,internal_object_printer,0,0,0,desc,sizer,structtype) |
1185 #define DEFINE_LRECORD_SEQUENCE_IMPLEMENTATION_WITH_PROPS(name,c_name,dumpable,marker,printer,nuker,equal,hash,desc,getprop,putprop,remprop,plist,sizer,structtype) \ | 1397 |
1186 MAKE_LRECORD_IMPLEMENTATION(name,c_name,dumpable,marker,printer,nuker,equal,hash,desc,getprop,putprop,remprop,plist,0,sizer,0,structtype) | 1398 /********* The non-dumpable versions *********** */ |
1399 | |
1400 #define DEFINE_NODUMP_LISP_OBJECT(name,c_name,marker,printer,nuker,equal,hash,desc,structtype) \ | |
1401 MAKE_LISP_OBJECT(name,c_name,0 /*non-dumpable*/,marker,printer,nuker,equal,hash,desc,sizeof (structtype),0,0,structtype) | |
1402 | |
1403 #define DEFINE_NODUMP_SIZABLE_LISP_OBJECT(name,c_name,marker,printer,nuker,equal,hash,desc,sizer,structtype) \ | |
1404 MAKE_LISP_OBJECT(name,c_name,0 /*non-dumpable*/,marker,printer,nuker,equal,hash,desc,0,sizer,0,structtype) | |
1405 | |
1406 #define DEFINE_NODUMP_FROB_BLOCK_LISP_OBJECT(name,c_name,marker,printer,nuker,equal,hash,desc,structtype) \ | |
1407 MAKE_LISP_OBJECT(name,c_name,0 /*non-dumpable*/,marker,printer,nuker,equal,hash,desc,sizeof(structtype),0,1,structtype) | |
1408 | |
1409 #define DEFINE_NODUMP_FROB_BLOCK_SIZABLE_LISP_OBJECT(name,c_name,marker,printer,nuker,equal,hash,desc,sizer,structtype) \ | |
1410 MAKE_LISP_OBJECT(name,c_name,0 /*non-dumpable*/,marker,printer,nuker,equal,hash,desc,0,sizer,1,structtype) | |
1411 | |
1412 #define DEFINE_NODUMP_INTERNAL_LISP_OBJECT(name,c_name,marker,desc,structtype) \ | |
1413 DEFINE_NODUMP_LISP_OBJECT(name,c_name,marker,internal_object_printer,0,0,0,desc,structtype) | |
1414 | |
1415 #define DEFINE_NODUMP_SIZABLE_INTERNAL_LISP_OBJECT(name,c_name,marker,desc,sizer,structtype) \ | |
1416 DEFINE_NODUMP_SIZABLE_LISP_OBJECT(name,c_name,marker,internal_object_printer,0,0,0,desc,sizer,structtype) | |
1417 | |
1418 /********* MAKE_LISP_OBJECT, the underlying macro *********** */ | |
1187 | 1419 |
1188 #ifdef NEW_GC | 1420 #ifdef NEW_GC |
1189 #define MAKE_LRECORD_IMPLEMENTATION(name,c_name,dumpable,marker,printer,nuker,equal,hash,desc,getprop,putprop,remprop,plist,size,sizer,basic_p,structtype) \ | 1421 #define MAKE_LISP_OBJECT(name,c_name,dumpable,marker,printer,nuker, \ |
1422 equal,hash,desc,size,sizer,frob_block_p,structtype) \ | |
1190 DECLARE_ERROR_CHECK_TYPES(c_name, structtype) \ | 1423 DECLARE_ERROR_CHECK_TYPES(c_name, structtype) \ |
1191 const struct lrecord_implementation lrecord_##c_name = \ | 1424 struct lrecord_implementation lrecord_##c_name = \ |
1192 { name, dumpable, marker, printer, nuker, equal, hash, desc, \ | 1425 { name, dumpable, marker, printer, nuker, equal, hash, desc, \ |
1193 getprop, putprop, remprop, plist, size, sizer, \ | 1426 size, sizer, lrecord_type_##c_name } |
1194 lrecord_type_##c_name } | |
1195 #else /* not NEW_GC */ | 1427 #else /* not NEW_GC */ |
1196 #define MAKE_LRECORD_IMPLEMENTATION(name,c_name,dumpable,marker,printer,nuker,equal,hash,desc,getprop,putprop,remprop,plist,size,sizer,basic_p,structtype) \ | 1428 #define MAKE_LISP_OBJECT(name,c_name,dumpable,marker,printer,nuker,equal,hash,desc,size,sizer,frob_block_p,structtype) \ |
1197 DECLARE_ERROR_CHECK_TYPES(c_name, structtype) \ | 1429 DECLARE_ERROR_CHECK_TYPES(c_name, structtype) \ |
1198 const struct lrecord_implementation lrecord_##c_name = \ | 1430 struct lrecord_implementation lrecord_##c_name = \ |
1199 { name, dumpable, marker, printer, nuker, equal, hash, desc, \ | 1431 { name, dumpable, marker, printer, nuker, equal, hash, desc, \ |
1200 getprop, putprop, remprop, plist, size, sizer, \ | 1432 size, sizer, lrecord_type_##c_name, frob_block_p } |
1201 lrecord_type_##c_name, basic_p } | |
1202 #endif /* not NEW_GC */ | 1433 #endif /* not NEW_GC */ |
1203 | 1434 |
1204 #define DEFINE_EXTERNAL_LRECORD_IMPLEMENTATION(name,c_name,dumpable,marker,printer,nuker,equal,hash,desc,structtype) \ | 1435 |
1205 DEFINE_EXTERNAL_LRECORD_IMPLEMENTATION_WITH_PROPS(name,c_name,dumpable,marker,printer,nuker,equal,hash,desc,0,0,0,0,structtype) | 1436 /********* The module dumpable versions *********** */ |
1206 | 1437 |
1207 #define DEFINE_EXTERNAL_LRECORD_IMPLEMENTATION_WITH_PROPS(name,c_name,dumpable,marker,printer,nuker,equal,hash,desc,getprop,putprop,remprop,plist,structtype) \ | 1438 #define DEFINE_DUMPABLE_MODULE_LISP_OBJECT(name,c_name,dumpable,marker,printer,nuker,equal,hash,desc,structtype) \ |
1208 MAKE_EXTERNAL_LRECORD_IMPLEMENTATION(name,c_name,dumpable,marker,printer,nuker,equal,hash,desc,getprop,putprop,remprop,plist,sizeof (structtype),0,0,structtype) | 1439 MAKE_MODULE_LISP_OBJECT(name,c_name,1 /*dumpable*/,marker,printer,nuker,equal,hash,desc,sizeof (structtype),0,0,structtype) |
1209 | 1440 |
1210 #define DEFINE_EXTERNAL_LRECORD_SEQUENCE_IMPLEMENTATION(name,c_name,dumpable,marker,printer,nuker,equal,hash,desc,sizer,structtype) \ | 1441 #define DEFINE_DUMPABLE_MODULE_SIZABLE_LISP_OBJECT(name,c_name,dumpable,marker,printer,nuker,equal,hash,desc,sizer,structtype) \ |
1211 DEFINE_EXTERNAL_LRECORD_SEQUENCE_IMPLEMENTATION_WITH_PROPS(name,c_name,dumpable,marker,printer,nuker,equal,hash,desc,0,0,0,0,sizer,structtype) | 1442 MAKE_MODULE_LISP_OBJECT(name,c_name,1 /*dumpable*/,marker,printer,nuker,equal,hash,desc,0,sizer,0,structtype) |
1212 | 1443 |
1213 #define DEFINE_EXTERNAL_LRECORD_SEQUENCE_IMPLEMENTATION_WITH_PROPS(name,c_name,dumpable,marker,printer,nuker,equal,hash,desc,getprop,putprop,remprop,plist,sizer,structtype) \ | 1444 /********* The module non-dumpable versions *********** */ |
1214 MAKE_EXTERNAL_LRECORD_IMPLEMENTATION(name,c_name,dumpable,marker,printer,nuker,equal,hash,desc,getprop,putprop,remprop,plist,0,sizer,0,structtype) | 1445 |
1446 #define DEFINE_NODUMP_MODULE_LISP_OBJECT(name,c_name,dumpable,marker, \ | |
1447 printer,nuker,equal,hash,desc,structtype) \ | |
1448 MAKE_MODULE_LISP_OBJECT(name,c_name,0 /*non-dumpable*/,marker,printer, \ | |
1449 nuker,equal,hash,desc,sizeof (structtype),0,0,structtype) | |
1450 | |
1451 #define DEFINE_NODUMP_MODULE_SIZABLE_LISP_OBJECT(name,c_name,dumpable, \ | |
1452 marker,printer,nuker,equal,hash,desc,sizer,structtype) \ | |
1453 MAKE_MODULE_LISP_OBJECT(name,c_name,0 /*non-dumpable*/,marker,printer, \ | |
1454 nuker,equal,hash,desc,0,sizer,0,structtype) | |
1455 | |
1456 /********* MAKE_MODULE_LISP_OBJECT, the underlying macro *********** */ | |
1215 | 1457 |
1216 #ifdef NEW_GC | 1458 #ifdef NEW_GC |
1217 #define MAKE_EXTERNAL_LRECORD_IMPLEMENTATION(name,c_name,dumpable,marker,printer,nuker,equal,hash,desc,getprop,putprop,remprop,plist,size,sizer,basic_p,structtype) \ | 1459 #define MAKE_MODULE_LISP_OBJECT(name,c_name,dumpable,marker,printer, \ |
1460 nuker,equal,hash,desc,size,sizer,frob_block_p,structtype) \ | |
1218 DECLARE_ERROR_CHECK_TYPES(c_name, structtype) \ | 1461 DECLARE_ERROR_CHECK_TYPES(c_name, structtype) \ |
1219 int lrecord_type_##c_name; \ | 1462 int lrecord_type_##c_name; \ |
1220 struct lrecord_implementation lrecord_##c_name = \ | 1463 struct lrecord_implementation lrecord_##c_name = \ |
1221 { name, dumpable, marker, printer, nuker, equal, hash, desc, \ | 1464 { name, dumpable, marker, printer, nuker, equal, hash, desc, \ |
1222 getprop, putprop, remprop, plist, size, sizer, \ | 1465 size, sizer, lrecord_type_last_built_in_type } |
1223 lrecord_type_last_built_in_type } | |
1224 #else /* not NEW_GC */ | 1466 #else /* not NEW_GC */ |
1225 #define MAKE_EXTERNAL_LRECORD_IMPLEMENTATION(name,c_name,dumpable,marker,printer,nuker,equal,hash,desc,getprop,putprop,remprop,plist,size,sizer,basic_p,structtype) \ | 1467 #define MAKE_MODULE_LISP_OBJECT(name,c_name,dumpable,marker,printer, \ |
1468 nuker,equal,hash,desc,size,sizer,frob_block_p,structtype) \ | |
1226 DECLARE_ERROR_CHECK_TYPES(c_name, structtype) \ | 1469 DECLARE_ERROR_CHECK_TYPES(c_name, structtype) \ |
1227 int lrecord_type_##c_name; \ | 1470 int lrecord_type_##c_name; \ |
1228 struct lrecord_implementation lrecord_##c_name = \ | 1471 struct lrecord_implementation lrecord_##c_name = \ |
1229 { name, dumpable, marker, printer, nuker, equal, hash, desc, \ | 1472 { name, dumpable, marker, printer, nuker, equal, hash, desc, \ |
1230 getprop, putprop, remprop, plist, size, sizer, \ | 1473 size, sizer, lrecord_type_last_built_in_type, frob_block_p } |
1231 lrecord_type_last_built_in_type, basic_p } | |
1232 #endif /* not NEW_GC */ | 1474 #endif /* not NEW_GC */ |
1475 | |
1476 #ifdef MEMORY_USAGE_STATS | |
1477 #define INIT_MEMORY_USAGE_STATS(type) \ | |
1478 do \ | |
1479 { \ | |
1480 lrecord_implementations_table[lrecord_type_##type]-> \ | |
1481 memusage_stats_list = Qnil; \ | |
1482 lrecord_implementations_table[lrecord_type_##type]-> \ | |
1483 num_extra_memusage_stats = -1; \ | |
1484 lrecord_implementations_table[lrecord_type_##type]-> \ | |
1485 num_extra_nonlisp_memusage_stats = -1; \ | |
1486 staticpro (&lrecord_implementations_table[lrecord_type_##type]-> \ | |
1487 memusage_stats_list); \ | |
1488 } while (0) | |
1489 #else | |
1490 #define INIT_MEMORY_USAGE_STATS(type) DO_NOTHING | |
1491 #endif /* (not) MEMORY_USAGE_STATS */ | |
1492 | |
1493 #define INIT_LISP_OBJECT_BEGINNING(type) \ | |
1494 do \ | |
1495 { \ | |
1496 lrecord_implementations_table[lrecord_type_##type] = &lrecord_##type; \ | |
1497 INIT_MEMORY_USAGE_STATS (type); \ | |
1498 } while (0) | |
1233 | 1499 |
1234 #ifdef USE_KKCC | 1500 #ifdef USE_KKCC |
1235 extern MODULE_API const struct memory_description *lrecord_memory_descriptions[]; | 1501 extern MODULE_API const struct memory_description *lrecord_memory_descriptions[]; |
1236 | 1502 |
1237 #define INIT_LRECORD_IMPLEMENTATION(type) do { \ | 1503 #define INIT_LISP_OBJECT(type) do { \ |
1238 lrecord_implementations_table[lrecord_type_##type] = &lrecord_##type; \ | 1504 INIT_LISP_OBJECT_BEGINNING (type); \ |
1239 lrecord_memory_descriptions[lrecord_type_##type] = \ | 1505 lrecord_memory_descriptions[lrecord_type_##type] = \ |
1240 lrecord_implementations_table[lrecord_type_##type]->description; \ | 1506 lrecord_implementations_table[lrecord_type_##type]->description; \ |
1241 } while (0) | 1507 } while (0) |
1242 #else /* not USE_KKCC */ | 1508 #else /* not USE_KKCC */ |
1243 extern MODULE_API Lisp_Object (*lrecord_markers[]) (Lisp_Object); | 1509 extern MODULE_API Lisp_Object (*lrecord_markers[]) (Lisp_Object); |
1244 | 1510 |
1245 #define INIT_LRECORD_IMPLEMENTATION(type) do { \ | 1511 #define INIT_LISP_OBJECT(type) do { \ |
1246 lrecord_implementations_table[lrecord_type_##type] = &lrecord_##type; \ | 1512 INIT_LISP_OBJECT_BEGINNING (type); \ |
1247 lrecord_markers[lrecord_type_##type] = \ | 1513 lrecord_markers[lrecord_type_##type] = \ |
1248 lrecord_implementations_table[lrecord_type_##type]->marker; \ | 1514 lrecord_implementations_table[lrecord_type_##type]->marker; \ |
1249 } while (0) | 1515 } while (0) |
1250 #endif /* not USE_KKCC */ | 1516 #endif /* not USE_KKCC */ |
1251 | 1517 |
1252 #define INIT_EXTERNAL_LRECORD_IMPLEMENTATION(type) do { \ | 1518 #define INIT_MODULE_LISP_OBJECT(type) do { \ |
1253 lrecord_type_##type = lrecord_type_count++; \ | 1519 lrecord_type_##type = lrecord_type_count++; \ |
1254 lrecord_##type.lrecord_type_index = lrecord_type_##type; \ | 1520 lrecord_##type.lrecord_type_index = lrecord_type_##type; \ |
1255 INIT_LRECORD_IMPLEMENTATION(type); \ | 1521 INIT_LISP_OBJECT (type); \ |
1256 } while (0) | 1522 } while (0) |
1257 | 1523 |
1258 #ifdef HAVE_SHLIB | 1524 #ifdef HAVE_SHLIB |
1259 /* Allow undefining types in order to support module unloading. */ | 1525 /* Allow undefining types in order to support module unloading. */ |
1260 | 1526 |
1261 #ifdef USE_KKCC | 1527 #ifdef USE_KKCC |
1262 #define UNDEF_LRECORD_IMPLEMENTATION(type) do { \ | 1528 #define UNDEF_LISP_OBJECT(type) do { \ |
1263 lrecord_implementations_table[lrecord_type_##type] = NULL; \ | 1529 lrecord_implementations_table[lrecord_type_##type] = NULL; \ |
1264 lrecord_memory_descriptions[lrecord_type_##type] = NULL; \ | 1530 lrecord_memory_descriptions[lrecord_type_##type] = NULL; \ |
1265 } while (0) | 1531 } while (0) |
1266 #else /* not USE_KKCC */ | 1532 #else /* not USE_KKCC */ |
1267 #define UNDEF_LRECORD_IMPLEMENTATION(type) do { \ | 1533 #define UNDEF_LISP_OBJECT(type) do { \ |
1268 lrecord_implementations_table[lrecord_type_##type] = NULL; \ | 1534 lrecord_implementations_table[lrecord_type_##type] = NULL; \ |
1269 lrecord_markers[lrecord_type_##type] = NULL; \ | 1535 lrecord_markers[lrecord_type_##type] = NULL; \ |
1270 } while (0) | 1536 } while (0) |
1271 #endif /* not USE_KKCC */ | 1537 #endif /* not USE_KKCC */ |
1272 | 1538 |
1273 #define UNDEF_EXTERNAL_LRECORD_IMPLEMENTATION(type) do { \ | 1539 #define UNDEF_MODULE_LISP_OBJECT(type) do { \ |
1274 if (lrecord_##type.lrecord_type_index == lrecord_type_count - 1) { \ | 1540 if (lrecord_##type.lrecord_type_index == lrecord_type_count - 1) { \ |
1275 /* This is the most recently defined type. Clean up nicely. */ \ | 1541 /* This is the most recently defined type. Clean up nicely. */ \ |
1276 lrecord_type_##type = lrecord_type_count--; \ | 1542 lrecord_type_##type = lrecord_type_count--; \ |
1277 } /* Else we can't help leaving a hole with this implementation. */ \ | 1543 } /* Else we can't help leaving a hole with this implementation. */ \ |
1278 UNDEF_LRECORD_IMPLEMENTATION(type); \ | 1544 UNDEF_LISP_OBJECT(type); \ |
1279 } while (0) | 1545 } while (0) |
1280 | 1546 |
1281 #endif /* HAVE_SHLIB */ | 1547 #endif /* HAVE_SHLIB */ |
1548 | |
1549 /*************** Macros for declaring that a Lisp object has a | |
1550 particular method, or for calling such a method. ********/ | |
1551 | |
1552 /* Declare that object-type TYPE has method M; used in | |
1553 initialization routines */ | |
1554 #define OBJECT_HAS_METHOD(type, m) \ | |
1555 (lrecord_##type.m = type##_##m) | |
1556 /* Same but the method name come before the type */ | |
1557 #define OBJECT_HAS_PREMETHOD(type, m) \ | |
1558 (lrecord_##type.m = m##_##type) | |
1559 /* Same but the name of the method is explicitly given */ | |
1560 #define OBJECT_HAS_NAMED_METHOD(type, m, func) \ | |
1561 (lrecord_##type.m = (func)) | |
1562 /* Object type has a property with the given value. */ | |
1563 #define OBJECT_HAS_PROPERTY(type, prop, val) \ | |
1564 (lrecord_##type.prop = (val)) | |
1565 | |
1566 /* Does the given object method exist? */ | |
1567 #define HAS_OBJECT_METH_P(obj, m) \ | |
1568 (!!(XRECORD_LHEADER_IMPLEMENTATION (obj)->m)) | |
1569 /* Call an object method. */ | |
1570 #define OBJECT_METH(obj, m, args) \ | |
1571 ((XRECORD_LHEADER_IMPLEMENTATION (obj)->m) args) | |
1572 | |
1573 /* Call an object method, if it exists. */ | |
1574 #define MAYBE_OBJECT_METH(obj, m, args) \ | |
1575 do \ | |
1576 { \ | |
1577 const struct lrecord_implementation *_mom_imp = \ | |
1578 XRECORD_LHEADER_IMPLEMENTATION (obj); \ | |
1579 if (_mom_imp->m) \ | |
1580 ((_mom_imp->m) args); \ | |
1581 } while (0) | |
1582 | |
1583 /* Call an object method, if it exists, or return GIVEN. NOTE: | |
1584 Multiply-evaluates OBJ. */ | |
1585 #define OBJECT_METH_OR_GIVEN(obj, m, args, given) \ | |
1586 (HAS_OBJECT_METH_P (obj, m) ? OBJECT_METH (obj, m, args) : (given)) | |
1587 | |
1588 #define OBJECT_PROPERTY(obj, prop) (XRECORD_LHEADER_IMPLEMENTATION (obj)->prop) | |
1589 | |
1590 /************** Other stuff **************/ | |
1282 | 1591 |
1283 #define LRECORDP(a) (XTYPE (a) == Lisp_Type_Record) | 1592 #define LRECORDP(a) (XTYPE (a) == Lisp_Type_Record) |
1284 #define XRECORD_LHEADER(a) ((struct lrecord_header *) XPNTR (a)) | 1593 #define XRECORD_LHEADER(a) ((struct lrecord_header *) XPNTR (a)) |
1285 | 1594 |
1286 #define RECORD_TYPEP(x, ty) \ | 1595 #define RECORD_TYPEP(x, ty) \ |
1289 /* Steps to create a new object: | 1598 /* Steps to create a new object: |
1290 | 1599 |
1291 1. Declare the struct for your object in a header file somewhere. | 1600 1. Declare the struct for your object in a header file somewhere. |
1292 Remember that it must begin with | 1601 Remember that it must begin with |
1293 | 1602 |
1294 struct LCRECORD_HEADER header; | 1603 NORMAL_LISP_OBJECT_HEADER header; |
1295 | 1604 |
1296 2. Put the "standard junk" (DECLARE_RECORD()/XFOO/etc.) below the | 1605 2. Put the "standard junk" (DECLARE_LISP_OBJECT()/XFOO/etc.) below the |
1297 struct definition -- see below. | 1606 struct definition -- see below. |
1298 | 1607 |
1299 3. Add this header file to inline.c. | 1608 3. Add this header file to inline.c. |
1300 | 1609 |
1301 4. Create the methods for your object. Note that technically you don't | 1610 4. Create the methods for your object. Note that technically you don't |
1304 4. Create the data layout description for your object. See | 1613 4. Create the data layout description for your object. See |
1305 toolbar_button_description below; the comment above in `struct lrecord', | 1614 toolbar_button_description below; the comment above in `struct lrecord', |
1306 describing the purpose of the descriptions; and comments elsewhere in | 1615 describing the purpose of the descriptions; and comments elsewhere in |
1307 this file describing the exact syntax of the description structures. | 1616 this file describing the exact syntax of the description structures. |
1308 | 1617 |
1309 6. Define your object with DEFINE_LRECORD_IMPLEMENTATION() or some | 1618 6. Define your object with DEFINE_*_LISP_OBJECT() or some |
1310 variant. | 1619 variant. At the minimum, you need to decide whether your object can |
1620 be dumped. Objects that are created as part of the loadup process and | |
1621 need to be persistent across dumping should be created dumpable. | |
1622 Nondumpable objects are generally those associated with display, | |
1623 particularly those containing a pointer to an external library object | |
1624 (e.g. a window-system window). | |
1311 | 1625 |
1312 7. Include the header file in the .c file where you defined the object. | 1626 7. Include the header file in the .c file where you defined the object. |
1313 | 1627 |
1314 8. Put a call to INIT_LRECORD_IMPLEMENTATION() for the object in the | 1628 8. Put a call to INIT_LISP_OBJECT() for the object in the |
1315 .c file's syms_of_foo() function. | 1629 .c file's syms_of_foo() function. |
1316 | 1630 |
1317 9. Add a type enum for the object to enum lrecord_type, earlier in this | 1631 9. Add a type enum for the object to enum lrecord_type, earlier in this |
1318 file. | 1632 file. |
1319 | 1633 |
1320 --ben | 1634 --ben |
1321 | 1635 |
1322 An example: | 1636 An example: |
1323 | 1637 |
1324 ------------------------------ in toolbar.h ----------------------------- | 1638 ------------------------------ in toolbar.h ----------------------------- |
1325 | 1639 |
1326 struct toolbar_button | 1640 struct toolbar_button |
1327 { | 1641 { |
1328 struct LCRECORD_HEADER header; | 1642 NORMAL_LISP_OBJECT_HEADER header; |
1329 | 1643 |
1330 Lisp_Object next; | 1644 Lisp_Object next; |
1331 Lisp_Object frame; | 1645 Lisp_Object frame; |
1332 | 1646 |
1333 Lisp_Object up_glyph; | 1647 Lisp_Object up_glyph; |
1334 Lisp_Object down_glyph; | 1648 Lisp_Object down_glyph; |
1335 Lisp_Object disabled_glyph; | 1649 Lisp_Object disabled_glyph; |
1336 | 1650 |
1337 Lisp_Object cap_up_glyph; | 1651 Lisp_Object cap_up_glyph; |
1338 Lisp_Object cap_down_glyph; | 1652 Lisp_Object cap_down_glyph; |
1339 Lisp_Object cap_disabled_glyph; | 1653 Lisp_Object cap_disabled_glyph; |
1340 | 1654 |
1341 Lisp_Object callback; | 1655 Lisp_Object callback; |
1342 Lisp_Object enabled_p; | 1656 Lisp_Object enabled_p; |
1343 Lisp_Object help_string; | 1657 Lisp_Object help_string; |
1344 | 1658 |
1345 char enabled; | 1659 char enabled; |
1346 char down; | 1660 char down; |
1347 char pushright; | 1661 char pushright; |
1348 char blank; | 1662 char blank; |
1349 | 1663 |
1350 int x, y; | 1664 int x, y; |
1351 int width, height; | 1665 int width, height; |
1352 int dirty; | 1666 int dirty; |
1353 int vertical; | 1667 int vertical; |
1354 int border_width; | 1668 int border_width; |
1355 }; | 1669 }; |
1356 | 1670 |
1357 [[ the standard junk: ]] | 1671 [[ the standard junk: ]] |
1358 | 1672 |
1359 DECLARE_LRECORD (toolbar_button, struct toolbar_button); | 1673 DECLARE_LISP_OBJECT (toolbar_button, struct toolbar_button); |
1360 #define XTOOLBAR_BUTTON(x) XRECORD (x, toolbar_button, struct toolbar_button) | 1674 #define XTOOLBAR_BUTTON(x) XRECORD (x, toolbar_button, struct toolbar_button) |
1361 #define wrap_toolbar_button(p) wrap_record (p, toolbar_button) | 1675 #define wrap_toolbar_button(p) wrap_record (p, toolbar_button) |
1362 #define TOOLBAR_BUTTONP(x) RECORDP (x, toolbar_button) | 1676 #define TOOLBAR_BUTTONP(x) RECORDP (x, toolbar_button) |
1363 #define CHECK_TOOLBAR_BUTTON(x) CHECK_RECORD (x, toolbar_button) | 1677 #define CHECK_TOOLBAR_BUTTON(x) CHECK_RECORD (x, toolbar_button) |
1364 #define CONCHECK_TOOLBAR_BUTTON(x) CONCHECK_RECORD (x, toolbar_button) | 1678 #define CONCHECK_TOOLBAR_BUTTON(x) CONCHECK_RECORD (x, toolbar_button) |
1365 | 1679 |
1366 ------------------------------ in toolbar.c ----------------------------- | 1680 ------------------------------ in toolbar.c ----------------------------- |
1367 | 1681 |
1368 #include "toolbar.h" | 1682 #include "toolbar.h" |
1369 | 1683 |
1370 ... | 1684 ... |
1371 | 1685 |
1372 static const struct memory_description toolbar_button_description [] = { | 1686 static const struct memory_description toolbar_button_description [] = { |
1373 { XD_LISP_OBJECT, offsetof (struct toolbar_button, next) }, | 1687 { XD_LISP_OBJECT, offsetof (struct toolbar_button, next) }, |
1374 { XD_LISP_OBJECT, offsetof (struct toolbar_button, frame) }, | 1688 { XD_LISP_OBJECT, offsetof (struct toolbar_button, frame) }, |
1375 { XD_LISP_OBJECT, offsetof (struct toolbar_button, up_glyph) }, | 1689 { XD_LISP_OBJECT, offsetof (struct toolbar_button, up_glyph) }, |
1376 { XD_LISP_OBJECT, offsetof (struct toolbar_button, down_glyph) }, | 1690 { XD_LISP_OBJECT, offsetof (struct toolbar_button, down_glyph) }, |
1377 { XD_LISP_OBJECT, offsetof (struct toolbar_button, disabled_glyph) }, | 1691 { XD_LISP_OBJECT, offsetof (struct toolbar_button, disabled_glyph) }, |
1378 { XD_LISP_OBJECT, offsetof (struct toolbar_button, cap_up_glyph) }, | 1692 { XD_LISP_OBJECT, offsetof (struct toolbar_button, cap_up_glyph) }, |
1379 { XD_LISP_OBJECT, offsetof (struct toolbar_button, cap_down_glyph) }, | 1693 { XD_LISP_OBJECT, offsetof (struct toolbar_button, cap_down_glyph) }, |
1380 { XD_LISP_OBJECT, offsetof (struct toolbar_button, cap_disabled_glyph) }, | 1694 { XD_LISP_OBJECT, offsetof (struct toolbar_button, cap_disabled_glyph) }, |
1381 { XD_LISP_OBJECT, offsetof (struct toolbar_button, callback) }, | 1695 { XD_LISP_OBJECT, offsetof (struct toolbar_button, callback) }, |
1382 { XD_LISP_OBJECT, offsetof (struct toolbar_button, enabled_p) }, | 1696 { XD_LISP_OBJECT, offsetof (struct toolbar_button, enabled_p) }, |
1383 { XD_LISP_OBJECT, offsetof (struct toolbar_button, help_string) }, | 1697 { XD_LISP_OBJECT, offsetof (struct toolbar_button, help_string) }, |
1384 { XD_END } | 1698 { XD_END } |
1385 }; | 1699 }; |
1386 | 1700 |
1387 static Lisp_Object | 1701 static Lisp_Object |
1388 mark_toolbar_button (Lisp_Object obj) | 1702 allocate_toolbar_button (struct frame *f, int pushright) |
1389 \{ | 1703 { |
1390 struct toolbar_button *data = XTOOLBAR_BUTTON (obj); | 1704 struct toolbar_button *tb; |
1391 mark_object (data->next); | 1705 |
1392 mark_object (data->frame); | 1706 tb = XTOOLBAR_BUTTON (ALLOC_NORMAL_LISP_OBJECT (toolbar_button)); |
1393 mark_object (data->up_glyph); | 1707 tb->next = Qnil; |
1394 mark_object (data->down_glyph); | 1708 tb->frame = wrap_frame (f); |
1395 mark_object (data->disabled_glyph); | 1709 tb->up_glyph = Qnil; |
1396 mark_object (data->cap_up_glyph); | 1710 tb->down_glyph = Qnil; |
1397 mark_object (data->cap_down_glyph); | 1711 tb->disabled_glyph = Qnil; |
1398 mark_object (data->cap_disabled_glyph); | 1712 tb->cap_up_glyph = Qnil; |
1399 mark_object (data->callback); | 1713 tb->cap_down_glyph = Qnil; |
1400 mark_object (data->enabled_p); | 1714 tb->cap_disabled_glyph = Qnil; |
1401 return data->help_string; | 1715 tb->callback = Qnil; |
1402 } | 1716 tb->enabled_p = Qnil; |
1403 | 1717 tb->help_string = Qnil; |
1404 [[ If your object should never escape to Lisp, declare its print method | 1718 |
1405 as internal_object_printer instead of 0. ]] | 1719 tb->pushright = pushright; |
1406 | 1720 tb->x = tb->y = tb->width = tb->height = -1; |
1407 DEFINE_LRECORD_IMPLEMENTATION ("toolbar-button", toolbar_button, | 1721 tb->dirty = 1; |
1408 0, mark_toolbar_button, 0, 0, 0, 0, | 1722 |
1409 toolbar_button_description, | 1723 return wrap_toolbar_button (tb); |
1410 struct toolbar_button); | 1724 } |
1411 | 1725 |
1412 ... | 1726 static Lisp_Object |
1413 | 1727 mark_toolbar_button (Lisp_Object obj) |
1414 void | 1728 { |
1415 syms_of_toolbar (void) | 1729 struct toolbar_button *data = XTOOLBAR_BUTTON (obj); |
1416 { | 1730 mark_object (data->next); |
1417 INIT_LRECORD_IMPLEMENTATION (toolbar_button); | 1731 mark_object (data->frame); |
1418 | 1732 mark_object (data->up_glyph); |
1419 ...; | 1733 mark_object (data->down_glyph); |
1420 } | 1734 mark_object (data->disabled_glyph); |
1421 | 1735 mark_object (data->cap_up_glyph); |
1736 mark_object (data->cap_down_glyph); | |
1737 mark_object (data->cap_disabled_glyph); | |
1738 mark_object (data->callback); | |
1739 mark_object (data->enabled_p); | |
1740 return data->help_string; | |
1741 } | |
1742 | |
1743 DEFINE_NODUMP_LISP_OBJECT ("toolbar-button", toolbar_button, | |
1744 mark_toolbar_button, | |
1745 external_object_printer, 0, 0, 0, | |
1746 toolbar_button_description, | |
1747 struct toolbar_button); | |
1748 | |
1749 ... | |
1750 | |
1751 void | |
1752 syms_of_toolbar (void) | |
1753 { | |
1754 INIT_LISP_OBJECT (toolbar_button); | |
1755 | |
1756 ...; | |
1757 } | |
1758 | |
1422 ------------------------------ in inline.c ----------------------------- | 1759 ------------------------------ in inline.c ----------------------------- |
1423 | 1760 |
1424 #ifdef HAVE_TOOLBARS | 1761 #ifdef HAVE_TOOLBARS |
1425 #include "toolbar.h" | 1762 #include "toolbar.h" |
1426 #endif | 1763 #endif |
1427 | 1764 |
1428 ------------------------------ in lrecord.h ----------------------------- | 1765 ------------------------------ in lrecord.h ----------------------------- |
1429 | 1766 |
1430 enum lrecord_type | 1767 enum lrecord_type |
1431 { | 1768 { |
1769 ... | |
1770 lrecord_type_toolbar_button, | |
1771 ... | |
1772 }; | |
1773 | |
1774 ------------------------------ in .gdbinit.in.in ----------------------------- | |
1775 | |
1432 ... | 1776 ... |
1433 lrecord_type_toolbar_button, | 1777 else |
1778 if $lrecord_type == lrecord_type_toolbar_button | |
1779 pstructtype toolbar_button | |
1434 ... | 1780 ... |
1435 }; | 1781 ... |
1436 | 1782 ... |
1437 | 1783 end |
1438 --ben | 1784 |
1785 --ben | |
1439 | 1786 |
1440 */ | 1787 */ |
1441 | 1788 |
1442 /* | 1789 /* |
1443 | 1790 |
1444 Note: Object types defined in external dynamically-loaded modules (not | 1791 Note: Object types defined in external dynamically-loaded modules (not |
1445 part of the XEmacs main source code) should use DECLARE_EXTERNAL_LRECORD | 1792 part of the XEmacs main source code) should use DECLARE_*_MODULE_LISP_OBJECT |
1446 and DEFINE_EXTERNAL_LRECORD_IMPLEMENTATION rather than DECLARE_LRECORD | 1793 and DEFINE_*_MODULE_LISP_OBJECT rather than DECLARE_*_LISP_OBJECT |
1447 and DEFINE_LRECORD_IMPLEMENTATION. The EXTERNAL versions declare and | 1794 and DEFINE_*_LISP_OBJECT. The MODULE versions declare and |
1448 allocate an enumerator for the type being defined. | 1795 allocate an enumerator for the type being defined. |
1449 | 1796 |
1450 */ | 1797 */ |
1451 | 1798 |
1452 | 1799 |
1453 #ifdef ERROR_CHECK_TYPES | 1800 #ifdef ERROR_CHECK_TYPES |
1454 | 1801 |
1455 # define DECLARE_LRECORD(c_name, structtype) \ | 1802 # define DECLARE_LISP_OBJECT(c_name, structtype) \ |
1456 extern const struct lrecord_implementation lrecord_##c_name; \ | 1803 extern struct lrecord_implementation lrecord_##c_name; \ |
1457 DECLARE_INLINE_HEADER ( \ | |
1458 structtype * \ | |
1459 error_check_##c_name (Lisp_Object obj, const Ascbyte *file, int line) \ | |
1460 ) \ | |
1461 { \ | |
1462 assert_at_line (RECORD_TYPEP (obj, lrecord_type_##c_name), file, line); \ | |
1463 return (structtype *) XPNTR (obj); \ | |
1464 } \ | |
1465 extern Lisp_Object Q##c_name##p | |
1466 | |
1467 # define DECLARE_MODULE_API_LRECORD(c_name, structtype) \ | |
1468 extern MODULE_API const struct lrecord_implementation lrecord_##c_name; \ | |
1469 DECLARE_INLINE_HEADER ( \ | |
1470 structtype * \ | |
1471 error_check_##c_name (Lisp_Object obj, const Ascbyte *file, int line) \ | |
1472 ) \ | |
1473 { \ | |
1474 assert_at_line (RECORD_TYPEP (obj, lrecord_type_##c_name), file, line); \ | |
1475 return (structtype *) XPNTR (obj); \ | |
1476 } \ | |
1477 extern MODULE_API Lisp_Object Q##c_name##p | |
1478 | |
1479 # define DECLARE_EXTERNAL_LRECORD(c_name, structtype) \ | |
1480 extern int lrecord_type_##c_name; \ | |
1481 extern struct lrecord_implementation lrecord_##c_name; \ | |
1482 DECLARE_INLINE_HEADER ( \ | |
1483 structtype * \ | |
1484 error_check_##c_name (Lisp_Object obj, const Ascbyte *file, int line) \ | |
1485 ) \ | |
1486 { \ | |
1487 assert_at_line (RECORD_TYPEP (obj, lrecord_type_##c_name), file, line); \ | |
1488 return (structtype *) XPNTR (obj); \ | |
1489 } \ | |
1490 extern Lisp_Object Q##c_name##p | |
1491 | |
1492 # define DECLARE_NONRECORD(c_name, type_enum, structtype) \ | |
1493 DECLARE_INLINE_HEADER ( \ | 1804 DECLARE_INLINE_HEADER ( \ |
1494 structtype * \ | 1805 structtype * \ |
1495 error_check_##c_name (Lisp_Object obj, const Ascbyte *file, int line) \ | 1806 error_check_##c_name (Lisp_Object obj, const Ascbyte *file, int line) \ |
1496 ) \ | 1807 ) \ |
1497 { \ | 1808 { \ |
1498 assert_at_line (XTYPE (obj) == type_enum, file, line); \ | 1809 assert_at_line (RECORD_TYPEP (obj, lrecord_type_##c_name), file, line); \ |
1499 return (structtype *) XPNTR (obj); \ | 1810 return (structtype *) XPNTR (obj); \ |
1500 } \ | 1811 } \ |
1501 extern Lisp_Object Q##c_name##p | 1812 extern Lisp_Object Q##c_name##p |
1502 | 1813 |
1814 # define DECLARE_MODULE_API_LISP_OBJECT(c_name, structtype) \ | |
1815 extern MODULE_API struct lrecord_implementation lrecord_##c_name; \ | |
1816 DECLARE_INLINE_HEADER ( \ | |
1817 structtype * \ | |
1818 error_check_##c_name (Lisp_Object obj, const Ascbyte *file, int line) \ | |
1819 ) \ | |
1820 { \ | |
1821 assert_at_line (RECORD_TYPEP (obj, lrecord_type_##c_name), file, line); \ | |
1822 return (structtype *) XPNTR (obj); \ | |
1823 } \ | |
1824 extern MODULE_API Lisp_Object Q##c_name##p | |
1825 | |
1826 # define DECLARE_MODULE_LISP_OBJECT(c_name, structtype) \ | |
1827 extern int lrecord_type_##c_name; \ | |
1828 extern struct lrecord_implementation lrecord_##c_name; \ | |
1829 DECLARE_INLINE_HEADER ( \ | |
1830 structtype * \ | |
1831 error_check_##c_name (Lisp_Object obj, const Ascbyte *file, int line) \ | |
1832 ) \ | |
1833 { \ | |
1834 assert_at_line (RECORD_TYPEP (obj, lrecord_type_##c_name), file, line); \ | |
1835 return (structtype *) XPNTR (obj); \ | |
1836 } \ | |
1837 extern Lisp_Object Q##c_name##p | |
1838 | |
1503 # define XRECORD(x, c_name, structtype) \ | 1839 # define XRECORD(x, c_name, structtype) \ |
1504 error_check_##c_name (x, __FILE__, __LINE__) | |
1505 # define XNONRECORD(x, c_name, type_enum, structtype) \ | |
1506 error_check_##c_name (x, __FILE__, __LINE__) | 1840 error_check_##c_name (x, __FILE__, __LINE__) |
1507 | 1841 |
1508 DECLARE_INLINE_HEADER ( | 1842 DECLARE_INLINE_HEADER ( |
1509 Lisp_Object | 1843 Lisp_Object |
1510 wrap_record_1 (const void *ptr, enum lrecord_type ty, const Ascbyte *file, | 1844 wrap_record_1 (const void *ptr, enum lrecord_type ty, const Ascbyte *file, |
1520 #define wrap_record(ptr, ty) \ | 1854 #define wrap_record(ptr, ty) \ |
1521 wrap_record_1 (ptr, lrecord_type_##ty, __FILE__, __LINE__) | 1855 wrap_record_1 (ptr, lrecord_type_##ty, __FILE__, __LINE__) |
1522 | 1856 |
1523 #else /* not ERROR_CHECK_TYPES */ | 1857 #else /* not ERROR_CHECK_TYPES */ |
1524 | 1858 |
1525 # define DECLARE_LRECORD(c_name, structtype) \ | 1859 # define DECLARE_LISP_OBJECT(c_name, structtype) \ |
1526 extern Lisp_Object Q##c_name##p; \ | 1860 extern Lisp_Object Q##c_name##p; \ |
1527 extern const struct lrecord_implementation lrecord_##c_name | 1861 extern struct lrecord_implementation lrecord_##c_name |
1528 # define DECLARE_MODULE_API_LRECORD(c_name, structtype) \ | 1862 # define DECLARE_MODULE_API_LISP_OBJECT(c_name, structtype) \ |
1529 extern MODULE_API Lisp_Object Q##c_name##p; \ | 1863 extern MODULE_API Lisp_Object Q##c_name##p; \ |
1530 extern MODULE_API const struct lrecord_implementation lrecord_##c_name | 1864 extern MODULE_API struct lrecord_implementation lrecord_##c_name |
1531 # define DECLARE_EXTERNAL_LRECORD(c_name, structtype) \ | 1865 # define DECLARE_MODULE_LISP_OBJECT(c_name, structtype) \ |
1532 extern Lisp_Object Q##c_name##p; \ | 1866 extern Lisp_Object Q##c_name##p; \ |
1533 extern int lrecord_type_##c_name; \ | 1867 extern int lrecord_type_##c_name; \ |
1534 extern struct lrecord_implementation lrecord_##c_name | 1868 extern struct lrecord_implementation lrecord_##c_name |
1535 # define DECLARE_NONRECORD(c_name, type_enum, structtype) \ | |
1536 extern Lisp_Object Q##c_name##p | |
1537 # define XRECORD(x, c_name, structtype) ((structtype *) XPNTR (x)) | 1869 # define XRECORD(x, c_name, structtype) ((structtype *) XPNTR (x)) |
1538 # define XNONRECORD(x, c_name, type_enum, structtype) \ | |
1539 ((structtype *) XPNTR (x)) | |
1540 /* wrap_pointer_1 is so named as a suggestion not to use it unless you | 1870 /* wrap_pointer_1 is so named as a suggestion not to use it unless you |
1541 know what you're doing. */ | 1871 know what you're doing. */ |
1542 #define wrap_record(ptr, ty) wrap_pointer_1 (ptr) | 1872 #define wrap_record(ptr, ty) wrap_pointer_1 (ptr) |
1543 | 1873 |
1544 #endif /* not ERROR_CHECK_TYPES */ | 1874 #endif /* not ERROR_CHECK_TYPES */ |
1588 #ifndef NEW_GC | 1918 #ifndef NEW_GC |
1589 /*-------------------------- lcrecord-list -----------------------------*/ | 1919 /*-------------------------- lcrecord-list -----------------------------*/ |
1590 | 1920 |
1591 struct lcrecord_list | 1921 struct lcrecord_list |
1592 { | 1922 { |
1593 struct LCRECORD_HEADER header; | 1923 NORMAL_LISP_OBJECT_HEADER header; |
1594 Lisp_Object free; | 1924 Lisp_Object free; |
1595 Elemcount size; | 1925 Elemcount size; |
1596 const struct lrecord_implementation *implementation; | 1926 const struct lrecord_implementation *implementation; |
1597 }; | 1927 }; |
1598 | 1928 |
1599 DECLARE_LRECORD (lcrecord_list, struct lcrecord_list); | 1929 DECLARE_LISP_OBJECT (lcrecord_list, struct lcrecord_list); |
1600 #define XLCRECORD_LIST(x) XRECORD (x, lcrecord_list, struct lcrecord_list) | 1930 #define XLCRECORD_LIST(x) XRECORD (x, lcrecord_list, struct lcrecord_list) |
1601 #define wrap_lcrecord_list(p) wrap_record (p, lcrecord_list) | 1931 #define wrap_lcrecord_list(p) wrap_record (p, lcrecord_list) |
1602 #define LCRECORD_LISTP(x) RECORDP (x, lcrecord_list) | 1932 #define LCRECORD_LISTP(x) RECORDP (x, lcrecord_list) |
1603 /* #define CHECK_LCRECORD_LIST(x) CHECK_RECORD (x, lcrecord_list) | 1933 /* #define CHECK_LCRECORD_LIST(x) CHECK_RECORD (x, lcrecord_list) |
1604 Lcrecord lists should never escape to the Lisp level, so | 1934 Lcrecord lists should never escape to the Lisp level, so |
1609 | 1939 |
1610 See above for a discussion of the difference between plain lrecords and | 1940 See above for a discussion of the difference between plain lrecords and |
1611 lrecords. lcrecords themselves are divided into three types: (1) | 1941 lrecords. lcrecords themselves are divided into three types: (1) |
1612 auto-managed, (2) hand-managed, and (3) unmanaged. "Managed" refers to | 1942 auto-managed, (2) hand-managed, and (3) unmanaged. "Managed" refers to |
1613 using a special object called an lcrecord-list to keep track of freed | 1943 using a special object called an lcrecord-list to keep track of freed |
1614 lcrecords, which can freed with FREE_LCRECORD() or the like and later be | 1944 lcrecords, which can freed with free_normal_lisp_object() or the like |
1615 recycled when a new lcrecord is required, rather than requiring new | 1945 and later be recycled when a new lcrecord is required, rather than |
1616 malloc(). Thus, allocation of lcrecords can be very | 1946 requiring new malloc(). Thus, allocation of lcrecords can be very |
1617 cheap. (Technically, the lcrecord-list manager could divide up large | 1947 cheap. (Technically, the lcrecord-list manager could divide up large |
1618 chunks of memory and allocate out of that, mimicking what happens with | 1948 chunks of memory and allocate out of that, mimicking what happens with |
1619 lrecords. At that point, however, we'd want to rethink the whole | 1949 lrecords. At that point, however, we'd want to rethink the whole |
1620 division between lrecords and lcrecords.) | 1950 division between lrecords and lcrecords.) |
1621 | 1951 |
1622 NOTE: There is a fundamental limitation of lcrecord-lists, which is that | 1952 NOTE: There is a fundamental limitation of lcrecord-lists, which is that |
1623 they only handle blocks of a particular, fixed size. Thus, objects that | 1953 they only handle blocks of a particular, fixed size. Thus, objects that |
1624 can be of varying sizes need to do various tricks. These considerations | 1954 can be of varying sizes need to do various tricks. These considerations |
1625 in particular dictate the various types of management: | 1955 in particular dictate the various types of management: |
1626 | 1956 |
1627 -- "Auto-managed" means that you just go ahead and allocate the lcrecord | 1957 -- "Auto-managed" means that you just go ahead and allocate the lcrecord |
1628 whenever you want, using old_alloc_lcrecord_type(), and the appropriate | 1958 whenever you want, using ALLOC_NORMAL_LISP_OBJECT(), and the appropriate |
1629 lcrecord-list manager is automatically created. To free, you just call | 1959 lcrecord-list manager is automatically created. To free, you just call |
1630 "FREE_LCRECORD()" and the appropriate lcrecord-list manager is | 1960 "free_normal_lisp_object()" and the appropriate lcrecord-list manager is |
1631 automatically located and called. The limitation here of course is that | 1961 automatically located and called. The limitation here of course is that |
1632 all your objects are of the same size. (#### Eventually we should have a | 1962 all your objects are of the same size. (#### Eventually we should have a |
1633 more sophisticated system that tracks the sizes seen and creates one | 1963 more sophisticated system that tracks the sizes seen and creates one |
1634 lcrecord list per size, indexed in a hash table. Usually there are only | 1964 lcrecord list per size, indexed in a hash table. Usually there are only |
1635 a limited number of sizes, so this works well.) | 1965 a limited number of sizes, so this works well.) |
1646 lcrecord-lists, no way to free them. This may be suitable when the | 1976 lcrecord-lists, no way to free them. This may be suitable when the |
1647 lcrecords are variable-sized and (a) you're too lazy to write the code | 1977 lcrecords are variable-sized and (a) you're too lazy to write the code |
1648 to hand-manage them, or (b) the objects you create are always or almost | 1978 to hand-manage them, or (b) the objects you create are always or almost |
1649 always Lisp-visible, and thus there's no point in freeing them (and it | 1979 always Lisp-visible, and thus there's no point in freeing them (and it |
1650 wouldn't be safe to do so). You just create them with | 1980 wouldn't be safe to do so). You just create them with |
1651 BASIC_ALLOC_LCRECORD(), and that's it. | 1981 ALLOC_SIZED_LISP_OBJECT(), and that's it. |
1652 | 1982 |
1653 --ben | 1983 --ben |
1654 | 1984 |
1655 Here is an in-depth look at the steps required to create a allocate an | 1985 Here is an in-depth look at the steps required to create a allocate an |
1656 lcrecord using the hand-managed style. Since this is the most | 1986 lcrecord using the hand-managed style. Since this is the most |
1659 lcrecord really entails, and what are the precautions: | 1989 lcrecord really entails, and what are the precautions: |
1660 | 1990 |
1661 1) Create an lcrecord-list object using make_lcrecord_list(). This is | 1991 1) Create an lcrecord-list object using make_lcrecord_list(). This is |
1662 often done at initialization. Remember to staticpro_nodump() this | 1992 often done at initialization. Remember to staticpro_nodump() this |
1663 object! The arguments to make_lcrecord_list() are the same as would be | 1993 object! The arguments to make_lcrecord_list() are the same as would be |
1664 passed to BASIC_ALLOC_LCRECORD(). | 1994 passed to ALLOC_SIZED_LISP_OBJECT(). |
1665 | 1995 |
1666 2) Instead of calling BASIC_ALLOC_LCRECORD(), call alloc_managed_lcrecord() | 1996 2) Instead of calling ALLOC_SIZED_LISP_OBJECT(), call |
1667 and pass the lcrecord-list earlier created. | 1997 alloc_managed_lcrecord() and pass the lcrecord-list earlier created. |
1668 | 1998 |
1669 3) When done with the lcrecord, call free_managed_lcrecord(). The | 1999 3) When done with the lcrecord, call free_managed_lcrecord(). The |
1670 standard freeing caveats apply: ** make sure there are no pointers to | 2000 standard freeing caveats apply: ** make sure there are no pointers to |
1671 the object anywhere! ** | 2001 the object anywhere! ** |
1672 | 2002 |
1673 4) Calling free_managed_lcrecord() is just like kissing the | 2003 4) Calling free_managed_lcrecord() is just like kissing the |
1674 lcrecord goodbye as if it were garbage-collected. This means: | 2004 lcrecord goodbye as if it were garbage-collected. This means: |
1675 -- the contents of the freed lcrecord are undefined, and the | 2005 -- the contents of the freed lcrecord are undefined, and the |
1676 contents of something produced by alloc_managed_lcrecord() | 2006 contents of something produced by alloc_managed_lcrecord() |
1677 are undefined, just like for BASIC_ALLOC_LCRECORD(). | 2007 are undefined, just like for ALLOC_SIZED_LISP_OBJECT(). |
1678 -- the mark method for the lcrecord's type will *NEVER* be called | 2008 -- the mark method for the lcrecord's type will *NEVER* be called |
1679 on freed lcrecords. | 2009 on freed lcrecords. |
1680 -- the finalize method for the lcrecord's type will be called | 2010 -- the finalize method for the lcrecord's type will be called |
1681 at the time that free_managed_lcrecord() is called. | 2011 at the time that free_managed_lcrecord() is called. |
1682 */ | 2012 */ |
1683 | 2013 |
1684 /* UNMANAGED MODEL: */ | 2014 /* UNMANAGED MODEL: */ |
1685 void *old_basic_alloc_lcrecord (Bytecount size, | 2015 Lisp_Object old_alloc_lcrecord (const struct lrecord_implementation *); |
1686 const struct lrecord_implementation *); | 2016 Lisp_Object old_alloc_sized_lcrecord (Bytecount size, |
2017 const struct lrecord_implementation *); | |
1687 | 2018 |
1688 /* HAND-MANAGED MODEL: */ | 2019 /* HAND-MANAGED MODEL: */ |
1689 Lisp_Object make_lcrecord_list (Elemcount size, | 2020 Lisp_Object make_lcrecord_list (Elemcount size, |
1690 const struct lrecord_implementation | 2021 const struct lrecord_implementation |
1691 *implementation); | 2022 *implementation); |
1692 Lisp_Object alloc_managed_lcrecord (Lisp_Object lcrecord_list); | 2023 Lisp_Object alloc_managed_lcrecord (Lisp_Object lcrecord_list); |
1693 void free_managed_lcrecord (Lisp_Object lcrecord_list, Lisp_Object lcrecord); | 2024 void free_managed_lcrecord (Lisp_Object lcrecord_list, Lisp_Object lcrecord); |
1694 | 2025 |
1695 /* AUTO-MANAGED MODEL: */ | 2026 /* AUTO-MANAGED MODEL: */ |
1696 MODULE_API void * | 2027 MODULE_API Lisp_Object |
1697 alloc_automanaged_lcrecord (Bytecount size, | 2028 alloc_automanaged_sized_lcrecord (Bytecount size, |
1698 const struct lrecord_implementation *); | 2029 const struct lrecord_implementation *imp); |
1699 | 2030 MODULE_API Lisp_Object |
1700 #define old_alloc_lcrecord_type(type, lrecord_implementation) \ | 2031 alloc_automanaged_lcrecord (const struct lrecord_implementation *imp); |
1701 ((type *) alloc_automanaged_lcrecord (sizeof (type), lrecord_implementation)) | 2032 |
2033 #define old_alloc_lcrecord_type(type, imp) \ | |
2034 ((type *) XPNTR (alloc_automanaged_lcrecord (sizeof (type), imp))) | |
1702 | 2035 |
1703 void old_free_lcrecord (Lisp_Object rec); | 2036 void old_free_lcrecord (Lisp_Object rec); |
1704 | 2037 |
1705 | |
1706 /* Copy the data from one lcrecord structure into another, but don't | |
1707 overwrite the header information. */ | |
1708 | |
1709 #define old_copy_sized_lcrecord(dst, src, size) \ | |
1710 memcpy ((Rawbyte *) (dst) + sizeof (struct old_lcrecord_header), \ | |
1711 (Rawbyte *) (src) + sizeof (struct old_lcrecord_header), \ | |
1712 (size) - sizeof (struct old_lcrecord_header)) | |
1713 | |
1714 #define old_copy_lcrecord(dst, src) \ | |
1715 old_copy_sized_lcrecord (dst, src, sizeof (*(dst))) | |
1716 | |
1717 #define old_zero_sized_lcrecord(lcr, size) \ | |
1718 memset ((Rawbyte *) (lcr) + sizeof (struct old_lcrecord_header), 0, \ | |
1719 (size) - sizeof (struct old_lcrecord_header)) | |
1720 | |
1721 #define old_zero_lcrecord(lcr) old_zero_sized_lcrecord (lcr, sizeof (*(lcr))) | |
1722 | |
1723 #else /* NEW_GC */ | 2038 #else /* NEW_GC */ |
1724 | 2039 |
1725 /* How to allocate a lrecord: | 2040 MODULE_API Lisp_Object alloc_sized_lrecord (Bytecount size, |
1726 | 2041 const struct lrecord_implementation *imp); |
1727 - If the size of the lrecord is fix, say it equals its size of its | 2042 Lisp_Object noseeum_alloc_sized_lrecord (Bytecount size, |
1728 struct, then use alloc_lrecord_type. | 2043 const struct lrecord_implementation *imp); |
1729 | 2044 MODULE_API Lisp_Object alloc_lrecord (const struct lrecord_implementation *imp); |
1730 - If the size varies, i.e. it is not equal to the size of its | 2045 Lisp_Object noseeum_alloc_lrecord (const struct lrecord_implementation *imp); |
1731 struct, use alloc_lrecord and specify the amount of storage you | 2046 |
1732 need for the object. | 2047 MODULE_API Lisp_Object alloc_lrecord_array (int elemcount, |
1733 | 2048 const struct lrecord_implementation *imp); |
1734 - Some lrecords, which are used totally internally, use the | 2049 MODULE_API Lisp_Object alloc_sized_lrecord_array (Bytecount size, |
1735 noseeum-* functions for the reason of debugging. | 2050 int elemcount, |
1736 | 2051 const struct lrecord_implementation *imp); |
1737 - To free a Lisp_Object manually, use free_lrecord. */ | |
1738 | |
1739 void *alloc_lrecord (Bytecount size, | |
1740 const struct lrecord_implementation *); | |
1741 | |
1742 void *alloc_lrecord_array (Bytecount size, int elemcount, | |
1743 const struct lrecord_implementation *); | |
1744 | |
1745 #define alloc_lrecord_type(type, lrecord_implementation) \ | |
1746 ((type *) alloc_lrecord (sizeof (type), lrecord_implementation)) | |
1747 | |
1748 void *noseeum_alloc_lrecord (Bytecount size, | |
1749 const struct lrecord_implementation *); | |
1750 | |
1751 #define noseeum_alloc_lrecord_type(type, lrecord_implementation) \ | |
1752 ((type *) noseeum_alloc_lrecord (sizeof (type), lrecord_implementation)) | |
1753 | |
1754 void free_lrecord (Lisp_Object rec); | |
1755 | |
1756 | |
1757 /* Copy the data from one lrecord structure into another, but don't | |
1758 overwrite the header information. */ | |
1759 | |
1760 #define copy_sized_lrecord(dst, src, size) \ | |
1761 memcpy ((char *) (dst) + sizeof (struct lrecord_header), \ | |
1762 (char *) (src) + sizeof (struct lrecord_header), \ | |
1763 (size) - sizeof (struct lrecord_header)) | |
1764 | |
1765 #define copy_lrecord(dst, src) copy_sized_lrecord (dst, src, sizeof (*(dst))) | |
1766 | 2052 |
1767 #endif /* NEW_GC */ | 2053 #endif /* NEW_GC */ |
1768 | |
1769 #define zero_sized_lrecord(lcr, size) \ | |
1770 memset ((char *) (lcr) + sizeof (struct lrecord_header), 0, \ | |
1771 (size) - sizeof (struct lrecord_header)) | |
1772 | |
1773 #define zero_lrecord(lcr) zero_sized_lrecord (lcr, sizeof (*(lcr))) | |
1774 | 2054 |
1775 DECLARE_INLINE_HEADER ( | 2055 DECLARE_INLINE_HEADER ( |
1776 Bytecount | 2056 Bytecount |
1777 detagged_lisp_object_size (const struct lrecord_header *h) | 2057 detagged_lisp_object_size (const struct lrecord_header *h) |
1778 ) | 2058 ) |
1779 { | 2059 { |
1780 const struct lrecord_implementation *imp = LHEADER_IMPLEMENTATION (h); | 2060 const struct lrecord_implementation *imp = LHEADER_IMPLEMENTATION (h); |
1781 | 2061 |
1782 return (imp->size_in_bytes_method ? | 2062 return (imp->size_in_bytes_method ? |
1783 imp->size_in_bytes_method (h) : | 2063 imp->size_in_bytes_method (wrap_pointer_1 (h)) : |
1784 imp->static_size); | 2064 imp->static_size); |
1785 } | 2065 } |
1786 | 2066 |
1787 DECLARE_INLINE_HEADER ( | 2067 DECLARE_INLINE_HEADER ( |
1788 Bytecount | 2068 Bytecount |
1789 lisp_object_size (Lisp_Object o) | 2069 lisp_object_size (Lisp_Object o) |
1790 ) | 2070 ) |
1791 { | 2071 { |
1792 return detagged_lisp_object_size (XRECORD_LHEADER (o)); | 2072 return detagged_lisp_object_size (XRECORD_LHEADER (o)); |
1793 } | 2073 } |
2074 | |
2075 struct usage_stats; | |
2076 | |
2077 MODULE_API void copy_lisp_object (Lisp_Object dst, Lisp_Object src); | |
2078 MODULE_API void zero_sized_lisp_object (Lisp_Object obj, Bytecount size); | |
2079 MODULE_API void zero_nonsized_lisp_object (Lisp_Object obj); | |
2080 Bytecount lisp_object_storage_size (Lisp_Object obj, | |
2081 struct usage_stats *ustats); | |
2082 Bytecount lisp_object_memory_usage_full (Lisp_Object object, | |
2083 Bytecount *storage_size, | |
2084 Bytecount *extra_nonlisp_storage, | |
2085 Bytecount *extra_lisp_storage, | |
2086 struct generic_usage_stats *stats); | |
2087 Bytecount lisp_object_memory_usage (Lisp_Object object); | |
2088 void free_normal_lisp_object (Lisp_Object obj); | |
1794 | 2089 |
1795 | 2090 |
1796 /************************************************************************/ | 2091 /************************************************************************/ |
1797 /* Dumping */ | 2092 /* Dumping */ |
1798 /************************************************************************/ | 2093 /************************************************************************/ |