Mercurial > emacs
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 { |
