aboutsummaryrefslogtreecommitdiffstats
path: root/src/alloc.c
diff options
context:
space:
mode:
authorGerd Moellmann2000-03-27 19:43:47 +0000
committerGerd Moellmann2000-03-27 19:43:47 +0000
commit182ff2422523ba57c925b772c9c564c06a07b3fc (patch)
tree2615d2111e35ca77d99c8f45b661c9a53608a6e9 /src/alloc.c
parent4b3fd719464fb07dc92ac7584bd7584878e0a8c4 (diff)
downloademacs-182ff2422523ba57c925b772c9c564c06a07b3fc.tar.gz
emacs-182ff2422523ba57c925b772c9c564c06a07b3fc.zip
(mark_maybe_object): New function.
(mark_memory): Use it. (SETJMP_WILL_LIKELY_WORK, SETJMP_WILL_NOT_WORK): New macros. (setjmp_tested_p, longjmp_done): New variables. (test_setjmp): New function. (mark_stack) [!GC_SETJMP_WORKS]: Call test_setjmp. (init_alloc): Initialize setjmp_tested_p and longjmp_done.
Diffstat (limited to 'src/alloc.c')
-rw-r--r--src/alloc.c309
1 files changed, 234 insertions, 75 deletions
diff --git a/src/alloc.c b/src/alloc.c
index 3027e08b467..9b82d45a0bf 100644
--- a/src/alloc.c
+++ b/src/alloc.c
@@ -296,6 +296,7 @@ static int live_cons_p P_ ((struct mem_node *, void *));
296static int live_symbol_p P_ ((struct mem_node *, void *)); 296static int live_symbol_p P_ ((struct mem_node *, void *));
297static int live_float_p P_ ((struct mem_node *, void *)); 297static int live_float_p P_ ((struct mem_node *, void *));
298static int live_misc_p P_ ((struct mem_node *, void *)); 298static int live_misc_p P_ ((struct mem_node *, void *));
299static void mark_maybe_object P_ ((Lisp_Object));
299static void mark_memory P_ ((void *, void *)); 300static void mark_memory P_ ((void *, void *));
300static void mem_init P_ ((void)); 301static void mem_init P_ ((void));
301static struct mem_node *mem_insert P_ ((void *, void *, enum mem_type)); 302static struct mem_node *mem_insert P_ ((void *, void *, enum mem_type));
@@ -2823,6 +2824,86 @@ DEFUN ("gc-status", Fgc_status, Sgc_status, 0, 0, "",
2823#endif /* GC_MARK_STACK == GC_USE_GCPROS_CHECK_ZOMBIES */ 2824#endif /* GC_MARK_STACK == GC_USE_GCPROS_CHECK_ZOMBIES */
2824 2825
2825 2826
2827/* Mark OBJ if we can prove it's a Lisp_Object. */
2828
2829static INLINE void
2830mark_maybe_object (obj)
2831 Lisp_Object obj;
2832{
2833 void *po = (void *) XPNTR (obj);
2834 struct mem_node *m = mem_find (po);
2835
2836 if (m != MEM_NIL)
2837 {
2838 int mark_p = 0;
2839
2840 switch (XGCTYPE (obj))
2841 {
2842 case Lisp_String:
2843 mark_p = (live_string_p (m, po)
2844 && !STRING_MARKED_P ((struct Lisp_String *) po));
2845 break;
2846
2847 case Lisp_Cons:
2848 mark_p = (live_cons_p (m, po)
2849 && !XMARKBIT (XCONS (obj)->car));
2850 break;
2851
2852 case Lisp_Symbol:
2853 mark_p = (live_symbol_p (m, po)
2854 && !XMARKBIT (XSYMBOL (obj)->plist));
2855 break;
2856
2857 case Lisp_Float:
2858 mark_p = (live_float_p (m, po)
2859 && !XMARKBIT (XFLOAT (obj)->type));
2860 break;
2861
2862 case Lisp_Vectorlike:
2863 /* Note: can't check GC_BUFFERP before we know it's a
2864 buffer because checking that dereferences the pointer
2865 PO which might point anywhere. */
2866 if (live_vector_p (m, po))
2867 mark_p = (!GC_SUBRP (obj)
2868 && !(XVECTOR (obj)->size & ARRAY_MARK_FLAG));
2869 else if (live_buffer_p (m, po))
2870 mark_p = GC_BUFFERP (obj) && !XMARKBIT (XBUFFER (obj)->name);
2871 break;
2872
2873 case Lisp_Misc:
2874 if (live_misc_p (m, po))
2875 {
2876 switch (XMISCTYPE (obj))
2877 {
2878 case Lisp_Misc_Marker:
2879 mark_p = !XMARKBIT (XMARKER (obj)->chain);
2880 break;
2881
2882 case Lisp_Misc_Buffer_Local_Value:
2883 case Lisp_Misc_Some_Buffer_Local_Value:
2884 mark_p = !XMARKBIT (XBUFFER_LOCAL_VALUE (obj)->realvalue);
2885 break;
2886
2887 case Lisp_Misc_Overlay:
2888 mark_p = !XMARKBIT (XOVERLAY (obj)->plist);
2889 break;
2890 }
2891 }
2892 break;
2893 }
2894
2895 if (mark_p)
2896 {
2897#if GC_MARK_STACK == GC_USE_GCPROS_CHECK_ZOMBIES
2898 if (nzombies < MAX_ZOMBIES)
2899 zombies[nzombies] = *p;
2900 ++nzombies;
2901#endif
2902 mark_object (&obj);
2903 }
2904 }
2905}
2906
2826/* Mark Lisp objects in the address range START..END. */ 2907/* Mark Lisp objects in the address range START..END. */
2827 2908
2828static void 2909static void
@@ -2843,84 +2924,91 @@ mark_memory (start, end)
2843 start = end; 2924 start = end;
2844 end = tem; 2925 end = tem;
2845 } 2926 }
2846 2927
2847 for (p = (Lisp_Object *) start; (void *) p < end; ++p) 2928 for (p = (Lisp_Object *) start; (void *) p < end; ++p)
2929 mark_maybe_object (*p);
2930}
2931
2932
2933#if !defined GC_SAVE_REGISTERS_ON_STACK && !defined GC_SETJMP_WORKS
2934
2935static int setjmp_tested_p, longjmps_done;
2936
2937#define SETJMP_WILL_LIKELY_WORK "\
2938\n\
2939Emacs garbage collector has been changed to use conservative stack\n\
2940marking. Emacs has determined that the method it uses to do the\n\
2941marking will likely work on your system, but this isn't sure.\n\
2942\n\
2943If you are a system-programmer, or can get the help of a local wizard\n\
2944who is, please take a look at the function mark_stack in alloc.c, and\n\
2945verify that the methods used are appropriate for your system.\n\
2946\n\
2947Please mail the result to <gerd@gnu.org>.\n\
2948"
2949
2950#define SETJMP_WILL_NOT_WORK "\
2951\n\
2952Emacs garbage collector has been changed to use conservative stack\n\
2953marking. Emacs has determined that the default method it uses to do the\n\
2954marking will not work on your system. We will need a system-dependent\n\
2955solution for your system.\n\
2956\n\
2957Please take a look at the function mark_stack in alloc.c, and\n\
2958try to find a way to make it work on your system.\n\
2959Please mail the result to <gerd@gnu.org>.\n\
2960"
2961
2962
2963/* Perform a quick check if it looks like setjmp saves registers in a
2964 jmp_buf. Print a message to stderr saying so. When this test
2965 succeeds, this is _not_ a proof that setjmp is sufficient for
2966 conservative stack marking. Only the sources or a disassembly
2967 can prove that. */
2968
2969static void
2970test_setjmp ()
2971{
2972 char buf[10];
2973 register int x;
2974 jmp_buf jbuf;
2975 int result = 0;
2976
2977 /* Arrange for X to be put in a register. */
2978 sprintf (buf, "1");
2979 x = strlen (buf);
2980 x = 2 * x - 1;
2981
2982 setjmp (jbuf);
2983 if (longjmps_done == 1)
2848 { 2984 {
2849 void *po = (void *) XPNTR (*p); 2985 /* Came here after the longjmp at the end of the function.
2850 struct mem_node *m = mem_find (po);
2851
2852 if (m != MEM_NIL)
2853 {
2854 int mark_p = 0;
2855 2986
2856 switch (XGCTYPE (*p)) 2987 If x == 1, the longjmp has restored the register to its
2857 { 2988 value before the setjmp, and we can hope that setjmp
2858 case Lisp_String: 2989 saves all such registers in the jmp_buf, although that
2859 mark_p = (live_string_p (m, po) 2990 isn't sure.
2860 && !STRING_MARKED_P ((struct Lisp_String *) po));
2861 break;
2862
2863 case Lisp_Cons:
2864 mark_p = (live_cons_p (m, po)
2865 && !XMARKBIT (XCONS (*p)->car));
2866 break;
2867
2868 case Lisp_Symbol:
2869 mark_p = (live_symbol_p (m, po)
2870 && !XMARKBIT (XSYMBOL (*p)->plist));
2871 break;
2872
2873 case Lisp_Float:
2874 mark_p = (live_float_p (m, po)
2875 && !XMARKBIT (XFLOAT (*p)->type));
2876 break;
2877
2878 case Lisp_Vectorlike:
2879 /* Note: can't check GC_BUFFERP before we know it's a
2880 buffer because checking that dereferences the pointer
2881 PO which might point anywhere. */
2882 if (live_vector_p (m, po))
2883 mark_p = (!GC_SUBRP (*p)
2884 && !(XVECTOR (*p)->size & ARRAY_MARK_FLAG));
2885 else if (live_buffer_p (m, po))
2886 mark_p = GC_BUFFERP (*p) && !XMARKBIT (XBUFFER (*p)->name);
2887 break;
2888
2889 case Lisp_Misc:
2890 if (live_misc_p (m, po))
2891 {
2892 switch (XMISCTYPE (*p))
2893 {
2894 case Lisp_Misc_Marker:
2895 mark_p = !XMARKBIT (XMARKER (*p)->chain);
2896 break;
2897
2898 case Lisp_Misc_Buffer_Local_Value:
2899 case Lisp_Misc_Some_Buffer_Local_Value:
2900 mark_p = !XMARKBIT (XBUFFER_LOCAL_VALUE (*p)->realvalue);
2901 break;
2902
2903 case Lisp_Misc_Overlay:
2904 mark_p = !XMARKBIT (XOVERLAY (*p)->plist);
2905 break;
2906 }
2907 }
2908 break;
2909 }
2910 2991
2911 if (mark_p) 2992 For other values of X, either something really strange is
2912 { 2993 taking place, or the setjmp just didn't save the register. */
2913#if GC_MARK_STACK == GC_USE_GCPROS_CHECK_ZOMBIES 2994
2914 if (nzombies < MAX_ZOMBIES) 2995 if (x == 1)
2915 zombies[nzombies] = *p; 2996 fprintf (stderr, SETJMP_WILL_LIKELY_WORK);
2916 ++nzombies; 2997 else
2917#endif 2998 {
2918 mark_object (p); 2999 fprintf (stderr, SETJMP_WILL_NOT_WORK);
2919 } 3000 exit (1);
2920 } 3001 }
2921 } 3002 }
3003
3004 ++longjmps_done;
3005 x = 2;
3006 if (longjmps_done == 1)
3007 longjmp (jbuf, 1);
2922} 3008}
2923 3009
3010#endif /* not GC_SAVE_REGISTERS_ON_STACK && not GC_SETJMP_WORKS */
3011
2924 3012
2925#if GC_MARK_STACK == GC_MARK_STACK_CHECK_GCPROS 3013#if GC_MARK_STACK == GC_MARK_STACK_CHECK_GCPROS
2926 3014
@@ -2956,7 +3044,51 @@ dump_zombies ()
2956#endif /* GC_MARK_STACK == GC_USE_GCPROS_CHECK_ZOMBIES */ 3044#endif /* GC_MARK_STACK == GC_USE_GCPROS_CHECK_ZOMBIES */
2957 3045
2958 3046
2959/* Mark live Lisp objects on the C stack. */ 3047/* Mark live Lisp objects on the C stack.
3048
3049 There are several system-dependent problems to consider when
3050 porting this to new architectures:
3051
3052 Processor Registers
3053
3054 We have to mark Lisp objects in CPU registers that can hold local
3055 variables or are used to pass parameters.
3056
3057 If GC_SAVE_REGISTERS_ON_STACK is defined, it should expand to
3058 something that either saves relevant registers on the stack, or
3059 calls mark_maybe_object passing it each register's contents.
3060
3061 If GC_SAVE_REGISTERS_ON_STACK is not defined, the current
3062 implementation assumes that calling setjmp saves registers we need
3063 to see in a jmp_buf which itself lies on the stack. This doesn't
3064 have to be true! It must be verified for each system, possibly
3065 by taking a look at the source code of setjmp.
3066
3067 Stack Layout
3068
3069 Architectures differ in the way their processor stack is organized.
3070 For example, the stack might look like this
3071
3072 +----------------+
3073 | Lisp_Object | size = 4
3074 +----------------+
3075 | something else | size = 2
3076 +----------------+
3077 | Lisp_Object | size = 4
3078 +----------------+
3079 | ... |
3080
3081 In such a case, not every Lisp_Object will be aligned equally. To
3082 find all Lisp_Object on the stack it won't be sufficient to walk
3083 the stack in steps of 4 bytes. Instead, two passes will be
3084 necessary, one starting at the start of the stack, and a second
3085 pass starting at the start of the stack + 2. Likewise, if the
3086 minimal alignment of Lisp_Objects on the stack is 1, four passes
3087 would be necessary, each one starting with one byte more offset
3088 from the stack start.
3089
3090 The current code assumes by default that Lisp_Objects are aligned
3091 equally on the stack. */
2960 3092
2961static void 3093static void
2962mark_stack () 3094mark_stack ()
@@ -2976,15 +3108,37 @@ mark_stack ()
2976 pass parameters. */ 3108 pass parameters. */
2977#ifdef GC_SAVE_REGISTERS_ON_STACK 3109#ifdef GC_SAVE_REGISTERS_ON_STACK
2978 GC_SAVE_REGISTERS_ON_STACK (end); 3110 GC_SAVE_REGISTERS_ON_STACK (end);
2979#else 3111#else /* not GC_SAVE_REGISTERS_ON_STACK */
3112
3113#ifndef GC_SETJMP_WORKS /* If it hasn't been checked yet that
3114 setjmp will definitely work, test it
3115 and print a message with the result
3116 of the test. */
3117 if (!setjmp_tested_p)
3118 {
3119 setjmp_tested_p = 1;
3120 test_setjmp ();
3121 }
3122#endif /* GC_SETJMP_WORKS */
3123
2980 setjmp (j); 3124 setjmp (j);
2981 end = stack_grows_down_p ? (char *) &j + sizeof j : (char *) &j; 3125 end = stack_grows_down_p ? (char *) &j + sizeof j : (char *) &j;
2982#endif 3126#endif /* not GC_SAVE_REGISTERS_ON_STACK */
2983 3127
2984 /* This assumes that the stack is a contiguous region in memory. If 3128 /* This assumes that the stack is a contiguous region in memory. If
2985 that's not the case, something has to be done here to iterate over 3129 that's not the case, something has to be done here to iterate
2986 the stack segments. */ 3130 over the stack segments. */
3131#if GC_LISP_OBJECT_ALIGNMENT == 1
3132 mark_memory (stack_base, end);
3133 mark_memory ((char *) stack_base + 1, end);
3134 mark_memory ((char *) stack_base + 2, end);
3135 mark_memory ((char *) stack_base + 3, end);
3136#elif GC_LISP_OBJECT_ALIGNMENT == 2
3137 mark_memory (stack_base, end);
3138 mark_memory ((char *) stack_base + 2, end);
3139#else
2987 mark_memory (stack_base, end); 3140 mark_memory (stack_base, end);
3141#endif
2988 3142
2989#if GC_MARK_STACK == GC_MARK_STACK_CHECK_GCPROS 3143#if GC_MARK_STACK == GC_MARK_STACK_CHECK_GCPROS
2990 check_gcpros (); 3144 check_gcpros ();
@@ -4548,6 +4702,11 @@ init_alloc ()
4548{ 4702{
4549 gcprolist = 0; 4703 gcprolist = 0;
4550 byte_stack_list = 0; 4704 byte_stack_list = 0;
4705#if GC_MARK_STACK
4706#if !defined GC_SAVE_REGISTERS_ON_STACK && !defined GC_SETJMP_WORKS
4707 setjmp_tested_p = longjmps_done = 0;
4708#endif
4709#endif
4551} 4710}
4552 4711
4553void 4712void