comparison src/alloc.c @ 1265:de6cf052e10b

[xemacs-hg @ 2003-02-07 00:49:41 by ben] add KKCC tail-recursion alloc.c: Implement tail-recursion in KKCC when the last-marked object is a Lisp object, to avoid stack-overflow errors when marking long lists. Factor out some duplicated error-checking into macros.
author ben
date Fri, 07 Feb 2003 00:49:42 +0000
parents f0af455e89d9
children beb703ae34fd
comparison
equal deleted inserted replaced
1264:032904d02169 1265:de6cf052e10b
1 /* Storage allocation and gc for XEmacs Lisp interpreter. 1 /* Storage allocation and gc for XEmacs Lisp interpreter.
2 Copyright (C) 1985-1998 Free Software Foundation, Inc. 2 Copyright (C) 1985-1998 Free Software Foundation, Inc.
3 Copyright (C) 1995 Sun Microsystems, Inc. 3 Copyright (C) 1995 Sun Microsystems, Inc.
4 Copyright (C) 1995, 1996, 2001, 2002 Ben Wing. 4 Copyright (C) 1995, 1996, 2001, 2002, 2003 Ben Wing.
5 5
6 This file is part of XEmacs. 6 This file is part of XEmacs.
7 7
8 XEmacs is free software; you can redistribute it and/or modify it 8 XEmacs is free software; you can redistribute it and/or modify it
9 under the terms of the GNU General Public License as published by the 9 under the terms of the GNU General Public License as published by the
3132 3132
3133 static void mark_struct_contents (const void *data, 3133 static void mark_struct_contents (const void *data,
3134 const struct sized_memory_description *sdesc, 3134 const struct sized_memory_description *sdesc,
3135 int count); 3135 int count);
3136 3136
3137 #define GC_CHECK_NOT_FREE(lheader) \
3138 gc_checking_assert (LHEADER_IMPLEMENTATION (lheader)->basic_p || \
3139 ! ((struct lcrecord_header *) lheader)->free)
3140
3141
3142 #ifdef ERROR_CHECK_GC
3143 #define KKCC_DO_CHECK_FREE(obj, allow_free) \
3144 do \
3145 { \
3146 if (!allow_free && XTYPE (obj) == Lisp_Type_Record) \
3147 { \
3148 struct lrecord_header *lheader = XRECORD_LHEADER (obj); \
3149 GC_CHECK_NOT_FREE (lheader); \
3150 } \
3151 } while (0)
3152 #else
3153 #define KKCC_DO_CHECK_FREE(obj, allow_free)
3154 #endif
3137 3155
3138 #ifdef ERROR_CHECK_GC 3156 #ifdef ERROR_CHECK_GC
3139 void 3157 void
3140 mark_object_maybe_checking_free (Lisp_Object obj, int allow_free) 3158 mark_object_maybe_checking_free (Lisp_Object obj, int allow_free)
3141 { 3159 {
3142 3160 KKCC_DO_CHECK_FREE (obj, allow_free);
3143 if (!allow_free && XTYPE (obj) == Lisp_Type_Record)
3144 {
3145 struct lrecord_header *lheader = XRECORD_LHEADER (obj);
3146 gc_checking_assert (LHEADER_IMPLEMENTATION (lheader)->basic_p ||
3147 ! ((struct lcrecord_header *) lheader)->free);
3148 }
3149 mark_object (obj); 3161 mark_object (obj);
3150 } 3162 }
3151 #else 3163 #else
3152 #define mark_object_maybe_checking_free(obj, allow_free) mark_object (obj) 3164 #define mark_object_maybe_checking_free(obj, allow_free) mark_object (obj)
3153 #endif /* ERROR_CHECK_GC */ 3165 #endif /* ERROR_CHECK_GC */
3163 static const Lisp_Object *last_occurred_object = (Lisp_Object *) 0; 3175 static const Lisp_Object *last_occurred_object = (Lisp_Object *) 0;
3164 static int mark_last_occurred_object = 0; 3176 static int mark_last_occurred_object = 0;
3165 #ifdef ERROR_CHECK_GC 3177 #ifdef ERROR_CHECK_GC
3166 static int last_occurred_flags; 3178 static int last_occurred_flags;
3167 #endif 3179 #endif
3180
3181 tail_recurse:
3168 3182
3169 for (pos = 0; desc[pos].type != XD_END; pos++) 3183 for (pos = 0; desc[pos].type != XD_END; pos++)
3170 { 3184 {
3171 const struct memory_description *desc1 = &desc[pos]; 3185 const struct memory_description *desc1 = &desc[pos];
3172 const void *rdata = 3186 const void *rdata =
3271 } 3285 }
3272 } 3286 }
3273 3287
3274 if (mark_last_occurred_object) 3288 if (mark_last_occurred_object)
3275 { 3289 {
3290 Lisp_Object obj = *last_occurred_object;
3291
3292 old_tail_recurse:
3276 /* NOTE: The second parameter isn't even evaluated 3293 /* NOTE: The second parameter isn't even evaluated
3277 non-ERROR_CHECK_GC, so it's OK for the variable not to exist. 3294 non-ERROR_CHECK_GC, so it's OK for the variable not to exist.
3278 */ 3295 */
3279 mark_object_maybe_checking_free (*last_occurred_object, 3296 KKCC_DO_CHECK_FREE
3280 last_occurred_flags & 3297 (obj, (last_occurred_flags & XD_FLAG_FREE_LISP_OBJECT) != 0);
3281 XD_FLAG_FREE_LISP_OBJECT); 3298
3299 if (XTYPE (obj) == Lisp_Type_Record)
3300 {
3301 struct lrecord_header *lheader = XRECORD_LHEADER (obj);
3302
3303 GC_CHECK_LHEADER_INVARIANTS (lheader);
3304
3305 /* All c_readonly objects have their mark bit set,
3306 so that we only need to check the mark bit here. */
3307 if (! MARKED_RECORD_HEADER_P (lheader))
3308 {
3309 MARK_RECORD_HEADER (lheader);
3310
3311 {
3312 desc = LHEADER_IMPLEMENTATION (lheader)->description;
3313 if (desc) /* && !CONSP(obj))*/ /* KKCC cons special case */
3314 {
3315 data = lheader;
3316 mark_last_occurred_object = 0;
3317 goto tail_recurse;
3318 }
3319 else
3320 {
3321 if (RECORD_MARKER (lheader))
3322 {
3323 obj = RECORD_MARKER (lheader) (obj);
3324 if (!NILP (obj)) goto old_tail_recurse;
3325 }
3326 }
3327 }
3328 }
3329 }
3330
3282 mark_last_occurred_object = 0; 3331 mark_last_occurred_object = 0;
3283 } 3332 }
3284 } 3333 }
3285 3334
3286 /* This function loops all elements of a struct pointer and calls 3335 /* This function loops all elements of a struct pointer and calls
3322 3371
3323 GC_CHECK_LHEADER_INVARIANTS (lheader); 3372 GC_CHECK_LHEADER_INVARIANTS (lheader);
3324 3373
3325 #ifndef USE_KKCC 3374 #ifndef USE_KKCC
3326 /* We handle this separately, above, so we can mark free objects */ 3375 /* We handle this separately, above, so we can mark free objects */
3327 gc_checking_assert (LHEADER_IMPLEMENTATION (lheader)->basic_p || 3376 GC_CHECK_NOT_FREE (lheader);
3328 ! ((struct lcrecord_header *) lheader)->free);
3329 #endif /* not USE_KKCC */ 3377 #endif /* not USE_KKCC */
3330
3331 3378
3332 /* All c_readonly objects have their mark bit set, 3379 /* All c_readonly objects have their mark bit set,
3333 so that we only need to check the mark bit here. */ 3380 so that we only need to check the mark bit here. */
3334 if (! MARKED_RECORD_HEADER_P (lheader)) 3381 if (! MARKED_RECORD_HEADER_P (lheader))
3335 { 3382 {
3336 MARK_RECORD_HEADER (lheader); 3383 MARK_RECORD_HEADER (lheader);
3337 3384
3338 { 3385 {
3339 #ifdef USE_KKCC 3386 #ifdef USE_KKCC
3340 const struct lrecord_implementation *imp;
3341 const struct memory_description *desc; 3387 const struct memory_description *desc;
3342 3388 desc = LHEADER_IMPLEMENTATION (lheader)->description;
3343 imp = LHEADER_IMPLEMENTATION (lheader);
3344 desc = imp->description;
3345
3346 if (desc) /* && !CONSP(obj))*/ /* KKCC cons special case */ 3389 if (desc) /* && !CONSP(obj))*/ /* KKCC cons special case */
3347 { 3390 mark_with_description (lheader, desc);
3348 mark_with_description (lheader, desc);
3349 }
3350 else 3391 else
3351 #endif /* USE_KKCC */ 3392 #endif /* USE_KKCC */
3352 { 3393 {
3353 if (RECORD_MARKER (lheader)) 3394 if (RECORD_MARKER (lheader))
3354 { 3395 {