comparison src/alloc.c @ 1676:a72f7bf813c9

[xemacs-hg @ 2003-09-11 09:11:07 by crestani] 2003-09-11 Marcus Crestani <crestani@informatik.uni-tuebingen.de> * alloc.c: Clean up #ifdef USE_KKCC, move stack code to better position. Add lrecord_memory_descriptions table. (KKCC_GC_STACK_FULL): Replace functions with macros. (KKCC_GC_STACK_EMPTY): (kkcc_gc_stack_push): (kkcc_gc_stack_pop): (kkcc_gc_stack_push_lisp_object): (mark_object): Add #ifdef to remove unused code. (garbage_collect_1): Remove some #ifdefs. * dumper.c (pdump): Dump lrecord_memory_descriptions table. * lrecord.h: Add lrecord_memory_descriptions.
author crestani
date Thu, 11 Sep 2003 09:11:08 +0000
parents 763f577d57b0
children a8d8f419b459
comparison
equal deleted inserted replaced
1675:114679353c2f 1676:a72f7bf813c9
2775 /* All the built-in lisp object types are enumerated in `enum lrecord_type'. 2775 /* All the built-in lisp object types are enumerated in `enum lrecord_type'.
2776 Additional ones may be defined by a module (none yet). We leave some 2776 Additional ones may be defined by a module (none yet). We leave some
2777 room in `lrecord_implementations_table' for such new lisp object types. */ 2777 room in `lrecord_implementations_table' for such new lisp object types. */
2778 const struct lrecord_implementation *lrecord_implementations_table[(int)lrecord_type_last_built_in_type + MODULE_DEFINABLE_TYPE_COUNT]; 2778 const struct lrecord_implementation *lrecord_implementations_table[(int)lrecord_type_last_built_in_type + MODULE_DEFINABLE_TYPE_COUNT];
2779 int lrecord_type_count = lrecord_type_last_built_in_type; 2779 int lrecord_type_count = lrecord_type_last_built_in_type;
2780 #ifndef USE_KKCC
2780 /* Object marker functions are in the lrecord_implementation structure. 2781 /* Object marker functions are in the lrecord_implementation structure.
2781 But copying them to a parallel array is much more cache-friendly. 2782 But copying them to a parallel array is much more cache-friendly.
2782 This hack speeds up (garbage-collect) by about 5%. */ 2783 This hack speeds up (garbage-collect) by about 5%. */
2783 Lisp_Object (*lrecord_markers[countof (lrecord_implementations_table)]) (Lisp_Object); 2784 Lisp_Object (*lrecord_markers[countof (lrecord_implementations_table)]) (Lisp_Object);
2785 #endif /* not USE_KKCC */
2784 2786
2785 struct gcpro *gcprolist; 2787 struct gcpro *gcprolist;
2786 2788
2787 /* We want the staticpro list relocated, but not the pointers found 2789 /* We want the staticpro list relocated, but not the pointers found
2788 therein, because they refer to locations in the global data segment, not 2790 therein, because they refer to locations in the global data segment, not
2948 sizeof (Lisp_Object), 2950 sizeof (Lisp_Object),
2949 lisp_object_description_1 2951 lisp_object_description_1
2950 }; 2952 };
2951 2953
2952 #if defined (USE_KKCC) || defined (PDUMP) 2954 #if defined (USE_KKCC) || defined (PDUMP)
2953
2954 /* the initial stack size in kkcc_gc_stack_entries */
2955 #define KKCC_INIT_GC_STACK_SIZE 16384
2956
2957 typedef struct
2958 {
2959 void *data;
2960 const struct memory_description *desc;
2961 } kkcc_gc_stack_entry;
2962
2963 static kkcc_gc_stack_entry *kkcc_gc_stack_ptr;
2964 static kkcc_gc_stack_entry *kkcc_gc_stack_top;
2965 static kkcc_gc_stack_entry *kkcc_gc_stack_last_entry;
2966 static int kkcc_gc_stack_size;
2967
2968 static void
2969 kkcc_gc_stack_init (void)
2970 {
2971 kkcc_gc_stack_size = KKCC_INIT_GC_STACK_SIZE;
2972 kkcc_gc_stack_ptr = (kkcc_gc_stack_entry *)
2973 malloc (kkcc_gc_stack_size * sizeof (kkcc_gc_stack_entry));
2974 if (!kkcc_gc_stack_ptr)
2975 {
2976 stderr_out ("stack init failed for size %d\n", kkcc_gc_stack_size);
2977 exit(23);
2978 }
2979 kkcc_gc_stack_top = kkcc_gc_stack_ptr - 1;
2980 kkcc_gc_stack_last_entry = kkcc_gc_stack_ptr + kkcc_gc_stack_size - 1;
2981 }
2982
2983 static void
2984 kkcc_gc_stack_free (void)
2985 {
2986 free (kkcc_gc_stack_ptr);
2987 kkcc_gc_stack_ptr = 0;
2988 kkcc_gc_stack_top = 0;
2989 kkcc_gc_stack_size = 0;
2990 }
2991
2992 static void
2993 kkcc_gc_stack_realloc (void)
2994 {
2995 int current_offset = (int)(kkcc_gc_stack_top - kkcc_gc_stack_ptr);
2996 kkcc_gc_stack_size *= 2;
2997 kkcc_gc_stack_ptr = (kkcc_gc_stack_entry *)
2998 realloc (kkcc_gc_stack_ptr,
2999 kkcc_gc_stack_size * sizeof (kkcc_gc_stack_entry));
3000 if (!kkcc_gc_stack_ptr)
3001 {
3002 stderr_out ("stack realloc failed for size %d\n", kkcc_gc_stack_size);
3003 exit(23);
3004 }
3005 kkcc_gc_stack_top = kkcc_gc_stack_ptr + current_offset;
3006 kkcc_gc_stack_last_entry = kkcc_gc_stack_ptr + kkcc_gc_stack_size - 1;
3007 }
3008
3009 static int
3010 kkcc_gc_stack_full (void)
3011 {
3012 if (kkcc_gc_stack_top >= kkcc_gc_stack_last_entry)
3013 return 1;
3014 return 0;
3015 }
3016
3017 static int
3018 kkcc_gc_stack_empty (void)
3019 {
3020 if (kkcc_gc_stack_top < kkcc_gc_stack_ptr)
3021 return 1;
3022 return 0;
3023 }
3024
3025 static void
3026 kkcc_gc_stack_push (void *data, const struct memory_description *desc)
3027 {
3028 if (kkcc_gc_stack_full ())
3029 kkcc_gc_stack_realloc();
3030 kkcc_gc_stack_top++;
3031 kkcc_gc_stack_top->data = data;
3032 kkcc_gc_stack_top->desc = desc;
3033 }
3034
3035 static kkcc_gc_stack_entry *
3036 kkcc_gc_stack_pop (void) //void *data, const struct memory_description *desc)
3037 {
3038 if (kkcc_gc_stack_empty ())
3039 return 0;
3040 kkcc_gc_stack_top--;
3041 return kkcc_gc_stack_top + 1;
3042 }
3043
3044 void
3045 kkcc_gc_stack_push_lisp_object (Lisp_Object obj)
3046 {
3047 if (XTYPE (obj) == Lisp_Type_Record)
3048 {
3049 struct lrecord_header *lheader = XRECORD_LHEADER (obj);
3050 const struct memory_description *desc;
3051 GC_CHECK_LHEADER_INVARIANTS (lheader);
3052 desc = LHEADER_IMPLEMENTATION (lheader)->description;
3053 if (! MARKED_RECORD_HEADER_P (lheader))
3054 {
3055 MARK_RECORD_HEADER (lheader);
3056 kkcc_gc_stack_push((void*) lheader, desc);
3057 }
3058 }
3059 }
3060 2955
3061 /* This function extracts the value of a count variable described somewhere 2956 /* This function extracts the value of a count variable described somewhere
3062 else in the description. It is converted corresponding to the type */ 2957 else in the description. It is converted corresponding to the type */
3063 EMACS_INT 2958 EMACS_INT
3064 lispdesc_indirect_count_1 (EMACS_INT code, 2959 lispdesc_indirect_count_1 (EMACS_INT code,
3298 #ifdef USE_KKCC 3193 #ifdef USE_KKCC
3299 /* The following functions implement the new mark algorithm. 3194 /* The following functions implement the new mark algorithm.
3300 They mark objects according to their descriptions. They 3195 They mark objects according to their descriptions. They
3301 are modeled on the corresponding pdumper procedures. */ 3196 are modeled on the corresponding pdumper procedures. */
3302 3197
3198 /* Object memory descriptions are in the lrecord_implementation structure.
3199 But copying them to a parallel array is much more cache-friendly. */
3200 const struct memory_description *lrecord_memory_descriptions[countof (lrecord_implementations_table)];
3201
3202 /* the initial stack size in kkcc_gc_stack_entries */
3203 #define KKCC_INIT_GC_STACK_SIZE 16384
3204
3205 typedef struct
3206 {
3207 void *data;
3208 const struct memory_description *desc;
3209 } kkcc_gc_stack_entry;
3210
3211 static kkcc_gc_stack_entry *kkcc_gc_stack_ptr;
3212 static kkcc_gc_stack_entry *kkcc_gc_stack_top;
3213 static kkcc_gc_stack_entry *kkcc_gc_stack_last_entry;
3214 static int kkcc_gc_stack_size;
3215
3216 static void
3217 kkcc_gc_stack_init (void)
3218 {
3219 kkcc_gc_stack_size = KKCC_INIT_GC_STACK_SIZE;
3220 kkcc_gc_stack_ptr = (kkcc_gc_stack_entry *)
3221 malloc (kkcc_gc_stack_size * sizeof (kkcc_gc_stack_entry));
3222 if (!kkcc_gc_stack_ptr)
3223 {
3224 stderr_out ("stack init failed for size %d\n", kkcc_gc_stack_size);
3225 exit(23);
3226 }
3227 kkcc_gc_stack_top = kkcc_gc_stack_ptr - 1;
3228 kkcc_gc_stack_last_entry = kkcc_gc_stack_ptr + kkcc_gc_stack_size - 1;
3229 }
3230
3231 static void
3232 kkcc_gc_stack_free (void)
3233 {
3234 free (kkcc_gc_stack_ptr);
3235 kkcc_gc_stack_ptr = 0;
3236 kkcc_gc_stack_top = 0;
3237 kkcc_gc_stack_size = 0;
3238 }
3239
3240 static void
3241 kkcc_gc_stack_realloc (void)
3242 {
3243 int current_offset = (int)(kkcc_gc_stack_top - kkcc_gc_stack_ptr);
3244 kkcc_gc_stack_size *= 2;
3245 kkcc_gc_stack_ptr = (kkcc_gc_stack_entry *)
3246 realloc (kkcc_gc_stack_ptr,
3247 kkcc_gc_stack_size * sizeof (kkcc_gc_stack_entry));
3248 if (!kkcc_gc_stack_ptr)
3249 {
3250 stderr_out ("stack realloc failed for size %d\n", kkcc_gc_stack_size);
3251 exit(23);
3252 }
3253 kkcc_gc_stack_top = kkcc_gc_stack_ptr + current_offset;
3254 kkcc_gc_stack_last_entry = kkcc_gc_stack_ptr + kkcc_gc_stack_size - 1;
3255 }
3256
3257 #define KKCC_GC_STACK_FULL (kkcc_gc_stack_top >= kkcc_gc_stack_last_entry)
3258 #define KKCC_GC_STACK_EMPTY (kkcc_gc_stack_top < kkcc_gc_stack_ptr)
3259
3260 static void
3261 kkcc_gc_stack_push (void *data, const struct memory_description *desc)
3262 {
3263 if (KKCC_GC_STACK_FULL)
3264 kkcc_gc_stack_realloc();
3265 kkcc_gc_stack_top++;
3266 kkcc_gc_stack_top->data = data;
3267 kkcc_gc_stack_top->desc = desc;
3268 }
3269
3270 static kkcc_gc_stack_entry *
3271 kkcc_gc_stack_pop (void)
3272 {
3273 if (KKCC_GC_STACK_EMPTY)
3274 return 0;
3275 kkcc_gc_stack_top--;
3276 return kkcc_gc_stack_top + 1;
3277 }
3278
3279 void
3280 kkcc_gc_stack_push_lisp_object (Lisp_Object obj)
3281 {
3282 if (XTYPE (obj) == Lisp_Type_Record)
3283 {
3284 struct lrecord_header *lheader = XRECORD_LHEADER (obj);
3285 const struct memory_description *desc;
3286 GC_CHECK_LHEADER_INVARIANTS (lheader);
3287 desc = RECORD_DESCRIPTION (lheader);
3288 if (! MARKED_RECORD_HEADER_P (lheader))
3289 {
3290 MARK_RECORD_HEADER (lheader);
3291 kkcc_gc_stack_push((void*) lheader, desc);
3292 }
3293 }
3294 }
3295
3303 #ifdef ERROR_CHECK_GC 3296 #ifdef ERROR_CHECK_GC
3304 #define KKCC_DO_CHECK_FREE(obj, allow_free) \ 3297 #define KKCC_DO_CHECK_FREE(obj, allow_free) \
3305 do \ 3298 do \
3306 { \ 3299 { \
3307 if (!allow_free && XTYPE (obj) == Lisp_Type_Record) \ 3300 if (!allow_free && XTYPE (obj) == Lisp_Type_Record) \
3317 #ifdef ERROR_CHECK_GC 3310 #ifdef ERROR_CHECK_GC
3318 static void 3311 static void
3319 mark_object_maybe_checking_free (Lisp_Object obj, int allow_free) 3312 mark_object_maybe_checking_free (Lisp_Object obj, int allow_free)
3320 { 3313 {
3321 KKCC_DO_CHECK_FREE (obj, allow_free); 3314 KKCC_DO_CHECK_FREE (obj, allow_free);
3322 #ifdef USE_KKCC
3323 kkcc_gc_stack_push_lisp_object (obj); 3315 kkcc_gc_stack_push_lisp_object (obj);
3324 #else /* NOT USE_KKCC */
3325 mark_object (obj);
3326 #endif /* NOT USE_KKCC */
3327 } 3316 }
3328 #else 3317 #else
3329 #define mark_object_maybe_checking_free(obj, allow_free) \ 3318 #define mark_object_maybe_checking_free(obj, allow_free) \
3330 kkcc_gc_stack_push_lisp_object (obj) 3319 kkcc_gc_stack_push_lisp_object (obj)
3331 #endif /* ERROR_CHECK_GC */ 3320 #endif /* ERROR_CHECK_GC */
3472 #ifdef USE_KKCC 3461 #ifdef USE_KKCC
3473 /* this code should never be reached when configured for KKCC */ 3462 /* this code should never be reached when configured for KKCC */
3474 stderr_out ("KKCC: Invalid mark_object call.\n"); 3463 stderr_out ("KKCC: Invalid mark_object call.\n");
3475 stderr_out ("Replace mark_object with kkcc_gc_stack_push_lisp_object.\n"); 3464 stderr_out ("Replace mark_object with kkcc_gc_stack_push_lisp_object.\n");
3476 abort (); 3465 abort ();
3477 #endif /* USE_KKCC */ 3466 #else /* not USE_KKCC */
3478 3467
3479 tail_recurse: 3468 tail_recurse:
3480 3469
3481 /* Checks we used to perform */ 3470 /* Checks we used to perform */
3482 /* if (EQ (obj, Qnull_pointer)) return; */ 3471 /* if (EQ (obj, Qnull_pointer)) return; */
3503 obj = RECORD_MARKER (lheader) (obj); 3492 obj = RECORD_MARKER (lheader) (obj);
3504 if (!NILP (obj)) goto tail_recurse; 3493 if (!NILP (obj)) goto tail_recurse;
3505 } 3494 }
3506 } 3495 }
3507 } 3496 }
3497 #endif /* not KKCC */
3508 } 3498 }
3509 3499
3510 3500
3511 static int gc_count_num_short_string_in_use; 3501 static int gc_count_num_short_string_in_use;
3512 static Bytecount gc_count_string_total_size; 3502 static Bytecount gc_count_string_total_size;
4588 /* Mark all the special slots that serve as the roots of accessibility. */ 4578 /* Mark all the special slots that serve as the roots of accessibility. */
4589 4579
4590 #ifdef USE_KKCC 4580 #ifdef USE_KKCC
4591 /* initialize kkcc stack */ 4581 /* initialize kkcc stack */
4592 kkcc_gc_stack_init(); 4582 kkcc_gc_stack_init();
4583 #define mark_object kkcc_gc_stack_push_lisp_object
4593 #endif /* USE_KKCC */ 4584 #endif /* USE_KKCC */
4594 4585
4595 { /* staticpro() */ 4586 { /* staticpro() */
4596 Lisp_Object **p = Dynarr_begin (staticpros); 4587 Lisp_Object **p = Dynarr_begin (staticpros);
4597 Elemcount count; 4588 Elemcount count;
4598 for (count = Dynarr_length (staticpros); count; count--) 4589 for (count = Dynarr_length (staticpros); count; count--)
4599 #ifdef USE_KKCC
4600 kkcc_gc_stack_push_lisp_object (**p++);
4601 #else /* NOT USE_KKCC */
4602 mark_object (**p++); 4590 mark_object (**p++);
4603 #endif /* NOT USE_KKCC */
4604 } 4591 }
4605 4592
4606 { /* staticpro_nodump() */ 4593 { /* staticpro_nodump() */
4607 Lisp_Object **p = Dynarr_begin (staticpros_nodump); 4594 Lisp_Object **p = Dynarr_begin (staticpros_nodump);
4608 Elemcount count; 4595 Elemcount count;
4609 for (count = Dynarr_length (staticpros_nodump); count; count--) 4596 for (count = Dynarr_length (staticpros_nodump); count; count--)
4610 #ifdef USE_KKCC
4611 kkcc_gc_stack_push_lisp_object (**p++);
4612 #else /* NOT USE_KKCC */
4613 mark_object (**p++); 4597 mark_object (**p++);
4614 #endif /* NOT USE_KKCC */
4615 } 4598 }
4616 4599
4617 { /* GCPRO() */ 4600 { /* GCPRO() */
4618 struct gcpro *tail; 4601 struct gcpro *tail;
4619 int i; 4602 int i;
4620 for (tail = gcprolist; tail; tail = tail->next) 4603 for (tail = gcprolist; tail; tail = tail->next)
4621 for (i = 0; i < tail->nvars; i++) 4604 for (i = 0; i < tail->nvars; i++)
4622 #ifdef USE_KKCC
4623 kkcc_gc_stack_push_lisp_object (tail->var[i]);
4624 #else /* NOT USE_KKCC */
4625 mark_object (tail->var[i]); 4605 mark_object (tail->var[i]);
4626 #endif /* NOT USE_KKCC */
4627 } 4606 }
4628 4607
4629 { /* specbind() */ 4608 { /* specbind() */
4630 struct specbinding *bind; 4609 struct specbinding *bind;
4631 for (bind = specpdl; bind != specpdl_ptr; bind++) 4610 for (bind = specpdl; bind != specpdl_ptr; bind++)
4632 { 4611 {
4633 #ifdef USE_KKCC
4634 kkcc_gc_stack_push_lisp_object (bind->symbol);
4635 kkcc_gc_stack_push_lisp_object (bind->old_value);
4636 #else /* NOT USE_KKCC */
4637 mark_object (bind->symbol); 4612 mark_object (bind->symbol);
4638 mark_object (bind->old_value); 4613 mark_object (bind->old_value);
4639 #endif /* NOT USE_KKCC */
4640 } 4614 }
4641 } 4615 }
4642 4616
4643 { 4617 {
4644 struct catchtag *catch; 4618 struct catchtag *catch;
4645 for (catch = catchlist; catch; catch = catch->next) 4619 for (catch = catchlist; catch; catch = catch->next)
4646 { 4620 {
4647 #ifdef USE_KKCC
4648 kkcc_gc_stack_push_lisp_object (catch->tag);
4649 kkcc_gc_stack_push_lisp_object (catch->val);
4650 kkcc_gc_stack_push_lisp_object (catch->actual_tag);
4651 #else /* NOT USE_KKCC */
4652 mark_object (catch->tag); 4621 mark_object (catch->tag);
4653 mark_object (catch->val); 4622 mark_object (catch->val);
4654 mark_object (catch->actual_tag); 4623 mark_object (catch->actual_tag);
4655 #endif /* NOT USE_KKCC */
4656 } 4624 }
4657 } 4625 }
4658 4626
4659 { 4627 {
4660 struct backtrace *backlist; 4628 struct backtrace *backlist;
4661 for (backlist = backtrace_list; backlist; backlist = backlist->next) 4629 for (backlist = backtrace_list; backlist; backlist = backlist->next)
4662 { 4630 {
4663 int nargs = backlist->nargs; 4631 int nargs = backlist->nargs;
4664 int i; 4632 int i;
4665 4633
4666 #ifdef USE_KKCC
4667 kkcc_gc_stack_push_lisp_object (*backlist->function);
4668 if (nargs < 0 /* nargs == UNEVALLED || nargs == MANY */
4669 /* might be fake (internal profiling entry) */
4670 && backlist->args)
4671 kkcc_gc_stack_push_lisp_object (backlist->args[0]);
4672 else
4673 for (i = 0; i < nargs; i++)
4674 kkcc_gc_stack_push_lisp_object (backlist->args[i]);
4675 #else /* NOT USE_KKCC */
4676 mark_object (*backlist->function); 4634 mark_object (*backlist->function);
4677 if (nargs < 0 /* nargs == UNEVALLED || nargs == MANY */ 4635 if (nargs < 0 /* nargs == UNEVALLED || nargs == MANY */
4678 /* might be fake (internal profiling entry) */ 4636 /* might be fake (internal profiling entry) */
4679 && backlist->args) 4637 && backlist->args)
4680 mark_object (backlist->args[0]); 4638 mark_object (backlist->args[0]);
4681 else 4639 else
4682 for (i = 0; i < nargs; i++) 4640 for (i = 0; i < nargs; i++)
4683 mark_object (backlist->args[i]); 4641 mark_object (backlist->args[i]);
4684 #endif /* NOT USE_KKCC */
4685 } 4642 }
4686 } 4643 }
4687 4644
4688 mark_profiling_info (); 4645 mark_profiling_info ();
4689 4646
4715 ; 4672 ;
4716 4673
4717 #ifdef USE_KKCC 4674 #ifdef USE_KKCC
4718 kkcc_marking (); 4675 kkcc_marking ();
4719 kkcc_gc_stack_free (); 4676 kkcc_gc_stack_free ();
4677 #undef mark_object
4720 #endif /* USE_KKCC */ 4678 #endif /* USE_KKCC */
4721 4679
4722 /* And prune (this needs to be called after everything else has been 4680 /* And prune (this needs to be called after everything else has been
4723 marked and before we do any sweeping). */ 4681 marked and before we do any sweeping). */
4724 /* #### this is somewhat ad-hoc and should probably be an object 4682 /* #### this is somewhat ad-hoc and should probably be an object