aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorDmitry Antipov2013-01-14 13:55:21 +0400
committerDmitry Antipov2013-01-14 13:55:21 +0400
commit73ebd38f16c4799b657e501f188e9f3a3eca7805 (patch)
tree2584576d6931b14b336ac4ed3eb9eb513892da2c /src
parentd6d02e06ee135655b604a12b0c53987988277a16 (diff)
downloademacs-73ebd38f16c4799b657e501f188e9f3a3eca7805.tar.gz
emacs-73ebd38f16c4799b657e501f188e9f3a3eca7805.zip
Make Lisp_Save_Value more versatile storage for up to four objects.
* lisp.h (toplevel): Enumeration to describe types of saved objects. (struct Lisp_Save_Value): New layout. Adjust comments. (XSAVE_POINTER): New macro. (XSAVE_INTEGER): Likewise. (allocate_misc): Add prototype. (free_misc): Likewise. * alloc.c (allocate_misc): Now global. (free_misc): Likewise. Adjust comment. (make_save_value): Use new Lisp_Save_Value layout. Adjust comment. (free_save_value): Likewise. (mark_object): Likewise. * editfns.c (save_excursion_save): Pack everything within Lisp_Save_Value and so avoid xmalloc. (save_excursion_restore): Adjust to match new layout. Use free_misc because we do not allocate extra memory any more. Add eassert. * print.c (print_object): New code to print Lisp_Save_Value. Do not rely on valid_lisp_object_p if !GC_MARK_STACK. Adjust comments. * dired.c, fileio.c, font.c, ftfont.c, gtkutil.c, keymap.c, * lread.c, nsmenu.m, nsterm.h, xfns.c, xmenu.c, xselect.c: Use XSAVE_POINTER and XSAVE_INTEGER where appropriate.
Diffstat (limited to 'src')
-rw-r--r--src/ChangeLog24
-rw-r--r--src/alloc.c59
-rw-r--r--src/dired.c2
-rw-r--r--src/editfns.c51
-rw-r--r--src/fileio.c2
-rw-r--r--src/font.c2
-rw-r--r--src/ftfont.c22
-rw-r--r--src/gtkutil.c3
-rw-r--r--src/keymap.c4
-rw-r--r--src/lisp.h48
-rw-r--r--src/lread.c2
-rw-r--r--src/nsmenu.m3
-rw-r--r--src/nsterm.h4
-rw-r--r--src/print.c73
-rw-r--r--src/xfns.c3
-rw-r--r--src/xmenu.c17
-rw-r--r--src/xselect.c2
17 files changed, 217 insertions, 104 deletions
diff --git a/src/ChangeLog b/src/ChangeLog
index 9096b904171..098d3ae027e 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,3 +1,27 @@
12013-01-14 Dmitry Antipov <dmantipov@yandex.ru>
2
3 Make Lisp_Save_Value more versatile storage for up to four objects.
4 * lisp.h (toplevel): Enumeration to describe types of saved objects.
5 (struct Lisp_Save_Value): New layout. Adjust comments.
6 (XSAVE_POINTER): New macro.
7 (XSAVE_INTEGER): Likewise.
8 (allocate_misc): Add prototype.
9 (free_misc): Likewise.
10 * alloc.c (allocate_misc): Now global.
11 (free_misc): Likewise. Adjust comment.
12 (make_save_value): Use new Lisp_Save_Value layout. Adjust comment.
13 (free_save_value): Likewise.
14 (mark_object): Likewise.
15 * editfns.c (save_excursion_save): Pack everything within
16 Lisp_Save_Value and so avoid xmalloc.
17 (save_excursion_restore): Adjust to match new layout. Use free_misc
18 because we do not allocate extra memory any more. Add eassert.
19 * print.c (print_object): New code to print Lisp_Save_Value. Do not
20 rely on valid_lisp_object_p if !GC_MARK_STACK. Adjust comments.
21 * dired.c, fileio.c, font.c, ftfont.c, gtkutil.c, keymap.c,
22 * lread.c, nsmenu.m, nsterm.h, xfns.c, xmenu.c, xselect.c:
23 Use XSAVE_POINTER and XSAVE_INTEGER where appropriate.
24
12013-01-13 Jan Djärv <jan.h.d@swipnet.se> 252013-01-13 Jan Djärv <jan.h.d@swipnet.se>
2 26
3 * nsfont.m (LCD_SMOOTHING_MARGIN): New define. 27 * nsfont.m (LCD_SMOOTHING_MARGIN): New define.
diff --git a/src/alloc.c b/src/alloc.c
index b147aa20723..c50bb0f32c7 100644
--- a/src/alloc.c
+++ b/src/alloc.c
@@ -219,7 +219,6 @@ static void refill_memory_reserve (void);
219#endif 219#endif
220static void compact_small_strings (void); 220static void compact_small_strings (void);
221static void free_large_strings (void); 221static void free_large_strings (void);
222static void free_misc (Lisp_Object);
223extern Lisp_Object which_symbols (Lisp_Object, EMACS_INT) EXTERNALLY_VISIBLE; 222extern Lisp_Object which_symbols (Lisp_Object, EMACS_INT) EXTERNALLY_VISIBLE;
224 223
225/* When scanning the C stack for live Lisp objects, Emacs keeps track of 224/* When scanning the C stack for live Lisp objects, Emacs keeps track of
@@ -3303,7 +3302,7 @@ static union Lisp_Misc *marker_free_list;
3303 3302
3304/* Return a newly allocated Lisp_Misc object of specified TYPE. */ 3303/* Return a newly allocated Lisp_Misc object of specified TYPE. */
3305 3304
3306static Lisp_Object 3305Lisp_Object
3307allocate_misc (enum Lisp_Misc_Type type) 3306allocate_misc (enum Lisp_Misc_Type type)
3308{ 3307{
3309 Lisp_Object val; 3308 Lisp_Object val;
@@ -3339,9 +3338,9 @@ allocate_misc (enum Lisp_Misc_Type type)
3339 return val; 3338 return val;
3340} 3339}
3341 3340
3342/* Free a Lisp_Misc object */ 3341/* Free a Lisp_Misc object. */
3343 3342
3344static void 3343void
3345free_misc (Lisp_Object misc) 3344free_misc (Lisp_Object misc)
3346{ 3345{
3347 XMISCTYPE (misc) = Lisp_Misc_Free; 3346 XMISCTYPE (misc) = Lisp_Misc_Free;
@@ -3351,9 +3350,10 @@ free_misc (Lisp_Object misc)
3351 total_free_markers++; 3350 total_free_markers++;
3352} 3351}
3353 3352
3354/* Return a Lisp_Misc_Save_Value object containing POINTER and 3353/* Return a Lisp_Save_Value object containing POINTER and INTEGER.
3355 INTEGER. This is used to package C values to call record_unwind_protect. 3354 Most code should use this to package C integers and pointers
3356 The unwind function can get the C values back using XSAVE_VALUE. */ 3355 to call record_unwind_protect. The unwind function can get the
3356 C values back using XSAVE_POINTER and XSAVE_INTEGER. */
3357 3357
3358Lisp_Object 3358Lisp_Object
3359make_save_value (void *pointer, ptrdiff_t integer) 3359make_save_value (void *pointer, ptrdiff_t integer)
@@ -3363,22 +3363,22 @@ make_save_value (void *pointer, ptrdiff_t integer)
3363 3363
3364 val = allocate_misc (Lisp_Misc_Save_Value); 3364 val = allocate_misc (Lisp_Misc_Save_Value);
3365 p = XSAVE_VALUE (val); 3365 p = XSAVE_VALUE (val);
3366 p->pointer = pointer; 3366 p->type0 = SAVE_POINTER;
3367 p->integer = integer; 3367 p->data[0].pointer = pointer;
3368 p->dogc = 0; 3368 p->type1 = SAVE_INTEGER;
3369 p->data[1].integer = integer;
3370 p->type2 = p->type3 = SAVE_UNUSED;
3371 p->area = 0;
3369 return val; 3372 return val;
3370} 3373}
3371 3374
3372/* Free a Lisp_Misc_Save_Value object. */ 3375/* Free a Lisp_Save_Value object. Do not use this function
3376 if SAVE contains pointer other than returned by xmalloc. */
3373 3377
3374void 3378void
3375free_save_value (Lisp_Object save) 3379free_save_value (Lisp_Object save)
3376{ 3380{
3377 register struct Lisp_Save_Value *p = XSAVE_VALUE (save); 3381 xfree (XSAVE_POINTER (save));
3378
3379 p->dogc = 0;
3380 xfree (p->pointer);
3381 p->pointer = NULL;
3382 free_misc (save); 3382 free_misc (save);
3383} 3383}
3384 3384
@@ -5935,20 +5935,33 @@ mark_object (Lisp_Object arg)
5935 5935
5936 case Lisp_Misc_Save_Value: 5936 case Lisp_Misc_Save_Value:
5937 XMISCANY (obj)->gcmarkbit = 1; 5937 XMISCANY (obj)->gcmarkbit = 1;
5938#if GC_MARK_STACK
5939 { 5938 {
5940 register struct Lisp_Save_Value *ptr = XSAVE_VALUE (obj); 5939 register struct Lisp_Save_Value *ptr = XSAVE_VALUE (obj);
5941 /* If DOGC is set, POINTER is the address of a memory 5940 /* If `area' is nonzero, `data[0].pointer' is the address
5942 area containing INTEGER potential Lisp_Objects. */ 5941 of a memory area containing `data[1].integer' potential
5943 if (ptr->dogc) 5942 Lisp_Objects. */
5943#if GC_MARK_STACK
5944 if (ptr->area)
5944 { 5945 {
5945 Lisp_Object *p = (Lisp_Object *) ptr->pointer; 5946 Lisp_Object *p = (Lisp_Object *) ptr->data[0].pointer;
5946 ptrdiff_t nelt; 5947 ptrdiff_t nelt;
5947 for (nelt = ptr->integer; nelt > 0; nelt--, p++) 5948 for (nelt = ptr->data[1].integer; nelt > 0; nelt--, p++)
5948 mark_maybe_object (*p); 5949 mark_maybe_object (*p);
5949 } 5950 }
5951 else
5952#endif /* GC_MARK_STACK */
5953 {
5954 /* Find Lisp_Objects in `data[N]' slots and mark them. */
5955 if (ptr->type0 == SAVE_OBJECT)
5956 mark_object (ptr->data[0].object);
5957 if (ptr->type1 == SAVE_OBJECT)
5958 mark_object (ptr->data[1].object);
5959 if (ptr->type2 == SAVE_OBJECT)
5960 mark_object (ptr->data[2].object);
5961 if (ptr->type3 == SAVE_OBJECT)
5962 mark_object (ptr->data[3].object);
5963 }
5950 } 5964 }
5951#endif
5952 break; 5965 break;
5953 5966
5954 case Lisp_Misc_Overlay: 5967 case Lisp_Misc_Overlay:
diff --git a/src/dired.c b/src/dired.c
index b4dc702112e..77e89c6e6b3 100644
--- a/src/dired.c
+++ b/src/dired.c
@@ -78,7 +78,7 @@ directory_files_internal_w32_unwind (Lisp_Object arg)
78static Lisp_Object 78static Lisp_Object
79directory_files_internal_unwind (Lisp_Object dh) 79directory_files_internal_unwind (Lisp_Object dh)
80{ 80{
81 DIR *d = (DIR *) XSAVE_VALUE (dh)->pointer; 81 DIR *d = (DIR *) XSAVE_POINTER (dh);
82 block_input (); 82 block_input ();
83 closedir (d); 83 closedir (d);
84 unblock_input (); 84 unblock_input ();
diff --git a/src/editfns.c b/src/editfns.c
index bf19acb42a8..feac17f64b8 100644
--- a/src/editfns.c
+++ b/src/editfns.c
@@ -833,20 +833,30 @@ This function does not move point. */)
833Lisp_Object 833Lisp_Object
834save_excursion_save (void) 834save_excursion_save (void)
835{ 835{
836 Lisp_Object save, *data = xmalloc (word_size * 4); 836 Lisp_Object save = allocate_misc (Lisp_Misc_Save_Value);
837 register struct Lisp_Save_Value *v = XSAVE_VALUE (save);
838
839 /* Do not allocate extra space and pack everything in SAVE. */
840 v->area = 0;
841
842 v->type0 = SAVE_OBJECT;
843 v->data[0].object = Fpoint_marker ();
837 844
838 data[0] = Fpoint_marker ();
839 /* Do not copy the mark if it points to nowhere. */ 845 /* Do not copy the mark if it points to nowhere. */
840 data[1] = (XMARKER (BVAR (current_buffer, mark))->buffer 846 v->type1 = SAVE_OBJECT;
841 ? Fcopy_marker (BVAR (current_buffer, mark), Qnil) 847 v->data[1].object = (XMARKER (BVAR (current_buffer, mark))->buffer
842 : Qnil); 848 ? Fcopy_marker (BVAR (current_buffer, mark), Qnil)
849 : Qnil);
850
843 /* Selected window if current buffer is shown in it, nil otherwise. */ 851 /* Selected window if current buffer is shown in it, nil otherwise. */
844 data[2] = ((XBUFFER (XWINDOW (selected_window)->buffer) == current_buffer) 852 v->type2 = SAVE_OBJECT;
845 ? selected_window : Qnil); 853 v->data[2].object
846 data[3] = BVAR (current_buffer, mark_active); 854 = ((XBUFFER (XWINDOW (selected_window)->buffer) == current_buffer)
855 ? selected_window : Qnil);
856
857 v->type3 = SAVE_OBJECT;
858 v->data[3].object = BVAR (current_buffer, mark_active);
847 859
848 save = make_save_value (data, 4);
849 XSAVE_VALUE (save)->dogc = 1;
850 return save; 860 return save;
851} 861}
852 862
@@ -855,10 +865,15 @@ save_excursion_save (void)
855Lisp_Object 865Lisp_Object
856save_excursion_restore (Lisp_Object info) 866save_excursion_restore (Lisp_Object info)
857{ 867{
858 Lisp_Object tem, tem1, omark, nmark, *data = XSAVE_VALUE (info)->pointer; 868 Lisp_Object tem, tem1, omark, nmark;
859 struct gcpro gcpro1, gcpro2, gcpro3; 869 struct gcpro gcpro1, gcpro2, gcpro3;
870 register struct Lisp_Save_Value *v = XSAVE_VALUE (info);
871
872 /* Paranoid. */
873 eassert (v->type0 == SAVE_OBJECT && v->type1 == SAVE_OBJECT
874 && v->type2 == SAVE_OBJECT && v->type3 == SAVE_OBJECT);
860 875
861 tem = Fmarker_buffer (data[0]); 876 tem = Fmarker_buffer (v->data[0].object);
862 /* If we're unwinding to top level, saved buffer may be deleted. This 877 /* If we're unwinding to top level, saved buffer may be deleted. This
863 means that all of its markers are unchained and so tem is nil. */ 878 means that all of its markers are unchained and so tem is nil. */
864 if (NILP (tem)) 879 if (NILP (tem))
@@ -870,12 +885,12 @@ save_excursion_restore (Lisp_Object info)
870 Fset_buffer (tem); 885 Fset_buffer (tem);
871 886
872 /* Point marker. */ 887 /* Point marker. */
873 tem = data[0]; 888 tem = v->data[0].object;
874 Fgoto_char (tem); 889 Fgoto_char (tem);
875 unchain_marker (XMARKER (tem)); 890 unchain_marker (XMARKER (tem));
876 891
877 /* Mark marker. */ 892 /* Mark marker. */
878 tem = data[1]; 893 tem = v->data[1].object;
879 omark = Fmarker_position (BVAR (current_buffer, mark)); 894 omark = Fmarker_position (BVAR (current_buffer, mark));
880 if (NILP (tem)) 895 if (NILP (tem))
881 unchain_marker (XMARKER (BVAR (current_buffer, mark))); 896 unchain_marker (XMARKER (BVAR (current_buffer, mark)));
@@ -887,7 +902,7 @@ save_excursion_restore (Lisp_Object info)
887 } 902 }
888 903
889 /* Mark active. */ 904 /* Mark active. */
890 tem = data[3]; 905 tem = v->data[3].object;
891 tem1 = BVAR (current_buffer, mark_active); 906 tem1 = BVAR (current_buffer, mark_active);
892 bset_mark_active (current_buffer, tem); 907 bset_mark_active (current_buffer, tem);
893 908
@@ -911,7 +926,7 @@ save_excursion_restore (Lisp_Object info)
911 /* If buffer was visible in a window, and a different window was 926 /* If buffer was visible in a window, and a different window was
912 selected, and the old selected window is still showing this 927 selected, and the old selected window is still showing this
913 buffer, restore point in that window. */ 928 buffer, restore point in that window. */
914 tem = data[2]; 929 tem = v->data[2].object;
915 if (WINDOWP (tem) 930 if (WINDOWP (tem)
916 && !EQ (tem, selected_window) 931 && !EQ (tem, selected_window)
917 && (tem1 = XWINDOW (tem)->buffer, 932 && (tem1 = XWINDOW (tem)->buffer,
@@ -925,7 +940,7 @@ save_excursion_restore (Lisp_Object info)
925 940
926 out: 941 out:
927 942
928 free_save_value (info); 943 free_misc (info);
929 return Qnil; 944 return Qnil;
930} 945}
931 946
@@ -4258,7 +4273,7 @@ usage: (format STRING &rest OBJECTS) */)
4258 memcpy (buf, initial_buffer, used); 4273 memcpy (buf, initial_buffer, used);
4259 } 4274 }
4260 else 4275 else
4261 XSAVE_VALUE (buf_save_value)->pointer = buf = xrealloc (buf, bufsize); 4276 XSAVE_POINTER (buf_save_value) = buf = xrealloc (buf, bufsize);
4262 4277
4263 p = buf + used; 4278 p = buf + used;
4264 } 4279 }
diff --git a/src/fileio.c b/src/fileio.c
index 5e9b36ee44a..67b4b884bc0 100644
--- a/src/fileio.c
+++ b/src/fileio.c
@@ -5507,7 +5507,7 @@ static Lisp_Object
5507do_auto_save_unwind (Lisp_Object arg) /* used as unwind-protect function */ 5507do_auto_save_unwind (Lisp_Object arg) /* used as unwind-protect function */
5508 5508
5509{ 5509{
5510 FILE *stream = (FILE *) XSAVE_VALUE (arg)->pointer; 5510 FILE *stream = (FILE *) XSAVE_POINTER (arg);
5511 auto_saving = 0; 5511 auto_saving = 0;
5512 if (stream != NULL) 5512 if (stream != NULL)
5513 { 5513 {
diff --git a/src/font.c b/src/font.c
index a3a41006f9b..c4153428147 100644
--- a/src/font.c
+++ b/src/font.c
@@ -1857,7 +1857,7 @@ otf_open (Lisp_Object file)
1857 OTF *otf; 1857 OTF *otf;
1858 1858
1859 if (! NILP (val)) 1859 if (! NILP (val))
1860 otf = XSAVE_VALUE (XCDR (val))->pointer; 1860 otf = XSAVE_POINTER (XCDR (val));
1861 else 1861 else
1862 { 1862 {
1863 otf = STRINGP (file) ? OTF_open (SSDATA (file)) : NULL; 1863 otf = STRINGP (file) ? OTF_open (SSDATA (file)) : NULL;
diff --git a/src/ftfont.c b/src/ftfont.c
index 1ada95d377c..1d7678bfe09 100644
--- a/src/ftfont.c
+++ b/src/ftfont.c
@@ -393,16 +393,14 @@ 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 (NULL, 0); 396 val = make_save_value (cache_data, 0);
397 XSAVE_VALUE (val)->integer = 0;
398 XSAVE_VALUE (val)->pointer = cache_data;
399 cache = Fcons (Qnil, val); 397 cache = Fcons (Qnil, val);
400 Fputhash (key, cache, ft_face_cache); 398 Fputhash (key, cache, ft_face_cache);
401 } 399 }
402 else 400 else
403 { 401 {
404 val = XCDR (cache); 402 val = XCDR (cache);
405 cache_data = XSAVE_VALUE (val)->pointer; 403 cache_data = XSAVE_POINTER (val);
406 } 404 }
407 405
408 if (cache_for == FTFONT_CACHE_FOR_ENTITY) 406 if (cache_for == FTFONT_CACHE_FOR_ENTITY)
@@ -468,7 +466,7 @@ ftfont_get_fc_charset (Lisp_Object entity)
468 466
469 cache = ftfont_lookup_cache (entity, FTFONT_CACHE_FOR_CHARSET); 467 cache = ftfont_lookup_cache (entity, FTFONT_CACHE_FOR_CHARSET);
470 val = XCDR (cache); 468 val = XCDR (cache);
471 cache_data = XSAVE_VALUE (val)->pointer; 469 cache_data = XSAVE_POINTER (val);
472 return cache_data->fc_charset; 470 return cache_data->fc_charset;
473} 471}
474 472
@@ -1200,9 +1198,9 @@ ftfont_open (FRAME_PTR f, Lisp_Object entity, int pixel_size)
1200 filename = XCAR (val); 1198 filename = XCAR (val);
1201 idx = XCDR (val); 1199 idx = XCDR (val);
1202 val = XCDR (cache); 1200 val = XCDR (cache);
1203 cache_data = XSAVE_VALUE (XCDR (cache))->pointer; 1201 cache_data = XSAVE_POINTER (XCDR (cache));
1204 ft_face = cache_data->ft_face; 1202 ft_face = cache_data->ft_face;
1205 if (XSAVE_VALUE (val)->integer > 0) 1203 if (XSAVE_INTEGER (val) > 0)
1206 { 1204 {
1207 /* FT_Face in this cache is already used by the different size. */ 1205 /* FT_Face in this cache is already used by the different size. */
1208 if (FT_New_Size (ft_face, &ft_size) != 0) 1206 if (FT_New_Size (ft_face, &ft_size) != 0)
@@ -1213,13 +1211,13 @@ ftfont_open (FRAME_PTR f, Lisp_Object entity, int pixel_size)
1213 return Qnil; 1211 return Qnil;
1214 } 1212 }
1215 } 1213 }
1216 XSAVE_VALUE (val)->integer++; 1214 XSAVE_INTEGER (val)++;
1217 size = XINT (AREF (entity, FONT_SIZE_INDEX)); 1215 size = XINT (AREF (entity, FONT_SIZE_INDEX));
1218 if (size == 0) 1216 if (size == 0)
1219 size = pixel_size; 1217 size = pixel_size;
1220 if (FT_Set_Pixel_Sizes (ft_face, size, size) != 0) 1218 if (FT_Set_Pixel_Sizes (ft_face, size, size) != 0)
1221 { 1219 {
1222 if (XSAVE_VALUE (val)->integer == 0) 1220 if (XSAVE_INTEGER (val) == 0)
1223 FT_Done_Face (ft_face); 1221 FT_Done_Face (ft_face);
1224 return Qnil; 1222 return Qnil;
1225 } 1223 }
@@ -1328,10 +1326,10 @@ ftfont_close (FRAME_PTR f, struct font *font)
1328 cache = ftfont_lookup_cache (val, FTFONT_CACHE_FOR_FACE); 1326 cache = ftfont_lookup_cache (val, FTFONT_CACHE_FOR_FACE);
1329 eassert (CONSP (cache)); 1327 eassert (CONSP (cache));
1330 val = XCDR (cache); 1328 val = XCDR (cache);
1331 (XSAVE_VALUE (val)->integer)--; 1329 (XSAVE_INTEGER (val))--;
1332 if (XSAVE_VALUE (val)->integer == 0) 1330 if (XSAVE_INTEGER (val) == 0)
1333 { 1331 {
1334 struct ftfont_cache_data *cache_data = XSAVE_VALUE (val)->pointer; 1332 struct ftfont_cache_data *cache_data = XSAVE_POINTER (val);
1335 1333
1336 FT_Done_Face (cache_data->ft_face); 1334 FT_Done_Face (cache_data->ft_face);
1337#ifdef HAVE_LIBOTF 1335#ifdef HAVE_LIBOTF
diff --git a/src/gtkutil.c b/src/gtkutil.c
index af845f69e62..3b1bbc73cff 100644
--- a/src/gtkutil.c
+++ b/src/gtkutil.c
@@ -1650,8 +1650,7 @@ xg_dialog_response_cb (GtkDialog *w,
1650static Lisp_Object 1650static Lisp_Object
1651pop_down_dialog (Lisp_Object arg) 1651pop_down_dialog (Lisp_Object arg)
1652{ 1652{
1653 struct Lisp_Save_Value *p = XSAVE_VALUE (arg); 1653 struct xg_dialog_data *dd = (struct xg_dialog_data *) XSAVE_POINTER (arg);
1654 struct xg_dialog_data *dd = (struct xg_dialog_data *) p->pointer;
1655 1654
1656 block_input (); 1655 block_input ();
1657 if (dd->w) gtk_widget_destroy (dd->w); 1656 if (dd->w) gtk_widget_destroy (dd->w);
diff --git a/src/keymap.c b/src/keymap.c
index d1ddd55a358..7b5aa45ebf3 100644
--- a/src/keymap.c
+++ b/src/keymap.c
@@ -566,14 +566,14 @@ map_keymap_char_table_item (Lisp_Object args, Lisp_Object key, Lisp_Object val)
566 if (!NILP (val)) 566 if (!NILP (val))
567 { 567 {
568 map_keymap_function_t fun 568 map_keymap_function_t fun
569 = (map_keymap_function_t) XSAVE_VALUE (XCAR (args))->pointer; 569 = (map_keymap_function_t) XSAVE_POINTER (XCAR (args));
570 args = XCDR (args); 570 args = XCDR (args);
571 /* If the key is a range, make a copy since map_char_table modifies 571 /* If the key is a range, make a copy since map_char_table modifies
572 it in place. */ 572 it in place. */
573 if (CONSP (key)) 573 if (CONSP (key))
574 key = Fcons (XCAR (key), XCDR (key)); 574 key = Fcons (XCAR (key), XCDR (key));
575 map_keymap_item (fun, XCDR (args), key, val, 575 map_keymap_item (fun, XCDR (args), key, val,
576 XSAVE_VALUE (XCAR (args))->pointer); 576 XSAVE_POINTER (XCAR (args)));
577 } 577 }
578} 578}
579 579
diff --git a/src/lisp.h b/src/lisp.h
index 3b7af46fdde..39e12835d98 100644
--- a/src/lisp.h
+++ b/src/lisp.h
@@ -1378,20 +1378,48 @@ struct Lisp_Overlay
1378 Lisp_Object plist; 1378 Lisp_Object plist;
1379 }; 1379 };
1380 1380
1381/* Hold a C pointer for later use. 1381/* Types of data which may be saved in a Lisp_Save_Value. */
1382 This type of object is used in the arg to record_unwind_protect. */ 1382
1383enum
1384 {
1385 SAVE_UNUSED,
1386 SAVE_INTEGER,
1387 SAVE_POINTER,
1388 SAVE_OBJECT
1389 };
1390
1391/* Special object used to hold a different values for later use. */
1392
1383struct Lisp_Save_Value 1393struct Lisp_Save_Value
1384 { 1394 {
1385 ENUM_BF (Lisp_Misc_Type) type : 16; /* = Lisp_Misc_Save_Value */ 1395 ENUM_BF (Lisp_Misc_Type) type : 16; /* = Lisp_Misc_Save_Value */
1386 unsigned gcmarkbit : 1; 1396 unsigned gcmarkbit : 1;
1387 int spacer : 14; 1397 int spacer : 6;
1388 /* If DOGC is set, POINTER is the address of a memory 1398 /* If `area' is nonzero, `data[0].pointer' is the address of a memory area
1389 area containing INTEGER potential Lisp_Objects. */ 1399 containing `data[1].integer' potential Lisp_Objects. The rest of `data'
1390 unsigned int dogc : 1; 1400 fields are unused. */
1391 void *pointer; 1401 unsigned area : 1;
1392 ptrdiff_t integer; 1402 /* If `area' is zero, `data[N]' may hold different objects which type is
1403 encoded in `typeN' fields as described by the anonymous enum above.
1404 E.g. if `type0' is SAVE_INTEGER, `data[0].integer' is in use. */
1405 unsigned type0 : 2;
1406 unsigned type1 : 2;
1407 unsigned type2 : 2;
1408 unsigned type3 : 2;
1409 union {
1410 void *pointer;
1411 ptrdiff_t integer;
1412 Lisp_Object object;
1413 } data[4];
1393 }; 1414 };
1394 1415
1416/* Compatibility macro to set and extract saved pointer. */
1417
1418#define XSAVE_POINTER(obj) XSAVE_VALUE (obj)->data[0].pointer
1419
1420/* Likewise for the saved ingeger. */
1421
1422#define XSAVE_INTEGER(obj) XSAVE_VALUE (obj)->data[1].integer
1395 1423
1396/* A miscellaneous object, when it's on the free list. */ 1424/* A miscellaneous object, when it's on the free list. */
1397struct Lisp_Free 1425struct Lisp_Free
@@ -2893,6 +2921,8 @@ extern void memory_warnings (void *, void (*warnfun) (const char *));
2893 2921
2894/* Defined in alloc.c. */ 2922/* Defined in alloc.c. */
2895extern void check_pure_size (void); 2923extern void check_pure_size (void);
2924extern Lisp_Object allocate_misc (enum Lisp_Misc_Type);
2925extern void free_misc (Lisp_Object);
2896extern void allocate_string_data (struct Lisp_String *, EMACS_INT, EMACS_INT); 2926extern void allocate_string_data (struct Lisp_String *, EMACS_INT, EMACS_INT);
2897extern void malloc_warning (const char *); 2927extern void malloc_warning (const char *);
2898extern _Noreturn void memory_full (size_t); 2928extern _Noreturn void memory_full (size_t);
@@ -3695,7 +3725,7 @@ extern void *record_xmalloc (size_t);
3695 Lisp_Object arg_; \ 3725 Lisp_Object arg_; \
3696 buf = xmalloc ((nelt) * word_size); \ 3726 buf = xmalloc ((nelt) * word_size); \
3697 arg_ = make_save_value (buf, nelt); \ 3727 arg_ = make_save_value (buf, nelt); \
3698 XSAVE_VALUE (arg_)->dogc = 1; \ 3728 XSAVE_VALUE (arg_)->area = 1; \
3699 sa_must_free = 1; \ 3729 sa_must_free = 1; \
3700 record_unwind_protect (safe_alloca_unwind, arg_); \ 3730 record_unwind_protect (safe_alloca_unwind, arg_); \
3701 } \ 3731 } \
diff --git a/src/lread.c b/src/lread.c
index 2b96dc16359..35b61cbad4d 100644
--- a/src/lread.c
+++ b/src/lread.c
@@ -1357,7 +1357,7 @@ Return t if the file exists and loads successfully. */)
1357static Lisp_Object 1357static Lisp_Object
1358load_unwind (Lisp_Object arg) /* Used as unwind-protect function in load. */ 1358load_unwind (Lisp_Object arg) /* Used as unwind-protect function in load. */
1359{ 1359{
1360 FILE *stream = (FILE *) XSAVE_VALUE (arg)->pointer; 1360 FILE *stream = (FILE *) XSAVE_POINTER (arg);
1361 if (stream != NULL) 1361 if (stream != NULL)
1362 { 1362 {
1363 block_input (); 1363 block_input ();
diff --git a/src/nsmenu.m b/src/nsmenu.m
index 39797d414f0..4e81b3201c8 100644
--- a/src/nsmenu.m
+++ b/src/nsmenu.m
@@ -1347,8 +1347,7 @@ struct Popdown_data
1347static Lisp_Object 1347static Lisp_Object
1348pop_down_menu (Lisp_Object arg) 1348pop_down_menu (Lisp_Object arg)
1349{ 1349{
1350 struct Lisp_Save_Value *p = XSAVE_VALUE (arg); 1350 struct Popdown_data *unwind_data = (struct Popdown_data *) XSAVE_POINTER (arg);
1351 struct Popdown_data *unwind_data = (struct Popdown_data *) p->pointer;
1352 1351
1353 block_input (); 1352 block_input ();
1354 if (popup_activated_flag) 1353 if (popup_activated_flag)
diff --git a/src/nsterm.h b/src/nsterm.h
index e58b8493c94..7732e6d27cc 100644
--- a/src/nsterm.h
+++ b/src/nsterm.h
@@ -675,9 +675,9 @@ struct x_output
675#define FRAME_FONT(f) ((f)->output_data.ns->font) 675#define FRAME_FONT(f) ((f)->output_data.ns->font)
676 676
677#ifdef __OBJC__ 677#ifdef __OBJC__
678#define XNS_SCROLL_BAR(vec) ((id) XSAVE_VALUE (vec)->pointer) 678#define XNS_SCROLL_BAR(vec) ((id) XSAVE_POINTER (vec))
679#else 679#else
680#define XNS_SCROLL_BAR(vec) XSAVE_VALUE (vec)->pointer 680#define XNS_SCROLL_BAR(vec) XSAVE_POINTER (vec)
681#endif 681#endif
682 682
683/* Compute pixel size for vertical scroll bars */ 683/* Compute pixel size for vertical scroll bars */
diff --git a/src/print.c b/src/print.c
index e87bbcce0e7..0ae83cdf6d2 100644
--- a/src/print.c
+++ b/src/print.c
@@ -2027,8 +2027,9 @@ print_object (Lisp_Object obj, register Lisp_Object printcharfun, int escapeflag
2027 PRINTCHAR ('>'); 2027 PRINTCHAR ('>');
2028 break; 2028 break;
2029 2029
2030 /* Remaining cases shouldn't happen in normal usage, but let's print 2030 /* Remaining cases shouldn't happen in normal usage, but let's
2031 them anyway for the benefit of the debugger. */ 2031 print them anyway for the benefit of the debugger. */
2032
2032 case Lisp_Misc_Free: 2033 case Lisp_Misc_Free:
2033 strout ("#<misc free cell>", -1, -1, printcharfun); 2034 strout ("#<misc free cell>", -1, -1, printcharfun);
2034 break; 2035 break;
@@ -2039,20 +2040,28 @@ print_object (Lisp_Object obj, register Lisp_Object printcharfun, int escapeflag
2039 struct Lisp_Save_Value *v = XSAVE_VALUE (obj); 2040 struct Lisp_Save_Value *v = XSAVE_VALUE (obj);
2040 2041
2041 strout ("#<save-value ", -1, -1, printcharfun); 2042 strout ("#<save-value ", -1, -1, printcharfun);
2042 if (v->dogc) 2043
2044 if (v->area)
2043 { 2045 {
2044 int lim = min (v->integer, 8); 2046 ptrdiff_t amount = v->data[1].integer;
2045 2047
2046 /* Try to print up to 8 objects we have saved. Although 2048#if GC_MARK_STACK
2047 valid_lisp_object_p is slow, this shouldn't be a real 2049
2048 bottleneck because such a saved values are quite rare. */ 2050 /* If GC_MARK_STACK, valid_lisp_object_p is quite reliable,
2051 and so we try to print up to 8 objects we have saved.
2052 Although valid_lisp_object_p is slow, this shouldn't be
2053 a real bottleneck because we do not use this code under
2054 normal circumstances. */
2049 2055
2050 i = sprintf (buf, "with %"pD"d objects", v->integer); 2056 int limit = min (amount, 8);
2057 Lisp_Object *area = (Lisp_Object *) v->data[0].pointer;
2058
2059 i = sprintf (buf, "with %"pD"d objects", amount);
2051 strout (buf, i, i, printcharfun); 2060 strout (buf, i, i, printcharfun);
2052 2061
2053 for (i = 0; i < lim; i++) 2062 for (i = 0; i < limit; i++)
2054 { 2063 {
2055 Lisp_Object maybe = ((Lisp_Object *) v->pointer)[i]; 2064 Lisp_Object maybe = area[i];
2056 2065
2057 if (valid_lisp_object_p (maybe) > 0) 2066 if (valid_lisp_object_p (maybe) > 0)
2058 { 2067 {
@@ -2062,13 +2071,49 @@ print_object (Lisp_Object obj, register Lisp_Object printcharfun, int escapeflag
2062 else 2071 else
2063 strout (" <invalid>", -1, -1, printcharfun); 2072 strout (" <invalid>", -1, -1, printcharfun);
2064 } 2073 }
2065 if (i == lim && i < v->integer) 2074 if (i == limit && i < amount)
2066 strout (" ...", 4, 4, printcharfun); 2075 strout (" ...", 4, 4, printcharfun);
2076
2077#else /* not GC_MARK_STACK */
2078
2079 /* If !GC_MARK_STACK, we have no reliable way to find
2080 whether Lisp_Object pointers points to an initialized
2081 objects, and so we do not ever trying to print them. */
2082
2083 i = sprintf (buf, "with %"pD"d objects", amount);
2084 strout (buf, i, i, printcharfun);
2085
2086#endif /* GC_MARK_STACK */
2067 } 2087 }
2068 else 2088 else
2069 { 2089 {
2070 i = sprintf (buf, "ptr=%p int=%"pD"d", v->pointer, v->integer); 2090 /* Print each `data[N]' slot according to its type. */
2071 strout (buf, i, i, printcharfun); 2091
2092#define PRINTX(index) \
2093 do { \
2094 i = 0; \
2095 if (v->type ## index == SAVE_UNUSED) \
2096 i = sprintf (buf, "<unused>"); \
2097 else if (v->type ## index == SAVE_INTEGER) \
2098 i = sprintf (buf, "<integer %"pD"d>", v->data[index].integer); \
2099 else if (v->type ## index == SAVE_POINTER) \
2100 i = sprintf (buf, "<pointer %p>", v->data[index].pointer); \
2101 else /* SAVE_OBJECT */ \
2102 print_object (v->data[index].object, printcharfun, escapeflag); \
2103 if (i) \
2104 strout (buf, i, i, printcharfun); \
2105 } while (0)
2106
2107 PRINTX (0);
2108 PRINTCHAR (' ');
2109 PRINTX (1);
2110 PRINTCHAR (' ');
2111 PRINTX (2);
2112 PRINTCHAR (' ');
2113 PRINTX (3);
2114
2115#undef PRINTX
2116
2072 } 2117 }
2073 PRINTCHAR ('>'); 2118 PRINTCHAR ('>');
2074 } 2119 }
diff --git a/src/xfns.c b/src/xfns.c
index 315d5093716..245ffae3573 100644
--- a/src/xfns.c
+++ b/src/xfns.c
@@ -5292,8 +5292,7 @@ file_dialog_unmap_cb (Widget widget, XtPointer client_data, XtPointer call_data)
5292static Lisp_Object 5292static Lisp_Object
5293clean_up_file_dialog (Lisp_Object arg) 5293clean_up_file_dialog (Lisp_Object arg)
5294{ 5294{
5295 struct Lisp_Save_Value *p = XSAVE_VALUE (arg); 5295 Widget dialog = (Widget) XSAVE_POINTER (arg);
5296 Widget dialog = (Widget) p->pointer;
5297 5296
5298 /* Clean up. */ 5297 /* Clean up. */
5299 block_input (); 5298 block_input ();
diff --git a/src/xmenu.c b/src/xmenu.c
index 3d76070c336..cbb5a3dc77e 100644
--- a/src/xmenu.c
+++ b/src/xmenu.c
@@ -1411,11 +1411,9 @@ popup_selection_callback (GtkWidget *widget, gpointer client_data)
1411static Lisp_Object 1411static Lisp_Object
1412pop_down_menu (Lisp_Object arg) 1412pop_down_menu (Lisp_Object arg)
1413{ 1413{
1414 struct Lisp_Save_Value *p = XSAVE_VALUE (arg);
1415
1416 popup_activated_flag = 0; 1414 popup_activated_flag = 0;
1417 block_input (); 1415 block_input ();
1418 gtk_widget_destroy (GTK_WIDGET (p->pointer)); 1416 gtk_widget_destroy (GTK_WIDGET (XSAVE_POINTER (arg)));
1419 unblock_input (); 1417 unblock_input ();
1420 return Qnil; 1418 return Qnil;
1421} 1419}
@@ -1612,11 +1610,7 @@ create_and_show_popup_menu (FRAME_PTR f, widget_value *first_wv,
1612static Lisp_Object 1610static Lisp_Object
1613cleanup_widget_value_tree (Lisp_Object arg) 1611cleanup_widget_value_tree (Lisp_Object arg)
1614{ 1612{
1615 struct Lisp_Save_Value *p = XSAVE_VALUE (arg); 1613 free_menubar_widget_value_tree ((widget_value *) XSAVE_POINTER (arg));
1616 widget_value *wv = p->pointer;
1617
1618 free_menubar_widget_value_tree (wv);
1619
1620 return Qnil; 1614 return Qnil;
1621} 1615}
1622 1616
@@ -2242,11 +2236,8 @@ menu_help_callback (char const *help_string, int pane, int item)
2242static Lisp_Object 2236static Lisp_Object
2243pop_down_menu (Lisp_Object arg) 2237pop_down_menu (Lisp_Object arg)
2244{ 2238{
2245 struct Lisp_Save_Value *p1 = XSAVE_VALUE (Fcar (arg)); 2239 FRAME_PTR f = XSAVE_POINTER (Fcar (arg));
2246 struct Lisp_Save_Value *p2 = XSAVE_VALUE (Fcdr (arg)); 2240 XMenu *menu = XSAVE_POINTER (Fcdr (arg));
2247
2248 FRAME_PTR f = p1->pointer;
2249 XMenu *menu = p2->pointer;
2250 2241
2251 block_input (); 2242 block_input ();
2252#ifndef MSDOS 2243#ifndef MSDOS
diff --git a/src/xselect.c b/src/xselect.c
index f43efab827b..9abfb2931f8 100644
--- a/src/xselect.c
+++ b/src/xselect.c
@@ -1120,7 +1120,7 @@ unexpect_property_change (struct prop_location *location)
1120static Lisp_Object 1120static Lisp_Object
1121wait_for_property_change_unwind (Lisp_Object loc) 1121wait_for_property_change_unwind (Lisp_Object loc)
1122{ 1122{
1123 struct prop_location *location = XSAVE_VALUE (loc)->pointer; 1123 struct prop_location *location = XSAVE_POINTER (loc);
1124 1124
1125 unexpect_property_change (location); 1125 unexpect_property_change (location);
1126 if (location == property_change_reply_object) 1126 if (location == property_change_reply_object)