comparison src/lrecord.h @ 400:a86b2b5e0111 r21-2-30

Import from CVS: tag r21-2-30
author cvs
date Mon, 13 Aug 2007 11:14:34 +0200
parents 74fd4e045ea6
children 2f8bb876ab1d
comparison
equal deleted inserted replaced
399:376370fb5946 400:a86b2b5e0111
59 59
60 struct lrecord_header 60 struct lrecord_header
61 { 61 {
62 /* index into lrecord_implementations_table[] */ 62 /* index into lrecord_implementations_table[] */
63 unsigned int type :8; 63 unsigned int type :8;
64 /* 1 if the object is marked during GC. */ 64
65 /* If `mark' is 0 after the GC mark phase, the object will be freed
66 during the GC sweep phase. There are 2 ways that `mark' can be 1:
67 - by being referenced from other objects during the GC mark phase
68 - because it is permanently on, for c_readonly objects */
65 unsigned int mark :1; 69 unsigned int mark :1;
66 /* 1 if the object resides in read-only space */ 70
71 /* 1 if the object resides in logically read-only space, and does not
72 reference other non-c_readonly objects.
73 Invariant: if (c_readonly == 1), then (mark == 1 && lisp_readonly == 1) */
67 unsigned int c_readonly :1; 74 unsigned int c_readonly :1;
75
68 /* 1 if the object is readonly from lisp */ 76 /* 1 if the object is readonly from lisp */
69 unsigned int lisp_readonly :1; 77 unsigned int lisp_readonly :1;
70 }; 78 };
71 79
72 struct lrecord_implementation; 80 struct lrecord_implementation;
73 int lrecord_type_index (const struct lrecord_implementation *implementation); 81 int lrecord_type_index (const struct lrecord_implementation *implementation);
74 82
75 #define set_lheader_implementation(header,imp) do { \ 83 #define set_lheader_implementation(header,imp) do { \
76 struct lrecord_header* SLI_header = (header); \ 84 struct lrecord_header* SLI_header = (header); \
77 SLI_header->type = lrecord_type_index (imp); \ 85 SLI_header->type = (imp)->lrecord_type_index; \
78 SLI_header->mark = 0; \ 86 SLI_header->mark = 0; \
79 SLI_header->c_readonly = 0; \ 87 SLI_header->c_readonly = 0; \
80 SLI_header->lisp_readonly = 0; \ 88 SLI_header->lisp_readonly = 0; \
81 } while (0) 89 } while (0)
82 90
116 { 124 {
117 struct lcrecord_header lcheader; 125 struct lcrecord_header lcheader;
118 Lisp_Object chain; 126 Lisp_Object chain;
119 }; 127 };
120 128
121 /* see alloc.c for an explanation */ 129 enum lrecord_type
122 Lisp_Object this_one_is_unmarkable (Lisp_Object obj); 130 {
131 /* Symbol value magic types come first to make SYMBOL_VALUE_MAGIC_P fast.
132 #### This should be replaced by a symbol_value_magic_p flag
133 in the Lisp_Symbol lrecord_header. */
134 lrecord_type_symbol_value_forward,
135 lrecord_type_symbol_value_varalias,
136 lrecord_type_symbol_value_lisp_magic,
137 lrecord_type_symbol_value_buffer_local,
138 lrecord_type_max_symbol_value_magic = lrecord_type_symbol_value_buffer_local,
139
140 lrecord_type_symbol,
141 lrecord_type_subr,
142 lrecord_type_cons,
143 lrecord_type_vector,
144 lrecord_type_string,
145 lrecord_type_lcrecord_list,
146 lrecord_type_compiled_function,
147 lrecord_type_weak_list,
148 lrecord_type_bit_vector,
149 lrecord_type_float,
150 lrecord_type_hash_table,
151 lrecord_type_lstream,
152 lrecord_type_process,
153 lrecord_type_charset,
154 lrecord_type_coding_system,
155 lrecord_type_char_table,
156 lrecord_type_char_table_entry,
157 lrecord_type_range_table,
158 lrecord_type_opaque,
159 lrecord_type_opaque_ptr,
160 lrecord_type_buffer,
161 lrecord_type_extent,
162 lrecord_type_extent_info,
163 lrecord_type_extent_auxiliary,
164 lrecord_type_marker,
165 lrecord_type_event,
166 lrecord_type_keymap,
167 lrecord_type_command_builder,
168 lrecord_type_timeout,
169 lrecord_type_specifier,
170 lrecord_type_console,
171 lrecord_type_device,
172 lrecord_type_frame,
173 lrecord_type_window,
174 lrecord_type_window_configuration,
175 lrecord_type_gui_item,
176 lrecord_type_popup_data,
177 lrecord_type_toolbar_button,
178 lrecord_type_color_instance,
179 lrecord_type_font_instance,
180 lrecord_type_image_instance,
181 lrecord_type_glyph,
182 lrecord_type_face,
183 lrecord_type_database,
184 lrecord_type_tooltalk_message,
185 lrecord_type_tooltalk_pattern,
186 lrecord_type_ldap,
187 lrecord_type_count
188 };
123 189
124 struct lrecord_implementation 190 struct lrecord_implementation
125 { 191 {
126 const char *name; 192 const char *name;
127 193
177 /* Only one of `static_size' and `size_in_bytes_method' is non-0. 243 /* Only one of `static_size' and `size_in_bytes_method' is non-0.
178 If both are 0, this type is not instantiable by alloc_lcrecord(). */ 244 If both are 0, this type is not instantiable by alloc_lcrecord(). */
179 size_t static_size; 245 size_t static_size;
180 size_t (*size_in_bytes_method) (const void *header); 246 size_t (*size_in_bytes_method) (const void *header);
181 247
182 /* A unique subtag-code (dynamically) assigned to this datatype. */ 248 /* The (constant) index into lrecord_implementations_table */
183 /* (This is a pointer so the rest of this structure can be read-only.) */ 249 enum lrecord_type lrecord_type_index;
184 int *lrecord_type_index;
185 250
186 /* A "basic" lrecord is any lrecord that's not an lcrecord, i.e. 251 /* A "basic" lrecord is any lrecord that's not an lcrecord, i.e.
187 one that does not have an lcrecord_header at the front and which 252 one that does not have an lcrecord_header at the front and which
188 is (usually) allocated in frob blocks. We only use this flag for 253 is (usually) allocated in frob blocks. We only use this flag for
189 some consistency checking, and that only when error-checking is 254 some consistency checking, and that only when error-checking is
192 }; 257 };
193 258
194 extern const struct lrecord_implementation *lrecord_implementations_table[]; 259 extern const struct lrecord_implementation *lrecord_implementations_table[];
195 260
196 #define XRECORD_LHEADER_IMPLEMENTATION(obj) \ 261 #define XRECORD_LHEADER_IMPLEMENTATION(obj) \
197 (lrecord_implementations_table[XRECORD_LHEADER (obj)->type]) 262 LHEADER_IMPLEMENTATION (XRECORD_LHEADER (obj))
198 #define LHEADER_IMPLEMENTATION(lh) (lrecord_implementations_table[(lh)->type]) 263 #define LHEADER_IMPLEMENTATION(lh) lrecord_implementations_table[(lh)->type]
199 264
200 extern int gc_in_progress; 265 extern int gc_in_progress;
201 266
202 #define MARKED_RECORD_P(obj) (gc_in_progress && XRECORD_LHEADER (obj)->mark) 267 #define MARKED_RECORD_P(obj) (XRECORD_LHEADER (obj)->mark)
203 #define MARKED_RECORD_HEADER_P(lheader) ((lheader)->mark) 268 #define MARKED_RECORD_HEADER_P(lheader) ((lheader)->mark)
204 #define MARK_RECORD_HEADER(lheader) ((void) ((lheader)->mark = 1)) 269 #define MARK_RECORD_HEADER(lheader) ((void) ((lheader)->mark = 1))
205 #define UNMARK_RECORD_HEADER(lheader) ((void) ((lheader)->mark = 0)) 270 #define UNMARK_RECORD_HEADER(lheader) ((void) ((lheader)->mark = 0))
206 271
207 #define UNMARKABLE_RECORD_HEADER_P(lheader) \
208 (LHEADER_IMPLEMENTATION (lheader)->marker == this_one_is_unmarkable)
209
210 #define C_READONLY_RECORD_HEADER_P(lheader) ((lheader)->c_readonly) 272 #define C_READONLY_RECORD_HEADER_P(lheader) ((lheader)->c_readonly)
211 #define LISP_READONLY_RECORD_HEADER_P(lheader) ((lheader)->lisp_readonly) 273 #define LISP_READONLY_RECORD_HEADER_P(lheader) ((lheader)->lisp_readonly)
212 #define SET_C_READONLY_RECORD_HEADER(lheader) \ 274 #define SET_C_READONLY_RECORD_HEADER(lheader) do { \
213 ((void) ((lheader)->c_readonly = (lheader)->lisp_readonly = 1)) 275 struct lrecord_header *SCRRH_lheader = (lheader); \
276 SCRRH_lheader->c_readonly = 1; \
277 SCRRH_lheader->lisp_readonly = 1; \
278 SCRRH_lheader->mark = 1; \
279 } while (0)
214 #define SET_LISP_READONLY_RECORD_HEADER(lheader) \ 280 #define SET_LISP_READONLY_RECORD_HEADER(lheader) \
215 ((void) ((lheader)->lisp_readonly = 1)) 281 ((void) ((lheader)->lisp_readonly = 1))
282 #define RECORD_MARKER(lheader) lrecord_markers[(lheader)->type]
216 283
217 /* External description stuff 284 /* External description stuff
218 285
219 A lrecord external description is an array of values. The first 286 A lrecord external description is an array of values. The first
220 value of each line is a type, the second the offset in the lrecord 287 value of each line is a type, the second the offset in the lrecord
345 #define XD_DYNARR_DESC(base_type, sub_desc) \ 412 #define XD_DYNARR_DESC(base_type, sub_desc) \
346 { XD_STRUCT_PTR, offsetof (base_type, base), XD_INDIRECT(1, 0), sub_desc }, \ 413 { XD_STRUCT_PTR, offsetof (base_type, base), XD_INDIRECT(1, 0), sub_desc }, \
347 { XD_INT, offsetof (base_type, cur) }, \ 414 { XD_INT, offsetof (base_type, cur) }, \
348 { XD_INT_RESET, offsetof (base_type, max), XD_INDIRECT(1, 0) } 415 { XD_INT_RESET, offsetof (base_type, max), XD_INDIRECT(1, 0) }
349 416
350 /* Declaring the following structures as const puts them in the
351 text (read-only) segment, which makes debugging inconvenient
352 because this segment is not mapped when processing a core-
353 dump file */
354
355 #ifdef DEBUG_XEMACS
356 #define CONST_IF_NOT_DEBUG
357 #else
358 #define CONST_IF_NOT_DEBUG const
359 #endif
360
361 /* DEFINE_LRECORD_IMPLEMENTATION is for objects with constant size. 417 /* DEFINE_LRECORD_IMPLEMENTATION is for objects with constant size.
362 DEFINE_LRECORD_SEQUENCE_IMPLEMENTATION is for objects whose size varies. 418 DEFINE_LRECORD_SEQUENCE_IMPLEMENTATION is for objects whose size varies.
363 */ 419 */
364 420
365 #if defined (ERROR_CHECK_TYPECHECK) 421 #if defined (ERROR_CHECK_TYPECHECK)
389 #define DEFINE_LRECORD_SEQUENCE_IMPLEMENTATION_WITH_PROPS(name,c_name,marker,printer,nuker,equal,hash,desc,getprop,putprop,remprop,plist,sizer,structtype) \ 445 #define DEFINE_LRECORD_SEQUENCE_IMPLEMENTATION_WITH_PROPS(name,c_name,marker,printer,nuker,equal,hash,desc,getprop,putprop,remprop,plist,sizer,structtype) \
390 MAKE_LRECORD_IMPLEMENTATION(name,c_name,marker,printer,nuker,equal,hash,desc,getprop,putprop,remprop,plist,0,sizer,0,structtype) \ 446 MAKE_LRECORD_IMPLEMENTATION(name,c_name,marker,printer,nuker,equal,hash,desc,getprop,putprop,remprop,plist,0,sizer,0,structtype) \
391 447
392 #define MAKE_LRECORD_IMPLEMENTATION(name,c_name,marker,printer,nuker,equal,hash,desc,getprop,putprop,remprop,plist,size,sizer,basic_p,structtype) \ 448 #define MAKE_LRECORD_IMPLEMENTATION(name,c_name,marker,printer,nuker,equal,hash,desc,getprop,putprop,remprop,plist,size,sizer,basic_p,structtype) \
393 DECLARE_ERROR_CHECK_TYPECHECK(c_name, structtype) \ 449 DECLARE_ERROR_CHECK_TYPECHECK(c_name, structtype) \
394 static int lrecord_##c_name##_lrecord_type_index; \ 450 const struct lrecord_implementation lrecord_##c_name = \
395 CONST_IF_NOT_DEBUG struct lrecord_implementation lrecord_##c_name = \
396 { name, marker, printer, nuker, equal, hash, desc, \ 451 { name, marker, printer, nuker, equal, hash, desc, \
397 getprop, putprop, remprop, plist, size, sizer, \ 452 getprop, putprop, remprop, plist, size, sizer, \
398 &(lrecord_##c_name##_lrecord_type_index), basic_p } \ 453 lrecord_type_##c_name, basic_p }
454
455 extern Lisp_Object (*lrecord_markers[]) (Lisp_Object);
456
457 #define INIT_LRECORD_IMPLEMENTATION(type) do { \
458 lrecord_implementations_table[lrecord_type_##type] = &lrecord_##type; \
459 lrecord_markers[lrecord_type_##type] = \
460 lrecord_implementations_table[lrecord_type_##type]->marker; \
461 } while (0)
399 462
400 #define LRECORDP(a) (XTYPE (a) == Lisp_Type_Record) 463 #define LRECORDP(a) (XTYPE (a) == Lisp_Type_Record)
401 #define XRECORD_LHEADER(a) ((struct lrecord_header *) XPNTR (a)) 464 #define XRECORD_LHEADER(a) ((struct lrecord_header *) XPNTR (a))
402 465
403 #define RECORD_TYPEP(x, ty) \ 466 #define RECORD_TYPEP(x, ty) \
404 (LRECORDP (x) && \ 467 (LRECORDP (x) && XRECORD_LHEADER (x)->type == (ty))
405 lrecord_implementations_table[XRECORD_LHEADER (x)->type] == (ty))
406 468
407 /* NOTE: the DECLARE_LRECORD() must come before the associated 469 /* NOTE: the DECLARE_LRECORD() must come before the associated
408 DEFINE_LRECORD_*() or you will get compile errors. 470 DEFINE_LRECORD_*() or you will get compile errors.
409 471
410 Furthermore, you always need to put the DECLARE_LRECORD() in a header 472 Furthermore, you always need to put the DECLARE_LRECORD() in a header
414 under GCC. */ 476 under GCC. */
415 477
416 #ifdef ERROR_CHECK_TYPECHECK 478 #ifdef ERROR_CHECK_TYPECHECK
417 479
418 # define DECLARE_LRECORD(c_name, structtype) \ 480 # define DECLARE_LRECORD(c_name, structtype) \
419 extern CONST_IF_NOT_DEBUG struct lrecord_implementation \ 481 extern const struct lrecord_implementation lrecord_##c_name; \
420 lrecord_##c_name; \
421 INLINE structtype *error_check_##c_name (Lisp_Object obj); \ 482 INLINE structtype *error_check_##c_name (Lisp_Object obj); \
422 INLINE structtype * \ 483 INLINE structtype * \
423 error_check_##c_name (Lisp_Object obj) \ 484 error_check_##c_name (Lisp_Object obj) \
424 { \ 485 { \
425 assert (RECORD_TYPEP (obj, &lrecord_##c_name)); \ 486 assert (RECORD_TYPEP (obj, lrecord_type_##c_name)); \
426 return (structtype *) XPNTR (obj); \ 487 return (structtype *) XPNTR (obj); \
427 } \ 488 } \
428 extern Lisp_Object Q##c_name##p 489 extern Lisp_Object Q##c_name##p
429 490
430 # define DECLARE_NONRECORD(c_name, type_enum, structtype) \ 491 # define DECLARE_NONRECORD(c_name, type_enum, structtype) \
441 # define XNONRECORD(x, c_name, type_enum, structtype) error_check_##c_name (x) 502 # define XNONRECORD(x, c_name, type_enum, structtype) error_check_##c_name (x)
442 503
443 # define XSETRECORD(var, p, c_name) do \ 504 # define XSETRECORD(var, p, c_name) do \
444 { \ 505 { \
445 XSETOBJ (var, Lisp_Type_Record, p); \ 506 XSETOBJ (var, Lisp_Type_Record, p); \
446 assert (RECORD_TYPEP (var, &lrecord_##c_name)); \ 507 assert (RECORD_TYPEP (var, lrecord_type_##c_name)); \
447 } while (0) 508 } while (0)
448 509
449 #else /* not ERROR_CHECK_TYPECHECK */ 510 #else /* not ERROR_CHECK_TYPECHECK */
450 511
451 # define DECLARE_LRECORD(c_name, structtype) \ 512 # define DECLARE_LRECORD(c_name, structtype) \
452 extern Lisp_Object Q##c_name##p; \ 513 extern Lisp_Object Q##c_name##p; \
453 extern CONST_IF_NOT_DEBUG struct lrecord_implementation \ 514 extern const struct lrecord_implementation lrecord_##c_name
454 lrecord_##c_name
455 # define DECLARE_NONRECORD(c_name, type_enum, structtype) \ 515 # define DECLARE_NONRECORD(c_name, type_enum, structtype) \
456 extern Lisp_Object Q##c_name##p 516 extern Lisp_Object Q##c_name##p
457 # define XRECORD(x, c_name, structtype) ((structtype *) XPNTR (x)) 517 # define XRECORD(x, c_name, structtype) ((structtype *) XPNTR (x))
458 # define XNONRECORD(x, c_name, type_enum, structtype) \ 518 # define XNONRECORD(x, c_name, type_enum, structtype) \
459 ((structtype *) XPNTR (x)) 519 ((structtype *) XPNTR (x))
460 # define XSETRECORD(var, p, c_name) XSETOBJ (var, Lisp_Type_Record, p) 520 # define XSETRECORD(var, p, c_name) XSETOBJ (var, Lisp_Type_Record, p)
461 521
462 #endif /* not ERROR_CHECK_TYPECHECK */ 522 #endif /* not ERROR_CHECK_TYPECHECK */
463 523
464 #define RECORDP(x, c_name) RECORD_TYPEP (x, &lrecord_##c_name) 524 #define RECORDP(x, c_name) RECORD_TYPEP (x, lrecord_type_##c_name)
465 525
466 /* Note: we now have two different kinds of type-checking macros. 526 /* Note: we now have two different kinds of type-checking macros.
467 The "old" kind has now been renamed CONCHECK_foo. The reason for 527 The "old" kind has now been renamed CONCHECK_foo. The reason for
468 this is that the CONCHECK_foo macros signal a continuable error, 528 this is that the CONCHECK_foo macros signal a continuable error,
469 allowing the user (through debug-on-error) to substitute a different 529 allowing the user (through debug-on-error) to substitute a different
485 545
486 FSF Emacs does not have this problem because RMS took the cheesy 546 FSF Emacs does not have this problem because RMS took the cheesy
487 way out and disabled returning from a signal entirely. */ 547 way out and disabled returning from a signal entirely. */
488 548
489 #define CONCHECK_RECORD(x, c_name) do { \ 549 #define CONCHECK_RECORD(x, c_name) do { \
490 if (!RECORD_TYPEP (x, &lrecord_##c_name)) \ 550 if (!RECORD_TYPEP (x, lrecord_type_##c_name)) \
491 x = wrong_type_argument (Q##c_name##p, x); \ 551 x = wrong_type_argument (Q##c_name##p, x); \
492 } while (0) 552 } while (0)
493 #define CONCHECK_NONRECORD(x, lisp_enum, predicate) do {\ 553 #define CONCHECK_NONRECORD(x, lisp_enum, predicate) do {\
494 if (XTYPE (x) != lisp_enum) \ 554 if (XTYPE (x) != lisp_enum) \
495 x = wrong_type_argument (predicate, x); \ 555 x = wrong_type_argument (predicate, x); \
496 } while (0) 556 } while (0)
497 #define CHECK_RECORD(x, c_name) do { \ 557 #define CHECK_RECORD(x, c_name) do { \
498 if (!RECORD_TYPEP (x, &lrecord_##c_name)) \ 558 if (!RECORD_TYPEP (x, lrecord_type_##c_name)) \
499 dead_wrong_type_argument (Q##c_name##p, x); \ 559 dead_wrong_type_argument (Q##c_name##p, x); \
500 } while (0) 560 } while (0)
501 #define CHECK_NONRECORD(x, lisp_enum, predicate) do { \ 561 #define CHECK_NONRECORD(x, lisp_enum, predicate) do { \
502 if (XTYPE (x) != lisp_enum) \ 562 if (XTYPE (x) != lisp_enum) \
503 dead_wrong_type_argument (predicate, x); \ 563 dead_wrong_type_argument (predicate, x); \