aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorPaul Eggert2013-03-21 13:56:22 -0700
committerPaul Eggert2013-03-21 13:56:22 -0700
commit7b1123d824e51d40496c242e7a7f173de8936100 (patch)
tree0aaafb8bc660f02c35516227bfde2fef344d318a /src
parentd6723bf7e58e17c889e354bc429f3f134281953a (diff)
downloademacs-7b1123d824e51d40496c242e7a7f173de8936100.tar.gz
emacs-7b1123d824e51d40496c242e7a7f173de8936100.zip
Use functions and constants to manipulate Lisp_Save_Value objects.
This replaces code that used macros and strings and token-pasting. The change makes the C source a bit easier to follow, and shrinks the Emacs executable a bit. * alloc.c: Verify some properties of Lisp_Save_Value's representation. (make_save_value): Change 1st arg from string to enum. All callers changed. (INTX): Remove. (mark_object): Use if, not #if, for GC_MARK_STACK. * lisp.h (SAVE_VALUEP, XSAVE_VALUE, XSAVE_POINTER, XSAVE_INTEGER) (XSAVE_OBJECT): Now functions, not macros. (STRING_BYTES_BOUND): Now just a macro, not a constant too; the constant was never used. (SAVE_SLOT_BITS, SAVE_VALUE_SLOTS, SAVE_TYPE_BITS, SAVE_TYPE_INT_INT) (SAVE_TYPE_INT_INT_INT, SAVE_TYPE_OBJ_OBJ, SAVE_TYPE_OBJ_OBJ_OBJ) (SAVE_TYPE_OBJ_OBJ_OBJ_OBJ, SAVE_TYPE_PTR_INT, SAVE_TYPE_PTR_OBJ) (SAVE_TYPE_PTR_PTR, SAVE_TYPE_PTR_PTR_OBJ, SAVE_TYPE_MEMORY): New constants. (struct Lisp_Save_Value): Replace members area, type0, type1, type2, type3 with a single member save_type. All uses changed. (save_type, set_save_pointer, set_save_integer): New functions. * print.c (PRINTX): Remove.
Diffstat (limited to 'src')
-rw-r--r--src/ChangeLog23
-rw-r--r--src/alloc.c95
-rw-r--r--src/editfns.c7
-rw-r--r--src/fileio.c3
-rw-r--r--src/ftfont.c6
-rw-r--r--src/keymap.c3
-rw-r--r--src/lisp.h153
-rw-r--r--src/print.c69
-rw-r--r--src/xmenu.c2
9 files changed, 220 insertions, 141 deletions
diff --git a/src/ChangeLog b/src/ChangeLog
index d6b50412f13..f65e08eb6fd 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,5 +1,28 @@
12013-03-21 Paul Eggert <eggert@cs.ucla.edu> 12013-03-21 Paul Eggert <eggert@cs.ucla.edu>
2 2
3 Use functions and constants to manipulate Lisp_Save_Value objects.
4 This replaces code that used macros and strings and token-pasting.
5 The change makes the C source a bit easier to follow,
6 and shrinks the Emacs executable a bit.
7 * alloc.c: Verify some properties of Lisp_Save_Value's representation.
8 (make_save_value): Change 1st arg from string to enum. All callers
9 changed.
10 (INTX): Remove.
11 (mark_object): Use if, not #if, for GC_MARK_STACK.
12 * lisp.h (SAVE_VALUEP, XSAVE_VALUE, XSAVE_POINTER, XSAVE_INTEGER)
13 (XSAVE_OBJECT): Now functions, not macros.
14 (STRING_BYTES_BOUND): Now just a macro, not a constant too;
15 the constant was never used.
16 (SAVE_SLOT_BITS, SAVE_VALUE_SLOTS, SAVE_TYPE_BITS, SAVE_TYPE_INT_INT)
17 (SAVE_TYPE_INT_INT_INT, SAVE_TYPE_OBJ_OBJ, SAVE_TYPE_OBJ_OBJ_OBJ)
18 (SAVE_TYPE_OBJ_OBJ_OBJ_OBJ, SAVE_TYPE_PTR_INT, SAVE_TYPE_PTR_OBJ)
19 (SAVE_TYPE_PTR_PTR, SAVE_TYPE_PTR_PTR_OBJ, SAVE_TYPE_MEMORY):
20 New constants.
21 (struct Lisp_Save_Value): Replace members area, type0, type1, type2,
22 type3 with a single member save_type. All uses changed.
23 (save_type, set_save_pointer, set_save_integer): New functions.
24 * print.c (PRINTX): Remove.
25
3 * alloc.c: Remove redundant static declarations. 26 * alloc.c: Remove redundant static declarations.
4 27
52013-03-20 Dmitry Antipov <dmantipov@yandex.ru> 282013-03-20 Dmitry Antipov <dmantipov@yandex.ru>
diff --git a/src/alloc.c b/src/alloc.c
index 39379bc3bd7..4245b3069fa 100644
--- a/src/alloc.c
+++ b/src/alloc.c
@@ -3326,56 +3326,50 @@ free_misc (Lisp_Object misc)
3326 total_free_markers++; 3326 total_free_markers++;
3327} 3327}
3328 3328
3329/* Verify properties of Lisp_Save_Value's representation
3330 that are assumed here and elsewhere. */
3331
3332verify (SAVE_UNUSED == 0);
3333verify ((SAVE_INTEGER | SAVE_POINTER | SAVE_OBJECT) >> SAVE_SLOT_BITS == 0);
3334
3329/* Return a Lisp_Save_Value object with the data saved according to 3335/* Return a Lisp_Save_Value object with the data saved according to
3330 FMT. Format specifiers are `i' for an integer, `p' for a pointer 3336 DATA_TYPE. DATA_TYPE should be one of SAVE_TYPE_INT_INT, etc. */
3331 and `o' for Lisp_Object. Up to 4 objects can be specified. */
3332 3337
3333Lisp_Object 3338Lisp_Object
3334make_save_value (const char *fmt, ...) 3339make_save_value (enum Lisp_Save_Type save_type, ...)
3335{ 3340{
3336 va_list ap; 3341 va_list ap;
3337 int len = strlen (fmt); 3342 int i;
3338 Lisp_Object val = allocate_misc (Lisp_Misc_Save_Value); 3343 Lisp_Object val = allocate_misc (Lisp_Misc_Save_Value);
3339 struct Lisp_Save_Value *p = XSAVE_VALUE (val); 3344 struct Lisp_Save_Value *p = XSAVE_VALUE (val);
3340 3345
3341 eassert (0 < len && len < 5); 3346 eassert (0 < save_type
3342 va_start (ap, fmt); 3347 && (save_type < 1 << (SAVE_TYPE_BITS - 1)
3343 3348 || save_type == SAVE_TYPE_MEMORY));
3344#define INITX(index) \ 3349 p->save_type = save_type;
3345 do { \ 3350 va_start (ap, save_type);
3346 if (len <= index) \ 3351 save_type &= ~ (1 << (SAVE_TYPE_BITS - 1));
3347 p->type ## index = SAVE_UNUSED; \ 3352
3348 else \ 3353 for (i = 0; save_type; i++, save_type >>= SAVE_SLOT_BITS)
3349 { \ 3354 switch (save_type & ((1 << SAVE_SLOT_BITS) - 1))
3350 if (fmt[index] == 'i') \ 3355 {
3351 { \ 3356 case SAVE_POINTER:
3352 p->type ## index = SAVE_INTEGER; \ 3357 p->data[i].pointer = va_arg (ap, void *);
3353 p->data[index].integer = va_arg (ap, ptrdiff_t); \ 3358 break;
3354 } \
3355 else if (fmt[index] == 'p') \
3356 { \
3357 p->type ## index = SAVE_POINTER; \
3358 p->data[index].pointer = va_arg (ap, void *); \
3359 } \
3360 else if (fmt[index] == 'o') \
3361 { \
3362 p->type ## index = SAVE_OBJECT; \
3363 p->data[index].object = va_arg (ap, Lisp_Object); \
3364 } \
3365 else \
3366 emacs_abort (); \
3367 } \
3368 } while (0)
3369 3359
3370 INITX (0); 3360 case SAVE_INTEGER:
3371 INITX (1); 3361 p->data[i].integer = va_arg (ap, ptrdiff_t);
3372 INITX (2); 3362 break;
3373 INITX (3);
3374 3363
3375#undef INITX 3364 case SAVE_OBJECT:
3365 p->data[i].object = va_arg (ap, Lisp_Object);
3366 break;
3367
3368 default:
3369 emacs_abort ();
3370 }
3376 3371
3377 va_end (ap); 3372 va_end (ap);
3378 p->area = 0;
3379 return val; 3373 return val;
3380} 3374}
3381 3375
@@ -3386,11 +3380,8 @@ make_save_pointer (void *pointer)
3386{ 3380{
3387 Lisp_Object val = allocate_misc (Lisp_Misc_Save_Value); 3381 Lisp_Object val = allocate_misc (Lisp_Misc_Save_Value);
3388 struct Lisp_Save_Value *p = XSAVE_VALUE (val); 3382 struct Lisp_Save_Value *p = XSAVE_VALUE (val);
3389 3383 p->save_type = SAVE_POINTER;
3390 p->area = 0;
3391 p->type0 = SAVE_POINTER;
3392 p->data[0].pointer = pointer; 3384 p->data[0].pointer = pointer;
3393 p->type1 = p->type2 = p->type3 = SAVE_UNUSED;
3394 return val; 3385 return val;
3395} 3386}
3396 3387
@@ -5958,12 +5949,11 @@ mark_object (Lisp_Object arg)
5958 case Lisp_Misc_Save_Value: 5949 case Lisp_Misc_Save_Value:
5959 XMISCANY (obj)->gcmarkbit = 1; 5950 XMISCANY (obj)->gcmarkbit = 1;
5960 { 5951 {
5961 register struct Lisp_Save_Value *ptr = XSAVE_VALUE (obj); 5952 struct Lisp_Save_Value *ptr = XSAVE_VALUE (obj);
5962 /* If `area' is nonzero, `data[0].pointer' is the address 5953 /* If `save_type' is zero, `data[0].pointer' is the address
5963 of a memory area containing `data[1].integer' potential 5954 of a memory area containing `data[1].integer' potential
5964 Lisp_Objects. */ 5955 Lisp_Objects. */
5965#if GC_MARK_STACK 5956 if (GC_MARK_STACK && ptr->save_type == SAVE_TYPE_MEMORY)
5966 if (ptr->area)
5967 { 5957 {
5968 Lisp_Object *p = ptr->data[0].pointer; 5958 Lisp_Object *p = ptr->data[0].pointer;
5969 ptrdiff_t nelt; 5959 ptrdiff_t nelt;
@@ -5971,17 +5961,12 @@ mark_object (Lisp_Object arg)
5971 mark_maybe_object (*p); 5961 mark_maybe_object (*p);
5972 } 5962 }
5973 else 5963 else
5974#endif /* GC_MARK_STACK */
5975 { 5964 {
5976 /* Find Lisp_Objects in `data[N]' slots and mark them. */ 5965 /* Find Lisp_Objects in `data[N]' slots and mark them. */
5977 if (ptr->type0 == SAVE_OBJECT) 5966 int i;
5978 mark_object (ptr->data[0].object); 5967 for (i = 0; i < SAVE_VALUE_SLOTS; i++)
5979 if (ptr->type1 == SAVE_OBJECT) 5968 if (save_type (ptr, i) == SAVE_OBJECT)
5980 mark_object (ptr->data[1].object); 5969 mark_object (ptr->data[i].object);
5981 if (ptr->type2 == SAVE_OBJECT)
5982 mark_object (ptr->data[2].object);
5983 if (ptr->type3 == SAVE_OBJECT)
5984 mark_object (ptr->data[3].object);
5985 } 5970 }
5986 } 5971 }
5987 break; 5972 break;
diff --git a/src/editfns.c b/src/editfns.c
index f34c574cae3..6357a28e8ea 100644
--- a/src/editfns.c
+++ b/src/editfns.c
@@ -839,7 +839,7 @@ Lisp_Object
839save_excursion_save (void) 839save_excursion_save (void)
840{ 840{
841 return make_save_value 841 return make_save_value
842 ("oooo", 842 (SAVE_TYPE_OBJ_OBJ_OBJ_OBJ,
843 Fpoint_marker (), 843 Fpoint_marker (),
844 /* Do not copy the mark if it points to nowhere. */ 844 /* Do not copy the mark if it points to nowhere. */
845 (XMARKER (BVAR (current_buffer, mark))->buffer 845 (XMARKER (BVAR (current_buffer, mark))->buffer
@@ -4241,7 +4241,10 @@ usage: (format STRING &rest OBJECTS) */)
4241 memcpy (buf, initial_buffer, used); 4241 memcpy (buf, initial_buffer, used);
4242 } 4242 }
4243 else 4243 else
4244 XSAVE_POINTER (buf_save_value, 0) = buf = xrealloc (buf, bufsize); 4244 {
4245 buf = xrealloc (buf, bufsize);
4246 set_save_pointer (buf_save_value, 0, buf);
4247 }
4245 4248
4246 p = buf + used; 4249 p = buf + used;
4247 } 4250 }
diff --git a/src/fileio.c b/src/fileio.c
index 724250c8aaa..3d7bd9fe216 100644
--- a/src/fileio.c
+++ b/src/fileio.c
@@ -4218,7 +4218,8 @@ by calling `format-decode', which see. */)
4218 to be signaled after decoding the text we read. */ 4218 to be signaled after decoding the text we read. */
4219 nbytes = internal_condition_case_1 4219 nbytes = internal_condition_case_1
4220 (read_non_regular, 4220 (read_non_regular,
4221 make_save_value ("iii", (ptrdiff_t) fd, inserted, trytry), 4221 make_save_value (SAVE_TYPE_INT_INT_INT, (ptrdiff_t) fd,
4222 inserted, trytry),
4222 Qerror, read_non_regular_quit); 4223 Qerror, read_non_regular_quit);
4223 4224
4224 if (NILP (nbytes)) 4225 if (NILP (nbytes))
diff --git a/src/ftfont.c b/src/ftfont.c
index 867e25a7a25..0ad173af98a 100644
--- a/src/ftfont.c
+++ b/src/ftfont.c
@@ -393,7 +393,7 @@ ftfont_lookup_cache (Lisp_Object key, enum ftfont_cache_for cache_for)
393 cache_data = xmalloc (sizeof *cache_data); 393 cache_data = xmalloc (sizeof *cache_data);
394 cache_data->ft_face = NULL; 394 cache_data->ft_face = NULL;
395 cache_data->fc_charset = NULL; 395 cache_data->fc_charset = NULL;
396 val = make_save_value ("pi", cache_data, 0); 396 val = make_save_value (SAVE_TYPE_PTR_INT, cache_data, 0);
397 cache = Fcons (Qnil, val); 397 cache = Fcons (Qnil, val);
398 Fputhash (key, cache, ft_face_cache); 398 Fputhash (key, cache, ft_face_cache);
399 } 399 }
@@ -1211,7 +1211,7 @@ ftfont_open (FRAME_PTR f, Lisp_Object entity, int pixel_size)
1211 return Qnil; 1211 return Qnil;
1212 } 1212 }
1213 } 1213 }
1214 XSAVE_INTEGER (val, 1)++; 1214 set_save_integer (val, 1, XSAVE_INTEGER (val, 1) + 1);
1215 size = XINT (AREF (entity, FONT_SIZE_INDEX)); 1215 size = XINT (AREF (entity, FONT_SIZE_INDEX));
1216 if (size == 0) 1216 if (size == 0)
1217 size = pixel_size; 1217 size = pixel_size;
@@ -1326,7 +1326,7 @@ ftfont_close (FRAME_PTR f, struct font *font)
1326 cache = ftfont_lookup_cache (val, FTFONT_CACHE_FOR_FACE); 1326 cache = ftfont_lookup_cache (val, FTFONT_CACHE_FOR_FACE);
1327 eassert (CONSP (cache)); 1327 eassert (CONSP (cache));
1328 val = XCDR (cache); 1328 val = XCDR (cache);
1329 XSAVE_INTEGER (val, 1)--; 1329 set_save_integer (val, 1, XSAVE_INTEGER (val, 1) - 1);
1330 if (XSAVE_INTEGER (val, 1) == 0) 1330 if (XSAVE_INTEGER (val, 1) == 0)
1331 { 1331 {
1332 struct ftfont_cache_data *cache_data = XSAVE_POINTER (val, 0); 1332 struct ftfont_cache_data *cache_data = XSAVE_POINTER (val, 0);
diff --git a/src/keymap.c b/src/keymap.c
index 00eefb375ef..34406a5fc70 100644
--- a/src/keymap.c
+++ b/src/keymap.c
@@ -611,7 +611,8 @@ map_keymap_internal (Lisp_Object map,
611 } 611 }
612 else if (CHAR_TABLE_P (binding)) 612 else if (CHAR_TABLE_P (binding))
613 map_char_table (map_keymap_char_table_item, Qnil, binding, 613 map_char_table (map_keymap_char_table_item, Qnil, binding,
614 make_save_value ("ppo", fun, data, args)); 614 make_save_value (SAVE_TYPE_PTR_PTR_OBJ,
615 fun, data, args));
615 } 616 }
616 UNGCPRO; 617 UNGCPRO;
617 return tail; 618 return tail;
diff --git a/src/lisp.h b/src/lisp.h
index f526cd36a6f..6838d4a93cb 100644
--- a/src/lisp.h
+++ b/src/lisp.h
@@ -551,6 +551,12 @@ clip_to_bounds (ptrdiff_t lower, EMACS_INT num, ptrdiff_t upper)
551 return num < lower ? lower : num <= upper ? num : upper; 551 return num < lower ? lower : num <= upper ? num : upper;
552} 552}
553 553
554
555/* Forward declarations. */
556
557LISP_INLINE bool SAVE_VALUEP (Lisp_Object);
558LISP_INLINE struct Lisp_Save_Value *XSAVE_VALUE (Lisp_Object);
559
554/* Extract a value or address from a Lisp_Object. */ 560/* Extract a value or address from a Lisp_Object. */
555 561
556#define XCONS(a) (eassert (CONSP (a)), \ 562#define XCONS(a) (eassert (CONSP (a)), \
@@ -571,7 +577,6 @@ clip_to_bounds (ptrdiff_t lower, EMACS_INT num, ptrdiff_t upper)
571#define XMISCTYPE(a) (XMISCANY (a)->type) 577#define XMISCTYPE(a) (XMISCANY (a)->type)
572#define XMARKER(a) (eassert (MARKERP (a)), &(XMISC (a)->u_marker)) 578#define XMARKER(a) (eassert (MARKERP (a)), &(XMISC (a)->u_marker))
573#define XOVERLAY(a) (eassert (OVERLAYP (a)), &(XMISC (a)->u_overlay)) 579#define XOVERLAY(a) (eassert (OVERLAYP (a)), &(XMISC (a)->u_overlay))
574#define XSAVE_VALUE(a) (eassert (SAVE_VALUEP (a)), &(XMISC (a)->u_save_value))
575 580
576/* Forwarding object types. */ 581/* Forwarding object types. */
577 582
@@ -781,13 +786,10 @@ extern ptrdiff_t string_bytes (struct Lisp_String *);
781 would expose alloc.c internal details that we'd rather keep 786 would expose alloc.c internal details that we'd rather keep
782 private. 787 private.
783 788
784 This is a macro for use in static initializers, and a constant for 789 This is a macro for use in static initializers. The cast to
785 visibility to GDB. The cast to ptrdiff_t ensures that 790 ptrdiff_t ensures that the macro is signed. */
786 the macro is signed. */
787static ptrdiff_t const STRING_BYTES_BOUND =
788#define STRING_BYTES_BOUND \ 791#define STRING_BYTES_BOUND \
789 ((ptrdiff_t) min (MOST_POSITIVE_FIXNUM, min (SIZE_MAX, PTRDIFF_MAX) - 1)) 792 ((ptrdiff_t) min (MOST_POSITIVE_FIXNUM, min (SIZE_MAX, PTRDIFF_MAX) - 1))
790 STRING_BYTES_BOUND;
791 793
792/* Mark STR as a unibyte string. */ 794/* Mark STR as a unibyte string. */
793#define STRING_SET_UNIBYTE(STR) \ 795#define STRING_SET_UNIBYTE(STR) \
@@ -1392,6 +1394,35 @@ enum
1392 SAVE_OBJECT 1394 SAVE_OBJECT
1393 }; 1395 };
1394 1396
1397/* Number of bits needed to store one of the above values. */
1398enum { SAVE_SLOT_BITS = 2 };
1399
1400/* Number of slots in a save value where save_type is nonzero. */
1401enum { SAVE_VALUE_SLOTS = 4 };
1402
1403/* Bit-width and values for struct Lisp_Save_Value's save_type member. */
1404
1405enum { SAVE_TYPE_BITS = SAVE_VALUE_SLOTS * SAVE_SLOT_BITS + 1 };
1406
1407enum Lisp_Save_Type
1408 {
1409 SAVE_TYPE_INT_INT = SAVE_INTEGER + (SAVE_INTEGER << SAVE_SLOT_BITS),
1410 SAVE_TYPE_INT_INT_INT
1411 = (SAVE_INTEGER + (SAVE_TYPE_INT_INT << SAVE_SLOT_BITS)),
1412 SAVE_TYPE_OBJ_OBJ = SAVE_OBJECT + (SAVE_OBJECT << SAVE_SLOT_BITS),
1413 SAVE_TYPE_OBJ_OBJ_OBJ = SAVE_OBJECT + (SAVE_TYPE_OBJ_OBJ << SAVE_SLOT_BITS),
1414 SAVE_TYPE_OBJ_OBJ_OBJ_OBJ
1415 = SAVE_OBJECT + (SAVE_TYPE_OBJ_OBJ_OBJ << SAVE_SLOT_BITS),
1416 SAVE_TYPE_PTR_INT = SAVE_POINTER + (SAVE_INTEGER << SAVE_SLOT_BITS),
1417 SAVE_TYPE_PTR_OBJ = SAVE_POINTER + (SAVE_OBJECT << SAVE_SLOT_BITS),
1418 SAVE_TYPE_PTR_PTR = SAVE_POINTER + (SAVE_POINTER << SAVE_SLOT_BITS),
1419 SAVE_TYPE_PTR_PTR_OBJ
1420 = SAVE_POINTER + (SAVE_TYPE_PTR_OBJ << SAVE_SLOT_BITS),
1421
1422 /* This has an extra bit indicating it's raw memory. */
1423 SAVE_TYPE_MEMORY = SAVE_TYPE_PTR_INT + (1 << (SAVE_TYPE_BITS - 1))
1424 };
1425
1395/* Special object used to hold a different values for later use. 1426/* Special object used to hold a different values for later use.
1396 1427
1397 This is mostly used to package C integers and pointers to call 1428 This is mostly used to package C integers and pointers to call
@@ -1412,73 +1443,96 @@ enum
1412 1443
1413 If yon need to pass more than just one C pointer, you should 1444 If yon need to pass more than just one C pointer, you should
1414 use make_save_value. This function allows you to pack up to 1445 use make_save_value. This function allows you to pack up to
1415 4 integers, pointers or Lisp_Objects and conveniently get them 1446 SAVE_VALUE_SLOTS integers, pointers or Lisp_Objects and
1416 back with XSAVE_POINTER, XSAVE_INTEGER and XSAVE_OBJECT macros: 1447 conveniently get them back with XSAVE_POINTER, XSAVE_INTEGER and
1448 XSAVE_OBJECT macros:
1417 1449
1418 ... 1450 ...
1419 struct my_data *md = get_my_data (); 1451 struct my_data *md = get_my_data ();
1420 ptrdiff_t my_offset = get_my_offset ();
1421 Lisp_Object my_object = get_my_object (); 1452 Lisp_Object my_object = get_my_object ();
1422 record_unwind_protect 1453 record_unwind_protect
1423 (my_unwind, make_save_value ("pio", md, my_offset, my_object)); 1454 (my_unwind, make_save_value (SAVE_TYPE_PTR_OBJ, md, my_object));
1424 ... 1455 ...
1425 1456
1426 Lisp_Object my_unwind (Lisp_Object arg) 1457 Lisp_Object my_unwind (Lisp_Object arg)
1427 { 1458 {
1428 struct my_data *md = XSAVE_POINTER (arg, 0); 1459 struct my_data *md = XSAVE_POINTER (arg, 0);
1429 ptrdiff_t my_offset = XSAVE_INTEGER (arg, 1); 1460 Lisp_Object my_object = XSAVE_OBJECT (arg, 1);
1430 Lisp_Object my_object = XSAVE_OBJECT (arg, 2);
1431 ... 1461 ...
1432 } 1462 }
1433 1463
1434 If ENABLE_CHECKING is in effect, XSAVE_xxx macros do type checking of the 1464 If ENABLE_CHECKING is in effect, XSAVE_xxx macros do type checking of the
1435 saved objects and raise eassert if type of the saved object doesn't match 1465 saved objects and raise eassert if type of the saved object doesn't match
1436 the type which is extracted. In the example above, XSAVE_INTEGER (arg, 2) 1466 the type which is extracted. In the example above, XSAVE_INTEGER (arg, 2)
1437 or XSAVE_OBJECT (arg, 1) are wrong because integer was saved in slot 1 and 1467 or XSAVE_OBJECT (arg, 0) are wrong because nothing was saved in slot 2 and
1438 Lisp_Object was saved in slot 2 of ARG. */ 1468 Lisp_Object was saved in slot 1 of ARG. */
1439 1469
1440struct Lisp_Save_Value 1470struct Lisp_Save_Value
1441 { 1471 {
1442 ENUM_BF (Lisp_Misc_Type) type : 16; /* = Lisp_Misc_Save_Value */ 1472 ENUM_BF (Lisp_Misc_Type) type : 16; /* = Lisp_Misc_Save_Value */
1443 unsigned gcmarkbit : 1; 1473 unsigned gcmarkbit : 1;
1444 int spacer : 6; 1474 int spacer : 32 - (16 + 1 + SAVE_TYPE_BITS);
1445 /* If `area' is nonzero, `data[0].pointer' is the address of a memory area 1475
1446 containing `data[1].integer' potential Lisp_Objects. The rest of `data' 1476 /* DATA[N] may hold up to SAVE_VALUE_SLOTS entries. The type of
1447 fields are unused. */ 1477 V's Ith entry is given by save_type (V, I). E.g., if save_type
1448 unsigned area : 1; 1478 (V, 3) == SAVE_INTEGER, V->data[3].integer is in use.
1449 /* If `area' is zero, `data[N]' may hold different objects which type is 1479
1450 encoded in `typeN' fields as described by the anonymous enum above. 1480 If SAVE_TYPE == SAVE_TYPE_MEMORY, DATA[0].pointer is the address of
1451 E.g. if `type0' is SAVE_INTEGER, `data[0].integer' is in use. */ 1481 a memory area containing DATA[1].integer potential Lisp_Objects. */
1452 unsigned type0 : 2; 1482 ENUM_BF (Lisp_Save_Type) save_type : SAVE_TYPE_BITS;
1453 unsigned type1 : 2;
1454 unsigned type2 : 2;
1455 unsigned type3 : 2;
1456 union { 1483 union {
1457 void *pointer; 1484 void *pointer;
1458 ptrdiff_t integer; 1485 ptrdiff_t integer;
1459 Lisp_Object object; 1486 Lisp_Object object;
1460 } data[4]; 1487 } data[SAVE_VALUE_SLOTS];
1461 }; 1488 };
1462 1489
1463/* Macro to set and extract Nth saved pointer. Type 1490/* Return the type of V's Nth saved value. */
1464 checking is ugly because it's used as an lvalue. */ 1491LISP_INLINE int
1492save_type (struct Lisp_Save_Value *v, int n)
1493{
1494 eassert (0 <= n && n < SAVE_VALUE_SLOTS);
1495 return (v->save_type >> (SAVE_SLOT_BITS * n) & ((1 << SAVE_SLOT_BITS) - 1));
1496}
1497
1498/* Get and set the Nth saved pointer. */
1465 1499
1466#define XSAVE_POINTER(obj, n) \ 1500LISP_INLINE void *
1467 XSAVE_VALUE (obj)->data[(eassert (XSAVE_VALUE (obj)->type \ 1501XSAVE_POINTER (Lisp_Object obj, int n)
1468 ## n == SAVE_POINTER), n)].pointer 1502{
1503 eassert (save_type (XSAVE_VALUE (obj), n) == SAVE_POINTER);
1504 return XSAVE_VALUE (obj)->data[n].pointer;;
1505}
1506LISP_INLINE void
1507set_save_pointer (Lisp_Object obj, int n, void *val)
1508{
1509 eassert (save_type (XSAVE_VALUE (obj), n) == SAVE_POINTER);
1510 XSAVE_VALUE (obj)->data[n].pointer = val;
1511}
1469 1512
1470/* Likewise for the saved integer. */ 1513/* Likewise for the saved integer. */
1471 1514
1472#define XSAVE_INTEGER(obj, n) \ 1515LISP_INLINE ptrdiff_t
1473 XSAVE_VALUE (obj)->data[(eassert (XSAVE_VALUE (obj)->type \ 1516XSAVE_INTEGER (Lisp_Object obj, int n)
1474 ## n == SAVE_INTEGER), n)].integer 1517{
1518 eassert (save_type (XSAVE_VALUE (obj), n) == SAVE_INTEGER);
1519 return XSAVE_VALUE (obj)->data[n].integer;
1520}
1521LISP_INLINE void
1522set_save_integer (Lisp_Object obj, int n, ptrdiff_t val)
1523{
1524 eassert (save_type (XSAVE_VALUE (obj), n) == SAVE_INTEGER);
1525 XSAVE_VALUE (obj)->data[n].integer = val;
1526}
1475 1527
1476/* Macro to extract Nth saved object. This is never used as 1528/* Extract Nth saved object. */
1477 an lvalue, so we can do more convenient type checking. */
1478 1529
1479#define XSAVE_OBJECT(obj, n) \ 1530LISP_INLINE Lisp_Object
1480 (eassert (XSAVE_VALUE (obj)->type ## n == SAVE_OBJECT), \ 1531XSAVE_OBJECT (Lisp_Object obj, int n)
1481 XSAVE_VALUE (obj)->data[n].object) 1532{
1533 eassert (save_type (XSAVE_VALUE (obj), n) == SAVE_OBJECT);
1534 return XSAVE_VALUE (obj)->data[n].object;
1535}
1482 1536
1483/* A miscellaneous object, when it's on the free list. */ 1537/* A miscellaneous object, when it's on the free list. */
1484struct Lisp_Free 1538struct Lisp_Free
@@ -1501,6 +1555,13 @@ union Lisp_Misc
1501 struct Lisp_Save_Value u_save_value; 1555 struct Lisp_Save_Value u_save_value;
1502 }; 1556 };
1503 1557
1558LISP_INLINE struct Lisp_Save_Value *
1559XSAVE_VALUE (Lisp_Object a)
1560{
1561 eassert (SAVE_VALUEP (a));
1562 return & XMISC (a)->u_save_value;
1563}
1564
1504/* Forwarding pointer to an int variable. 1565/* Forwarding pointer to an int variable.
1505 This is allowed only in the value cell of a symbol, 1566 This is allowed only in the value cell of a symbol,
1506 and it means that the symbol's value really lives in the 1567 and it means that the symbol's value really lives in the
@@ -1786,7 +1847,12 @@ typedef struct {
1786#define VECTORP(x) (VECTORLIKEP (x) && !(ASIZE (x) & PSEUDOVECTOR_FLAG)) 1847#define VECTORP(x) (VECTORLIKEP (x) && !(ASIZE (x) & PSEUDOVECTOR_FLAG))
1787#define OVERLAYP(x) (MISCP (x) && XMISCTYPE (x) == Lisp_Misc_Overlay) 1848#define OVERLAYP(x) (MISCP (x) && XMISCTYPE (x) == Lisp_Misc_Overlay)
1788#define MARKERP(x) (MISCP (x) && XMISCTYPE (x) == Lisp_Misc_Marker) 1849#define MARKERP(x) (MISCP (x) && XMISCTYPE (x) == Lisp_Misc_Marker)
1789#define SAVE_VALUEP(x) (MISCP (x) && XMISCTYPE (x) == Lisp_Misc_Save_Value) 1850
1851LISP_INLINE bool
1852SAVE_VALUEP (Lisp_Object x)
1853{
1854 return MISCP (x) && XMISCTYPE (x) == Lisp_Misc_Save_Value;
1855}
1790 1856
1791#define AUTOLOADP(x) (CONSP (x) && EQ (Qautoload, XCAR (x))) 1857#define AUTOLOADP(x) (CONSP (x) && EQ (Qautoload, XCAR (x)))
1792 1858
@@ -3105,7 +3171,7 @@ extern bool abort_on_gc;
3105extern Lisp_Object make_float (double); 3171extern Lisp_Object make_float (double);
3106extern void display_malloc_warning (void); 3172extern void display_malloc_warning (void);
3107extern ptrdiff_t inhibit_garbage_collection (void); 3173extern ptrdiff_t inhibit_garbage_collection (void);
3108extern Lisp_Object make_save_value (const char *, ...); 3174extern Lisp_Object make_save_value (enum Lisp_Save_Type, ...);
3109extern Lisp_Object make_save_pointer (void *); 3175extern Lisp_Object make_save_pointer (void *);
3110extern Lisp_Object build_overlay (Lisp_Object, Lisp_Object, Lisp_Object); 3176extern Lisp_Object build_overlay (Lisp_Object, Lisp_Object, Lisp_Object);
3111extern void free_marker (Lisp_Object); 3177extern void free_marker (Lisp_Object);
@@ -3822,8 +3888,7 @@ extern void *record_xmalloc (size_t);
3822 { \ 3888 { \
3823 Lisp_Object arg_; \ 3889 Lisp_Object arg_; \
3824 buf = xmalloc ((nelt) * word_size); \ 3890 buf = xmalloc ((nelt) * word_size); \
3825 arg_ = make_save_value ("pi", buf, nelt); \ 3891 arg_ = make_save_value (SAVE_TYPE_MEMORY, buf, nelt); \
3826 XSAVE_VALUE (arg_)->area = 1; \
3827 sa_must_free = 1; \ 3892 sa_must_free = 1; \
3828 record_unwind_protect (safe_alloca_unwind, arg_); \ 3893 record_unwind_protect (safe_alloca_unwind, arg_); \
3829 } \ 3894 } \
diff --git a/src/print.c b/src/print.c
index 53c0d99f836..4ab80fe1605 100644
--- a/src/print.c
+++ b/src/print.c
@@ -2042,17 +2042,15 @@ print_object (Lisp_Object obj, Lisp_Object printcharfun, bool escapeflag)
2042 2042
2043 strout ("#<save-value ", -1, -1, printcharfun); 2043 strout ("#<save-value ", -1, -1, printcharfun);
2044 2044
2045 if (v->area) 2045 if (v->save_type == SAVE_TYPE_MEMORY)
2046 { 2046 {
2047 ptrdiff_t amount = v->data[1].integer; 2047 ptrdiff_t amount = v->data[1].integer;
2048 2048
2049#if GC_MARK_STACK 2049#if GC_MARK_STACK
2050 2050
2051 /* If GC_MARK_STACK, valid_lisp_object_p is quite reliable, 2051 /* valid_lisp_object_p is reliable, so try to print up
2052 and so we try to print up to 8 objects we have saved. 2052 to 8 saved objects. This code is rarely used, so
2053 Although valid_lisp_object_p is slow, this shouldn't be 2053 it's OK that valid_lisp_object_p is slow. */
2054 a real bottleneck because we do not use this code under
2055 normal circumstances. */
2056 2054
2057 int limit = min (amount, 8); 2055 int limit = min (amount, 8);
2058 Lisp_Object *area = v->data[0].pointer; 2056 Lisp_Object *area = v->data[0].pointer;
@@ -2077,9 +2075,8 @@ print_object (Lisp_Object obj, Lisp_Object printcharfun, bool escapeflag)
2077 2075
2078#else /* not GC_MARK_STACK */ 2076#else /* not GC_MARK_STACK */
2079 2077
2080 /* If !GC_MARK_STACK, we have no reliable way to find 2078 /* There is no reliable way to determine whether the objects
2081 whether Lisp_Object pointers points to an initialized 2079 are initialized, so do not try to print them. */
2082 objects, and so we do not ever trying to print them. */
2083 2080
2084 i = sprintf (buf, "with %"pD"d objects", amount); 2081 i = sprintf (buf, "with %"pD"d objects", amount);
2085 strout (buf, i, i, printcharfun); 2082 strout (buf, i, i, printcharfun);
@@ -2088,33 +2085,37 @@ print_object (Lisp_Object obj, Lisp_Object printcharfun, bool escapeflag)
2088 } 2085 }
2089 else 2086 else
2090 { 2087 {
2091 /* Print each `data[N]' slot according to its type. */ 2088 /* Print each slot according to its type. */
2092 2089 int index;
2093#define PRINTX(index) \ 2090 for (index = 0; index < SAVE_VALUE_SLOTS; index++)
2094 do { \ 2091 {
2095 i = 0; \ 2092 if (index)
2096 if (v->type ## index == SAVE_UNUSED) \ 2093 PRINTCHAR (' ');
2097 i = sprintf (buf, "<unused>"); \
2098 else if (v->type ## index == SAVE_INTEGER) \
2099 i = sprintf (buf, "<integer %"pD"d>", v->data[index].integer); \
2100 else if (v->type ## index == SAVE_POINTER) \
2101 i = sprintf (buf, "<pointer %p>", v->data[index].pointer); \
2102 else /* SAVE_OBJECT */ \
2103 print_object (v->data[index].object, printcharfun, escapeflag); \
2104 if (i) \
2105 strout (buf, i, i, printcharfun); \
2106 } while (0)
2107
2108 PRINTX (0);
2109 PRINTCHAR (' ');
2110 PRINTX (1);
2111 PRINTCHAR (' ');
2112 PRINTX (2);
2113 PRINTCHAR (' ');
2114 PRINTX (3);
2115 2094
2116#undef PRINTX 2095 switch (save_type (v, index))
2096 {
2097 case SAVE_UNUSED:
2098 i = sprintf (buf, "<unused>");
2099 break;
2100
2101 case SAVE_POINTER:
2102 i = sprintf (buf, "<pointer %p>",
2103 v->data[index].pointer);
2104 break;
2105
2106 case SAVE_INTEGER:
2107 i = sprintf (buf, "<integer %"pD"d>",
2108 v->data[index].integer);
2109 break;
2110
2111 case SAVE_OBJECT:
2112 print_object (v->data[index].object, printcharfun,
2113 escapeflag);
2114 continue;
2115 }
2117 2116
2117 strout (buf, i, i, printcharfun);
2118 }
2118 } 2119 }
2119 PRINTCHAR ('>'); 2120 PRINTCHAR ('>');
2120 } 2121 }
diff --git a/src/xmenu.c b/src/xmenu.c
index 958cd220393..57cf27f955d 100644
--- a/src/xmenu.c
+++ b/src/xmenu.c
@@ -2479,7 +2479,7 @@ xmenu_show (FRAME_PTR f, int x, int y, bool for_click, bool keymaps,
2479#endif 2479#endif
2480 2480
2481 record_unwind_protect (pop_down_menu, 2481 record_unwind_protect (pop_down_menu,
2482 make_save_value ("pp", f, menu)); 2482 make_save_value (SAVE_TYPE_PTR_PTR, f, menu));
2483 2483
2484 /* Help display under X won't work because XMenuActivate contains 2484 /* Help display under X won't work because XMenuActivate contains
2485 a loop that doesn't give Emacs a chance to process it. */ 2485 a loop that doesn't give Emacs a chance to process it. */