Mercurial > hg > xemacs-beta
annotate src/lrecord.h @ 5090:0ca81354c4c7
Further frame-geometry cleanups
-------------------- ChangeLog entries follow: --------------------
man/ChangeLog addition:
2010-03-03 Ben Wing <ben@xemacs.org>
* internals/internals.texi (Intro to Window and Frame Geometry):
* internals/internals.texi (The Paned Area):
* internals/internals.texi (The Displayable Area):
Update to make note of e.g. the fact that the bottom gutter is
actually above the minibuffer.
src/ChangeLog addition:
2010-03-03 Ben Wing <ben@xemacs.org>
* emacs.c:
* emacs.c (assert_equal_failed):
* lisp.h:
* lisp.h (assert_equal):
New fun assert_equal, asserting that two values == each other, and
printing out both values upon failure.
* frame-gtk.c (gtk_initialize_frame_size):
* frame-impl.h:
* frame-impl.h (FRAME_TOP_INTERNAL_BORDER_START):
* frame-impl.h (FRAME_BOTTOM_INTERNAL_BORDER_START):
* frame-impl.h (FRAME_LEFT_INTERNAL_BORDER_START):
* frame-impl.h (FRAME_PANED_TOP_EDGE):
* frame-impl.h (FRAME_NONPANED_SIZE):
* frame-x.c (x_initialize_frame_size):
* frame.c:
* gutter.c (get_gutter_coords):
* gutter.c (calculate_gutter_size):
* gutter.h:
* gutter.h (WINDOW_REAL_TOP_GUTTER_BOUNDS):
* gutter.h (FRAME_TOP_GUTTER_BOUNDS):
* input-method-xlib.c:
* input-method-xlib.c (XIM_SetGeometry):
* redisplay-output.c (clear_left_border):
* redisplay-output.c (clear_right_border):
* redisplay-output.c (redisplay_output_pixmap):
* redisplay-output.c (redisplay_clear_region):
* redisplay-output.c (redisplay_clear_top_of_window):
* redisplay-output.c (redisplay_clear_to_window_end):
* redisplay-xlike-inc.c (XLIKE_clear_frame):
* redisplay.c:
* redisplay.c (UPDATE_CACHE_RETURN):
* redisplay.c (pixel_to_glyph_translation):
* toolbar.c (update_frame_toolbars_geometry):
* window.c (Fwindow_pixel_edges):
Get rid of some redundant macros. Consistently use the
FRAME_TOP_*_START, FRAME_RIGHT_*_END, etc. format. Rename
FRAME_*_BORDER_* to FRAME_*_INTERNAL_BORDER_*. Comment out
FRAME_BOTTOM_* for gutters and the paned area due to the
uncertainty over where the paned area actually begins. (Eventually
we should probably move the gutters outside the minibuffer so that
the paned area is contiguous.) Use FRAME_PANED_* more often in the
code to make things clearer.
Update the diagram to show that the bottom gutter is inside the
minibuffer (!) and that there are "junk boxes" when you have left
and/or right gutters (dead boxes that are mistakenly left uncleared,
unlike the corresponding scrollbar dead boxes). Update the text
appropriately to cover the bottom gutter position, etc.
Rewrite gutter-geometry code to use the FRAME_*_GUTTER_* in place of
equivalent expressions referencing other frame elements, to make the
code more portable in case we move around the gutter location.
Cleanup FRAME_*_GUTTER_BOUNDS() in gutter.h.
Add some #### GEOM! comments where I think code is incorrect --
typically, it wasn't fixed up properly when the gutter was added.
Some cosmetic changes.
author | Ben Wing <ben@xemacs.org> |
---|---|
date | Wed, 03 Mar 2010 05:07:47 -0600 |
parents | c8f90d61dcf3 |
children | ebee7d1e58bd 2a462149bd6a b785049378e3 |
rev | line source |
---|---|
428 | 1 /* The "lrecord" structure (header of a compound lisp object). |
2 Copyright (C) 1993, 1994, 1995 Free Software Foundation, Inc. | |
4930
9f04877ce07e
fix up comments about finalizers and NEWGC internal objects
Ben Wing <ben@xemacs.org>
parents:
4844
diff
changeset
|
3 Copyright (C) 1996, 2001, 2002, 2004, 2005, 2010 Ben Wing. |
428 | 4 |
5 This file is part of XEmacs. | |
6 | |
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 | |
9 Free Software Foundation; either version 2, or (at your option) any | |
10 later version. | |
11 | |
12 XEmacs is distributed in the hope that it will be useful, but WITHOUT | |
13 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
15 for more details. | |
16 | |
17 You should have received a copy of the GNU General Public License | |
18 along with XEmacs; see the file COPYING. If not, write to | |
19 the Free Software Foundation, Inc., 59 Temple Place - Suite 330, | |
20 Boston, MA 02111-1307, USA. */ | |
21 | |
22 /* Synched up with: Not in FSF. */ | |
23 | |
2367 | 24 /* This file has been Mule-ized, Ben Wing, 10-13-04. */ |
25 | |
440 | 26 #ifndef INCLUDED_lrecord_h_ |
27 #define INCLUDED_lrecord_h_ | |
428 | 28 |
4930
9f04877ce07e
fix up comments about finalizers and NEWGC internal objects
Ben Wing <ben@xemacs.org>
parents:
4844
diff
changeset
|
29 /* The "lrecord" type of Lisp object is used for all object types other |
9f04877ce07e
fix up comments about finalizers and NEWGC internal objects
Ben Wing <ben@xemacs.org>
parents:
4844
diff
changeset
|
30 than a few simple ones (like char and int). This allows many types to be |
9f04877ce07e
fix up comments about finalizers and NEWGC internal objects
Ben Wing <ben@xemacs.org>
parents:
4844
diff
changeset
|
31 implemented but only a few bits required in a Lisp object for type |
9f04877ce07e
fix up comments about finalizers and NEWGC internal objects
Ben Wing <ben@xemacs.org>
parents:
4844
diff
changeset
|
32 information. (The tradeoff is that each object has its type marked in |
9f04877ce07e
fix up comments about finalizers and NEWGC internal objects
Ben Wing <ben@xemacs.org>
parents:
4844
diff
changeset
|
33 it, thereby increasing its size.) All lrecords begin with a `struct |
9f04877ce07e
fix up comments about finalizers and NEWGC internal objects
Ben Wing <ben@xemacs.org>
parents:
4844
diff
changeset
|
34 lrecord_header', which identifies the lisp object type, by providing an |
9f04877ce07e
fix up comments about finalizers and NEWGC internal objects
Ben Wing <ben@xemacs.org>
parents:
4844
diff
changeset
|
35 index into a table of `struct lrecord_implementation', which describes |
9f04877ce07e
fix up comments about finalizers and NEWGC internal objects
Ben Wing <ben@xemacs.org>
parents:
4844
diff
changeset
|
36 the behavior of the lisp object. It also contains some other data bits. |
2720 | 37 |
4930
9f04877ce07e
fix up comments about finalizers and NEWGC internal objects
Ben Wing <ben@xemacs.org>
parents:
4844
diff
changeset
|
38 #ifndef NEW_GC |
428 | 39 Lrecords are of two types: straight lrecords, and lcrecords. |
40 Straight lrecords are used for those types of objects that have | |
41 their own allocation routines (typically allocated out of 2K chunks | |
42 of memory called `frob blocks'). These objects have a `struct | |
43 lrecord_header' at the top, containing only the bits needed to find | |
44 the lrecord_implementation for the object. There are special | |
1204 | 45 routines in alloc.c to create an object of each such type. |
428 | 46 |
442 | 47 Lcrecords are used for less common sorts of objects that don't do |
48 their own allocation. Each such object is malloc()ed individually, | |
49 and the objects are chained together through a `next' pointer. | |
3024 | 50 Lcrecords have a `struct old_lcrecord_header' at the top, which |
442 | 51 contains a `struct lrecord_header' and a `next' pointer, and are |
3024 | 52 allocated using old_alloc_lcrecord_type() or its variants. |
4930
9f04877ce07e
fix up comments about finalizers and NEWGC internal objects
Ben Wing <ben@xemacs.org>
parents:
4844
diff
changeset
|
53 #endif |
428 | 54 |
4930
9f04877ce07e
fix up comments about finalizers and NEWGC internal objects
Ben Wing <ben@xemacs.org>
parents:
4844
diff
changeset
|
55 Creating a new Lisp object type is fairly easy; just follow the |
428 | 56 lead of some existing type (e.g. hash tables). Note that you |
57 do not need to supply all the methods (see below); reasonable | |
58 defaults are provided for many of them. Alternatively, if you're | |
59 just looking for a way of encapsulating data (which possibly | |
60 could contain Lisp_Objects in it), you may well be able to use | |
4930
9f04877ce07e
fix up comments about finalizers and NEWGC internal objects
Ben Wing <ben@xemacs.org>
parents:
4844
diff
changeset
|
61 the opaque type. |
1204 | 62 */ |
4930
9f04877ce07e
fix up comments about finalizers and NEWGC internal objects
Ben Wing <ben@xemacs.org>
parents:
4844
diff
changeset
|
63 |
9f04877ce07e
fix up comments about finalizers and NEWGC internal objects
Ben Wing <ben@xemacs.org>
parents:
4844
diff
changeset
|
64 #ifdef NEW_GC |
9f04877ce07e
fix up comments about finalizers and NEWGC internal objects
Ben Wing <ben@xemacs.org>
parents:
4844
diff
changeset
|
65 /* |
9f04877ce07e
fix up comments about finalizers and NEWGC internal objects
Ben Wing <ben@xemacs.org>
parents:
4844
diff
changeset
|
66 There are some limitations under New-GC that lead to the creation of a |
9f04877ce07e
fix up comments about finalizers and NEWGC internal objects
Ben Wing <ben@xemacs.org>
parents:
4844
diff
changeset
|
67 large number of new internal object types. I'm not completely sure what |
9f04877ce07e
fix up comments about finalizers and NEWGC internal objects
Ben Wing <ben@xemacs.org>
parents:
4844
diff
changeset
|
68 all of them are, but they are at least partially related to limitations |
9f04877ce07e
fix up comments about finalizers and NEWGC internal objects
Ben Wing <ben@xemacs.org>
parents:
4844
diff
changeset
|
69 on finalizers. Something else must be going on as well, because |
9f04877ce07e
fix up comments about finalizers and NEWGC internal objects
Ben Wing <ben@xemacs.org>
parents:
4844
diff
changeset
|
70 non-dumpable, non-finalizable objects like devices and frames also have |
9f04877ce07e
fix up comments about finalizers and NEWGC internal objects
Ben Wing <ben@xemacs.org>
parents:
4844
diff
changeset
|
71 their window-system-specific substructures converted into Lisp objects. |
9f04877ce07e
fix up comments about finalizers and NEWGC internal objects
Ben Wing <ben@xemacs.org>
parents:
4844
diff
changeset
|
72 It must have something to do with the fact that these substructures |
9f04877ce07e
fix up comments about finalizers and NEWGC internal objects
Ben Wing <ben@xemacs.org>
parents:
4844
diff
changeset
|
73 contain pointers to Lisp objects, but it's not completely clear why -- |
9f04877ce07e
fix up comments about finalizers and NEWGC internal objects
Ben Wing <ben@xemacs.org>
parents:
4844
diff
changeset
|
74 object descriptions exist to indicate the size of these structures and |
9f04877ce07e
fix up comments about finalizers and NEWGC internal objects
Ben Wing <ben@xemacs.org>
parents:
4844
diff
changeset
|
75 the Lisp object pointers within them. |
9f04877ce07e
fix up comments about finalizers and NEWGC internal objects
Ben Wing <ben@xemacs.org>
parents:
4844
diff
changeset
|
76 |
9f04877ce07e
fix up comments about finalizers and NEWGC internal objects
Ben Wing <ben@xemacs.org>
parents:
4844
diff
changeset
|
77 At least one definite issue is that under New-GC dumpable objects cannot |
9f04877ce07e
fix up comments about finalizers and NEWGC internal objects
Ben Wing <ben@xemacs.org>
parents:
4844
diff
changeset
|
78 contain any finalizers (see pdump_register_object()). This means that any |
9f04877ce07e
fix up comments about finalizers and NEWGC internal objects
Ben Wing <ben@xemacs.org>
parents:
4844
diff
changeset
|
79 substructures in dumpable objects that are allocated separately and |
9f04877ce07e
fix up comments about finalizers and NEWGC internal objects
Ben Wing <ben@xemacs.org>
parents:
4844
diff
changeset
|
80 normally freed in a finalizer need instead to be made into actual Lisp |
9f04877ce07e
fix up comments about finalizers and NEWGC internal objects
Ben Wing <ben@xemacs.org>
parents:
4844
diff
changeset
|
81 objects. If those structures are Dynarrs, they need to be made into |
9f04877ce07e
fix up comments about finalizers and NEWGC internal objects
Ben Wing <ben@xemacs.org>
parents:
4844
diff
changeset
|
82 Dynarr Lisp objects (e.g. face-cachel-dynarr or glyph-cachel-dynarr), |
9f04877ce07e
fix up comments about finalizers and NEWGC internal objects
Ben Wing <ben@xemacs.org>
parents:
4844
diff
changeset
|
83 which are created using Dynarr_lisp_new() or Dynarr_new_new2(). |
9f04877ce07e
fix up comments about finalizers and NEWGC internal objects
Ben Wing <ben@xemacs.org>
parents:
4844
diff
changeset
|
84 Furthermore, the objects contained in the Dynarr also need to be Lisp |
9f04877ce07e
fix up comments about finalizers and NEWGC internal objects
Ben Wing <ben@xemacs.org>
parents:
4844
diff
changeset
|
85 objects (e.g. face-cachel or glyph-cachel). |
9f04877ce07e
fix up comments about finalizers and NEWGC internal objects
Ben Wing <ben@xemacs.org>
parents:
4844
diff
changeset
|
86 |
9f04877ce07e
fix up comments about finalizers and NEWGC internal objects
Ben Wing <ben@xemacs.org>
parents:
4844
diff
changeset
|
87 --ben |
9f04877ce07e
fix up comments about finalizers and NEWGC internal objects
Ben Wing <ben@xemacs.org>
parents:
4844
diff
changeset
|
88 */ |
9f04877ce07e
fix up comments about finalizers and NEWGC internal objects
Ben Wing <ben@xemacs.org>
parents:
4844
diff
changeset
|
89 |
9f04877ce07e
fix up comments about finalizers and NEWGC internal objects
Ben Wing <ben@xemacs.org>
parents:
4844
diff
changeset
|
90 #endif |
9f04877ce07e
fix up comments about finalizers and NEWGC internal objects
Ben Wing <ben@xemacs.org>
parents:
4844
diff
changeset
|
91 |
9f04877ce07e
fix up comments about finalizers and NEWGC internal objects
Ben Wing <ben@xemacs.org>
parents:
4844
diff
changeset
|
92 |
428 | 93 |
3263 | 94 #ifdef NEW_GC |
3024 | 95 #define ALLOC_LCRECORD_TYPE alloc_lrecord_type |
96 #define COPY_SIZED_LCRECORD copy_sized_lrecord | |
97 #define COPY_LCRECORD copy_lrecord | |
98 #define LISPOBJ_STORAGE_SIZE(ptr, size, stats) \ | |
99 mc_alloced_storage_size (size, stats) | |
100 #define ZERO_LCRECORD zero_lrecord | |
101 #define LCRECORD_HEADER lrecord_header | |
102 #define BASIC_ALLOC_LCRECORD alloc_lrecord | |
103 #define FREE_LCRECORD free_lrecord | |
3263 | 104 #else /* not NEW_GC */ |
3024 | 105 #define ALLOC_LCRECORD_TYPE old_alloc_lcrecord_type |
106 #define COPY_SIZED_LCRECORD old_copy_sized_lcrecord | |
107 #define COPY_LCRECORD old_copy_lcrecord | |
108 #define LISPOBJ_STORAGE_SIZE malloced_storage_size | |
109 #define ZERO_LCRECORD old_zero_lcrecord | |
110 #define LCRECORD_HEADER old_lcrecord_header | |
111 #define BASIC_ALLOC_LCRECORD old_basic_alloc_lcrecord | |
112 #define FREE_LCRECORD old_free_lcrecord | |
3263 | 113 #endif /* not NEW_GC */ |
3024 | 114 |
1743 | 115 BEGIN_C_DECLS |
1650 | 116 |
428 | 117 struct lrecord_header |
118 { | |
1204 | 119 /* Index into lrecord_implementations_table[]. Objects that have been |
120 explicitly freed using e.g. free_cons() have lrecord_type_free in this | |
121 field. */ | |
442 | 122 unsigned int type :8; |
123 | |
3263 | 124 #ifdef NEW_GC |
2720 | 125 /* 1 if the object is readonly from lisp */ |
126 unsigned int lisp_readonly :1; | |
127 | |
128 /* The `free' field is a flag that indicates whether this lrecord | |
129 is currently free or not. This is used for error checking and | |
130 debugging. */ | |
131 unsigned int free :1; | |
132 | |
3063 | 133 /* The `uid' field is just for debugging/printing convenience. Having |
134 this slot doesn't hurt us spacewise, since the bits are unused | |
135 anyway. (The bits are used for strings, though.) */ | |
2720 | 136 unsigned int uid :22; |
137 | |
3263 | 138 #else /* not NEW_GC */ |
442 | 139 /* If `mark' is 0 after the GC mark phase, the object will be freed |
140 during the GC sweep phase. There are 2 ways that `mark' can be 1: | |
141 - by being referenced from other objects during the GC mark phase | |
142 - because it is permanently on, for c_readonly objects */ | |
143 unsigned int mark :1; | |
144 | |
145 /* 1 if the object resides in logically read-only space, and does not | |
146 reference other non-c_readonly objects. | |
147 Invariant: if (c_readonly == 1), then (mark == 1 && lisp_readonly == 1) */ | |
148 unsigned int c_readonly :1; | |
149 | |
428 | 150 /* 1 if the object is readonly from lisp */ |
442 | 151 unsigned int lisp_readonly :1; |
771 | 152 |
3063 | 153 /* The `uid' field is just for debugging/printing convenience. Having |
154 this slot doesn't hurt us spacewise, since the bits are unused | |
155 anyway. (The bits are used for strings, though.) */ | |
156 unsigned int uid :21; | |
934 | 157 |
3263 | 158 #endif /* not NEW_GC */ |
428 | 159 }; |
160 | |
161 struct lrecord_implementation; | |
442 | 162 int lrecord_type_index (const struct lrecord_implementation *implementation); |
3063 | 163 extern int lrecord_uid_counter; |
428 | 164 |
3263 | 165 #ifdef NEW_GC |
2720 | 166 #define set_lheader_implementation(header,imp) do { \ |
167 struct lrecord_header* SLI_header = (header); \ | |
168 SLI_header->type = (imp)->lrecord_type_index; \ | |
169 SLI_header->lisp_readonly = 0; \ | |
170 SLI_header->free = 0; \ | |
3063 | 171 SLI_header->uid = lrecord_uid_counter++; \ |
2720 | 172 } while (0) |
3263 | 173 #else /* not NEW_GC */ |
430 | 174 #define set_lheader_implementation(header,imp) do { \ |
428 | 175 struct lrecord_header* SLI_header = (header); \ |
442 | 176 SLI_header->type = (imp)->lrecord_type_index; \ |
430 | 177 SLI_header->mark = 0; \ |
178 SLI_header->c_readonly = 0; \ | |
179 SLI_header->lisp_readonly = 0; \ | |
3063 | 180 SLI_header->uid = lrecord_uid_counter++; \ |
428 | 181 } while (0) |
3263 | 182 #endif /* not NEW_GC */ |
428 | 183 |
3263 | 184 #ifndef NEW_GC |
3024 | 185 struct old_lcrecord_header |
428 | 186 { |
187 struct lrecord_header lheader; | |
188 | |
442 | 189 /* The `next' field is normally used to chain all lcrecords together |
428 | 190 so that the GC can find (and free) all of them. |
3024 | 191 `old_basic_alloc_lcrecord' threads lcrecords together. |
428 | 192 |
193 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. | |
195 | |
196 For example, the event and marker object types allocate members | |
197 out of memory chunks, and are able to find all unmarked members | |
198 by sweeping through the elements of the list of chunks. */ | |
3024 | 199 struct old_lcrecord_header *next; |
428 | 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 }; | |
215 | |
216 /* Used for lcrecords in an lcrecord-list. */ | |
217 struct free_lcrecord_header | |
218 { | |
3024 | 219 struct old_lcrecord_header lcheader; |
428 | 220 Lisp_Object chain; |
221 }; | |
3263 | 222 #endif /* not NEW_GC */ |
428 | 223 |
3931 | 224 /* DON'T FORGET to update .gdbinit.in if you change this list. */ |
442 | 225 enum lrecord_type |
226 { | |
227 /* 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 | |
229 in the Lisp_Symbol lrecord_header. */ | |
2720 | 230 lrecord_type_symbol_value_forward, /* 0 */ |
3092 | 231 lrecord_type_symbol_value_varalias, |
232 lrecord_type_symbol_value_lisp_magic, | |
233 lrecord_type_symbol_value_buffer_local, | |
442 | 234 lrecord_type_max_symbol_value_magic = lrecord_type_symbol_value_buffer_local, |
3092 | 235 lrecord_type_symbol, |
236 lrecord_type_subr, | |
4677
8f1ee2d15784
Support full Common Lisp multiple values in C.
Aidan Kehoe <kehoea@parhasard.net>
parents:
3931
diff
changeset
|
237 lrecord_type_multiple_value, |
3092 | 238 lrecord_type_cons, |
239 lrecord_type_vector, | |
240 lrecord_type_string, | |
3263 | 241 #ifndef NEW_GC |
442 | 242 lrecord_type_lcrecord_list, |
3263 | 243 #endif /* not NEW_GC */ |
3092 | 244 lrecord_type_compiled_function, |
245 lrecord_type_weak_list, | |
246 lrecord_type_bit_vector, | |
247 lrecord_type_float, | |
248 lrecord_type_hash_table, | |
249 lrecord_type_lstream, | |
250 lrecord_type_process, | |
251 lrecord_type_charset, | |
252 lrecord_type_coding_system, | |
253 lrecord_type_char_table, | |
254 lrecord_type_char_table_entry, | |
255 lrecord_type_range_table, | |
256 lrecord_type_opaque, | |
257 lrecord_type_opaque_ptr, | |
258 lrecord_type_buffer, | |
259 lrecord_type_extent, | |
260 lrecord_type_extent_info, | |
261 lrecord_type_extent_auxiliary, | |
262 lrecord_type_marker, | |
263 lrecord_type_event, | |
2720 | 264 #ifdef EVENT_DATA_AS_OBJECTS /* not defined */ |
934 | 265 lrecord_type_key_data, |
266 lrecord_type_button_data, | |
267 lrecord_type_motion_data, | |
268 lrecord_type_process_data, | |
269 lrecord_type_timeout_data, | |
270 lrecord_type_eval_data, | |
271 lrecord_type_misc_user_data, | |
272 lrecord_type_magic_eval_data, | |
273 lrecord_type_magic_data, | |
1204 | 274 #endif /* EVENT_DATA_AS_OBJECTS */ |
3092 | 275 lrecord_type_keymap, |
276 lrecord_type_command_builder, | |
277 lrecord_type_timeout, | |
278 lrecord_type_specifier, | |
279 lrecord_type_console, | |
280 lrecord_type_device, | |
281 lrecord_type_frame, | |
282 lrecord_type_window, | |
283 lrecord_type_window_mirror, | |
284 lrecord_type_window_configuration, | |
285 lrecord_type_gui_item, | |
286 lrecord_type_popup_data, | |
287 lrecord_type_toolbar_button, | |
288 lrecord_type_scrollbar_instance, | |
289 lrecord_type_color_instance, | |
290 lrecord_type_font_instance, | |
291 lrecord_type_image_instance, | |
292 lrecord_type_glyph, | |
293 lrecord_type_face, | |
3931 | 294 lrecord_type_fc_config, |
3094 | 295 lrecord_type_fc_pattern, |
3092 | 296 lrecord_type_database, |
297 lrecord_type_tooltalk_message, | |
298 lrecord_type_tooltalk_pattern, | |
299 lrecord_type_ldap, | |
300 lrecord_type_pgconn, | |
301 lrecord_type_pgresult, | |
302 lrecord_type_devmode, | |
303 lrecord_type_mswindows_dialog_id, | |
304 lrecord_type_case_table, | |
305 lrecord_type_emacs_ffi, | |
306 lrecord_type_emacs_gtk_object, | |
307 lrecord_type_emacs_gtk_boxed, | |
308 lrecord_type_weak_box, | |
309 lrecord_type_ephemeron, | |
310 lrecord_type_bignum, | |
311 lrecord_type_ratio, | |
312 lrecord_type_bigfloat, | |
3263 | 313 #ifndef NEW_GC |
454 | 314 lrecord_type_free, /* only used for "free" lrecords */ |
315 lrecord_type_undefined, /* only used for debugging */ | |
3263 | 316 #endif /* not NEW_GC */ |
3092 | 317 #ifdef NEW_GC |
4930
9f04877ce07e
fix up comments about finalizers and NEWGC internal objects
Ben Wing <ben@xemacs.org>
parents:
4844
diff
changeset
|
318 /* See comment up top explaining why these extra object types must exist. */ |
3092 | 319 lrecord_type_string_indirect_data, |
320 lrecord_type_string_direct_data, | |
321 lrecord_type_hash_table_entry, | |
322 lrecord_type_syntax_cache, | |
323 lrecord_type_buffer_text, | |
324 lrecord_type_compiled_function_args, | |
325 lrecord_type_tty_console, | |
326 lrecord_type_stream_console, | |
327 lrecord_type_dynarr, | |
328 lrecord_type_face_cachel, | |
329 lrecord_type_face_cachel_dynarr, | |
330 lrecord_type_glyph_cachel, | |
331 lrecord_type_glyph_cachel_dynarr, | |
332 lrecord_type_x_device, | |
333 lrecord_type_gtk_device, | |
334 lrecord_type_tty_device, | |
335 lrecord_type_mswindows_device, | |
336 lrecord_type_msprinter_device, | |
337 lrecord_type_x_frame, | |
338 lrecord_type_gtk_frame, | |
339 lrecord_type_mswindows_frame, | |
340 lrecord_type_gap_array_marker, | |
341 lrecord_type_gap_array, | |
342 lrecord_type_extent_list_marker, | |
343 lrecord_type_extent_list, | |
344 lrecord_type_stack_of_extents, | |
345 lrecord_type_tty_color_instance_data, | |
346 lrecord_type_tty_font_instance_data, | |
347 lrecord_type_specifier_caching, | |
348 lrecord_type_expose_ignore, | |
349 #endif /* NEW_GC */ | |
350 lrecord_type_last_built_in_type /* must be last */ | |
442 | 351 }; |
352 | |
1632 | 353 extern MODULE_API int lrecord_type_count; |
428 | 354 |
355 struct lrecord_implementation | |
356 { | |
2367 | 357 const Ascbyte *name; |
442 | 358 |
934 | 359 /* information for the dumper: is the object dumpable and should it |
360 be dumped. */ | |
361 unsigned int dumpable :1; | |
362 | |
442 | 363 /* `marker' is called at GC time, to make sure that all Lisp_Objects |
428 | 364 pointed to by this object get properly marked. It should call |
365 the mark_object function on all Lisp_Objects in the object. If | |
366 the return value is non-nil, it should be a Lisp_Object to be | |
367 marked (don't call the mark_object function explicitly on it, | |
368 because the GC routines will do this). Doing it this way reduces | |
369 recursion, so the object returned should preferably be the one | |
370 with the deepest level of Lisp_Object pointers. This function | |
1204 | 371 can be NULL, meaning no GC marking is necessary. |
372 | |
373 NOTE NOTE NOTE: This is not used by KKCC (which uses the data | |
374 description below instead), unless the data description is missing. | |
375 Yes, this currently means there is logic duplication. Eventually the | |
376 mark methods will be removed. */ | |
428 | 377 Lisp_Object (*marker) (Lisp_Object); |
442 | 378 |
379 /* `printer' converts the object to a printed representation. | |
380 This can be NULL; in this case default_object_printer() will be | |
381 used instead. */ | |
428 | 382 void (*printer) (Lisp_Object, Lisp_Object printcharfun, int escapeflag); |
442 | 383 |
4930
9f04877ce07e
fix up comments about finalizers and NEWGC internal objects
Ben Wing <ben@xemacs.org>
parents:
4844
diff
changeset
|
384 /* `finalizer' is called at GC time when the object is about to be freed, |
9f04877ce07e
fix up comments about finalizers and NEWGC internal objects
Ben Wing <ben@xemacs.org>
parents:
4844
diff
changeset
|
385 and at dump time (FOR_DISKSAVE will be non-zero in this case). It |
9f04877ce07e
fix up comments about finalizers and NEWGC internal objects
Ben Wing <ben@xemacs.org>
parents:
4844
diff
changeset
|
386 should perform any necessary cleanup (e.g. freeing malloc()ed memory |
9f04877ce07e
fix up comments about finalizers and NEWGC internal objects
Ben Wing <ben@xemacs.org>
parents:
4844
diff
changeset
|
387 or releasing objects created in external libraries, such as |
9f04877ce07e
fix up comments about finalizers and NEWGC internal objects
Ben Wing <ben@xemacs.org>
parents:
4844
diff
changeset
|
388 window-system windows or file handles). This can be NULL, meaning no |
9f04877ce07e
fix up comments about finalizers and NEWGC internal objects
Ben Wing <ben@xemacs.org>
parents:
4844
diff
changeset
|
389 special finalization is necessary. |
428 | 390 |
4930
9f04877ce07e
fix up comments about finalizers and NEWGC internal objects
Ben Wing <ben@xemacs.org>
parents:
4844
diff
changeset
|
391 WARNING: remember that `finalizer' is called at dump time even though |
9f04877ce07e
fix up comments about finalizers and NEWGC internal objects
Ben Wing <ben@xemacs.org>
parents:
4844
diff
changeset
|
392 the object is not being freed -- check the FOR_DISKSAVE argument. */ |
428 | 393 void (*finalizer) (void *header, int for_disksave); |
442 | 394 |
428 | 395 /* This can be NULL, meaning compare objects with EQ(). */ |
4906
6ef8256a020a
implement equalp in C, fix case-folding, add equal() method for keymaps
Ben Wing <ben@xemacs.org>
parents:
4844
diff
changeset
|
396 int (*equal) (Lisp_Object obj1, Lisp_Object obj2, int depth, |
6ef8256a020a
implement equalp in C, fix case-folding, add equal() method for keymaps
Ben Wing <ben@xemacs.org>
parents:
4844
diff
changeset
|
397 int foldcase); |
442 | 398 |
399 /* `hash' generates hash values for use with hash tables that have | |
400 `equal' as their test function. This can be NULL, meaning use | |
401 the Lisp_Object itself as the hash. But, you must still satisfy | |
402 the constraint that if two objects are `equal', then they *must* | |
403 hash to the same value in order for hash tables to work properly. | |
404 This means that `hash' can be NULL only if the `equal' method is | |
405 also NULL. */ | |
2515 | 406 Hashcode (*hash) (Lisp_Object, int); |
428 | 407 |
1204 | 408 /* Data layout description for your object. See long comment below. */ |
409 const struct memory_description *description; | |
428 | 410 |
442 | 411 /* These functions allow any object type to have builtin property |
412 lists that can be manipulated from the lisp level with | |
413 `get', `put', `remprop', and `object-plist'. */ | |
428 | 414 Lisp_Object (*getprop) (Lisp_Object obj, Lisp_Object prop); |
415 int (*putprop) (Lisp_Object obj, Lisp_Object prop, Lisp_Object val); | |
416 int (*remprop) (Lisp_Object obj, Lisp_Object prop); | |
417 Lisp_Object (*plist) (Lisp_Object obj); | |
418 | |
3263 | 419 #ifdef NEW_GC |
2720 | 420 /* Only one of `static_size' and `size_in_bytes_method' is non-0. */ |
3263 | 421 #else /* not NEW_GC */ |
442 | 422 /* Only one of `static_size' and `size_in_bytes_method' is non-0. |
3024 | 423 If both are 0, this type is not instantiable by |
424 old_basic_alloc_lcrecord(). */ | |
3263 | 425 #endif /* not NEW_GC */ |
665 | 426 Bytecount static_size; |
427 Bytecount (*size_in_bytes_method) (const void *header); | |
442 | 428 |
429 /* The (constant) index into lrecord_implementations_table */ | |
430 enum lrecord_type lrecord_type_index; | |
431 | |
3263 | 432 #ifndef NEW_GC |
428 | 433 /* A "basic" lrecord is any lrecord that's not an lcrecord, i.e. |
3024 | 434 one that does not have an old_lcrecord_header at the front and which |
1204 | 435 is (usually) allocated in frob blocks. */ |
442 | 436 unsigned int basic_p :1; |
3263 | 437 #endif /* not NEW_GC */ |
428 | 438 }; |
439 | |
617 | 440 /* All the built-in lisp object types are enumerated in `enum lrecord_type'. |
442 | 441 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. */ | |
443 #define MODULE_DEFINABLE_TYPE_COUNT 32 | |
444 | |
1632 | 445 extern MODULE_API const struct lrecord_implementation * |
446 lrecord_implementations_table[lrecord_type_last_built_in_type + MODULE_DEFINABLE_TYPE_COUNT]; | |
428 | 447 |
448 #define XRECORD_LHEADER_IMPLEMENTATION(obj) \ | |
442 | 449 LHEADER_IMPLEMENTATION (XRECORD_LHEADER (obj)) |
450 #define LHEADER_IMPLEMENTATION(lh) lrecord_implementations_table[(lh)->type] | |
428 | 451 |
3092 | 452 #include "gc.h" |
453 | |
454 #ifdef NEW_GC | |
455 #include "vdb.h" | |
456 #endif /* NEW_GC */ | |
457 | |
428 | 458 extern int gc_in_progress; |
459 | |
3263 | 460 #ifdef NEW_GC |
2720 | 461 #include "mc-alloc.h" |
462 | |
2994 | 463 #ifdef ALLOC_TYPE_STATS |
2720 | 464 void init_lrecord_stats (void); |
465 void inc_lrecord_stats (Bytecount size, const struct lrecord_header *h); | |
466 void dec_lrecord_stats (Bytecount size_including_overhead, | |
467 const struct lrecord_header *h); | |
3092 | 468 int lrecord_stats_heap_size (void); |
2994 | 469 #endif /* ALLOC_TYPE_STATS */ |
2720 | 470 |
471 /* Tell mc-alloc how to call a finalizer. */ | |
3092 | 472 #define MC_ALLOC_CALL_FINALIZER(ptr) \ |
473 { \ | |
474 Lisp_Object MCACF_obj = wrap_pointer_1 (ptr); \ | |
475 struct lrecord_header *MCACF_lheader = XRECORD_LHEADER (MCACF_obj); \ | |
476 if (XRECORD_LHEADER (MCACF_obj) && LRECORDP (MCACF_obj) \ | |
477 && !LRECORD_FREE_P (MCACF_lheader) ) \ | |
478 { \ | |
479 const struct lrecord_implementation *MCACF_implementation \ | |
480 = LHEADER_IMPLEMENTATION (MCACF_lheader); \ | |
481 if (MCACF_implementation && MCACF_implementation->finalizer) \ | |
482 { \ | |
483 GC_STAT_FINALIZED; \ | |
484 MCACF_implementation->finalizer (ptr, 0); \ | |
485 } \ | |
486 } \ | |
487 } while (0) | |
2720 | 488 |
489 /* Tell mc-alloc how to call a finalizer for disksave. */ | |
490 #define MC_ALLOC_CALL_FINALIZER_FOR_DISKSAVE(ptr) \ | |
491 { \ | |
492 Lisp_Object MCACF_obj = wrap_pointer_1 (ptr); \ | |
493 struct lrecord_header *MCACF_lheader = XRECORD_LHEADER (MCACF_obj); \ | |
494 if (XRECORD_LHEADER (MCACF_obj) && LRECORDP (MCACF_obj) \ | |
495 && !LRECORD_FREE_P (MCACF_lheader) ) \ | |
496 { \ | |
497 const struct lrecord_implementation *MCACF_implementation \ | |
498 = LHEADER_IMPLEMENTATION (MCACF_lheader); \ | |
499 if (MCACF_implementation && MCACF_implementation->finalizer) \ | |
500 MCACF_implementation->finalizer (ptr, 1); \ | |
501 } \ | |
502 } while (0) | |
503 | |
504 #define LRECORD_FREE_P(ptr) \ | |
505 (((struct lrecord_header *) ptr)->free) | |
506 | |
507 #define MARK_LRECORD_AS_FREE(ptr) \ | |
508 ((void) (((struct lrecord_header *) ptr)->free = 1)) | |
509 | |
510 #define MARK_LRECORD_AS_NOT_FREE(ptr) \ | |
511 ((void) (((struct lrecord_header *) ptr)->free = 0)) | |
512 | |
513 #define MARKED_RECORD_P(obj) MARKED_P (obj) | |
514 #define MARKED_RECORD_HEADER_P(lheader) MARKED_P (lheader) | |
515 #define MARK_RECORD_HEADER(lheader) MARK (lheader) | |
516 #define UNMARK_RECORD_HEADER(lheader) UNMARK (lheader) | |
517 | |
518 #define LISP_READONLY_RECORD_HEADER_P(lheader) ((lheader)->lisp_readonly) | |
519 #define SET_LISP_READONLY_RECORD_HEADER(lheader) \ | |
520 ((void) ((lheader)->lisp_readonly = 1)) | |
521 #define MARK_LRECORD_AS_LISP_READONLY(ptr) \ | |
522 ((void) (((struct lrecord_header *) ptr)->lisp_readonly = 1)) | |
523 | |
3263 | 524 #else /* not NEW_GC */ |
2720 | 525 |
5059
c8f90d61dcf3
fix memory usage stats to include pdumped objects
Ben Wing <ben@xemacs.org>
parents:
4967
diff
changeset
|
526 enum lrecord_alloc_status |
c8f90d61dcf3
fix memory usage stats to include pdumped objects
Ben Wing <ben@xemacs.org>
parents:
4967
diff
changeset
|
527 { |
c8f90d61dcf3
fix memory usage stats to include pdumped objects
Ben Wing <ben@xemacs.org>
parents:
4967
diff
changeset
|
528 ALLOC_IN_USE, |
c8f90d61dcf3
fix memory usage stats to include pdumped objects
Ben Wing <ben@xemacs.org>
parents:
4967
diff
changeset
|
529 ALLOC_FREE, |
c8f90d61dcf3
fix memory usage stats to include pdumped objects
Ben Wing <ben@xemacs.org>
parents:
4967
diff
changeset
|
530 ALLOC_ON_FREE_LIST |
c8f90d61dcf3
fix memory usage stats to include pdumped objects
Ben Wing <ben@xemacs.org>
parents:
4967
diff
changeset
|
531 }; |
c8f90d61dcf3
fix memory usage stats to include pdumped objects
Ben Wing <ben@xemacs.org>
parents:
4967
diff
changeset
|
532 |
c8f90d61dcf3
fix memory usage stats to include pdumped objects
Ben Wing <ben@xemacs.org>
parents:
4967
diff
changeset
|
533 void tick_lrecord_stats (const struct lrecord_header *h, |
c8f90d61dcf3
fix memory usage stats to include pdumped objects
Ben Wing <ben@xemacs.org>
parents:
4967
diff
changeset
|
534 enum lrecord_alloc_status status); |
c8f90d61dcf3
fix memory usage stats to include pdumped objects
Ben Wing <ben@xemacs.org>
parents:
4967
diff
changeset
|
535 |
2720 | 536 #define LRECORD_FREE_P(ptr) \ |
537 (((struct lrecord_header *) ptr)->type == lrecord_type_free) | |
538 | |
539 #define MARK_LRECORD_AS_FREE(ptr) \ | |
540 ((void) (((struct lrecord_header *) ptr)->type = lrecord_type_free)) | |
541 | |
442 | 542 #define MARKED_RECORD_P(obj) (XRECORD_LHEADER (obj)->mark) |
428 | 543 #define MARKED_RECORD_HEADER_P(lheader) ((lheader)->mark) |
544 #define MARK_RECORD_HEADER(lheader) ((void) ((lheader)->mark = 1)) | |
545 #define UNMARK_RECORD_HEADER(lheader) ((void) ((lheader)->mark = 0)) | |
546 | |
547 #define C_READONLY_RECORD_HEADER_P(lheader) ((lheader)->c_readonly) | |
548 #define LISP_READONLY_RECORD_HEADER_P(lheader) ((lheader)->lisp_readonly) | |
442 | 549 #define SET_C_READONLY_RECORD_HEADER(lheader) do { \ |
550 struct lrecord_header *SCRRH_lheader = (lheader); \ | |
551 SCRRH_lheader->c_readonly = 1; \ | |
552 SCRRH_lheader->lisp_readonly = 1; \ | |
553 SCRRH_lheader->mark = 1; \ | |
554 } while (0) | |
428 | 555 #define SET_LISP_READONLY_RECORD_HEADER(lheader) \ |
556 ((void) ((lheader)->lisp_readonly = 1)) | |
3263 | 557 #endif /* not NEW_GC */ |
1676 | 558 |
559 #ifdef USE_KKCC | |
560 #define RECORD_DESCRIPTION(lheader) lrecord_memory_descriptions[(lheader)->type] | |
561 #else /* not USE_KKCC */ | |
442 | 562 #define RECORD_MARKER(lheader) lrecord_markers[(lheader)->type] |
1676 | 563 #endif /* not USE_KKCC */ |
428 | 564 |
934 | 565 #define RECORD_DUMPABLE(lheader) (lrecord_implementations_table[(lheader)->type])->dumpable |
1204 | 566 |
567 /* Data description stuff | |
934 | 568 |
1204 | 569 Data layout descriptions describe blocks of memory (in particular, Lisp |
570 objects and other objects on the heap, and global objects with pointers | |
571 to such heap objects), including their size and a list of the elements | |
572 that need relocating, marking or other special handling. They are | |
573 currently used in two places: by pdump [the new, portable dumper] and | |
574 KKCC [the new garbage collector]. The two subsystems use the | |
575 descriptions in different ways, and as a result some of the descriptions | |
576 are appropriate only for one or the other, when it is known that only | |
577 that subsystem will use the description. (This is particularly the case | |
578 with objects that can't be dumped, because pdump needs more info than | |
579 KKCC.) However, properly written descriptions are appropriate for both, | |
580 and you should strive to write your descriptions that way, since the | |
581 dumpable status of an object may change and new uses for the | |
582 descriptions may be created. (An example that comes to mind is a | |
583 facility for determining the memory usage of XEmacs data structures -- | |
584 like `buffer-memory-usage', `window-memory-usage', etc. but more | |
585 general.) | |
586 | |
587 More specifically: | |
428 | 588 |
1204 | 589 Pdump (the portable dumper) needs to write out all objects in heap |
590 space, and later on (in another invocation of XEmacs) load them back | |
591 into the heap, relocating all pointers to the heap objects in the global | |
592 data space. ("Heap" means anything malloc()ed, including all Lisp | |
593 objects, and "global data" means anything declared globally or | |
594 `static'.) Pdump, then, needs to be told about the location of all | |
595 global pointers to heap objects, all the description of all such | |
596 objects, including their size and any pointers to other heap (aka | |
597 "relocatable") objects. (Pdump assumes that the heap may occur in | |
598 different places in different invocations -- therefore, it is not enough | |
599 simply to write out the entire heap and later reload it at the same | |
600 location -- but that global data is always in the same place, and hence | |
601 pointers to it do not need to be relocated. This assumption holds true | |
602 in general for modern operating systems, but would be broken, for | |
603 example, in a system without virtual memory, or when dealing with shared | |
604 libraries. Also, unlike unexec, pdump does not usually write out or | |
605 restore objects in the global data space, and thus they need to be | |
606 initialized every time XEmacs is loaded. This is the purpose of the | |
607 reinit_*() functions throughout XEmacs. [It's possible, however, to make | |
608 pdump restore global data. This must be done, of course, for heap | |
609 pointers, but is also done for other values that are not easy to | |
610 recompute -- in particular, values established by the Lisp code loaded | |
611 at dump time.]) Note that the data type `Lisp_Object' is basically just | |
612 a relocatable pointer disguised as a long, and in general pdump treats | |
613 the Lisp_Object values and pointers to Lisp objects (e.g. Lisp_Object | |
614 vs. `struct frame *') identically. (NOTE: This equivalence depends | |
615 crucially on the current "minimal tagbits" implementation of Lisp_Object | |
616 pointers.) | |
428 | 617 |
1204 | 618 Descriptions are used by pdump in three places: (a) descriptions of Lisp |
619 objects, referenced in the DEFINE_*LRECORD_*IMPLEMENTATION*() call; (b) | |
620 descriptions of global objects to be dumped, registered by | |
621 dump_add_root_block(); (c) descriptions of global pointers to | |
2367 | 622 non-Lisp_Object heap objects, registered by dump_add_root_block_ptr(). |
1204 | 623 The descriptions need to tell pdump which elements of your structure are |
624 Lisp_Objects or structure pointers, plus the descriptions in turn of the | |
625 non-Lisp_Object structures pointed to. If these structures are you own | |
626 private ones, you will have to write these recursive descriptions | |
627 yourself; otherwise, you are reusing a structure already in existence | |
628 elsewhere and there is probably already a description for it. | |
629 | |
630 Pdump does not care about Lisp objects that cannot be dumped (the | |
631 dumpable flag to DEFINE_*LRECORD_*IMPLEMENTATION*() is 0). | |
632 | |
633 KKCC also uses data layout descriptions, but differently. It cares | |
634 about all objects, dumpable or not, but specifically only wants to know | |
635 about Lisp_Objects in your object and in structures pointed to. Thus, | |
636 it doesn't care about things like pointers to structures ot other blocks | |
637 of memory with no Lisp Objects in them, which pdump would care a lot | |
638 about. | |
639 | |
640 Technically, then, you could write your description differently | |
641 depending on whether your object is dumpable -- the full pdump | |
642 description if so, the abbreviated KKCC description if not. In fact, | |
643 some descriptions are written this way. This is dangerous, though, | |
644 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 | |
646 normally omitted from the "abbreviated" description -- see above. | |
647 | |
648 A memory_description is an array of values. (This is actually | |
771 | 649 misnamed, in that it does not just describe lrecords, but any |
650 blocks of memory.) The first value of each line is a type, the | |
651 second the offset in the lrecord structure. The third and | |
652 following elements are parameters; their presence, type and number | |
653 is type-dependent. | |
654 | |
1204 | 655 The description ends with an "XD_END" record. |
771 | 656 |
657 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, | |
659 since the size of the lrecord is known. (The same goes for nested | |
660 structures, whenever the structure size is given, rather than being | |
661 defaulted by specifying 0 for the size.) | |
662 | |
1204 | 663 A sized_memory_description is a memory_description plus the size of the |
664 block of memory. The size field in a sized_memory_description can be | |
665 given as zero, i.e. unspecified, meaning that the last element in the | |
666 structure is described in the description and the size of the block can | |
667 therefore be computed from it. (This is useful for stretchy arrays.) | |
668 | |
669 memory_descriptions are used to describe lrecords (the size of the | |
670 lrecord is elsewhere in its description, attached to its methods, so it | |
671 does not need to be given here) and global objects, where the size is an | |
672 argument to the call to dump_add_root_block(). | |
673 sized_memory_descriptions are used for pointers and arrays in | |
2367 | 674 memory_descriptions and for calls to dump_add_root_block_ptr(). (#### |
1204 | 675 It is not obvious why this is so in the latter case. Probably, calls to |
2367 | 676 dump_add_root_block_ptr() should use plain memory_descriptions and have |
1204 | 677 the size be an argument to the call.) |
678 | |
679 NOTE: Anywhere that a sized_memory_description occurs inside of a plain | |
680 memory_description, a "description map" can be substituted. Rather than | |
681 being an actual description, this describes how to find the description | |
682 by looking inside of the object being described. This is a convenient | |
683 way to describe Lisp objects with subtypes and corresponding | |
684 type-specific data. | |
428 | 685 |
686 Some example descriptions : | |
440 | 687 |
814 | 688 struct Lisp_String |
689 { | |
690 struct lrecord_header lheader; | |
691 Bytecount size; | |
867 | 692 Ibyte *data; |
814 | 693 Lisp_Object plist; |
694 }; | |
695 | |
1204 | 696 static const struct memory_description cons_description[] = { |
440 | 697 { XD_LISP_OBJECT, offsetof (Lisp_Cons, car) }, |
698 { XD_LISP_OBJECT, offsetof (Lisp_Cons, cdr) }, | |
428 | 699 { XD_END } |
700 }; | |
701 | |
440 | 702 Which means "two lisp objects starting at the 'car' and 'cdr' elements" |
428 | 703 |
1204 | 704 static const struct memory_description string_description[] = { |
814 | 705 { XD_BYTECOUNT, offsetof (Lisp_String, size) }, |
1204 | 706 { XD_OPAQUE_DATA_PTR, offsetof (Lisp_String, data), XD_INDIRECT (0, 1) }, |
814 | 707 { XD_LISP_OBJECT, offsetof (Lisp_String, plist) }, |
708 { XD_END } | |
709 }; | |
710 | |
711 "A pointer to string data at 'data', the size of the pointed array being | |
712 the value of the size variable plus 1, and one lisp object at 'plist'" | |
713 | |
714 If your object has a pointer to an array of Lisp_Objects in it, something | |
715 like this: | |
716 | |
717 struct Lisp_Foo | |
718 { | |
719 ...; | |
720 int count; | |
721 Lisp_Object *objects; | |
722 ...; | |
723 } | |
724 | |
2367 | 725 You'd use XD_BLOCK_PTR, something like: |
814 | 726 |
1204 | 727 static const struct memory_description foo_description[] = { |
728 ... | |
729 { XD_INT, offsetof (Lisp_Foo, count) }, | |
2367 | 730 { XD_BLOCK_PTR, offsetof (Lisp_Foo, objects), |
2551 | 731 XD_INDIRECT (0, 0), { &lisp_object_description } }, |
1204 | 732 ... |
733 }; | |
734 | |
4952
19a72041c5ed
Mule-izing, various fixes related to char * arguments
Ben Wing <ben@xemacs.org>
parents:
4937
diff
changeset
|
735 lisp_object_description is declared in gc.c, like this: |
1204 | 736 |
737 static const struct memory_description lisp_object_description_1[] = { | |
814 | 738 { XD_LISP_OBJECT, 0 }, |
739 { XD_END } | |
740 }; | |
741 | |
1204 | 742 const struct sized_memory_description lisp_object_description = { |
814 | 743 sizeof (Lisp_Object), |
1204 | 744 lisp_object_description_1 |
814 | 745 }; |
746 | |
2367 | 747 Another example of XD_BLOCK_PTR: |
428 | 748 |
1204 | 749 typedef struct htentry |
814 | 750 { |
751 Lisp_Object key; | |
752 Lisp_Object value; | |
1204 | 753 } htentry; |
814 | 754 |
755 struct Lisp_Hash_Table | |
756 { | |
3017 | 757 struct LCRECORD_HEADER header; |
814 | 758 Elemcount size; |
759 Elemcount count; | |
760 Elemcount rehash_count; | |
761 double rehash_size; | |
762 double rehash_threshold; | |
763 Elemcount golden_ratio; | |
764 hash_table_hash_function_t hash_function; | |
765 hash_table_test_function_t test_function; | |
1204 | 766 htentry *hentries; |
814 | 767 enum hash_table_weakness weakness; |
768 Lisp_Object next_weak; // Used to chain together all of the weak | |
769 // hash tables. Don't mark through this. | |
770 }; | |
771 | |
1204 | 772 static const struct memory_description htentry_description_1[] = { |
773 { XD_LISP_OBJECT, offsetof (htentry, key) }, | |
774 { XD_LISP_OBJECT, offsetof (htentry, value) }, | |
814 | 775 { XD_END } |
776 }; | |
777 | |
1204 | 778 static const struct sized_memory_description htentry_description = { |
779 sizeof (htentry), | |
780 htentry_description_1 | |
814 | 781 }; |
782 | |
1204 | 783 const struct memory_description hash_table_description[] = { |
814 | 784 { XD_ELEMCOUNT, offsetof (Lisp_Hash_Table, size) }, |
2367 | 785 { XD_BLOCK_PTR, offsetof (Lisp_Hash_Table, hentries), XD_INDIRECT (0, 1), |
2551 | 786 { &htentry_description } }, |
814 | 787 { XD_LO_LINK, offsetof (Lisp_Hash_Table, next_weak) }, |
788 { XD_END } | |
789 }; | |
790 | |
791 Note that we don't need to declare all the elements in the structure, just | |
792 the ones that need to be relocated (Lisp_Objects and structures) or that | |
793 need to be referenced as counts for relocated objects. | |
794 | |
1204 | 795 A description map looks like this: |
796 | |
797 static const struct sized_memory_description specifier_extra_description_map [] = { | |
798 { offsetof (Lisp_Specifier, methods) }, | |
799 { offsetof (struct specifier_methods, extra_description) }, | |
800 { -1 } | |
801 }; | |
802 | |
803 const struct memory_description specifier_description[] = { | |
804 ... | |
2367 | 805 { XD_BLOCK_ARRAY, offset (Lisp_Specifier, data), 1, |
2551 | 806 { specifier_extra_description_map } }, |
1204 | 807 ... |
808 { XD_END } | |
809 }; | |
810 | |
811 This would be appropriate for an object that looks like this: | |
812 | |
813 struct specifier_methods | |
814 { | |
815 ... | |
816 const struct sized_memory_description *extra_description; | |
817 ... | |
818 }; | |
819 | |
820 struct Lisp_Specifier | |
821 { | |
3017 | 822 struct LCRECORD_HEADER header; |
1204 | 823 struct specifier_methods *methods; |
824 | |
825 ... | |
826 // type-specific extra data attached to a specifier | |
827 max_align_t data[1]; | |
828 }; | |
829 | |
830 The description map means "retrieve a pointer into the object at offset | |
831 `offsetof (Lisp_Specifier, methods)' , then in turn retrieve a pointer | |
832 into that object at offset `offsetof (struct specifier_methods, | |
833 extra_description)', and that is the sized_memory_description to use." | |
834 There can be any number of indirections, which can be either into | |
835 straight pointers or Lisp_Objects. The way that description maps are | |
836 distinguished from normal sized_memory_descriptions is that in the | |
837 former, the memory_description pointer is NULL. | |
838 | |
839 --ben | |
840 | |
814 | 841 |
842 The existing types : | |
843 | |
844 | |
428 | 845 XD_LISP_OBJECT |
1204 | 846 |
847 A Lisp object. This is also the type to use for pointers to other lrecords | |
848 (e.g. struct frame *). | |
428 | 849 |
440 | 850 XD_LISP_OBJECT_ARRAY |
1204 | 851 |
771 | 852 An array of Lisp objects or (equivalently) pointers to lrecords. |
853 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, | |
2367 | 855 use XD_BLOCK_PTR, whose description parameter is a sized_memory_description |
771 | 856 consisting of only XD_LISP_OBJECT and XD_END. |
440 | 857 |
428 | 858 XD_LO_LINK |
1204 | 859 |
771 | 860 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 | |
862 not automatically add the referenced object to the table of all | |
863 objects to be dumped, and when storing and loading the dumped data | |
864 will automatically prune unreferenced objects in the chain and link | |
865 each referenced object to the next referenced object, even if it's | |
866 many links away. We also need to special handling of a similar | |
867 nature for the root of the chain, which will be a staticpro()ed | |
868 object. | |
432 | 869 |
428 | 870 XD_OPAQUE_PTR |
1204 | 871 |
428 | 872 Pointer to undumpable data. Must be NULL when dumping. |
873 | |
2551 | 874 XD_OPAQUE_PTR_CONVERTIBLE |
875 | |
876 Pointer to data which is not directly dumpable but can be converted | |
877 to a dumpable, opaque external representation. The parameter is | |
878 a pointer to an opaque_convert_functions struct. | |
879 | |
880 XD_OPAQUE_DATA_CONVERTIBLE | |
881 | |
882 Data which is not directly dumpable but can be converted to a | |
883 dumpable, opaque external representation. The parameter is a | |
884 pointer to an opaque_convert_functions struct. | |
885 | |
2367 | 886 XD_BLOCK_PTR |
1204 | 887 |
771 | 888 Pointer to block of described memory. (This is misnamed: It is NOT |
889 necessarily a pointer to a struct foo.) Parameters are number of | |
1204 | 890 contiguous blocks and sized_memory_description. |
771 | 891 |
2367 | 892 XD_BLOCK_ARRAY |
1204 | 893 |
771 | 894 Array of blocks of described memory. Parameters are number of |
2367 | 895 structures and sized_memory_description. This differs from XD_BLOCK_PTR |
771 | 896 in that the parameter is declared as struct foo[666] instead of |
897 struct *foo. In other words, the block of memory holding the | |
898 structures is within the containing structure, rather than being | |
899 elsewhere, with a pointer in the containing structure. | |
428 | 900 |
1204 | 901 NOTE NOTE NOTE: Be sure that you understand the difference between |
2367 | 902 XD_BLOCK_PTR and XD_BLOCK_ARRAY: |
1204 | 903 - struct foo bar[666], i.e. 666 inline struct foos |
2367 | 904 --> XD_BLOCK_ARRAY, argument 666, pointing to a description of |
1204 | 905 struct foo |
906 - struct foo *bar, i.e. pointer to a block of 666 struct foos | |
2367 | 907 --> XD_BLOCK_PTR, argument 666, pointing to a description of |
1204 | 908 struct foo |
909 - struct foo *bar[666], i.e. 666 pointers to separate blocks of struct foos | |
2367 | 910 --> XD_BLOCK_ARRAY, argument 666, pointing to a description of |
1204 | 911 a single pointer to struct foo; the description is a single |
2367 | 912 XD_BLOCK_PTR, argument 1, which in turn points to a description |
1204 | 913 of struct foo. |
914 | |
2367 | 915 NOTE also that an XD_BLOCK_PTR of 666 foos is equivalent to an |
916 XD_BLOCK_PTR of 1 bar, where the description of `bar' is an | |
917 XD_BLOCK_ARRAY of 666 foos. | |
918 | |
428 | 919 XD_OPAQUE_DATA_PTR |
1204 | 920 |
428 | 921 Pointer to dumpable opaque data. Parameter is the size of the data. |
922 Pointed data must be relocatable without changes. | |
923 | |
771 | 924 XD_UNION |
1204 | 925 |
926 Union of two or more different types of data. Parameters are a constant | |
927 which determines which type the data is (this is usually an XD_INDIRECT, | |
928 referring to one of the fields in the structure), and a "sizing lobby" (a | |
929 sized_memory_description, which points to a memory_description and | |
930 indicates its size). The size field in the sizing lobby describes the | |
931 size of the union field in the object, and the memory_description in it | |
932 is referred to as a "union map" and has a special interpretation: The | |
933 offset field is replaced by a constant, which is compared to the first | |
934 parameter of the XD_UNION descriptor to determine if this description | |
935 applies to the union data, and XD_INDIRECT references refer to the | |
936 containing object and description. Note that the description applies | |
2367 | 937 "inline" to the union data, like XD_BLOCK_ARRAY and not XD_BLOCK_PTR. |
1204 | 938 If the union data is a pointer to different types of structures, each |
2367 | 939 element in the memory_description should be an XD_BLOCK_PTR. See |
1204 | 940 unicode.c, redisplay.c and objects.c for examples of XD_UNION. |
941 | |
942 XD_UNION_DYNAMIC_SIZE | |
943 | |
944 Same as XD_UNION except that this is used for objects where the size of | |
945 the object containing the union varies depending on the particular value | |
946 of the union constant. That is, an object with plain XD_UNION typically | |
947 has the union declared as `union foo' or as `void *', where an object | |
948 with XD_UNION_DYNAMIC_SIZE typically has the union as the last element, | |
2367 | 949 and declared as something like Rawbyte foo[1]. With plain XD_UNION, the |
1204 | 950 object is (usually) of fixed size and always contains enough space for |
951 the data associated with all possible union constants, and thus the union | |
952 constant can potentially change during the lifetime of the object. With | |
953 XD_UNION_DYNAMIC_SIZE, however, the union constant is fixed at the time | |
954 of creation of the object, and the size of the object is computed | |
955 dynamically at creation time based on the size of the data associated | |
956 with the union constant. Currently, the only difference between XD_UNION | |
957 and XD_UNION_DYNAMIC_SIZE is how the size of the union data is | |
958 calculated, when (a) the structure containing the union has no size | |
959 given; (b) the union occurs as the last element in the structure; and (c) | |
960 the union has no size given (in the first-level sized_memory_description | |
961 pointed to). In this circumstance, the size of XD_UNION comes from the | |
962 max size of the data associated with all possible union constants, | |
963 whereas the size of XD_UNION_DYNAMIC_SIZE comes from the size of the data | |
964 associated with the currently specified (and unchangeable) union | |
965 constant. | |
771 | 966 |
2367 | 967 XD_ASCII_STRING |
1204 | 968 |
2367 | 969 Pointer to a C string, purely ASCII. |
428 | 970 |
971 XD_DOC_STRING | |
1204 | 972 |
2367 | 973 Pointer to a doc string (C string in pure ASCII if positive, |
974 opaque value if negative) | |
428 | 975 |
976 XD_INT_RESET | |
1204 | 977 |
428 | 978 An integer which will be reset to a given value in the dump file. |
979 | |
1204 | 980 XD_ELEMCOUNT |
771 | 981 |
665 | 982 Elemcount value. Used for counts. |
647 | 983 |
665 | 984 XD_BYTECOUNT |
1204 | 985 |
665 | 986 Bytecount value. Used for counts. |
647 | 987 |
665 | 988 XD_HASHCODE |
1204 | 989 |
665 | 990 Hashcode value. Used for the results of hashing functions. |
428 | 991 |
992 XD_INT | |
1204 | 993 |
428 | 994 int value. Used for counts. |
995 | |
996 XD_LONG | |
1204 | 997 |
428 | 998 long value. Used for counts. |
999 | |
771 | 1000 XD_BYTECOUNT |
1204 | 1001 |
771 | 1002 bytecount value. Used for counts. |
1003 | |
428 | 1004 XD_END |
1204 | 1005 |
428 | 1006 Special type indicating the end of the array. |
1007 | |
1008 | |
1009 Special macros: | |
1204 | 1010 |
1011 XD_INDIRECT (line, delta) | |
1012 Usable where a count, size, offset or union constant is requested. Gives | |
1013 the value of the element which is at line number 'line' in the | |
1014 description (count starts at zero) and adds delta to it, which must | |
1015 (currently) be positive. | |
428 | 1016 */ |
1017 | |
1204 | 1018 enum memory_description_type |
647 | 1019 { |
440 | 1020 XD_LISP_OBJECT_ARRAY, |
428 | 1021 XD_LISP_OBJECT, |
3092 | 1022 #ifdef NEW_GC |
1023 XD_LISP_OBJECT_BLOCK_PTR, | |
1024 #endif /* NEW_GC */ | |
428 | 1025 XD_LO_LINK, |
1026 XD_OPAQUE_PTR, | |
2551 | 1027 XD_OPAQUE_PTR_CONVERTIBLE, |
1028 XD_OPAQUE_DATA_CONVERTIBLE, | |
1029 XD_OPAQUE_DATA_PTR, | |
2367 | 1030 XD_BLOCK_PTR, |
1031 XD_BLOCK_ARRAY, | |
771 | 1032 XD_UNION, |
1204 | 1033 XD_UNION_DYNAMIC_SIZE, |
2367 | 1034 XD_ASCII_STRING, |
428 | 1035 XD_DOC_STRING, |
1036 XD_INT_RESET, | |
665 | 1037 XD_BYTECOUNT, |
1038 XD_ELEMCOUNT, | |
1039 XD_HASHCODE, | |
428 | 1040 XD_INT, |
1041 XD_LONG, | |
1204 | 1042 XD_END |
428 | 1043 }; |
1044 | |
1204 | 1045 enum data_description_entry_flags |
647 | 1046 { |
1204 | 1047 /* If set, KKCC does not process this entry. |
1048 | |
1049 (1) One obvious use is with things that pdump saves but which do not get | |
1050 marked normally -- for example the next and prev fields in a marker. The | |
1051 marker chain is weak, with its entries removed when they are finalized. | |
1052 | |
1053 (2) This can be set on structures not containing any Lisp objects, or (more | |
1054 usefully) on structures that contain Lisp objects but where the objects | |
1055 always occur in another structure as well. For example, the extent lists | |
1056 kept by a buffer keep the extents in two lists, one sorted by the start | |
1057 of the extent and the other by the end. There's no point in marking | |
1058 both, since each contains the same objects as the other; but when dumping | |
1059 (if we were to dump such a structure), when computing memory size, etc., | |
1060 it's crucial to tag both sides. | |
1061 */ | |
1062 XD_FLAG_NO_KKCC = 1, | |
1063 /* If set, pdump does not process this entry. */ | |
1064 XD_FLAG_NO_PDUMP = 2, | |
1065 /* Indicates that this is a "default" entry in a union map. */ | |
1066 XD_FLAG_UNION_DEFAULT_ENTRY = 4, | |
3263 | 1067 #ifndef NEW_GC |
1204 | 1068 /* Indicates that this is a free Lisp object we're marking. |
1069 Only relevant for ERROR_CHECK_GC. This occurs when we're marking | |
1070 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 | |
1072 them as normal. */ | |
1429 | 1073 XD_FLAG_FREE_LISP_OBJECT = 8 |
3263 | 1074 #endif /* not NEW_GC */ |
1204 | 1075 #if 0 |
1429 | 1076 , |
1204 | 1077 /* Suggestions for other possible flags: */ |
1078 | |
1079 /* Eliminate XD_UNION_DYNAMIC_SIZE and replace it with a flag, like this. */ | |
1080 XD_FLAG_UNION_DYNAMIC_SIZE = 16, | |
1081 /* Require that everyone who uses a description map has to flag it, so | |
1082 that it's easy to tell, when looking through the code, where the | |
1083 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 | |
1085 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 | |
1087 or <0). */ | |
1429 | 1088 XD_FLAG_DESCRIPTION_MAP = 32 |
1204 | 1089 #endif |
428 | 1090 }; |
1091 | |
2551 | 1092 union memory_contents_description |
1093 { | |
1094 /* The first element is used by static initializers only. We always read | |
1095 from one of the other two pointers. */ | |
1096 const void *write_only; | |
1097 const struct sized_memory_description *descr; | |
1098 const struct opaque_convert_functions *funcs; | |
1099 }; | |
1100 | |
1204 | 1101 struct memory_description |
1102 { | |
1103 enum memory_description_type type; | |
1104 Bytecount offset; | |
1105 EMACS_INT data1; | |
2551 | 1106 union memory_contents_description data2; |
1204 | 1107 /* Indicates which subsystems process this entry, plus (potentially) other |
1108 flags that apply to this entry. */ | |
1109 int flags; | |
1110 }; | |
428 | 1111 |
1204 | 1112 struct sized_memory_description |
1113 { | |
1114 Bytecount size; | |
1115 const struct memory_description *description; | |
1116 }; | |
1117 | |
2551 | 1118 |
1119 struct opaque_convert_functions | |
1120 { | |
1121 /* Used by XD_OPAQUE_PTR_CONVERTIBLE and | |
1122 XD_OPAQUE_DATA_CONVERTIBLE */ | |
1123 | |
1124 /* Converter to external representation, for those objects from | |
1125 external libraries that can't be directly dumped as opaque data | |
1126 because they contain pointers. This is called at dump time to | |
1127 convert to an opaque, pointer-less representation. | |
1128 | |
1129 This function must put a pointer to the opaque result in *data | |
1130 and its size in *size. */ | |
1131 void (*convert)(const void *object, void **data, Bytecount *size); | |
1132 | |
1133 /* Post-conversion cleanup. Optional (null if not provided). | |
1134 | |
1135 When provided it will be called post-dumping to free any storage | |
1136 allocated for the conversion results. */ | |
1137 void (*convert_free)(const void *object, void *data, Bytecount size); | |
1138 | |
1139 /* De-conversion. | |
1140 | |
1141 At reload time, rebuilds the object from the converted form. | |
1142 "object" is 0 for the PTR case, return is ignored in the DATA | |
1143 case. */ | |
1144 void *(*deconvert)(void *object, void *data, Bytecount size); | |
1145 | |
1146 }; | |
1147 | |
1204 | 1148 extern const struct sized_memory_description lisp_object_description; |
1149 | |
1150 #define XD_INDIRECT(val, delta) (-1 - (Bytecount) ((val) | ((delta) << 8))) | |
428 | 1151 |
1204 | 1152 #define XD_IS_INDIRECT(code) ((code) < 0) |
1153 #define XD_INDIRECT_VAL(code) ((-1 - (code)) & 255) | |
1154 #define XD_INDIRECT_DELTA(code) ((-1 - (code)) >> 8) | |
1155 | |
428 | 1156 /* DEFINE_LRECORD_IMPLEMENTATION is for objects with constant size. |
1157 DEFINE_LRECORD_SEQUENCE_IMPLEMENTATION is for objects whose size varies. | |
1158 */ | |
1159 | |
800 | 1160 #if defined (ERROR_CHECK_TYPES) |
1161 # define DECLARE_ERROR_CHECK_TYPES(c_name, structtype) | |
428 | 1162 #else |
800 | 1163 # define DECLARE_ERROR_CHECK_TYPES(c_name, structtype) |
428 | 1164 #endif |
1165 | |
934 | 1166 |
1167 #define DEFINE_BASIC_LRECORD_IMPLEMENTATION(name,c_name,dumpable,marker,printer,nuker,equal,hash,desc,structtype) \ | |
1168 DEFINE_BASIC_LRECORD_IMPLEMENTATION_WITH_PROPS(name,c_name,dumpable,marker,printer,nuker,equal,hash,desc,0,0,0,0,structtype) | |
1169 | |
1170 #define DEFINE_BASIC_LRECORD_IMPLEMENTATION_WITH_PROPS(name,c_name,dumpable,marker,printer,nuker,equal,hash,desc,getprop,putprop,remprop,plist,structtype) \ | |
1171 MAKE_LRECORD_IMPLEMENTATION(name,c_name,dumpable,marker,printer,nuker,equal,hash,desc,getprop,putprop,remprop,plist,sizeof(structtype),0,1,structtype) | |
1172 | |
1173 #define DEFINE_LRECORD_IMPLEMENTATION(name,c_name,dumpable,marker,printer,nuker,equal,hash,desc,structtype) \ | |
1174 DEFINE_LRECORD_IMPLEMENTATION_WITH_PROPS(name,c_name,dumpable,marker,printer,nuker,equal,hash,desc,0,0,0,0,structtype) | |
1175 | |
1176 #define DEFINE_LRECORD_IMPLEMENTATION_WITH_PROPS(name,c_name,dumpable,marker,printer,nuker,equal,hash,desc,getprop,putprop,remprop,plist,structtype) \ | |
1177 MAKE_LRECORD_IMPLEMENTATION(name,c_name,dumpable,marker,printer,nuker,equal,hash,desc,getprop,putprop,remprop,plist,sizeof (structtype),0,0,structtype) | |
1178 | |
1179 #define DEFINE_LRECORD_SEQUENCE_IMPLEMENTATION(name,c_name,dumpable,marker,printer,nuker,equal,hash,desc,sizer,structtype) \ | |
1180 DEFINE_LRECORD_SEQUENCE_IMPLEMENTATION_WITH_PROPS(name,c_name,dumpable,marker,printer,nuker,equal,hash,desc,0,0,0,0,sizer,structtype) | |
1181 | |
1182 #define DEFINE_BASIC_LRECORD_SEQUENCE_IMPLEMENTATION(name,c_name,dumpable,marker,printer,nuker,equal,hash,desc,sizer,structtype) \ | |
1183 MAKE_LRECORD_IMPLEMENTATION(name,c_name,dumpable,marker,printer,nuker,equal,hash,desc,0,0,0,0,0,sizer,1,structtype) | |
1184 | |
1185 #define DEFINE_LRECORD_SEQUENCE_IMPLEMENTATION_WITH_PROPS(name,c_name,dumpable,marker,printer,nuker,equal,hash,desc,getprop,putprop,remprop,plist,sizer,structtype) \ | |
1186 MAKE_LRECORD_IMPLEMENTATION(name,c_name,dumpable,marker,printer,nuker,equal,hash,desc,getprop,putprop,remprop,plist,0,sizer,0,structtype) | |
1187 | |
3263 | 1188 #ifdef NEW_GC |
2720 | 1189 #define MAKE_LRECORD_IMPLEMENTATION(name,c_name,dumpable,marker,printer,nuker,equal,hash,desc,getprop,putprop,remprop,plist,size,sizer,basic_p,structtype) \ |
1190 DECLARE_ERROR_CHECK_TYPES(c_name, structtype) \ | |
1191 const struct lrecord_implementation lrecord_##c_name = \ | |
1192 { name, dumpable, marker, printer, nuker, equal, hash, desc, \ | |
1193 getprop, putprop, remprop, plist, size, sizer, \ | |
1194 lrecord_type_##c_name } | |
3263 | 1195 #else /* not NEW_GC */ |
934 | 1196 #define MAKE_LRECORD_IMPLEMENTATION(name,c_name,dumpable,marker,printer,nuker,equal,hash,desc,getprop,putprop,remprop,plist,size,sizer,basic_p,structtype) \ |
1204 | 1197 DECLARE_ERROR_CHECK_TYPES(c_name, structtype) \ |
934 | 1198 const struct lrecord_implementation lrecord_##c_name = \ |
1199 { name, dumpable, marker, printer, nuker, equal, hash, desc, \ | |
1200 getprop, putprop, remprop, plist, size, sizer, \ | |
1201 lrecord_type_##c_name, basic_p } | |
3263 | 1202 #endif /* not NEW_GC */ |
934 | 1203 |
1204 #define DEFINE_EXTERNAL_LRECORD_IMPLEMENTATION(name,c_name,dumpable,marker,printer,nuker,equal,hash,desc,structtype) \ | |
1205 DEFINE_EXTERNAL_LRECORD_IMPLEMENTATION_WITH_PROPS(name,c_name,dumpable,marker,printer,nuker,equal,hash,desc,0,0,0,0,structtype) | |
1206 | |
1207 #define DEFINE_EXTERNAL_LRECORD_IMPLEMENTATION_WITH_PROPS(name,c_name,dumpable,marker,printer,nuker,equal,hash,desc,getprop,putprop,remprop,plist,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) | |
1209 | |
1210 #define DEFINE_EXTERNAL_LRECORD_SEQUENCE_IMPLEMENTATION(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) | |
1212 | |
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) \ | |
1214 MAKE_EXTERNAL_LRECORD_IMPLEMENTATION(name,c_name,dumpable,marker,printer,nuker,equal,hash,desc,getprop,putprop,remprop,plist,0,sizer,0,structtype) | |
1215 | |
3263 | 1216 #ifdef NEW_GC |
2720 | 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) \ |
1218 DECLARE_ERROR_CHECK_TYPES(c_name, structtype) \ | |
1219 int lrecord_type_##c_name; \ | |
1220 struct lrecord_implementation lrecord_##c_name = \ | |
1221 { name, dumpable, marker, printer, nuker, equal, hash, desc, \ | |
1222 getprop, putprop, remprop, plist, size, sizer, \ | |
1223 lrecord_type_last_built_in_type } | |
3263 | 1224 #else /* not NEW_GC */ |
934 | 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) \ |
1204 | 1226 DECLARE_ERROR_CHECK_TYPES(c_name, structtype) \ |
934 | 1227 int lrecord_type_##c_name; \ |
1228 struct lrecord_implementation lrecord_##c_name = \ | |
1229 { name, dumpable, marker, printer, nuker, equal, hash, desc, \ | |
1230 getprop, putprop, remprop, plist, size, sizer, \ | |
1231 lrecord_type_last_built_in_type, basic_p } | |
3263 | 1232 #endif /* not NEW_GC */ |
934 | 1233 |
1676 | 1234 #ifdef USE_KKCC |
1235 extern MODULE_API const struct memory_description *lrecord_memory_descriptions[]; | |
1236 | |
1237 #define INIT_LRECORD_IMPLEMENTATION(type) do { \ | |
1238 lrecord_implementations_table[lrecord_type_##type] = &lrecord_##type; \ | |
1239 lrecord_memory_descriptions[lrecord_type_##type] = \ | |
1240 lrecord_implementations_table[lrecord_type_##type]->description; \ | |
1241 } while (0) | |
1242 #else /* not USE_KKCC */ | |
1632 | 1243 extern MODULE_API Lisp_Object (*lrecord_markers[]) (Lisp_Object); |
442 | 1244 |
1245 #define INIT_LRECORD_IMPLEMENTATION(type) do { \ | |
1246 lrecord_implementations_table[lrecord_type_##type] = &lrecord_##type; \ | |
1247 lrecord_markers[lrecord_type_##type] = \ | |
1248 lrecord_implementations_table[lrecord_type_##type]->marker; \ | |
1249 } while (0) | |
1676 | 1250 #endif /* not USE_KKCC */ |
428 | 1251 |
444 | 1252 #define INIT_EXTERNAL_LRECORD_IMPLEMENTATION(type) do { \ |
1253 lrecord_type_##type = lrecord_type_count++; \ | |
1254 lrecord_##type.lrecord_type_index = lrecord_type_##type; \ | |
1255 INIT_LRECORD_IMPLEMENTATION(type); \ | |
1256 } while (0) | |
1257 | |
996 | 1258 #ifdef HAVE_SHLIB |
1259 /* Allow undefining types in order to support module unloading. */ | |
1260 | |
1676 | 1261 #ifdef USE_KKCC |
1262 #define UNDEF_LRECORD_IMPLEMENTATION(type) do { \ | |
1263 lrecord_implementations_table[lrecord_type_##type] = NULL; \ | |
1264 lrecord_memory_descriptions[lrecord_type_##type] = NULL; \ | |
1265 } while (0) | |
1266 #else /* not USE_KKCC */ | |
996 | 1267 #define UNDEF_LRECORD_IMPLEMENTATION(type) do { \ |
1268 lrecord_implementations_table[lrecord_type_##type] = NULL; \ | |
1269 lrecord_markers[lrecord_type_##type] = NULL; \ | |
1270 } while (0) | |
1676 | 1271 #endif /* not USE_KKCC */ |
996 | 1272 |
1273 #define UNDEF_EXTERNAL_LRECORD_IMPLEMENTATION(type) do { \ | |
1274 if (lrecord_##type.lrecord_type_index == lrecord_type_count - 1) { \ | |
1275 /* This is the most recently defined type. Clean up nicely. */ \ | |
1276 lrecord_type_##type = lrecord_type_count--; \ | |
1277 } /* Else we can't help leaving a hole with this implementation. */ \ | |
1278 UNDEF_LRECORD_IMPLEMENTATION(type); \ | |
1279 } while (0) | |
1280 | |
1281 #endif /* HAVE_SHLIB */ | |
1282 | |
428 | 1283 #define LRECORDP(a) (XTYPE (a) == Lisp_Type_Record) |
1284 #define XRECORD_LHEADER(a) ((struct lrecord_header *) XPNTR (a)) | |
1285 | |
1286 #define RECORD_TYPEP(x, ty) \ | |
647 | 1287 (LRECORDP (x) && (XRECORD_LHEADER (x)->type == (unsigned int) (ty))) |
442 | 1288 |
1289 /* Steps to create a new object: | |
1290 | |
1291 1. Declare the struct for your object in a header file somewhere. | |
1292 Remember that it must begin with | |
1293 | |
3017 | 1294 struct LCRECORD_HEADER header; |
442 | 1295 |
793 | 1296 2. Put the "standard junk" (DECLARE_RECORD()/XFOO/etc.) below the |
617 | 1297 struct definition -- see below. |
442 | 1298 |
1299 3. Add this header file to inline.c. | |
1300 | |
1301 4. Create the methods for your object. Note that technically you don't | |
1302 need any, but you will almost always want at least a mark method. | |
1303 | |
1204 | 1304 4. Create the data layout description for your object. See |
1305 toolbar_button_description below; the comment above in `struct lrecord', | |
1306 describing the purpose of the descriptions; and comments elsewhere in | |
1307 this file describing the exact syntax of the description structures. | |
1308 | |
1309 6. Define your object with DEFINE_LRECORD_IMPLEMENTATION() or some | |
442 | 1310 variant. |
1311 | |
1204 | 1312 7. Include the header file in the .c file where you defined the object. |
442 | 1313 |
1204 | 1314 8. Put a call to INIT_LRECORD_IMPLEMENTATION() for the object in the |
442 | 1315 .c file's syms_of_foo() function. |
1316 | |
1204 | 1317 9. Add a type enum for the object to enum lrecord_type, earlier in this |
442 | 1318 file. |
1319 | |
1204 | 1320 --ben |
1321 | |
442 | 1322 An example: |
428 | 1323 |
442 | 1324 ------------------------------ in toolbar.h ----------------------------- |
1325 | |
1326 struct toolbar_button | |
1327 { | |
3017 | 1328 struct LCRECORD_HEADER header; |
442 | 1329 |
1330 Lisp_Object next; | |
1331 Lisp_Object frame; | |
1332 | |
1333 Lisp_Object up_glyph; | |
1334 Lisp_Object down_glyph; | |
1335 Lisp_Object disabled_glyph; | |
1336 | |
1337 Lisp_Object cap_up_glyph; | |
1338 Lisp_Object cap_down_glyph; | |
1339 Lisp_Object cap_disabled_glyph; | |
1340 | |
1341 Lisp_Object callback; | |
1342 Lisp_Object enabled_p; | |
1343 Lisp_Object help_string; | |
1344 | |
1345 char enabled; | |
1346 char down; | |
1347 char pushright; | |
1348 char blank; | |
1349 | |
1350 int x, y; | |
1351 int width, height; | |
1352 int dirty; | |
1353 int vertical; | |
1354 int border_width; | |
1355 }; | |
428 | 1356 |
617 | 1357 [[ the standard junk: ]] |
1358 | |
442 | 1359 DECLARE_LRECORD (toolbar_button, struct toolbar_button); |
1360 #define XTOOLBAR_BUTTON(x) XRECORD (x, toolbar_button, struct toolbar_button) | |
617 | 1361 #define wrap_toolbar_button(p) wrap_record (p, toolbar_button) |
442 | 1362 #define TOOLBAR_BUTTONP(x) RECORDP (x, toolbar_button) |
1363 #define CHECK_TOOLBAR_BUTTON(x) CHECK_RECORD (x, toolbar_button) | |
1364 #define CONCHECK_TOOLBAR_BUTTON(x) CONCHECK_RECORD (x, toolbar_button) | |
1365 | |
1366 ------------------------------ in toolbar.c ----------------------------- | |
1367 | |
1368 #include "toolbar.h" | |
1369 | |
1370 ... | |
1371 | |
1204 | 1372 static const struct memory_description toolbar_button_description [] = { |
1373 { XD_LISP_OBJECT, offsetof (struct toolbar_button, next) }, | |
1374 { XD_LISP_OBJECT, offsetof (struct toolbar_button, frame) }, | |
1375 { XD_LISP_OBJECT, offsetof (struct toolbar_button, up_glyph) }, | |
1376 { XD_LISP_OBJECT, offsetof (struct toolbar_button, down_glyph) }, | |
1377 { XD_LISP_OBJECT, offsetof (struct toolbar_button, disabled_glyph) }, | |
1378 { XD_LISP_OBJECT, offsetof (struct toolbar_button, cap_up_glyph) }, | |
1379 { XD_LISP_OBJECT, offsetof (struct toolbar_button, cap_down_glyph) }, | |
1380 { XD_LISP_OBJECT, offsetof (struct toolbar_button, cap_disabled_glyph) }, | |
1381 { XD_LISP_OBJECT, offsetof (struct toolbar_button, callback) }, | |
1382 { XD_LISP_OBJECT, offsetof (struct toolbar_button, enabled_p) }, | |
1383 { XD_LISP_OBJECT, offsetof (struct toolbar_button, help_string) }, | |
1384 { XD_END } | |
1385 }; | |
1386 | |
442 | 1387 static Lisp_Object |
1388 mark_toolbar_button (Lisp_Object obj) | |
1204 | 1389 \{ |
442 | 1390 struct toolbar_button *data = XTOOLBAR_BUTTON (obj); |
1391 mark_object (data->next); | |
1392 mark_object (data->frame); | |
1393 mark_object (data->up_glyph); | |
1394 mark_object (data->down_glyph); | |
1395 mark_object (data->disabled_glyph); | |
1396 mark_object (data->cap_up_glyph); | |
1397 mark_object (data->cap_down_glyph); | |
1398 mark_object (data->cap_disabled_glyph); | |
1399 mark_object (data->callback); | |
1400 mark_object (data->enabled_p); | |
1401 return data->help_string; | |
1402 } | |
1403 | |
617 | 1404 [[ If your object should never escape to Lisp, declare its print method |
1405 as internal_object_printer instead of 0. ]] | |
1406 | |
442 | 1407 DEFINE_LRECORD_IMPLEMENTATION ("toolbar-button", toolbar_button, |
1204 | 1408 0, mark_toolbar_button, 0, 0, 0, 0, |
1409 toolbar_button_description, | |
1410 struct toolbar_button); | |
442 | 1411 |
1412 ... | |
1413 | |
1414 void | |
1415 syms_of_toolbar (void) | |
1416 { | |
1417 INIT_LRECORD_IMPLEMENTATION (toolbar_button); | |
1418 | |
1419 ...; | |
1420 } | |
1421 | |
1422 ------------------------------ in inline.c ----------------------------- | |
1423 | |
1424 #ifdef HAVE_TOOLBARS | |
1425 #include "toolbar.h" | |
1426 #endif | |
1427 | |
1428 ------------------------------ in lrecord.h ----------------------------- | |
1429 | |
1430 enum lrecord_type | |
1431 { | |
1432 ... | |
1433 lrecord_type_toolbar_button, | |
1434 ... | |
1435 }; | |
1436 | |
1204 | 1437 |
1438 --ben | |
1439 | |
442 | 1440 */ |
1441 | |
1442 /* | |
1443 | |
1444 Note: Object types defined in external dynamically-loaded modules (not | |
1445 part of the XEmacs main source code) should use DECLARE_EXTERNAL_LRECORD | |
1446 and DEFINE_EXTERNAL_LRECORD_IMPLEMENTATION rather than DECLARE_LRECORD | |
3029 | 1447 and DEFINE_LRECORD_IMPLEMENTATION. The EXTERNAL versions declare and |
1448 allocate an enumerator for the type being defined. | |
442 | 1449 |
1450 */ | |
1451 | |
428 | 1452 |
800 | 1453 #ifdef ERROR_CHECK_TYPES |
428 | 1454 |
788 | 1455 # define DECLARE_LRECORD(c_name, structtype) \ |
1456 extern const struct lrecord_implementation lrecord_##c_name; \ | |
826 | 1457 DECLARE_INLINE_HEADER ( \ |
1458 structtype * \ | |
2367 | 1459 error_check_##c_name (Lisp_Object obj, const Ascbyte *file, int line) \ |
826 | 1460 ) \ |
788 | 1461 { \ |
1462 assert_at_line (RECORD_TYPEP (obj, lrecord_type_##c_name), file, line); \ | |
1463 return (structtype *) XPNTR (obj); \ | |
1464 } \ | |
428 | 1465 extern Lisp_Object Q##c_name##p |
1466 | |
1632 | 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 * \ | |
2367 | 1471 error_check_##c_name (Lisp_Object obj, const Ascbyte *file, int line) \ |
1632 | 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 | |
788 | 1479 # define DECLARE_EXTERNAL_LRECORD(c_name, structtype) \ |
1480 extern int lrecord_type_##c_name; \ | |
1481 extern struct lrecord_implementation lrecord_##c_name; \ | |
826 | 1482 DECLARE_INLINE_HEADER ( \ |
1483 structtype * \ | |
2367 | 1484 error_check_##c_name (Lisp_Object obj, const Ascbyte *file, int line) \ |
826 | 1485 ) \ |
788 | 1486 { \ |
1487 assert_at_line (RECORD_TYPEP (obj, lrecord_type_##c_name), file, line); \ | |
1488 return (structtype *) XPNTR (obj); \ | |
1489 } \ | |
444 | 1490 extern Lisp_Object Q##c_name##p |
442 | 1491 |
788 | 1492 # define DECLARE_NONRECORD(c_name, type_enum, structtype) \ |
826 | 1493 DECLARE_INLINE_HEADER ( \ |
1494 structtype * \ | |
2367 | 1495 error_check_##c_name (Lisp_Object obj, const Ascbyte *file, int line) \ |
826 | 1496 ) \ |
788 | 1497 { \ |
1498 assert_at_line (XTYPE (obj) == type_enum, file, line); \ | |
1499 return (structtype *) XPNTR (obj); \ | |
1500 } \ | |
428 | 1501 extern Lisp_Object Q##c_name##p |
1502 | |
788 | 1503 # 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__) | |
428 | 1507 |
826 | 1508 DECLARE_INLINE_HEADER ( |
1509 Lisp_Object | |
2367 | 1510 wrap_record_1 (const void *ptr, enum lrecord_type ty, const Ascbyte *file, |
800 | 1511 int line) |
826 | 1512 ) |
617 | 1513 { |
793 | 1514 Lisp_Object obj = wrap_pointer_1 (ptr); |
1515 | |
788 | 1516 assert_at_line (RECORD_TYPEP (obj, ty), file, line); |
617 | 1517 return obj; |
1518 } | |
1519 | |
788 | 1520 #define wrap_record(ptr, ty) \ |
1521 wrap_record_1 (ptr, lrecord_type_##ty, __FILE__, __LINE__) | |
617 | 1522 |
800 | 1523 #else /* not ERROR_CHECK_TYPES */ |
428 | 1524 |
1525 # define DECLARE_LRECORD(c_name, structtype) \ | |
1526 extern Lisp_Object Q##c_name##p; \ | |
442 | 1527 extern const struct lrecord_implementation lrecord_##c_name |
1638 | 1528 # define DECLARE_MODULE_API_LRECORD(c_name, structtype) \ |
1529 extern MODULE_API Lisp_Object Q##c_name##p; \ | |
1530 extern MODULE_API const struct lrecord_implementation lrecord_##c_name | |
442 | 1531 # define DECLARE_EXTERNAL_LRECORD(c_name, structtype) \ |
1532 extern Lisp_Object Q##c_name##p; \ | |
647 | 1533 extern int lrecord_type_##c_name; \ |
444 | 1534 extern struct lrecord_implementation lrecord_##c_name |
428 | 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)) | |
1538 # define XNONRECORD(x, c_name, type_enum, structtype) \ | |
1539 ((structtype *) XPNTR (x)) | |
617 | 1540 /* wrap_pointer_1 is so named as a suggestion not to use it unless you |
1541 know what you're doing. */ | |
1542 #define wrap_record(ptr, ty) wrap_pointer_1 (ptr) | |
428 | 1543 |
800 | 1544 #endif /* not ERROR_CHECK_TYPES */ |
428 | 1545 |
442 | 1546 #define RECORDP(x, c_name) RECORD_TYPEP (x, lrecord_type_##c_name) |
428 | 1547 |
1548 /* Note: we now have two different kinds of type-checking macros. | |
1549 The "old" kind has now been renamed CONCHECK_foo. The reason for | |
1550 this is that the CONCHECK_foo macros signal a continuable error, | |
1551 allowing the user (through debug-on-error) to substitute a different | |
1552 value and return from the signal, which causes the lvalue argument | |
1553 to get changed. Quite a lot of code would crash if that happened, | |
1554 because it did things like | |
1555 | |
1556 foo = XCAR (list); | |
1557 CHECK_STRING (foo); | |
1558 | |
1559 and later on did XSTRING (XCAR (list)), assuming that the type | |
1560 is correct (when it might be wrong, if the user substituted a | |
1561 correct value in the debugger). | |
1562 | |
1563 To get around this, I made all the CHECK_foo macros signal a | |
1564 non-continuable error. Places where a continuable error is OK | |
1565 (generally only when called directly on the argument of a Lisp | |
1566 primitive) should be changed to use CONCHECK(). | |
1567 | |
1568 FSF Emacs does not have this problem because RMS took the cheesy | |
1569 way out and disabled returning from a signal entirely. */ | |
1570 | |
1571 #define CONCHECK_RECORD(x, c_name) do { \ | |
442 | 1572 if (!RECORD_TYPEP (x, lrecord_type_##c_name)) \ |
428 | 1573 x = wrong_type_argument (Q##c_name##p, x); \ |
1574 } while (0) | |
1575 #define CONCHECK_NONRECORD(x, lisp_enum, predicate) do {\ | |
1576 if (XTYPE (x) != lisp_enum) \ | |
1577 x = wrong_type_argument (predicate, x); \ | |
1578 } while (0) | |
1579 #define CHECK_RECORD(x, c_name) do { \ | |
442 | 1580 if (!RECORD_TYPEP (x, lrecord_type_##c_name)) \ |
428 | 1581 dead_wrong_type_argument (Q##c_name##p, x); \ |
1582 } while (0) | |
1583 #define CHECK_NONRECORD(x, lisp_enum, predicate) do { \ | |
1584 if (XTYPE (x) != lisp_enum) \ | |
1585 dead_wrong_type_argument (predicate, x); \ | |
1586 } while (0) | |
1587 | |
3263 | 1588 #ifndef NEW_GC |
1204 | 1589 /*-------------------------- lcrecord-list -----------------------------*/ |
1590 | |
1591 struct lcrecord_list | |
1592 { | |
3024 | 1593 struct LCRECORD_HEADER header; |
1204 | 1594 Lisp_Object free; |
1595 Elemcount size; | |
1596 const struct lrecord_implementation *implementation; | |
1597 }; | |
1598 | |
1599 DECLARE_LRECORD (lcrecord_list, struct lcrecord_list); | |
1600 #define XLCRECORD_LIST(x) XRECORD (x, lcrecord_list, struct lcrecord_list) | |
1601 #define wrap_lcrecord_list(p) wrap_record (p, lcrecord_list) | |
1602 #define LCRECORD_LISTP(x) RECORDP (x, lcrecord_list) | |
1603 /* #define CHECK_LCRECORD_LIST(x) CHECK_RECORD (x, lcrecord_list) | |
1604 Lcrecord lists should never escape to the Lisp level, so | |
1605 functions should not be doing this. */ | |
1606 | |
826 | 1607 /* Various ways of allocating lcrecords. All bytes (except lcrecord |
1204 | 1608 header) are zeroed in returned structure. |
1609 | |
1610 See above for a discussion of the difference between plain lrecords and | |
1611 lrecords. lcrecords themselves are divided into three types: (1) | |
1612 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 | |
3024 | 1614 lcrecords, which can freed with FREE_LCRECORD() or the like and later be |
1204 | 1615 recycled when a new lcrecord is required, rather than requiring new |
1616 malloc(). Thus, allocation of lcrecords can be very | |
1617 cheap. (Technically, the lcrecord-list manager could divide up large | |
1618 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 | |
1620 division between lrecords and lcrecords.) | |
1621 | |
1622 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 | |
1624 can be of varying sizes need to do various tricks. These considerations | |
1625 in particular dictate the various types of management: | |
1626 | |
1627 -- "Auto-managed" means that you just go ahead and allocate the lcrecord | |
3024 | 1628 whenever you want, using old_alloc_lcrecord_type(), and the appropriate |
1204 | 1629 lcrecord-list manager is automatically created. To free, you just call |
3024 | 1630 "FREE_LCRECORD()" and the appropriate lcrecord-list manager is |
1204 | 1631 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 | |
1633 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 | |
1635 a limited number of sizes, so this works well.) | |
826 | 1636 |
1204 | 1637 -- "Hand-managed" exists because we haven't yet written the more |
1638 sophisticated scheme for auto-handling different-sized lcrecords, as | |
1639 described in the end of the last paragraph. In this model, you go ahead | |
1640 and create the lcrecord-list objects yourself for the sizes you will | |
1641 need, using make_lcrecord_list(). Then, create lcrecords using | |
1642 alloc_managed_lcrecord(), passing in the lcrecord-list you created, and | |
1643 free them with free_managed_lcrecord(). | |
1644 | |
1645 -- "Unmanaged" means you simply allocate lcrecords, period. No | |
1646 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 | |
1648 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 | |
1650 wouldn't be safe to do so). You just create them with | |
3024 | 1651 BASIC_ALLOC_LCRECORD(), and that's it. |
1204 | 1652 |
1653 --ben | |
1654 | |
1655 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 | |
1657 complicated, you will learn a lot about the other styles as well. In | |
1658 addition, there is useful general information about what freeing an | |
1659 lcrecord really entails, and what are the precautions: | |
1660 | |
1661 1) Create an lcrecord-list object using make_lcrecord_list(). This is | |
1662 often done at initialization. Remember to staticpro_nodump() this | |
1663 object! The arguments to make_lcrecord_list() are the same as would be | |
3024 | 1664 passed to BASIC_ALLOC_LCRECORD(). |
428 | 1665 |
3024 | 1666 2) Instead of calling BASIC_ALLOC_LCRECORD(), call alloc_managed_lcrecord() |
1204 | 1667 and pass the lcrecord-list earlier created. |
1668 | |
1669 3) When done with the lcrecord, call free_managed_lcrecord(). The | |
1670 standard freeing caveats apply: ** make sure there are no pointers to | |
1671 the object anywhere! ** | |
1672 | |
1673 4) Calling free_managed_lcrecord() is just like kissing the | |
1674 lcrecord goodbye as if it were garbage-collected. This means: | |
1675 -- the contents of the freed lcrecord are undefined, and the | |
1676 contents of something produced by alloc_managed_lcrecord() | |
3024 | 1677 are undefined, just like for BASIC_ALLOC_LCRECORD(). |
1204 | 1678 -- the mark method for the lcrecord's type will *NEVER* be called |
1679 on freed lcrecords. | |
1680 -- the finalize method for the lcrecord's type will be called | |
1681 at the time that free_managed_lcrecord() is called. | |
1682 */ | |
1683 | |
1684 /* UNMANAGED MODEL: */ | |
3024 | 1685 void *old_basic_alloc_lcrecord (Bytecount size, |
1686 const struct lrecord_implementation *); | |
1204 | 1687 |
1688 /* HAND-MANAGED MODEL: */ | |
1689 Lisp_Object make_lcrecord_list (Elemcount size, | |
1690 const struct lrecord_implementation | |
1691 *implementation); | |
1692 Lisp_Object alloc_managed_lcrecord (Lisp_Object lcrecord_list); | |
1693 void free_managed_lcrecord (Lisp_Object lcrecord_list, Lisp_Object lcrecord); | |
1694 | |
1695 /* AUTO-MANAGED MODEL: */ | |
1632 | 1696 MODULE_API void * |
1697 alloc_automanaged_lcrecord (Bytecount size, | |
1698 const struct lrecord_implementation *); | |
3017 | 1699 |
3024 | 1700 #define old_alloc_lcrecord_type(type, lrecord_implementation) \ |
771 | 1701 ((type *) alloc_automanaged_lcrecord (sizeof (type), lrecord_implementation)) |
2720 | 1702 |
3024 | 1703 void old_free_lcrecord (Lisp_Object rec); |
771 | 1704 |
428 | 1705 |
1706 /* Copy the data from one lcrecord structure into another, but don't | |
1707 overwrite the header information. */ | |
1708 | |
3024 | 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)) | |
771 | 1713 |
3024 | 1714 #define old_copy_lcrecord(dst, src) \ |
1715 old_copy_sized_lcrecord (dst, src, sizeof (*(dst))) | |
428 | 1716 |
3024 | 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)) | |
771 | 1720 |
3024 | 1721 #define old_zero_lcrecord(lcr) old_zero_sized_lcrecord (lcr, sizeof (*(lcr))) |
1204 | 1722 |
3263 | 1723 #else /* NEW_GC */ |
2720 | 1724 |
1725 /* How to allocate a lrecord: | |
1726 | |
1727 - If the size of the lrecord is fix, say it equals its size of its | |
1728 struct, then use alloc_lrecord_type. | |
1729 | |
1730 - If the size varies, i.e. it is not equal to the size of its | |
1731 struct, use alloc_lrecord and specify the amount of storage you | |
1732 need for the object. | |
1733 | |
1734 - Some lrecords, which are used totally internally, use the | |
1735 noseeum-* functions for the reason of debugging. | |
1736 | |
1737 - To free a Lisp_Object manually, use free_lrecord. */ | |
1738 | |
1739 void *alloc_lrecord (Bytecount size, | |
1740 const struct lrecord_implementation *); | |
1741 | |
3092 | 1742 void *alloc_lrecord_array (Bytecount size, int elemcount, |
1743 const struct lrecord_implementation *); | |
1744 | |
2720 | 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 | |
3263 | 1767 #endif /* NEW_GC */ |
3017 | 1768 |
2720 | 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 | |
1204 | 1775 DECLARE_INLINE_HEADER ( |
1776 Bytecount | |
1777 detagged_lisp_object_size (const struct lrecord_header *h) | |
1778 ) | |
1779 { | |
1780 const struct lrecord_implementation *imp = LHEADER_IMPLEMENTATION (h); | |
1781 | |
1782 return (imp->size_in_bytes_method ? | |
1783 imp->size_in_bytes_method (h) : | |
1784 imp->static_size); | |
1785 } | |
1786 | |
1787 DECLARE_INLINE_HEADER ( | |
1788 Bytecount | |
1789 lisp_object_size (Lisp_Object o) | |
1790 ) | |
1791 { | |
1792 return detagged_lisp_object_size (XRECORD_LHEADER (o)); | |
1793 } | |
1794 | |
1795 | |
1796 /************************************************************************/ | |
1797 /* Dumping */ | |
1798 /************************************************************************/ | |
1799 | |
2367 | 1800 /* dump_add_root_block_ptr (&var, &desc) dumps the structure pointed to by |
1204 | 1801 `var'. This is for a single relocatable pointer located in the data |
2367 | 1802 segment (i.e. the block pointed to is in the heap). |
1803 | |
1804 If the structure pointed to is not a `struct' but an array, you should | |
1805 set the size field of the sized_memory_description to 0, and use | |
1806 XD_BLOCK_ARRAY in the inner memory_description. | |
1807 | |
1808 NOTE that a "root struct pointer" could also be described using | |
1809 dump_add_root_block(), with SIZE == sizeof (void *), and a description | |
1810 containing a single XD_BLOCK_PTR entry, offset 0, size 1, with a | |
1811 structure description the same as the value passed to | |
1812 dump_add_root_block_ptr(). That would require an extra level of | |
1813 description, though, as compared to using dump_add_root_block_ptr(), | |
1814 and thus this function is generally more convenient. | |
1815 */ | |
1204 | 1816 #ifdef PDUMP |
2367 | 1817 void dump_add_root_block_ptr (void *, const struct sized_memory_description *); |
1204 | 1818 #else |
2367 | 1819 #define dump_add_root_block_ptr(varaddr, descaddr) DO_NOTHING |
1204 | 1820 #endif |
1821 | |
1822 /* dump_add_opaque (&var, size) dumps the opaque static structure `var'. | |
1823 This is for a static block of memory (in the data segment, not the | |
1824 heap), with no relocatable pointers in it. */ | |
1825 #ifdef PDUMP | |
1826 #define dump_add_opaque(varaddr,size) dump_add_root_block (varaddr, size, NULL) | |
1827 #else | |
1828 #define dump_add_opaque(varaddr,size) DO_NOTHING | |
1829 #endif | |
1830 | |
1831 /* dump_add_root_block (ptr, size, desc) dumps the static structure | |
1832 located at `var' of size SIZE and described by DESC. This is for a | |
1833 static block of memory (in the data segment, not the heap), with | |
1834 relocatable pointers in it. */ | |
1835 #ifdef PDUMP | |
1836 void dump_add_root_block (const void *ptraddress, Bytecount size, | |
1837 const struct memory_description *desc); | |
1838 #else | |
2367 | 1839 #define dump_add_root_block(ptraddress, size, desc) DO_NOTHING |
1204 | 1840 #endif |
1841 | |
1842 /* Call dump_add_opaque_int (&int_var) to dump `int_var', of type `int'. */ | |
1843 #ifdef PDUMP | |
1844 #define dump_add_opaque_int(int_varaddr) do { \ | |
1845 int *dao_ = (int_varaddr); /* type check */ \ | |
1846 dump_add_opaque (dao_, sizeof (*dao_)); \ | |
1847 } while (0) | |
1848 #else | |
1849 #define dump_add_opaque_int(int_varaddr) DO_NOTHING | |
1850 #endif | |
1851 | |
1852 /* Call dump_add_opaque_fixnum (&fixnum_var) to dump `fixnum_var', of type | |
1853 `Fixnum'. */ | |
1854 #ifdef PDUMP | |
1855 #define dump_add_opaque_fixnum(fixnum_varaddr) do { \ | |
1856 Fixnum *dao_ = (fixnum_varaddr); /* type check */ \ | |
1857 dump_add_opaque (dao_, sizeof (*dao_)); \ | |
1858 } while (0) | |
1859 #else | |
1860 #define dump_add_opaque_fixnum(fixnum_varaddr) DO_NOTHING | |
1861 #endif | |
1862 | |
1863 /* Call dump_add_root_lisp_object (&var) to ensure that var is properly | |
1864 updated after pdump. */ | |
1865 #ifdef PDUMP | |
1866 void dump_add_root_lisp_object (Lisp_Object *); | |
1867 #else | |
1868 #define dump_add_root_lisp_object(varaddr) DO_NOTHING | |
1869 #endif | |
1870 | |
1871 /* Call dump_add_weak_lisp_object (&var) to ensure that var is properly | |
1872 updated after pdump. var must point to a linked list of objects out of | |
1873 which some may not be dumped */ | |
1874 #ifdef PDUMP | |
1875 void dump_add_weak_object_chain (Lisp_Object *); | |
1876 #else | |
1877 #define dump_add_weak_object_chain(varaddr) DO_NOTHING | |
1878 #endif | |
1879 | |
1880 /* Nonzero means Emacs has already been initialized. | |
1881 Used during startup to detect startup of dumped Emacs. */ | |
1632 | 1882 extern MODULE_API int initialized; |
1204 | 1883 |
1884 #ifdef PDUMP | |
1688 | 1885 #include "dumper.h" |
3263 | 1886 #ifdef NEW_GC |
2720 | 1887 #define DUMPEDP(adr) 0 |
3263 | 1888 #else /* not NEW_GC */ |
2367 | 1889 #define DUMPEDP(adr) ((((Rawbyte *) (adr)) < pdump_end) && \ |
1890 (((Rawbyte *) (adr)) >= pdump_start)) | |
3263 | 1891 #endif /* not NEW_GC */ |
1204 | 1892 #else |
1893 #define DUMPEDP(adr) 0 | |
1894 #endif | |
1895 | |
1330 | 1896 #define OBJECT_DUMPED_P(obj) DUMPEDP (XPNTR (obj)) |
1897 | |
1204 | 1898 /***********************************************************************/ |
1899 /* data descriptions */ | |
1900 /***********************************************************************/ | |
1901 | |
1902 | |
1903 #if defined (USE_KKCC) || defined (PDUMP) | |
1904 | |
1905 extern int in_pdump; | |
1906 | |
1907 EMACS_INT lispdesc_indirect_count_1 (EMACS_INT code, | |
1908 const struct memory_description *idesc, | |
1909 const void *idata); | |
1910 const struct sized_memory_description *lispdesc_indirect_description_1 | |
1911 (const void *obj, const struct sized_memory_description *sdesc); | |
2367 | 1912 Bytecount lispdesc_block_size_1 (const void *obj, Bytecount size, |
1913 const struct memory_description *desc); | |
1914 | |
1915 DECLARE_INLINE_HEADER ( | |
1916 Bytecount lispdesc_block_size (const void *obj, | |
1917 const struct sized_memory_description *sdesc)) | |
1918 { | |
1919 return lispdesc_block_size_1 (obj, sdesc->size, sdesc->description); | |
1920 } | |
1204 | 1921 |
1922 DECLARE_INLINE_HEADER ( | |
1923 EMACS_INT | |
1924 lispdesc_indirect_count (EMACS_INT code, | |
1925 const struct memory_description *idesc, | |
1926 const void *idata) | |
1927 ) | |
1928 { | |
1929 if (XD_IS_INDIRECT (code)) | |
1930 code = lispdesc_indirect_count_1 (code, idesc, idata); | |
1931 return code; | |
1932 } | |
1933 | |
1934 DECLARE_INLINE_HEADER ( | |
1935 const struct sized_memory_description * | |
1936 lispdesc_indirect_description (const void *obj, | |
1937 const struct sized_memory_description *sdesc) | |
1938 ) | |
1939 { | |
1940 if (sdesc->description) | |
1941 return sdesc; | |
1942 else | |
1943 return lispdesc_indirect_description_1 (obj, sdesc); | |
1944 } | |
1945 | |
1946 | |
1947 /* Do standard XD_UNION processing. DESC1 is an entry in DESC, which | |
1948 describes the entire data structure. Returns NULL (do nothing, nothing | |
1949 matched), or a new value for DESC1. In the latter case, assign to DESC1 | |
1950 in your function and goto union_switcheroo. */ | |
1951 | |
1952 DECLARE_INLINE_HEADER ( | |
1953 const struct memory_description * | |
1954 lispdesc_process_xd_union (const struct memory_description *desc1, | |
1955 const struct memory_description *desc, | |
1956 const void *data) | |
1957 ) | |
1958 { | |
1959 int count = 0; | |
1960 EMACS_INT variant = lispdesc_indirect_count (desc1->data1, desc, | |
1961 data); | |
1962 desc1 = | |
2551 | 1963 lispdesc_indirect_description (data, desc1->data2.descr)->description; |
1204 | 1964 |
1965 for (count = 0; desc1[count].type != XD_END; count++) | |
1966 { | |
1967 if ((desc1[count].flags & XD_FLAG_UNION_DEFAULT_ENTRY) || | |
1968 desc1[count].offset == variant) | |
1969 { | |
1970 return &desc1[count]; | |
1971 } | |
1972 } | |
1973 | |
1974 return NULL; | |
1975 } | |
1976 | |
1977 #endif /* defined (USE_KKCC) || defined (PDUMP) */ | |
428 | 1978 |
1743 | 1979 END_C_DECLS |
1650 | 1980 |
440 | 1981 #endif /* INCLUDED_lrecord_h_ */ |