comparison src/alloc.c @ 28365:a72abbd8dc16

(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.
author Gerd Moellmann <gerd@gnu.org>
date Mon, 27 Mar 2000 19:42:47 +0000
parents fd13be8ae190
children 7a3e8a76057b
comparison
equal deleted inserted replaced
28364:e24d2e75dea0 28365:a72abbd8dc16
294 static int live_string_p P_ ((struct mem_node *, void *)); 294 static int live_string_p P_ ((struct mem_node *, void *));
295 static int live_cons_p P_ ((struct mem_node *, void *)); 295 static int live_cons_p P_ ((struct mem_node *, void *));
296 static int live_symbol_p P_ ((struct mem_node *, void *)); 296 static int live_symbol_p P_ ((struct mem_node *, void *));
297 static int live_float_p P_ ((struct mem_node *, void *)); 297 static int live_float_p P_ ((struct mem_node *, void *));
298 static int live_misc_p P_ ((struct mem_node *, void *)); 298 static int live_misc_p P_ ((struct mem_node *, void *));
299 static void mark_maybe_object P_ ((Lisp_Object));
299 static void mark_memory P_ ((void *, void *)); 300 static void mark_memory P_ ((void *, void *));
300 static void mem_init P_ ((void)); 301 static void mem_init P_ ((void));
301 static struct mem_node *mem_insert P_ ((void *, void *, enum mem_type)); 302 static struct mem_node *mem_insert P_ ((void *, void *, enum mem_type));
302 static void mem_insert_fixup P_ ((struct mem_node *)); 303 static void mem_insert_fixup P_ ((struct mem_node *));
303 static void mem_rotate_left P_ ((struct mem_node *)); 304 static void mem_rotate_left P_ ((struct mem_node *));
2821 } 2822 }
2822 2823
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
2829 static INLINE void
2830 mark_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
2828 static void 2909 static void
2829 mark_memory (start, end) 2910 mark_memory (start, end)
2830 void *start, *end; 2911 void *start, *end;
2841 { 2922 {
2842 void *tem = start; 2923 void *tem = start;
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)
2848 { 2929 mark_maybe_object (*p);
2849 void *po = (void *) XPNTR (*p); 2930 }
2850 struct mem_node *m = mem_find (po); 2931
2851 2932
2852 if (m != MEM_NIL) 2933 #if !defined GC_SAVE_REGISTERS_ON_STACK && !defined GC_SETJMP_WORKS
2934
2935 static int setjmp_tested_p, longjmps_done;
2936
2937 #define SETJMP_WILL_LIKELY_WORK "\
2938 \n\
2939 Emacs garbage collector has been changed to use conservative stack\n\
2940 marking. Emacs has determined that the method it uses to do the\n\
2941 marking will likely work on your system, but this isn't sure.\n\
2942 \n\
2943 If you are a system-programmer, or can get the help of a local wizard\n\
2944 who is, please take a look at the function mark_stack in alloc.c, and\n\
2945 verify that the methods used are appropriate for your system.\n\
2946 \n\
2947 Please mail the result to <gerd@gnu.org>.\n\
2948 "
2949
2950 #define SETJMP_WILL_NOT_WORK "\
2951 \n\
2952 Emacs garbage collector has been changed to use conservative stack\n\
2953 marking. Emacs has determined that the default method it uses to do the\n\
2954 marking will not work on your system. We will need a system-dependent\n\
2955 solution for your system.\n\
2956 \n\
2957 Please take a look at the function mark_stack in alloc.c, and\n\
2958 try to find a way to make it work on your system.\n\
2959 Please 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
2969 static void
2970 test_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)
2984 {
2985 /* Came here after the longjmp at the end of the function.
2986
2987 If x == 1, the longjmp has restored the register to its
2988 value before the setjmp, and we can hope that setjmp
2989 saves all such registers in the jmp_buf, although that
2990 isn't sure.
2991
2992 For other values of X, either something really strange is
2993 taking place, or the setjmp just didn't save the register. */
2994
2995 if (x == 1)
2996 fprintf (stderr, SETJMP_WILL_LIKELY_WORK);
2997 else
2853 { 2998 {
2854 int mark_p = 0; 2999 fprintf (stderr, SETJMP_WILL_NOT_WORK);
2855 3000 exit (1);
2856 switch (XGCTYPE (*p))
2857 {
2858 case Lisp_String:
2859 mark_p = (live_string_p (m, po)
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
2911 if (mark_p)
2912 {
2913 #if GC_MARK_STACK == GC_USE_GCPROS_CHECK_ZOMBIES
2914 if (nzombies < MAX_ZOMBIES)
2915 zombies[nzombies] = *p;
2916 ++nzombies;
2917 #endif
2918 mark_object (p);
2919 }
2920 } 3001 }
2921 } 3002 }
2922 } 3003
3004 ++longjmps_done;
3005 x = 2;
3006 if (longjmps_done == 1)
3007 longjmp (jbuf, 1);
3008 }
3009
3010 #endif /* not GC_SAVE_REGISTERS_ON_STACK && not GC_SETJMP_WORKS */
2923 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
2927 /* Abort if anything GCPRO'd doesn't survive the GC. */ 3015 /* Abort if anything GCPRO'd doesn't survive the GC. */
2954 } 3042 }
2955 3043
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
2961 static void 3093 static void
2962 mark_stack () 3094 mark_stack ()
2963 { 3095 {
2964 jmp_buf j; 3096 jmp_buf j;
2974 /* Save registers that we need to see on the stack. We need to see 3106 /* Save registers that we need to see on the stack. We need to see
2975 registers used to hold register variables and registers used to 3107 registers used to hold register variables and registers used to
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;
3126 #endif /* not GC_SAVE_REGISTERS_ON_STACK */
3127
3128 /* This assumes that the stack is a contiguous region in memory. If
3129 that's not the case, something has to be done here to iterate
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
3140 mark_memory (stack_base, end);
2982 #endif 3141 #endif
2983
2984 /* 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
2986 the stack segments. */
2987 mark_memory (stack_base, end);
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 ();
2991 #endif 3145 #endif
2992 } 3146 }
4546 void 4700 void
4547 init_alloc () 4701 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
4553 void 4712 void
4554 syms_of_alloc () 4713 syms_of_alloc ()
4555 { 4714 {