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 /************************************************************************/