Mercurial > hg > xemacs-beta
changeset 5059:c8f90d61dcf3
fix memory usage stats to include pdumped objects
-------------------- ChangeLog entries follow: --------------------
lisp/ChangeLog addition:
2010-02-21 Ben Wing <ben@xemacs.org>
* diagnose.el:
* diagnose.el (show-object-memory-usage-stats):
Fix errors preventing this from working properly, account for
words like "entry" pluralized to "entries".
src/ChangeLog addition:
2010-02-21 Ben Wing <ben@xemacs.org>
* alloc.c:
* alloc.c (FREE_FIXED_TYPE_WHEN_NOT_IN_GC):
* alloc.c (struct):
* alloc.c (tick_lrecord_stats):
* alloc.c (tick_lcrecord_stats):
* alloc.c (sweep_lcrecords_1):
* alloc.c (COUNT_FROB_BLOCK_USAGE):
* alloc.c (SWEEP_FIXED_TYPE_BLOCK_1):
* alloc.c (free_cons):
* alloc.c (free_key_data):
* alloc.c (free_button_data):
* alloc.c (free_motion_data):
* alloc.c (free_process_data):
* alloc.c (free_timeout_data):
* alloc.c (free_magic_data):
* alloc.c (free_magic_eval_data):
* alloc.c (free_eval_data):
* alloc.c (free_misc_user_data):
* alloc.c (free_marker):
* alloc.c (gc_sweep_1):
* alloc.c (HACK_O_MATIC):
* alloc.c (FROB):
* alloc.c (object_memory_usage_stats):
* alloc.c (Fgarbage_collect):
* dumper.c:
* dumper.c (pdump_objects_unmark):
* lrecord.h:
* lrecord.h (enum lrecord_alloc_status):
Fixes to memory-usage-tracking code, etc.
(1) Incorporate NEW_GC stuff into FREE_FIXED_TYPE_WHEN_NOT_IN_GC
to avoid duplication.
(2) Rewrite tick_lcrecord_stats() to include separate
tick_lrecord_stats(); use in dumper.c to note pdumped objects.
(3) Instead of handling frob-block objects specially in
object_memory_usage_stats(), have SWEEP_FIXED_TYPE_BLOCK_1
increment the stats in lrecord_stats[] so that they get handled
like other objects.
(4) Pluralize entry as entries, etc.
author | Ben Wing <ben@xemacs.org> |
---|---|
date | Sun, 21 Feb 2010 15:29:12 -0600 |
parents | eb17f0c176ac |
children | 86041556214b |
files | lisp/ChangeLog lisp/diagnose.el src/ChangeLog src/alloc.c src/dumper.c src/lrecord.h |
diffstat | 6 files changed, 301 insertions(+), 223 deletions(-) [+] |
line wrap: on
line diff
--- a/lisp/ChangeLog Sun Feb 21 05:19:08 2010 -0600 +++ b/lisp/ChangeLog Sun Feb 21 15:29:12 2010 -0600 @@ -1,3 +1,10 @@ +2010-02-21 Ben Wing <ben@xemacs.org> + + * diagnose.el: + * diagnose.el (show-object-memory-usage-stats): + Fix errors preventing this from working properly, account for + words like "entry" pluralized to "entries". + 2010-02-08 Ben Wing <ben@xemacs.org> * help.el (describe-function-1):
--- a/lisp/diagnose.el Sun Feb 21 05:19:08 2010 -0600 +++ b/lisp/diagnose.el Sun Feb 21 15:29:12 2010 -0600 @@ -1,6 +1,6 @@ ;;; diagnose.el --- routines for debugging problems in XEmacs -;; Copyright (C) 2002 Ben Wing. +;; Copyright (C) 2002, 2010 Ben Wing. ;; Maintainer: XEmacs Development Team ;; Keywords: dumped @@ -197,29 +197,33 @@ (intern (concat (match-string 1 (symbol-name stat)) "-storage-including-overhead")))) (storage-count - (or (plist-get - plist - (intern - (concat (match-string 1 (symbol-name stat)) - "s-used"))) + (or (loop for str in '("s-used" "es-used" "-used") + for val = (plist-get + plist + (intern + (concat (match-string + 1 (symbol-name stat)) + str))) + if val + return val) (plist-get plist (intern - (concat (match-string 1 (symbol-name stat)) - "es-used"))) - (plist-get - plist - (intern - (concat (match-string 1 (symbol-name stat)) - "-used")))))) + (concat (substring + (match-string 1 (symbol-name stat)) + 0 -1) + "ies-used"))) + ))) (incf total-use storage-use) (incf total-use-overhead (if storage-use-overhead storage-use-overhead storage-use)) - (incf total-count storage-count) - (princ (format fmt - (match-string 1 (symbol-name stat)) - storage-count storage-use))))) + (incf total-count (or storage-count 0)) + (and (> storage-use 0) + (princ (format fmt + (match-string 1 (symbol-name stat)) + (or storage-count "unknown") + storage-use)))))) plist) (princ "\n") (princ (format fmt "total" @@ -229,7 +233,7 @@ (sort-numeric-fields -1 (save-excursion (goto-char begin) - (forward-line 2) + (forward-line 3) (point)) (save-excursion (forward-line -2)
--- a/src/ChangeLog Sun Feb 21 05:19:08 2010 -0600 +++ b/src/ChangeLog Sun Feb 21 15:29:12 2010 -0600 @@ -1,3 +1,48 @@ +2010-02-21 Ben Wing <ben@xemacs.org> + + * alloc.c: + * alloc.c (FREE_FIXED_TYPE_WHEN_NOT_IN_GC): + * alloc.c (struct): + * alloc.c (tick_lrecord_stats): + * alloc.c (tick_lcrecord_stats): + * alloc.c (sweep_lcrecords_1): + * alloc.c (COUNT_FROB_BLOCK_USAGE): + * alloc.c (SWEEP_FIXED_TYPE_BLOCK_1): + * alloc.c (free_cons): + * alloc.c (free_key_data): + * alloc.c (free_button_data): + * alloc.c (free_motion_data): + * alloc.c (free_process_data): + * alloc.c (free_timeout_data): + * alloc.c (free_magic_data): + * alloc.c (free_magic_eval_data): + * alloc.c (free_eval_data): + * alloc.c (free_misc_user_data): + * alloc.c (free_marker): + * alloc.c (gc_sweep_1): + * alloc.c (HACK_O_MATIC): + * alloc.c (FROB): + * alloc.c (object_memory_usage_stats): + * alloc.c (Fgarbage_collect): + * dumper.c: + * dumper.c (pdump_objects_unmark): + * lrecord.h: + * lrecord.h (enum lrecord_alloc_status): + Fixes to memory-usage-tracking code, etc. + + (1) Incorporate NEW_GC stuff into FREE_FIXED_TYPE_WHEN_NOT_IN_GC + to avoid duplication. + + (2) Rewrite tick_lcrecord_stats() to include separate + tick_lrecord_stats(); use in dumper.c to note pdumped objects. + + (3) Instead of handling frob-block objects specially in + object_memory_usage_stats(), have SWEEP_FIXED_TYPE_BLOCK_1 + increment the stats in lrecord_stats[] so that they get handled + like other objects. + + (4) Pluralize entry as entries, etc. + 2010-02-21 Ben Wing <ben@xemacs.org> * alloc.c:
--- a/src/alloc.c Sun Feb 21 05:19:08 2010 -0600 +++ b/src/alloc.c Sun Feb 21 15:29:12 2010 -0600 @@ -1150,7 +1150,12 @@ PUT_FIXED_TYPE_ON_FREE_LIST (type, structtype, FFT_ptr); \ MARK_LRECORD_AS_FREE (FFT_ptr); \ } while (0) - +#endif /* NEW_GC */ + +#ifdef NEW_GC +#define FREE_FIXED_TYPE_WHEN_NOT_IN_GC(lo, type, structtype, ptr) \ + free_lrecord (lo) +#else /* not NEW_GC */ /* Like FREE_FIXED_TYPE() but used when we are explicitly freeing a structure through free_cons(), free_marker(), etc. rather than through the normal process of sweeping. @@ -1165,15 +1170,15 @@ set, which is used for Purify and the like. */ #ifndef ALLOC_NO_POOLS -#define FREE_FIXED_TYPE_WHEN_NOT_IN_GC(type, structtype, ptr) \ -do { FREE_FIXED_TYPE (type, structtype, ptr); \ - DECREMENT_CONS_COUNTER (sizeof (structtype)); \ - gc_count_num_##type##_freelist++; \ +#define FREE_FIXED_TYPE_WHEN_NOT_IN_GC(lo, type, structtype, ptr) \ +do { FREE_FIXED_TYPE (type, structtype, ptr); \ + DECREMENT_CONS_COUNTER (sizeof (structtype)); \ + gc_count_num_##type##_freelist++; \ } while (0) #else -#define FREE_FIXED_TYPE_WHEN_NOT_IN_GC(type, structtype, ptr) +#define FREE_FIXED_TYPE_WHEN_NOT_IN_GC(lo, type, structtype, ptr) #endif -#endif /* NEW_GC */ +#endif /* (not) NEW_GC */ #ifdef NEW_GC #define ALLOCATE_FIXED_TYPE_AND_SET_IMPL(type, lisp_type, var, lrec_ptr) \ @@ -3481,33 +3486,45 @@ int instances_freed; int bytes_freed; int instances_on_free_list; -} lcrecord_stats [countof (lrecord_implementations_table)]; - -static void -tick_lcrecord_stats (const struct lrecord_header *h, int free_p) + int bytes_on_free_list; +} lrecord_stats [countof (lrecord_implementations_table)]; + +void +tick_lrecord_stats (const struct lrecord_header *h, + enum lrecord_alloc_status status) { int type_index = h->type; - + Bytecount sz = detagged_lisp_object_size (h); + + switch (status) + { + case ALLOC_IN_USE: + lrecord_stats[type_index].instances_in_use++; + lrecord_stats[type_index].bytes_in_use += sz; + break; + case ALLOC_FREE: + lrecord_stats[type_index].instances_freed++; + lrecord_stats[type_index].bytes_freed += sz; + break; + case ALLOC_ON_FREE_LIST: + lrecord_stats[type_index].instances_on_free_list++; + lrecord_stats[type_index].bytes_on_free_list += sz; + break; + default: + ABORT (); + } +} + +inline static void +tick_lcrecord_stats (const struct lrecord_header *h, int free_p) +{ if (((struct old_lcrecord_header *) h)->free) { gc_checking_assert (!free_p); - lcrecord_stats[type_index].instances_on_free_list++; + tick_lrecord_stats (h, ALLOC_ON_FREE_LIST); } else - { - Bytecount sz = detagged_lisp_object_size (h); - - if (free_p) - { - lcrecord_stats[type_index].instances_freed++; - lcrecord_stats[type_index].bytes_freed += sz; - } - else - { - lcrecord_stats[type_index].instances_in_use++; - lcrecord_stats[type_index].bytes_in_use += sz; - } - } + tick_lrecord_stats (h, free_p ? ALLOC_FREE : ALLOC_IN_USE); } #endif /* not NEW_GC */ @@ -3521,8 +3538,6 @@ int num_used = 0; /* int total_size = 0; */ - xzero (lcrecord_stats); /* Reset all statistics to 0. */ - /* First go through and call all the finalize methods. Then go through and free the objects. There used to be only one loop here, with the call to the finalizer @@ -3577,6 +3592,22 @@ /* And the Lord said: Thou shalt use the `c-backslash-region' command to make macros prettier. */ +#define COUNT_FROB_BLOCK_USAGE(type) \ + EMACS_INT s = 0; \ + struct type##_block *x = current_##type##_block; \ + while (x) { s += sizeof (*x) + MALLOC_OVERHEAD; x = x->prev; } \ + DO_NOTHING + +#define COPY_INTO_LRECORD_STATS(type) \ +do { \ + COUNT_FROB_BLOCK_USAGE (type); \ + lrecord_stats[lrecord_type_##type].bytes_in_use += s; \ + lrecord_stats[lrecord_type_##type].instances_on_free_list += \ + gc_count_num_##type##_freelist; \ + lrecord_stats[lrecord_type_##type].instances_in_use += \ + gc_count_num_##type##_in_use; \ +} while (0) + #ifdef ERROR_CHECK_GC #define SWEEP_FIXED_TYPE_BLOCK_1(typename, obj_type, lheader) \ @@ -3621,86 +3652,88 @@ \ gc_count_num_##typename##_in_use = num_used; \ gc_count_num_##typename##_freelist = num_free; \ + COPY_INTO_LRECORD_STATS (typename); \ } while (0) #else /* !ERROR_CHECK_GC */ -#define SWEEP_FIXED_TYPE_BLOCK_1(typename, obj_type, lheader) \ -do { \ - struct typename##_block *SFTB_current; \ - struct typename##_block **SFTB_prev; \ - int SFTB_limit; \ - int num_free = 0, num_used = 0; \ - \ - typename##_free_list = 0; \ - \ - for (SFTB_prev = ¤t_##typename##_block, \ - SFTB_current = current_##typename##_block, \ - SFTB_limit = current_##typename##_block_index; \ - SFTB_current; \ - ) \ - { \ - int SFTB_iii; \ - int SFTB_empty = 1; \ - Lisp_Free *SFTB_old_free_list = typename##_free_list; \ - \ - for (SFTB_iii = 0; SFTB_iii < SFTB_limit; SFTB_iii++) \ - { \ - obj_type *SFTB_victim = &(SFTB_current->block[SFTB_iii]); \ - \ - if (LRECORD_FREE_P (SFTB_victim)) \ - { \ - num_free++; \ +#define SWEEP_FIXED_TYPE_BLOCK_1(typename, obj_type, lheader) \ +do { \ + struct typename##_block *SFTB_current; \ + struct typename##_block **SFTB_prev; \ + int SFTB_limit; \ + int num_free = 0, num_used = 0; \ + \ + typename##_free_list = 0; \ + \ + for (SFTB_prev = ¤t_##typename##_block, \ + SFTB_current = current_##typename##_block, \ + SFTB_limit = current_##typename##_block_index; \ + SFTB_current; \ + ) \ + { \ + int SFTB_iii; \ + int SFTB_empty = 1; \ + Lisp_Free *SFTB_old_free_list = typename##_free_list; \ + \ + for (SFTB_iii = 0; SFTB_iii < SFTB_limit; SFTB_iii++) \ + { \ + obj_type *SFTB_victim = &(SFTB_current->block[SFTB_iii]); \ + \ + if (LRECORD_FREE_P (SFTB_victim)) \ + { \ + num_free++; \ PUT_FIXED_TYPE_ON_FREE_LIST (typename, obj_type, SFTB_victim); \ - } \ - else if (C_READONLY_RECORD_HEADER_P (&SFTB_victim->lheader)) \ - { \ - SFTB_empty = 0; \ - num_used++; \ - } \ - else if (! MARKED_RECORD_HEADER_P (&SFTB_victim->lheader)) \ - { \ - num_free++; \ - FREE_FIXED_TYPE (typename, obj_type, SFTB_victim); \ - } \ - else \ - { \ - SFTB_empty = 0; \ - num_used++; \ - UNMARK_##typename (SFTB_victim); \ - } \ - } \ - if (!SFTB_empty) \ - { \ - SFTB_prev = &(SFTB_current->prev); \ - SFTB_current = SFTB_current->prev; \ - } \ - else if (SFTB_current == current_##typename##_block \ - && !SFTB_current->prev) \ - { \ - /* No real point in freeing sole allocation block */ \ - break; \ - } \ - else \ - { \ - struct typename##_block *SFTB_victim_block = SFTB_current; \ - if (SFTB_victim_block == current_##typename##_block) \ - current_##typename##_block_index \ - = countof (current_##typename##_block->block); \ - SFTB_current = SFTB_current->prev; \ - { \ - *SFTB_prev = SFTB_current; \ - xfree (SFTB_victim_block); \ - /* Restore free list to what it was before victim was swept */ \ - typename##_free_list = SFTB_old_free_list; \ - num_free -= SFTB_limit; \ - } \ - } \ - SFTB_limit = countof (current_##typename##_block->block); \ - } \ - \ - gc_count_num_##typename##_in_use = num_used; \ - gc_count_num_##typename##_freelist = num_free; \ + } \ + else if (C_READONLY_RECORD_HEADER_P (&SFTB_victim->lheader)) \ + { \ + SFTB_empty = 0; \ + num_used++; \ + } \ + else if (! MARKED_RECORD_HEADER_P (&SFTB_victim->lheader)) \ + { \ + num_free++; \ + FREE_FIXED_TYPE (typename, obj_type, SFTB_victim); \ + } \ + else \ + { \ + SFTB_empty = 0; \ + num_used++; \ + UNMARK_##typename (SFTB_victim); \ + } \ + } \ + if (!SFTB_empty) \ + { \ + SFTB_prev = &(SFTB_current->prev); \ + SFTB_current = SFTB_current->prev; \ + } \ + else if (SFTB_current == current_##typename##_block \ + && !SFTB_current->prev) \ + { \ + /* No real point in freeing sole allocation block */ \ + break; \ + } \ + else \ + { \ + struct typename##_block *SFTB_victim_block = SFTB_current; \ + if (SFTB_victim_block == current_##typename##_block) \ + current_##typename##_block_index \ + = countof (current_##typename##_block->block); \ + SFTB_current = SFTB_current->prev; \ + { \ + *SFTB_prev = SFTB_current; \ + xfree (SFTB_victim_block); \ + /* Restore free list to what it was before victim was swept */ \ + typename##_free_list = SFTB_old_free_list; \ + num_free -= SFTB_limit; \ + } \ + } \ + SFTB_limit = countof (current_##typename##_block->block); \ + } \ + \ + gc_count_num_##typename##_in_use = num_used; \ + gc_count_num_##typename##_freelist = num_free; \ + COPY_INTO_LRECORD_STATS (typename); \ } while (0) #endif /* !ERROR_CHECK_GC */ @@ -3748,11 +3781,7 @@ ASSERT_VALID_POINTER (XPNTR (cons_car (ptr))); #endif /* ERROR_CHECK_GC */ -#ifdef NEW_GC - free_lrecord (cons); -#else /* not NEW_GC */ - FREE_FIXED_TYPE_WHEN_NOT_IN_GC (cons, Lisp_Cons, ptr); -#endif /* not NEW_GC */ + FREE_FIXED_TYPE_WHEN_NOT_IN_GC (cons, cons, Lisp_Cons, ptr); } /* explicitly free a list. You **must make sure** that you have @@ -3887,11 +3916,8 @@ void free_key_data (Lisp_Object ptr) { -#ifdef NEW_GC - free_lrecord (ptr); -#else /* not NEW_GC */ - FREE_FIXED_TYPE_WHEN_NOT_IN_GC (key_data, Lisp_Key_Data, XKEY_DATA (ptr)); -#endif /* not NEW_GC */ + FREE_FIXED_TYPE_WHEN_NOT_IN_GC (ptr, key_data, Lisp_Key_Data, + XKEY_DATA (ptr)); } #ifndef NEW_GC @@ -3908,11 +3934,8 @@ void free_button_data (Lisp_Object ptr) { -#ifdef NEW_GC - free_lrecord (ptr); -#else /* not NEW_GC */ - FREE_FIXED_TYPE_WHEN_NOT_IN_GC (button_data, Lisp_Button_Data, XBUTTON_DATA (ptr)); -#endif /* not NEW_GC */ + FREE_FIXED_TYPE_WHEN_NOT_IN_GC (ptr, button_data, Lisp_Button_Data, + XBUTTON_DATA (ptr)); } #ifndef NEW_GC @@ -3929,11 +3952,8 @@ void free_motion_data (Lisp_Object ptr) { -#ifdef NEW_GC - free_lrecord (ptr); -#else /* not NEW_GC */ - FREE_FIXED_TYPE_WHEN_NOT_IN_GC (motion_data, Lisp_Motion_Data, XMOTION_DATA (ptr)); -#endif /* not NEW_GC */ + FREE_FIXED_TYPE_WHEN_NOT_IN_GC (ptr, motion_data, Lisp_Motion_Data, + XMOTION_DATA (ptr)); } #ifndef NEW_GC @@ -3950,11 +3970,8 @@ void free_process_data (Lisp_Object ptr) { -#ifdef NEW_GC - free_lrecord (ptr); -#else /* not NEW_GC */ - FREE_FIXED_TYPE_WHEN_NOT_IN_GC (process_data, Lisp_Process_Data, XPROCESS_DATA (ptr)); -#endif /* not NEW_GC */ + FREE_FIXED_TYPE_WHEN_NOT_IN_GC (ptr, process_data, Lisp_Process_Data, + XPROCESS_DATA (ptr)); } #ifndef NEW_GC @@ -3971,11 +3988,8 @@ void free_timeout_data (Lisp_Object ptr) { -#ifdef NEW_GC - free_lrecord (ptr); -#else /* not NEW_GC */ - FREE_FIXED_TYPE_WHEN_NOT_IN_GC (timeout_data, Lisp_Timeout_Data, XTIMEOUT_DATA (ptr)); -#endif /* not NEW_GC */ + FREE_FIXED_TYPE_WHEN_NOT_IN_GC (ptr, timeout_data, Lisp_Timeout_Data, + XTIMEOUT_DATA (ptr)); } #ifndef NEW_GC @@ -3992,11 +4006,8 @@ void free_magic_data (Lisp_Object ptr) { -#ifdef NEW_GC - free_lrecord (ptr); -#else /* not NEW_GC */ - FREE_FIXED_TYPE_WHEN_NOT_IN_GC (magic_data, Lisp_Magic_Data, XMAGIC_DATA (ptr)); -#endif /* not NEW_GC */ + FREE_FIXED_TYPE_WHEN_NOT_IN_GC (ptr, magic_data, Lisp_Magic_Data, + XMAGIC_DATA (ptr)); } #ifndef NEW_GC @@ -4013,11 +4024,8 @@ void free_magic_eval_data (Lisp_Object ptr) { -#ifdef NEW_GC - free_lrecord (ptr); -#else /* not NEW_GC */ - FREE_FIXED_TYPE_WHEN_NOT_IN_GC (magic_eval_data, Lisp_Magic_Eval_Data, XMAGIC_EVAL_DATA (ptr)); -#endif /* not NEW_GC */ + FREE_FIXED_TYPE_WHEN_NOT_IN_GC (ptr, magic_eval_data, Lisp_Magic_Eval_Data, + XMAGIC_EVAL_DATA (ptr)); } #ifndef NEW_GC @@ -4034,11 +4042,8 @@ void free_eval_data (Lisp_Object ptr) { -#ifdef NEW_GC - free_lrecord (ptr); -#else /* not NEW_GC */ - FREE_FIXED_TYPE_WHEN_NOT_IN_GC (eval_data, Lisp_Eval_Data, XEVAL_DATA (ptr)); -#endif /* not NEW_GC */ + FREE_FIXED_TYPE_WHEN_NOT_IN_GC (ptr, eval_data, Lisp_Eval_Data, + XEVAL_DATA (ptr)); } #ifndef NEW_GC @@ -4055,11 +4060,8 @@ void free_misc_user_data (Lisp_Object ptr) { -#ifdef NEW_GC - free_lrecord (ptr); -#else /* not NEW_GC */ - FREE_FIXED_TYPE_WHEN_NOT_IN_GC (misc_user_data, Lisp_Misc_User_Data, XMISC_USER_DATA (ptr)); -#endif /* not NEW_GC */ + FREE_FIXED_TYPE_WHEN_NOT_IN_GC (ptr, misc_user_data, Lisp_Misc_User_Data, + XMISC_USER_DATA (ptr)); } #endif /* EVENT_DATA_AS_OBJECTS */ @@ -4083,11 +4085,7 @@ void free_marker (Lisp_Object ptr) { -#ifdef NEW_GC - free_lrecord (ptr); -#else /* not NEW_GC */ - FREE_FIXED_TYPE_WHEN_NOT_IN_GC (marker, Lisp_Marker, XMARKER (ptr)); -#endif /* not NEW_GC */ + FREE_FIXED_TYPE_WHEN_NOT_IN_GC (ptr, marker, Lisp_Marker, XMARKER (ptr)); } @@ -4304,6 +4302,10 @@ void gc_sweep_1 (void) { + /* Reset all statistics to 0. They will be incremented when + sweeping lcrecords, frob-block lrecords and dumped objects. */ + xzero (lrecord_stats); + /* Free all unmarked records. Do this at the very beginning, before anything else, so that the finalize methods can safely examine items in the objects. sweep_lcrecords_1() makes @@ -4560,47 +4562,18 @@ #else /* not NEW_GC */ -#define HACK_O_MATIC(type, name, pl) do { \ - EMACS_INT s = 0; \ - struct type##_block *x = current_##type##_block; \ - while (x) { s += sizeof (*x) + MALLOC_OVERHEAD; x = x->prev; } \ - tgu_val += s; \ - (pl) = gc_plist_hack ((name), s, (pl)); \ +#define HACK_O_MATIC(type, name, pl) \ +do { \ + COUNT_FROB_BLOCK_USAGE (type); \ + tgu_val += s; \ + (pl) = gc_plist_hack ((name), s, (pl)); \ } while (0) - for (i = 0; i < lrecord_type_count; i++) - { - if (lcrecord_stats[i].bytes_in_use != 0 - || lcrecord_stats[i].bytes_freed != 0 - || lcrecord_stats[i].instances_on_free_list != 0) - { - Ascbyte buf[255]; - const Ascbyte *name = lrecord_implementations_table[i]->name; - - sprintf (buf, "%s-storage", name); - pl = gc_plist_hack (buf, lcrecord_stats[i].bytes_in_use, pl); - tgu_val += lcrecord_stats[i].bytes_in_use; - pluralize_and_append (buf, name, "-freed"); - if (lcrecord_stats[i].instances_freed != 0) - pl = gc_plist_hack (buf, lcrecord_stats[i].instances_freed, pl); - pluralize_and_append (buf, name, "-on-free-list"); - if (lcrecord_stats[i].instances_on_free_list != 0) - pl = gc_plist_hack (buf, lcrecord_stats[i].instances_on_free_list, - pl); - pluralize_and_append (buf, name, "-used"); - pl = gc_plist_hack (buf, lcrecord_stats[i].instances_in_use, pl); - } - } - -/* The most general version -- handle TYPE, with strings using ENGTYPE - instead (generally the same, but with hyphen in place of underscore) - and ENGTYPES as the plural of ENGTYPE. */ -#define FROB3(type, engtype, engtypes) \ - HACK_O_MATIC (type, engtype "-storage", pl); \ - pl = gc_plist_hack (engtypes "-free", gc_count_num_##type##_freelist, pl); \ - pl = gc_plist_hack (engtypes "-used", gc_count_num_##type##_in_use, pl) - -#define FROB(type) FROB3(type, #type, #type "s") +#define FROB(type) \ +do { \ + COUNT_FROB_BLOCK_USAGE (type); \ + tgu_val += s; \ +} while (0) FROB (extent); FROB (event); @@ -4615,6 +4588,36 @@ #ifdef HAVE_BIGFLOAT FROB (bigfloat); #endif /* HAVE_BIGFLOAT */ + FROB (compiled_function); + FROB (symbol); + FROB (cons); + +#undef FROB + + for (i = 0; i < lrecord_type_count; i++) + { + if (lrecord_stats[i].bytes_in_use != 0 + || lrecord_stats[i].bytes_freed != 0 + || lrecord_stats[i].instances_on_free_list != 0) + { + Ascbyte buf[255]; + const Ascbyte *name = lrecord_implementations_table[i]->name; + + sprintf (buf, "%s-storage", name); + pl = gc_plist_hack (buf, lrecord_stats[i].bytes_in_use, pl); + tgu_val += lrecord_stats[i].bytes_in_use; + pluralize_and_append (buf, name, "-freed"); + if (lrecord_stats[i].instances_freed != 0) + pl = gc_plist_hack (buf, lrecord_stats[i].instances_freed, pl); + pluralize_and_append (buf, name, "-on-free-list"); + if (lrecord_stats[i].instances_on_free_list != 0) + pl = gc_plist_hack (buf, lrecord_stats[i].instances_on_free_list, + pl); + pluralize_and_append (buf, name, "-used"); + pl = gc_plist_hack (buf, lrecord_stats[i].instances_in_use, pl); + } + } + HACK_O_MATIC (string, "string-header-storage", pl); pl = gc_plist_hack ("long-strings-total-length", gc_count_string_total_size @@ -4629,10 +4632,6 @@ pl = gc_plist_hack ("short-strings-used", gc_count_num_short_string_in_use, pl); - FROB3 (compiled_function, "compiled-function", "compiled-functions"); - FROB (symbol); - FROB3 (cons, "cons", "conses"); - #undef HACK_O_MATIC #endif /* NEW_GC */ @@ -4709,8 +4708,9 @@ Fcons (make_int (gc_count_num_marker_in_use), make_int (gc_count_num_marker_freelist)), make_int (gc_count_string_total_size), - make_int (lcrecord_stats[lrecord_type_vector].bytes_in_use + - lcrecord_stats[lrecord_type_vector].bytes_freed), + make_int (lrecord_stats[lrecord_type_vector].bytes_in_use + + lrecord_stats[lrecord_type_vector].bytes_freed + + lrecord_stats[lrecord_type_vector].bytes_on_free_list), object_memory_usage_stats (1)); #endif /* not NEW_GC */ #else /* not ALLOC_TYPE_STATS */
--- a/src/dumper.c Sun Feb 21 05:19:08 2010 -0600 +++ b/src/dumper.c Sun Feb 21 15:29:12 2010 -0600 @@ -1,7 +1,7 @@ /* Portable data dumper for XEmacs. Copyright (C) 1999-2000,2004 Olivier Galibert Copyright (C) 2001 Martin Buchholz - Copyright (C) 2001, 2002, 2003, 2004, 2005 Ben Wing. + Copyright (C) 2001, 2002, 2003, 2004, 2005, 2010 Ben Wing. This file is part of XEmacs. @@ -253,8 +253,20 @@ for (i=0; i<rt->count; i++) { struct lrecord_header *lh = * (struct lrecord_header **) p; +#ifdef ALLOC_TYPE_STATS + if (C_READONLY_RECORD_HEADER_P (lh)) + tick_lrecord_stats (lh, ALLOC_IN_USE); + + else + { + tick_lrecord_stats (lh, MARKED_RECORD_HEADER_P (lh) ? + ALLOC_IN_USE : ALLOC_ON_FREE_LIST); + UNMARK_RECORD_HEADER (lh); + } +#else /* not ALLOC_TYPE_STATS */ if (! C_READONLY_RECORD_HEADER_P (lh)) UNMARK_RECORD_HEADER (lh); +#endif /* (not) ALLOC_TYPE_STATS */ p += sizeof (EMACS_INT); } } else
--- a/src/lrecord.h Sun Feb 21 05:19:08 2010 -0600 +++ b/src/lrecord.h Sun Feb 21 15:29:12 2010 -0600 @@ -523,6 +523,16 @@ #else /* not NEW_GC */ +enum lrecord_alloc_status +{ + ALLOC_IN_USE, + ALLOC_FREE, + ALLOC_ON_FREE_LIST +}; + +void tick_lrecord_stats (const struct lrecord_header *h, + enum lrecord_alloc_status status); + #define LRECORD_FREE_P(ptr) \ (((struct lrecord_header *) ptr)->type == lrecord_type_free)