# HG changeset patch # User Ben Wing # Date 1269515245 18000 # Node ID 5ddbab03b0e66959468285d3db17c8f5b2211d7f # Parent 6c6d78781d592dad3e59a3ad66ce83875a83ecad various fixes to memory-usage stats -------------------- ChangeLog entries follow: -------------------- lisp/ChangeLog addition: 2010-03-25 Ben Wing * diagnose.el (show-memory-usage): * diagnose.el (show-object-memory-usage-stats): Further changes to correspond with changes in the C code; add an additional column in show-object-memory-usage-stats showing the ancillary Lisp overhead used with each type; shrink columns for windows in show-memory-usage to get it to fit in 79 chars. src/ChangeLog addition: 2010-03-25 Ben Wing * alloc.c: * alloc.c (struct): * alloc.c (finish_object_memory_usage_stats): * alloc.c (object_memory_usage_stats): * alloc.c (Fobject_memory_usage): * alloc.c (lisp_object_memory_usage_full): * alloc.c (compute_memusage_stats_length): * lrecord.h: * lrecord.h (struct lrecord_implementation): Add fields to the `lrecord_implementation' structure to list an offset into the array of extra statistics in a `struct generic_usage_stats' and a length, listing the first slice of ancillary Lisp-object memory. Compute automatically in compute_memusage_stats_length(). Use to add an entry `FOO-lisp-ancillary-storage' for object type FOO. Don't crash when an int or char is given to object-memory-usage, signal an error instead. Add functions lisp_object_memory_usage_full() and lisp_object_memory_usage() to compute the total memory usage of an object (sum of object, non-Lisp attached, and Lisp ancillary memory). * array.c: * array.c (gap_array_memory_usage): * array.h: Add function to return memory usage of a gap array. * buffer.c (struct buffer_stats): * buffer.c (compute_buffer_usage): * buffer.c (vars_of_buffer): * extents.c (compute_buffer_extent_usage): * marker.c: * marker.c (compute_buffer_marker_usage): * extents.h: * lisp.h: Remove `struct usage_stats' arg from compute_buffer_marker_usage() and compute_buffer_extent_usage() -- these are ancillary Lisp objects and don't get accumulated into `struct usage_stats'; change the value of `memusage_stats_list' so that `markers' and `extents' memory is in Lisp-ancillary, where it belongs. In compute_buffer_marker_usage(), use lisp_object_memory_usage() rather than lisp_object_storage_size(). * casetab.c: * casetab.c (case_table_memory_usage): * casetab.c (vars_of_casetab): * emacs.c (main_1): Add memory usage stats for case tables. * lisp.h: Add comment explaining the `struct generic_usage_stats' more, as well as the new fields in lrecord_implementation. * console-impl.h: * console-impl.h (struct console_methods): * scrollbar-gtk.c: * scrollbar-gtk.c (gtk_compute_scrollbar_instance_usage): * scrollbar-msw.c: * scrollbar-msw.c (mswindows_compute_scrollbar_instance_usage): * scrollbar-x.c: * scrollbar-x.c (x_compute_scrollbar_instance_usage): * scrollbar.c: * scrollbar.c (struct scrollbar_instance_stats): * scrollbar.c (compute_all_scrollbar_instance_usage): * scrollbar.c (scrollbar_instance_memory_usage): * scrollbar.c (scrollbar_objects_create): * scrollbar.c (vars_of_scrollbar): * scrollbar.h: * symsinit.h: * window.c: * window.c (find_window_mirror_maybe): * window.c (struct window_mirror_stats): * window.c (compute_window_mirror_usage): * window.c (window_mirror_memory_usage): * window.c (compute_window_usage): * window.c (window_objects_create): * window.c (syms_of_window): * window.c (vars_of_window): Redo memory-usage associated with windows, window mirrors, and scrollbar instances. Should fix crash in find_window_mirror, among other things. Properly assign memo ry to object memory, non-Lisp extra memory, and Lisp ancillary memory. For example, redisplay structures are non-Lisp memory hanging off a window mirror, not a window; make it an ancillary Lisp-object field. Window mirrors and scrollbar instances have their own statistics, among other things. diff -r 6c6d78781d59 -r 5ddbab03b0e6 lisp/ChangeLog --- a/lisp/ChangeLog Wed Mar 24 01:22:51 2010 -0500 +++ b/lisp/ChangeLog Thu Mar 25 06:07:25 2010 -0500 @@ -1,3 +1,12 @@ +2010-03-25 Ben Wing + + * diagnose.el (show-memory-usage): + * diagnose.el (show-object-memory-usage-stats): + Further changes to correspond with changes in the C code; + add an additional column in show-object-memory-usage-stats showing + the ancillary Lisp overhead used with each type; shrink columns for + windows in show-memory-usage to get it to fit in 79 chars. + 2010-03-20 Ben Wing * diagnose.el (show-memory-usage): diff -r 6c6d78781d59 -r 5ddbab03b0e6 lisp/diagnose.el --- a/lisp/diagnose.el Wed Mar 24 01:22:51 2010 -0500 +++ b/lisp/diagnose.el Thu Mar 25 06:07:25 2010 -0500 @@ -35,11 +35,12 @@ "Show statistics about memory usage of various sorts in XEmacs." (interactive) (garbage-collect) - (flet ((show-foo-stats (objtypename cleanfun objlist) + (flet ((show-foo-stats (objtypename statname-plist cleanfun objlist + &optional objnamelen) (let* ((hash (make-hash-table)) (first t) - types fmt - (objnamelen 25) + types origtypes fmt + (objnamelen (or objnamelen 25)) (linelen objnamelen) (totaltotal 0)) (loop for obj in objlist do @@ -54,19 +55,22 @@ ;; the memory grouped by type (while (and stats (pop stats))) - (loop for (type . num) in stats while type do + (loop for (type . num) in (remq t stats) while type do + (if first (push type origtypes)) + (setq type (getf statname-plist type type)) (puthash type (+ num (or (gethash type hash) 0)) hash) (incf total num) (if first (push type types))) (incf totaltotal total) (when first (setq types (nreverse types)) + (setq origtypes (nreverse origtypes)) (setq fmt (concat (format "%%-%ds" objnamelen) (mapconcat #'(lambda (type) (let ((fieldlen - (max 8 (+ 2 (length + (max 7 (+ 2 (length (symbol-name type)))))) (incf linelen fieldlen) (format "%%%ds" fieldlen))) @@ -83,7 +87,7 @@ (1- objnamelen))) (nconc (mapcar #'(lambda (type) (cdr (assq type stats))) - types) + origtypes) (list total))))) (setq first nil))) (princ "\n") @@ -103,7 +107,7 @@ (when-fboundp 'charset-list (setq begin (point)) (incf grandtotal - (show-foo-stats 'charset 'charset-name + (show-foo-stats 'charset nil 'charset-name (mapcar 'get-charset (charset-list)))) (when-fboundp 'sort-numeric-fields (sort-numeric-fields -1 @@ -117,7 +121,7 @@ (princ "\n")) (setq begin (point)) (incf grandtotal - (show-foo-stats 'buffer 'buffer-name (buffer-list))) + (show-foo-stats 'buffer nil 'buffer-name (buffer-list))) (when-fboundp 'sort-numeric-fields (sort-numeric-fields -1 (save-excursion @@ -130,11 +134,19 @@ (princ "\n") (setq begin (point)) (incf grandtotal - (show-foo-stats 'window #'(lambda (x) - (buffer-name (window-buffer x))) + (show-foo-stats 'window + '(line-start-cache line-st. + face-cache face + glyph-cache glyph + redisplay-structs redisplay + scrollbar-instances scrollbar + window-mirror mirror) + #'(lambda (x) + (buffer-name (window-buffer x))) (mapcan #'(lambda (fr) (window-list fr t)) - (frame-list)))) + (frame-list)) + 16)) (when-fboundp #'sort-numeric-fields (sort-numeric-fields -1 (save-excursion @@ -152,9 +164,14 @@ (princ (make-string 40 ?-)) (princ "\n") (map-plist #'(lambda (stat num) - (when (string-match - "\\(.*\\)-storage$" - (symbol-name stat)) + (when (and + (not + (string-match + "\\(.*\\)-ancillary-storage$" + (symbol-name stat))) + (string-match + "\\(.*\\)-storage$" + (symbol-name stat))) (incf total num) (princ (format fmt (match-string 1 (symbol-name stat)) @@ -184,12 +201,14 @@ (garbage-collect) (let ((buffer "*object memory usage statistics*") (plist (object-memory-usage-stats)) - (fmt "%-30s%10s%10s%10s%18s\n") + (fmt "%-28s%10s%10s%10s%10s%10s\n") (grandtotal 0) begin) (flet ((show-stats (match-string) - (princ (format fmt "object" "count" "storage" "overhead" - "non-Lisp storage")) + (princ (format "%28s%10s%40s\n" "" "" + "--------------storage---------------")) + (princ (format fmt "object" "count" "object" "overhead" + "non-Lisp" "ancillary")) (princ (make-string 78 ?-)) (princ "\n") (let ((total-use 0) @@ -202,9 +221,13 @@ (let ((symmatch (and (string-match match-string (symbol-name stat)) (match-string 1 (symbol-name stat))))) - (when (and symmatch (or (< (length symmatch) 9) - (not (equal (substring symmatch -9) - "-non-lisp")))) + (when (and symmatch + (or (< (length symmatch) 9) + (not (equal (substring symmatch -9) + "-non-lisp"))) + (or (< (length symmatch) 15) + (not (equal (substring symmatch -15) + "-lisp-ancillary")))) (let* ((storage-use num) (storage-use-overhead (or (plist-get @@ -227,6 +250,12 @@ (intern (concat symmatch "-non-lisp-storage"))) 0)) + (lisp-ancillary-storage + (or (plist-get + plist + (intern (concat symmatch + "-lisp-ancillary-storage"))) + 0)) (storage-count (or (loop for str in '("s-used" "es-used" "-used") for val = (plist-get @@ -251,19 +280,20 @@ (or storage-count "unknown") storage-use storage-use-overhead - non-lisp-storage))))))) + non-lisp-storage + lisp-ancillary-storage))))))) plist) (princ "\n") (princ (format fmt "total" total-count total-use total-use-overhead - total-non-lisp-use)) + total-non-lisp-use "")) (incf grandtotal total-use-with-overhead) (incf grandtotal total-non-lisp-use) (when-fboundp #'sort-numeric-fields - (sort-numeric-fields -3 + (sort-numeric-fields -4 (save-excursion (goto-char begin) - (forward-line 3) + (forward-line 4) (point)) (save-excursion (forward-line -2) diff -r 6c6d78781d59 -r 5ddbab03b0e6 src/ChangeLog --- a/src/ChangeLog Wed Mar 24 01:22:51 2010 -0500 +++ b/src/ChangeLog Thu Mar 25 06:07:25 2010 -0500 @@ -1,3 +1,95 @@ +2010-03-25 Ben Wing + + * alloc.c: + * alloc.c (struct): + * alloc.c (finish_object_memory_usage_stats): + * alloc.c (object_memory_usage_stats): + * alloc.c (Fobject_memory_usage): + * alloc.c (lisp_object_memory_usage_full): + * alloc.c (compute_memusage_stats_length): + * lrecord.h: + * lrecord.h (struct lrecord_implementation): + Add fields to the `lrecord_implementation' structure to list an + offset into the array of extra statistics in a + `struct generic_usage_stats' and a length, listing the first slice + of ancillary Lisp-object memory. Compute automatically in + compute_memusage_stats_length(). Use to add an entry + `FOO-lisp-ancillary-storage' for object type FOO. + + Don't crash when an int or char is given to object-memory-usage, + signal an error instead. + + Add functions lisp_object_memory_usage_full() and + lisp_object_memory_usage() to compute the total memory usage of an + object (sum of object, non-Lisp attached, and Lisp ancillary + memory). + + * array.c: + * array.c (gap_array_memory_usage): + * array.h: + Add function to return memory usage of a gap array. + + * buffer.c (struct buffer_stats): + * buffer.c (compute_buffer_usage): + * buffer.c (vars_of_buffer): + * extents.c (compute_buffer_extent_usage): + * marker.c: + * marker.c (compute_buffer_marker_usage): + * extents.h: + * lisp.h: + Remove `struct usage_stats' arg from compute_buffer_marker_usage() + and compute_buffer_extent_usage() -- these are ancillary Lisp + objects and don't get accumulated into `struct usage_stats'; + change the value of `memusage_stats_list' so that `markers' and + `extents' memory is in Lisp-ancillary, where it belongs. + + In compute_buffer_marker_usage(), use lisp_object_memory_usage() + rather than lisp_object_storage_size(). + + * casetab.c: + * casetab.c (case_table_memory_usage): + * casetab.c (vars_of_casetab): + * emacs.c (main_1): + Add memory usage stats for case tables. + + * lisp.h: + Add comment explaining the `struct generic_usage_stats' more, + as well as the new fields in lrecord_implementation. + + * console-impl.h: + * console-impl.h (struct console_methods): + * scrollbar-gtk.c: + * scrollbar-gtk.c (gtk_compute_scrollbar_instance_usage): + * scrollbar-msw.c: + * scrollbar-msw.c (mswindows_compute_scrollbar_instance_usage): + * scrollbar-x.c: + * scrollbar-x.c (x_compute_scrollbar_instance_usage): + * scrollbar.c: + * scrollbar.c (struct scrollbar_instance_stats): + * scrollbar.c (compute_all_scrollbar_instance_usage): + * scrollbar.c (scrollbar_instance_memory_usage): + * scrollbar.c (scrollbar_objects_create): + * scrollbar.c (vars_of_scrollbar): + * scrollbar.h: + * symsinit.h: + * window.c: + * window.c (find_window_mirror_maybe): + * window.c (struct window_mirror_stats): + * window.c (compute_window_mirror_usage): + * window.c (window_mirror_memory_usage): + * window.c (compute_window_usage): + * window.c (window_objects_create): + * window.c (syms_of_window): + * window.c (vars_of_window): + Redo memory-usage associated with windows, window mirrors, and + scrollbar instances. Should fix crash in find_window_mirror, + among other things. Properly assign memo ry to object memory, + non-Lisp extra memory, and Lisp ancillary memory. For example, + redisplay structures are non-Lisp memory hanging off a window + mirror, not a window; make it an ancillary Lisp-object field. + Window mirrors and scrollbar instances have their own statistics, + among other things. + 2010-03-24 Ben Wing * array.h: @@ -6,7 +98,7 @@ * dumper.c (pdump_store_new_pointer_offsets): * dumper.c (pdump_reloc_one_mc): * elhash.c: - * gc.c (lispdesc_one_description_line_size): + * gc.c (lispdesc_one_description_line_size): * gc.c (kkcc_marking): * lrecord.h: * lrecord.h (IF_NEW_GC): diff -r 6c6d78781d59 -r 5ddbab03b0e6 src/alloc.c --- a/src/alloc.c Wed Mar 24 01:22:51 2010 -0500 +++ b/src/alloc.c Thu Mar 25 06:07:25 2010 -0500 @@ -177,6 +177,7 @@ Bytecount bytes_on_free_list_overhead; #ifdef MEMORY_USAGE_STATS Bytecount nonlisp_bytes_in_use; + Bytecount lisp_ancillary_bytes_in_use; struct generic_usage_stats stats; #endif } lrecord_stats [countof (lrecord_implementations_table)]; @@ -3888,6 +3889,14 @@ lrecord_stats[i].nonlisp_bytes_in_use += lrecord_stats[i].stats.othervals[j]; } + if (imp && imp->num_extra_lisp_ancillary_memusage_stats) + { + int j; + for (j = 0; j < imp->num_extra_lisp_ancillary_memusage_stats; j++) + lrecord_stats[i].lisp_ancillary_bytes_in_use += + lrecord_stats[i].stats.othervals + [j + imp->offset_lisp_ancillary_memusage_stats]; + } } #endif /* defined (MEMORY_USAGE_STATS) && !defined (NEW_GC) */ } @@ -4041,6 +4050,14 @@ pl); tgu_val += lrecord_stats[i].nonlisp_bytes_in_use; } + if (lrecord_stats[i].lisp_ancillary_bytes_in_use) + { + sprintf (buf, "%s-lisp-ancillary-storage", name); + pl = gc_plist_hack (buf, lrecord_stats[i]. + lisp_ancillary_bytes_in_use, + pl); + tgu_val += lrecord_stats[i].lisp_ancillary_bytes_in_use; + } #endif /* MEMORY_USAGE_STATS */ pluralize_and_append (buf, name, "-freed"); if (lrecord_stats[i].instances_freed != 0) @@ -4175,7 +4192,13 @@ struct usage_stats object_stats; int i; Lisp_Object val = Qnil; - Lisp_Object stats_list = OBJECT_PROPERTY (object, memusage_stats_list); + Lisp_Object stats_list; + + if (INTP (object) || CHARP (object)) + invalid_argument ("No memory associated with immediate objects (int or char)", + object); + + stats_list = OBJECT_PROPERTY (object, memusage_stats_list); xzero (object_stats); lisp_object_storage_size (object, &object_stats); @@ -4223,6 +4246,80 @@ return Fnreverse (val); } +/* Compute total memory usage associated with an object, including + + (a) Storage (including overhead) allocated to the object itself + (b) Storage (including overhead) for ancillary non-Lisp structures attached + to the object + (c) Storage (including overhead) for ancillary Lisp objects attached + to the object + + Store the three types of memory into the return values provided they + aren't NULL, and return a sum of the three values. Also store the + structure of individual statistics into STATS if non-zero. + + Note that the value for type (c) is the sum of all three types of + memory associated with the ancillary Lisp objects. +*/ + +Bytecount +lisp_object_memory_usage_full (Lisp_Object object, Bytecount *storage_size, + Bytecount *extra_nonlisp_storage, + Bytecount *extra_lisp_ancillary_storage, + struct generic_usage_stats *stats) +{ + Bytecount total; + struct lrecord_implementation *imp = XRECORD_LHEADER_IMPLEMENTATION (object); + + total = lisp_object_storage_size (object, NULL); + if (storage_size) + *storage_size = total; + + if (HAS_OBJECT_METH_P (object, memory_usage)) + { + int i; + struct generic_usage_stats gustats; + Bytecount sum; + + xzero (gustats); + OBJECT_METH (object, memory_usage, (object, &gustats)); + + if (stats) + *stats = gustats; + + sum = 0; + for (i = 0; i < imp->num_extra_nonlisp_memusage_stats; i++) + sum += gustats.othervals[i]; + total += sum; + if (extra_nonlisp_storage) + *extra_nonlisp_storage = sum; + + sum = 0; + for (i = 0; i < imp->num_extra_lisp_ancillary_memusage_stats; i++) + sum += gustats.othervals[imp->offset_lisp_ancillary_memusage_stats + + i]; + total += sum; + if (extra_lisp_ancillary_storage) + *extra_lisp_ancillary_storage = sum; + } + else + { + if (extra_nonlisp_storage) + *extra_nonlisp_storage = 0; + if (extra_lisp_ancillary_storage) + *extra_lisp_ancillary_storage = 0; + } + + return total; +} + + +Bytecount +lisp_object_memory_usage (Lisp_Object object) +{ + return lisp_object_memory_usage_full (object, NULL, NULL, NULL, NULL); +} + #endif /* MEMORY_USAGE_STATS */ #ifdef ALLOC_TYPE_STATS @@ -4258,10 +4355,6 @@ for (i = 0; i < countof (lrecord_implementations_table); i++) { - int len = 0; - int nonlisp_len = 0; - int seen_break = 0; - struct lrecord_implementation *imp = lrecord_implementations_table[i]; if (!imp) @@ -4272,21 +4365,44 @@ if (EQ (imp->memusage_stats_list, Qnull_pointer)) imp->memusage_stats_list = Qnil; { + Elemcount len = 0; + Elemcount nonlisp_len = 0; + Elemcount lisp_len = 0; + Elemcount lisp_offset = 0; + int group_num = 0; + int slice_num = 0; + LIST_LOOP_2 (item, imp->memusage_stats_list) { - if (!NILP (item) && !EQ (item, Qt)) + if (EQ (item, Qt)) { - len++; - if (!seen_break) - nonlisp_len++; + group_num++; + if (group_num == 1) + lisp_offset = len; + slice_num = 0; + } + else if (EQ (item, Qnil)) + { + slice_num++; } else - seen_break++; + { + if (slice_num == 0) + { + if (group_num == 0) + nonlisp_len++; + else if (group_num == 1) + lisp_len++; + } + len++; + } } + + imp->num_extra_memusage_stats = len; + imp->num_extra_nonlisp_memusage_stats = nonlisp_len; + imp->num_extra_lisp_ancillary_memusage_stats = lisp_len; + imp->offset_lisp_ancillary_memusage_stats = lisp_offset; } - - imp->num_extra_memusage_stats = len; - imp->num_extra_nonlisp_memusage_stats = nonlisp_len; } } diff -r 6c6d78781d59 -r 5ddbab03b0e6 src/array.c --- a/src/array.c Wed Mar 24 01:22:51 2010 -0500 +++ b/src/array.c Thu Mar 25 06:07:25 2010 -0500 @@ -940,6 +940,59 @@ } #endif /* not NEW_GC */ +#ifdef MEMORY_USAGE_STATS + +/* Return memory usage for gap array GA. The returned value is the total + amount of bytes actually being used for the gap array, including all + overhead. The extra amount of space in the gap array that is used + for the gap is counted in GAP_OVERHEAD, not in WAS_REQUESTED. + If NEW_GC, space for gap-array markers is returned through MARKER_ANCILLARY; + otherwise it's added into the gap array usage. */ + +Bytecount +gap_array_memory_usage (Gap_Array *ga, struct usage_stats *stats, + Bytecount *marker_ancillary) +{ + Bytecount total = 0; + + /* We have to be a bit tricky here because not all of the + memory that malloc() will claim as "requested" was actually + requested -- some of it makes up the gap. */ + + Bytecount size = gap_array_byte_size (ga); + Bytecount gap_size = ga->gapsize * ga->elsize; + Bytecount malloc_used = malloced_storage_size (ga, size, 0); + total += malloc_used; + stats->was_requested += size - gap_size; + stats->gap_overhead += gap_size; + stats->malloc_overhead += malloc_used - size; + +#ifdef NEW_GC + { + Bytecount marker_usage = 0; + Gap_Array_Marker *p; + + for (p = ga->markers; p; p = p->next) + marker_usage += lisp_object_memory_usage (wrap_gap_array_marker (p)); + if (marker_ancillary) + *marker_ancillary = marker_usage; + } +#else + { + Gap_Array_Marker *p; + + for (p = ga->markers; p; p = p->next) + total += malloced_storage_size (p, sizeof (p), stats); + if (marker_ancillary) + *marker_ancillary = 0; + } +#endif /* (not) NEW_GC */ + + return total; +} + +#endif /* MEMORY_USAGE_STATS */ + /*****************************************************************************/ /* Initialization */ diff -r 6c6d78781d59 -r 5ddbab03b0e6 src/array.h --- a/src/array.h Wed Mar 24 01:22:51 2010 -0500 +++ b/src/array.h Thu Mar 25 06:07:25 2010 -0500 @@ -763,5 +763,7 @@ Gap_Array *make_gap_array (Elemcount elsize, int USED_IF_NEW_GC (do_lisp)); Gap_Array *gap_array_clone (Gap_Array *ga); void free_gap_array (Gap_Array *ga); +Bytecount gap_array_memory_usage (Gap_Array *ga, struct usage_stats *stats, + Bytecount *marker_ancillary); #endif /* INCLUDED_array_h_ */ diff -r 6c6d78781d59 -r 5ddbab03b0e6 src/buffer.c --- a/src/buffer.c Wed Mar 24 01:22:51 2010 -0500 +++ b/src/buffer.c Thu Mar 25 06:07:25 2010 -0500 @@ -1754,6 +1754,7 @@ { struct usage_stats u; Bytecount text; + /* Ancillary Lisp */ Bytecount markers; Bytecount extents; }; @@ -1787,8 +1788,8 @@ struct usage_stats *ustats) { stats->text += compute_buffer_text_usage (b, ustats); - stats->markers += compute_buffer_marker_usage (b, ustats); - stats->extents += compute_buffer_extent_usage (b, ustats); + stats->markers += compute_buffer_marker_usage (b); + stats->extents += compute_buffer_extent_usage (b); } static void @@ -1976,7 +1977,7 @@ /* This function can GC */ #ifdef MEMORY_USAGE_STATS OBJECT_HAS_PROPERTY - (buffer, memusage_stats_list, list3 (Qtext, Qmarkers, Qextents)); + (buffer, memusage_stats_list, list4 (Qtext, Qt, Qmarkers, Qextents)); #endif /* MEMORY_USAGE_STATS */ staticpro (&QSFundamental); diff -r 6c6d78781d59 -r 5ddbab03b0e6 src/casetab.c --- a/src/casetab.c Wed Mar 24 01:22:51 2010 -0500 +++ b/src/casetab.c Thu Mar 25 06:07:25 2010 -0500 @@ -508,6 +508,38 @@ } +#ifdef MEMORY_USAGE_STATS + +struct case_table_stats +{ + struct usage_stats u; + /* Ancillary Lisp */ + Bytecount downcase, upcase, case_canon, case_eqv; +}; + +static void +case_table_memory_usage (Lisp_Object casetab, + struct generic_usage_stats *gustats) +{ + struct case_table_stats *stats = (struct case_table_stats *) gustats; + + stats->downcase = lisp_object_memory_usage (XCASE_TABLE_DOWNCASE (casetab)); + stats->upcase = lisp_object_memory_usage (XCASE_TABLE_UPCASE (casetab)); + stats->case_canon = lisp_object_memory_usage (XCASE_TABLE_CANON (casetab)); + stats->case_eqv = lisp_object_memory_usage (XCASE_TABLE_EQV (casetab)); +} + +#endif /* MEMORY_USAGE_STATS */ + + +void +casetab_objects_create (void) +{ +#ifdef MEMORY_USAGE_STATS + OBJECT_HAS_METHOD (case_table, memory_usage); +#endif +} + void syms_of_casetab (void) { @@ -530,6 +562,19 @@ } void +vars_of_casetab (void) +{ +#ifdef MEMORY_USAGE_STATS + OBJECT_HAS_PROPERTY (case_table, memusage_stats_list, + list5 (Qt, + intern ("downcase"), + intern ("upcase"), + intern ("case-canon"), + intern ("case-eqv"))); +#endif /* MEMORY_USAGE_STATS */ +} + +void complex_vars_of_casetab (void) { REGISTER Ichar i; diff -r 6c6d78781d59 -r 5ddbab03b0e6 src/console-impl.h --- a/src/console-impl.h Wed Mar 24 01:22:51 2010 -0500 +++ b/src/console-impl.h Thu Mar 25 06:07:25 2010 -0500 @@ -1,5 +1,5 @@ /* Define console object for XEmacs. - Copyright (C) 1996, 2002, 2003, 2005 Ben Wing + Copyright (C) 1996, 2002, 2003, 2005, 2010 Ben Wing This file is part of XEmacs. @@ -290,9 +290,10 @@ scrollbar_instance *); void (*scrollbar_pointer_changed_in_window_method) (struct window *w); #ifdef MEMORY_USAGE_STATS - int (*compute_scrollbar_instance_usage_method) (struct device *, - struct scrollbar_instance *, - struct usage_stats *); + Bytecount (*compute_scrollbar_instance_usage_method) + (struct device *, + struct scrollbar_instance *, + struct usage_stats *); #endif /* Paint the window's deadbox, a rectangle between window borders and two short edges of both scrollbars. */ diff -r 6c6d78781d59 -r 5ddbab03b0e6 src/emacs.c --- a/src/emacs.c Wed Mar 24 01:22:51 2010 -0500 +++ b/src/emacs.c Thu Mar 25 06:07:25 2010 -0500 @@ -1763,6 +1763,7 @@ ) { buffer_objects_create (); + casetab_objects_create (); extent_objects_create (); face_objects_create (); frame_objects_create (); @@ -1772,6 +1773,9 @@ #ifdef MULE mule_charset_objects_create (); #endif +#ifdef HAVE_SCROLLBARS + scrollbar_objects_create (); +#endif #ifdef HAVE_GTK ui_gtk_objects_create (); #endif @@ -2094,6 +2098,7 @@ vars_of_buffer (); vars_of_bytecode (); vars_of_callint (); + vars_of_casetab (); vars_of_chartab (); vars_of_cmdloop (); vars_of_cmds (); diff -r 6c6d78781d59 -r 5ddbab03b0e6 src/extents.c --- a/src/extents.c Wed Mar 24 01:22:51 2010 -0500 +++ b/src/extents.c Thu Mar 25 06:07:25 2010 -0500 @@ -7003,9 +7003,8 @@ #ifdef MEMORY_USAGE_STATS -int -compute_buffer_extent_usage (struct buffer *UNUSED (b), - struct usage_stats *UNUSED (ustats)) +Bytecount +compute_buffer_extent_usage (struct buffer *UNUSED (b)) { /* #### not yet written */ return 0; diff -r 6c6d78781d59 -r 5ddbab03b0e6 src/extents.h --- a/src/extents.h Wed Mar 24 01:22:51 2010 -0500 +++ b/src/extents.h Thu Mar 25 06:07:25 2010 -0500 @@ -218,8 +218,7 @@ #endif #ifdef MEMORY_USAGE_STATS -int compute_buffer_extent_usage (struct buffer *b, - struct usage_stats *ustats); +Bytecount compute_buffer_extent_usage (struct buffer *b); #endif #endif /* INCLUDED_extents_h_ */ diff -r 6c6d78781d59 -r 5ddbab03b0e6 src/lisp.h --- a/src/lisp.h Wed Mar 24 01:22:51 2010 -0500 +++ b/src/lisp.h Thu Mar 25 06:07:25 2010 -0500 @@ -1619,6 +1619,18 @@ Bytecount gap_overhead; }; +/* Generic version of usage stats structure including extra non-Lisp and + Lisp storage associated with the object, but not including the memory + used to hold the object itself. Up to 32 statistics are allowed, + in addition to the statistics in `U', which store another slice onto the + ancillary non-Lisp storage. + + Normally, each object creates its own version of this structure, e.g. + `struct window_stats', which parallels the structure in beginning with + a `struct usage_stats' and followed by Bytecount fields, so that a + pointer to that structure can be cast to a pointer of this structure + and sensible results gotten. */ + struct generic_usage_stats { struct usage_stats u; @@ -5334,7 +5346,7 @@ Lisp_Object noseeum_copy_marker (Lisp_Object, Lisp_Object); Lisp_Object set_marker_restricted (Lisp_Object, Lisp_Object, Lisp_Object); #ifdef MEMORY_USAGE_STATS -Bytecount compute_buffer_marker_usage (struct buffer *, struct usage_stats *); +Bytecount compute_buffer_marker_usage (struct buffer *b); #endif void init_buffer_markers (struct buffer *b); void uninit_buffer_markers (struct buffer *b); diff -r 6c6d78781d59 -r 5ddbab03b0e6 src/lrecord.h --- a/src/lrecord.h Wed Mar 24 01:22:51 2010 -0500 +++ b/src/lrecord.h Thu Mar 25 06:07:25 2010 -0500 @@ -514,8 +514,8 @@ /**********************************************************************/ /* Remaining stuff is not assignable statically using - DEFINE_*_LISP_OBJECT, but must be assigned with OBJECT_HAS_METHOD - or the like. */ + DEFINE_*_LISP_OBJECT, but must be assigned with OBJECT_HAS_METHOD, + OBJECT_HAS_PROPERTY or the like. */ /* These functions allow any object type to have builtin property lists that can be manipulated from the lisp level with @@ -542,34 +542,73 @@ #ifdef MEMORY_USAGE_STATS /* Return memory-usage information about the object in question, stored - into STATS. */ - void (*memory_usage) (Lisp_Object obj, struct generic_usage_stats *stats); + into STATS. - /* Number of additional type-specific statistics related to memory usage. - Automatically calculated (see compute_memusage_stats_length()) based - on the value placed in `memusage_stats_list'. */ - Elemcount num_extra_memusage_stats; + Two types of information are stored: storage (including overhead) for + ancillary non-Lisp structures attached to the object, and storage + (including overhead) for ancillary Lisp objects attached to the + object. The third type of memory-usage information (storage for the + object itself) is not noted here, because it's computed automatically + by the calling function. Also, the computed storage for ancillary + Lisp objects is the sum of all three source of memory associated with + the Lisp object: the object itself, ancillary non-Lisp structures and + ancillary Lisp objects. Note also that the `struct usage_stats u' at + the beginning of the STATS structure is for ancillary non-Lisp usage + *ONLY*; do not store any memory into it related to ancillary Lisp + objects. - /* Number of additional type-specific statistics related to - non-Lisp-Object memory usage for this object. Automatically - calculated (see compute_memusage_stats_length()) based on the value - placed in `memusage_stats_list'. */ - Elemcount num_extra_nonlisp_memusage_stats; + Note that it may be subjective which Lisp objects are considered + "attached" to the object. Some guidelines: + + -- Lisp objects which are "internal" to the main object and not + accessible except through the main object should be included + -- Objects linked by a weak reference should *NOT* be included + */ + void (*memory_usage) (Lisp_Object obj, struct generic_usage_stats *stats); /* List of tags to be given to the extra statistics, one per statistic. Qnil or Qt can be present to separate off different slices. Qnil - separates different slices within the same type of statistics. - Qt separates slices corresponding to different types of statistics. + separates different slices within the same group of statistics. + These represent different ways of partitioning the same memory space. + Qt separates different groups; these represent different spaces of + memory. + If Qt is not present, all slices describe extra non-Lisp-Object memory - associated with a Lisp object. If Qt is present, slices after Qt - describe non-Lisp-Object memory and slices before Qt describe - Lisp-Object memory logically associated with the object. For example, - if the object is a table, then Lisp-Object memory might be the entries - in the table. This info is only advisory since it will duplicate - memory described elsewhere and since it may not be possible to be - completely accurate if the same object occurs multiple times in the - table. */ + associated with a Lisp object. If Qt is present, slices before Qt + describe non-Lisp-Object memory, as before, and slices after Qt + describe ancillary Lisp-Object memory logically associated with the + object. For example, if the object is a table, then ancillary + Lisp-Object memory might be the entries in the table. This info is + only advisory since it will duplicate memory described elsewhere and + since it may not be possible to be completely accurate, e.g. it may + not be clear what to count in "ancillary objects", and the value may + be too high if the same object occurs multiple times in the table. */ Lisp_Object memusage_stats_list; + + /* --------------------------------------------------------------------- */ + + /* The following are automatically computed based on the value in + `memusage_stats_list' (see compute_memusage_stats_length()). */ + + /* Total number of additional type-specific statistics related to memory + usage. */ + Elemcount num_extra_memusage_stats; + + /* Number of additional type-specific statistics belonging to the first + slice of the group describing non-Lisp-Object memory usage for this + object. These stats occur starting at offset 0. */ + Elemcount num_extra_nonlisp_memusage_stats; + + /* The offset into the extra statistics at which the Lisp-Object + memory-usage statistics begin. */ + Elemcount offset_lisp_ancillary_memusage_stats; + + /* Number of additional type-specific statistics belonging to the first + slice of the group describing Lisp-Object memory usage for this + object. These stats occur starting at offset + `offset_lisp_ancillary_memusage_stats'. */ + Elemcount num_extra_lisp_ancillary_memusage_stats; + #endif /* MEMORY_USAGE_STATS */ }; @@ -2040,6 +2079,12 @@ MODULE_API void zero_nonsized_lisp_object (Lisp_Object obj); Bytecount lisp_object_storage_size (Lisp_Object obj, struct usage_stats *ustats); +Bytecount lisp_object_memory_usage_full (Lisp_Object object, + Bytecount *storage_size, + Bytecount *extra_nonlisp_storage, + Bytecount *extra_lisp_storage, + struct generic_usage_stats *stats); +Bytecount lisp_object_memory_usage (Lisp_Object object); void free_normal_lisp_object (Lisp_Object obj); diff -r 6c6d78781d59 -r 5ddbab03b0e6 src/marker.c --- a/src/marker.c Wed Mar 24 01:22:51 2010 -0500 +++ b/src/marker.c Thu Mar 25 06:07:25 2010 -0500 @@ -493,13 +493,13 @@ #ifdef MEMORY_USAGE_STATS Bytecount -compute_buffer_marker_usage (struct buffer *b, struct usage_stats *ustats) +compute_buffer_marker_usage (struct buffer *b) { Lisp_Marker *m; Bytecount total = 0; for (m = BUF_MARKERS (b); m; m = m->next) - total += lisp_object_storage_size (wrap_marker (m), ustats); + total += lisp_object_memory_usage (wrap_marker (m)); return total; } diff -r 6c6d78781d59 -r 5ddbab03b0e6 src/scrollbar-gtk.c --- a/src/scrollbar-gtk.c Wed Mar 24 01:22:51 2010 -0500 +++ b/src/scrollbar-gtk.c Thu Mar 25 06:07:25 2010 -0500 @@ -476,23 +476,15 @@ } #ifdef MEMORY_USAGE_STATS -static int +static Bytecount gtk_compute_scrollbar_instance_usage (struct device *UNUSED (d), struct scrollbar_instance *inst, struct usage_stats *ustats) { - int total = 0; + struct gtk_scrollbar_data *data = + (struct gtk_scrollbar_data *) inst->scrollbar_data; - while (inst) - { - struct gtk_scrollbar_data *data = - (struct gtk_scrollbar_data *) inst->scrollbar_data; - - total += malloced_storage_size (data, sizeof (*data), ustats); - inst = inst->next; - } - - return total; + return malloced_storage_size (data, sizeof (*data), ustats); } #endif /* MEMORY_USAGE_STATS */ diff -r 6c6d78781d59 -r 5ddbab03b0e6 src/scrollbar-msw.c --- a/src/scrollbar-msw.c Wed Mar 24 01:22:51 2010 -0500 +++ b/src/scrollbar-msw.c Thu Mar 25 06:07:25 2010 -0500 @@ -424,23 +424,15 @@ #ifdef MEMORY_USAGE_STATS -static int +static Bytecount mswindows_compute_scrollbar_instance_usage (struct device *UNUSED (d), struct scrollbar_instance *inst, struct usage_stats *ustats) { - int total = 0; + struct mswindows_scrollbar_data *data = + (struct mswindows_scrollbar_data *) inst->scrollbar_data; - while (inst) - { - struct mswindows_scrollbar_data *data = - (struct mswindows_scrollbar_data *) inst->scrollbar_data; - - total += malloced_storage_size (data, sizeof (*data), ustats); - inst = inst->next; - } - - return total; + return malloced_storage_size (data, sizeof (*data), ustats); } #endif /* MEMORY_USAGE_STATS */ diff -r 6c6d78781d59 -r 5ddbab03b0e6 src/scrollbar-x.c --- a/src/scrollbar-x.c Wed Mar 24 01:22:51 2010 -0500 +++ b/src/scrollbar-x.c Thu Mar 25 06:07:25 2010 -0500 @@ -698,23 +698,18 @@ #ifdef MEMORY_USAGE_STATS -static int +static Bytecount x_compute_scrollbar_instance_usage (struct device *UNUSED (d), struct scrollbar_instance *inst, struct usage_stats *ustats) { - int total = 0; + Bytecount total = 0; + struct x_scrollbar_data *data = + (struct x_scrollbar_data *) inst->scrollbar_data; - while (inst) - { - struct x_scrollbar_data *data = - (struct x_scrollbar_data *) inst->scrollbar_data; - - total += malloced_storage_size (data, sizeof (*data), ustats); - total += malloced_storage_size (data->name, 1 + strlen (data->name), - ustats); - inst = inst->next; - } + total += malloced_storage_size (data, sizeof (*data), ustats); + total += malloced_storage_size (data->name, 1 + strlen (data->name), + ustats); return total; } diff -r 6c6d78781d59 -r 5ddbab03b0e6 src/scrollbar.c --- a/src/scrollbar.c Wed Mar 24 01:22:51 2010 -0500 +++ b/src/scrollbar.c Thu Mar 25 06:07:25 2010 -0500 @@ -257,26 +257,43 @@ #ifdef MEMORY_USAGE_STATS -int -compute_scrollbar_instance_usage (struct device *d, - struct scrollbar_instance *inst, - struct usage_stats *ustats) +struct scrollbar_instance_stats { - int total = 0; + struct usage_stats u; + Bytecount device_data; +}; - if (HAS_DEVMETH_P(d, compute_scrollbar_instance_usage)) - total += DEVMETH (d, compute_scrollbar_instance_usage, (d, inst, ustats)); +Bytecount +compute_all_scrollbar_instance_usage (struct scrollbar_instance *inst) +{ + Bytecount total = 0; while (inst) { - total += lisp_object_storage_size (wrap_scrollbar_instance (inst), - ustats); + total += lisp_object_memory_usage (wrap_scrollbar_instance (inst)); inst = inst->next; } return total; } +static void +scrollbar_instance_memory_usage (Lisp_Object scrollbar_instance, + struct generic_usage_stats *gustats) +{ + struct scrollbar_instance_stats *stats = + (struct scrollbar_instance_stats *) gustats; + struct scrollbar_instance *inst = XSCROLLBAR_INSTANCE (scrollbar_instance); + struct device *d = FRAME_XDEVICE (inst->mirror->frame); + Bytecount total = 0; + + if (HAS_DEVMETH_P (d, compute_scrollbar_instance_usage)) + total += DEVMETH (d, compute_scrollbar_instance_usage, (d, inst, + &gustats->u)); + + stats->device_data = total; +} + #endif /* MEMORY_USAGE_STATS */ void @@ -924,6 +941,13 @@ /************************************************************************/ void +scrollbar_objects_create (void) +{ +#ifdef MEMORY_USAGE_STATS + OBJECT_HAS_METHOD (scrollbar_instance, memory_usage); +#endif +} +void syms_of_scrollbar (void) { INIT_LISP_OBJECT (scrollbar_instance); @@ -962,6 +986,12 @@ void vars_of_scrollbar (void) { +#ifdef MEMORY_USAGE_STATS + OBJECT_HAS_PROPERTY + (scrollbar_instance, memusage_stats_list, + list1 (intern ("device-data"))); +#endif /* MEMORY_USAGE_STATS */ + DEFVAR_LISP ("scrollbar-pointer-glyph", &Vscrollbar_pointer_glyph /* *The shape of the mouse-pointer when over a scrollbar. This is a glyph; use `set-glyph-image' to change it. diff -r 6c6d78781d59 -r 5ddbab03b0e6 src/scrollbar.h --- a/src/scrollbar.h Wed Mar 24 01:22:51 2010 -0500 +++ b/src/scrollbar.h Thu Mar 25 06:07:25 2010 -0500 @@ -1,5 +1,6 @@ /* Define scrollbar instance. Copyright (C) 1994, 1995 Board of Trustees, University of Illinois. + Copyright (C) 2010 Ben Wing. This file is part of XEmacs. @@ -65,9 +66,8 @@ struct window_mirror *mirror, int active, int horiz_only); #ifdef MEMORY_USAGE_STATS -int compute_scrollbar_instance_usage (struct device *d, - struct scrollbar_instance *inst, - struct usage_stats *ustats); +Bytecount compute_all_scrollbar_instance_usage (struct scrollbar_instance * + inst); #endif extern Lisp_Object Vscrollbar_width, Vscrollbar_height; diff -r 6c6d78781d59 -r 5ddbab03b0e6 src/symsinit.h --- a/src/symsinit.h Wed Mar 24 01:22:51 2010 -0500 +++ b/src/symsinit.h Thu Mar 25 06:07:25 2010 -0500 @@ -209,6 +209,7 @@ Dump time and post-pdump-load-time. */ void buffer_objects_create (void); +void casetab_objects_create (void); void extent_objects_create (void); void face_objects_create (void); void frame_objects_create (void); @@ -216,6 +217,7 @@ void hash_table_objects_create (void); void lstream_objects_create (void); void mule_charset_objects_create (void); +void scrollbar_objects_create (void); void ui_gtk_objects_create (void); void window_objects_create (void); @@ -354,6 +356,7 @@ void reinit_vars_of_bytecode (void); void vars_of_callint (void); EXTERN_C void vars_of_canna_api (void); +void vars_of_casetab (void); void vars_of_chartab (void); void vars_of_cmdloop (void); void vars_of_cmds (void); diff -r 6c6d78781d59 -r 5ddbab03b0e6 src/window.c --- a/src/window.c Wed Mar 24 01:22:51 2010 -0500 +++ b/src/window.c Thu Mar 25 06:07:25 2010 -0500 @@ -55,7 +55,7 @@ Lisp_Object Qdisplay_buffer; #ifdef MEMORY_USAGE_STATS -Lisp_Object Qface_cache, Qglyph_cache, Qline_start_cache, Qother_redisplay; +Lisp_Object Qface_cache, Qglyph_cache, Qline_start_cache, Qredisplay_structs; #ifdef HAVE_SCROLLBARS Lisp_Object Qscrollbar_instances; #endif @@ -710,6 +710,18 @@ XWINDOW_MIRROR (f->root_mirror), w); } +/* Given a real window, return its mirror structure, if it exists. + Don't do any updating. */ +static struct window_mirror * +find_window_mirror_maybe (struct window *w) +{ + struct frame *f = XFRAME (w->frame); + if (!WINDOW_MIRRORP (f->root_mirror)) + return 0; + return find_window_mirror_internal (f->root_window, + XWINDOW_MIRROR (f->root_mirror), w); +} + /***************************************************************************** find_window_by_pixel_pos @@ -5156,52 +5168,93 @@ #ifdef MEMORY_USAGE_STATS +struct window_mirror_stats +{ + struct usage_stats u; + /* Ancilliary non-lisp */ + Bytecount redisplay_structs; +#ifdef HAVE_SCROLLBARS + /* Ancilliary Lisp */ + Bytecount scrollbar; +#endif +}; + struct window_stats { struct usage_stats u; + /* Ancillary non-Lisp */ + Bytecount line_start; + /* The next two: ancillary non-Lisp under old-GC, ancillary Lisp under + NEW_GC */ Bytecount face; Bytecount glyph; - Bytecount line_start; - Bytecount other_redisplay; + /* The next two are copied out of the window mirror, which is an ancillary + Lisp structure; the first is non-Lisp, the second Lisp, but from our + perspective, they are both counted as Lisp */ + Bytecount redisplay_structs; #ifdef HAVE_SCROLLBARS Bytecount scrollbar; #endif + /* Remaining memory associated with window mirror (ancillary Lisp) */ + Bytecount window_mirror; }; static void compute_window_mirror_usage (struct window_mirror *mir, - struct window_stats *stats, - struct usage_stats *ustats) -{ - if (!mir) - return; + struct window_mirror_stats *stats) +{ + stats->redisplay_structs = + compute_display_line_dynarr_usage (mir->current_display_lines, &stats->u) + + + compute_display_line_dynarr_usage (mir->desired_display_lines, &stats->u); #ifdef HAVE_SCROLLBARS - { - struct device *d = XDEVICE (FRAME_DEVICE (mir->frame)); - - stats->scrollbar += - compute_scrollbar_instance_usage (d, mir->scrollbar_vertical_instance, - ustats); - stats->scrollbar += - compute_scrollbar_instance_usage (d, mir->scrollbar_horizontal_instance, - ustats); - } + stats->scrollbar = + compute_all_scrollbar_instance_usage (mir->scrollbar_vertical_instance) + + compute_all_scrollbar_instance_usage (mir->scrollbar_horizontal_instance); #endif /* HAVE_SCROLLBARS */ - stats->other_redisplay += - compute_display_line_dynarr_usage (mir->current_display_lines, ustats); - stats->other_redisplay += - compute_display_line_dynarr_usage (mir->desired_display_lines, ustats); +} + + +static void +window_mirror_memory_usage (Lisp_Object window_mirror, + struct generic_usage_stats *gustats) +{ + struct window_mirror_stats *stats = (struct window_mirror_stats *) gustats; + + compute_window_mirror_usage (XWINDOW_MIRROR (window_mirror), stats); } static void compute_window_usage (struct window *w, struct window_stats *stats, struct usage_stats *ustats) { - stats->face += compute_face_cachel_usage (w->face_cachels, ustats); - stats->glyph += compute_glyph_cachel_usage (w->glyph_cachels, ustats); - stats->line_start += + stats->line_start = compute_line_start_cache_dynarr_usage (w->line_start_cache, ustats); - compute_window_mirror_usage (find_window_mirror (w), stats, ustats); + stats->face = compute_face_cachel_usage (w->face_cachels, + IF_OLD_GC (ustats)); + stats->glyph = compute_glyph_cachel_usage (w->glyph_cachels, + IF_OLD_GC (ustats)); + { + struct window_mirror *wm; + + wm = find_window_mirror_maybe (w); + if (wm) + { + struct generic_usage_stats gustats; + struct window_mirror_stats *wmstats; + Bytecount total; + total = lisp_object_memory_usage_full (wrap_window_mirror (wm), + NULL, NULL, NULL, &gustats); + wmstats = (struct window_mirror_stats *) &gustats; + stats->redisplay_structs = wmstats->redisplay_structs; + total -= stats->redisplay_structs; +#ifdef HAVE_SCROLLBARS + stats->scrollbar = wmstats->scrollbar; + total -= stats->scrollbar; +#endif + stats->window_mirror = total; + } + } } static void @@ -5396,6 +5449,7 @@ { #ifdef MEMORY_USAGE_STATS OBJECT_HAS_METHOD (window, memory_usage); + OBJECT_HAS_METHOD (window_mirror, memory_usage); #endif } @@ -5422,7 +5476,7 @@ #ifdef HAVE_SCROLLBARS DEFSYMBOL (Qscrollbar_instances); #endif - DEFSYMBOL (Qother_redisplay); + DEFSYMBOL (Qredisplay_structs); #endif DEFSYMBOL (Qtruncate_partial_width_windows); @@ -5516,14 +5570,31 @@ vars_of_window (void) { #ifdef MEMORY_USAGE_STATS - OBJECT_HAS_PROPERTY - (window, memusage_stats_list, - listu (Qface_cache, Qglyph_cache, - Qline_start_cache, Qother_redisplay, + Lisp_Object l; + + l = listu (Qline_start_cache, +#ifdef NEW_GC + Qt, +#endif + Qface_cache, Qglyph_cache, +#ifndef NEW_GC + Qt, +#endif + Qredisplay_structs, #ifdef HAVE_SCROLLBARS - Qscrollbar_instances, + Qscrollbar_instances, #endif - Qunbound)); + intern ("window-mirror"), + Qunbound); + + OBJECT_HAS_PROPERTY (window, memusage_stats_list, l); + + l = listu (Qredisplay_structs, +#ifdef HAVE_SCROLLBARS + Qt, Qscrollbar_instances, +#endif + Qunbound); + OBJECT_HAS_PROPERTY (window_mirror, memusage_stats_list, l); #endif /* MEMORY_USAGE_STATS */ DEFVAR_BOOL ("scroll-on-clipped-lines", &scroll_on_clipped_lines /*