Mercurial > hg > xemacs-beta
changeset 5157:1fae11d56ad2
redo memory-usage mechanism, add way of dynamically initializing Lisp objects
-------------------- ChangeLog entries follow: --------------------
lisp/ChangeLog addition:
2010-03-18 Ben Wing <ben@xemacs.org>
* diagnose.el (show-memory-usage):
Rewrite to take into account API changes in memory-usage functions.
src/ChangeLog addition:
2010-03-18 Ben Wing <ben@xemacs.org>
* alloc.c:
* alloc.c (disksave_object_finalization_1):
* alloc.c (lisp_object_storage_size):
* alloc.c (listu):
* alloc.c (listn):
* alloc.c (Fobject_memory_usage_stats):
* alloc.c (compute_memusage_stats_length):
* alloc.c (Fobject_memory_usage):
* alloc.c (Ftotal_object_memory_usage):
* alloc.c (malloced_storage_size):
* alloc.c (common_init_alloc_early):
* alloc.c (reinit_alloc_objects_early):
* alloc.c (reinit_alloc_early):
* alloc.c (init_alloc_once_early):
* alloc.c (syms_of_alloc):
* alloc.c (reinit_vars_of_alloc):
* buffer.c:
* buffer.c (struct buffer_stats):
* buffer.c (compute_buffer_text_usage):
* buffer.c (compute_buffer_usage):
* buffer.c (buffer_memory_usage):
* buffer.c (buffer_objects_create):
* buffer.c (syms_of_buffer):
* buffer.c (vars_of_buffer):
* console-impl.h (struct console_methods):
* dynarr.c (Dynarr_memory_usage):
* emacs.c (main_1):
* events.c (clear_event_resource):
* extents.c:
* extents.c (compute_buffer_extent_usage):
* extents.c (extent_objects_create):
* extents.h:
* faces.c:
* faces.c (compute_face_cachel_usage):
* faces.c (face_objects_create):
* faces.h:
* general-slots.h:
* glyphs.c:
* glyphs.c (compute_glyph_cachel_usage):
* glyphs.c (glyph_objects_create):
* glyphs.h:
* lisp.h:
* lisp.h (struct usage_stats):
* lrecord.h:
* lrecord.h (enum lrecord_type):
* lrecord.h (struct lrecord_implementation):
* lrecord.h (MC_ALLOC_CALL_FINALIZER_FOR_DISKSAVE):
* lrecord.h (DEFINE_DUMPABLE_LISP_OBJECT):
* lrecord.h (DEFINE_DUMPABLE_SIZABLE_LISP_OBJECT):
* lrecord.h (DEFINE_DUMPABLE_FROB_BLOCK_LISP_OBJECT):
* lrecord.h (DEFINE_DUMPABLE_FROB_BLOCK_SIZABLE_LISP_OBJECT):
* lrecord.h (DEFINE_DUMPABLE_INTERNAL_LISP_OBJECT):
* lrecord.h (DEFINE_DUMPABLE_SIZABLE_INTERNAL_LISP_OBJECT):
* lrecord.h (DEFINE_NODUMP_LISP_OBJECT):
* lrecord.h (DEFINE_NODUMP_SIZABLE_LISP_OBJECT):
* lrecord.h (DEFINE_NODUMP_FROB_BLOCK_LISP_OBJECT):
* lrecord.h (DEFINE_NODUMP_FROB_BLOCK_SIZABLE_LISP_OBJECT):
* lrecord.h (DEFINE_NODUMP_INTERNAL_LISP_OBJECT):
* lrecord.h (DEFINE_NODUMP_SIZABLE_INTERNAL_LISP_OBJECT):
* lrecord.h (MAKE_LISP_OBJECT):
* lrecord.h (DEFINE_DUMPABLE_MODULE_LISP_OBJECT):
* lrecord.h (DEFINE_DUMPABLE_MODULE_SIZABLE_LISP_OBJECT):
* lrecord.h (DEFINE_NODUMP_MODULE_LISP_OBJECT):
* lrecord.h (DEFINE_NODUMP_MODULE_SIZABLE_LISP_OBJECT):
* lrecord.h (MAKE_MODULE_LISP_OBJECT):
* lrecord.h (INIT_LISP_OBJECT):
* lrecord.h (INIT_MODULE_LISP_OBJECT):
* lrecord.h (UNDEF_LISP_OBJECT):
* lrecord.h (UNDEF_MODULE_LISP_OBJECT):
* lrecord.h (DECLARE_LISP_OBJECT):
* lrecord.h (DECLARE_MODULE_API_LISP_OBJECT):
* lrecord.h (DECLARE_MODULE_LISP_OBJECT):
* lstream.c:
* lstream.c (syms_of_lstream):
* lstream.c (vars_of_lstream):
* marker.c:
* marker.c (compute_buffer_marker_usage):
* mc-alloc.c (mc_alloced_storage_size):
* mc-alloc.h:
* mule-charset.c:
* mule-charset.c (struct charset_stats):
* mule-charset.c (compute_charset_usage):
* mule-charset.c (charset_memory_usage):
* mule-charset.c (mule_charset_objects_create):
* mule-charset.c (syms_of_mule_charset):
* mule-charset.c (vars_of_mule_charset):
* redisplay.c:
* redisplay.c (compute_rune_dynarr_usage):
* redisplay.c (compute_display_block_dynarr_usage):
* redisplay.c (compute_glyph_block_dynarr_usage):
* redisplay.c (compute_display_line_dynarr_usage):
* redisplay.c (compute_line_start_cache_dynarr_usage):
* redisplay.h:
* scrollbar-gtk.c (gtk_compute_scrollbar_instance_usage):
* scrollbar-msw.c (mswindows_compute_scrollbar_instance_usage):
* scrollbar-x.c (x_compute_scrollbar_instance_usage):
* scrollbar.c (compute_scrollbar_instance_usage):
* scrollbar.h:
* symbols.c:
* symbols.c (reinit_symbol_objects_early):
* symbols.c (init_symbols_once_early):
* symbols.c (reinit_symbols_early):
* symbols.c (defsymbol_massage_name_1):
* symsinit.h:
* ui-gtk.c:
* ui-gtk.c (emacs_gtk_object_getprop):
* ui-gtk.c (emacs_gtk_object_putprop):
* ui-gtk.c (ui_gtk_objects_create):
* unicode.c (compute_from_unicode_table_size_1):
* unicode.c (compute_to_unicode_table_size_1):
* unicode.c (compute_from_unicode_table_size):
* unicode.c (compute_to_unicode_table_size):
* window.c:
* window.c (struct window_stats):
* window.c (compute_window_mirror_usage):
* window.c (compute_window_usage):
* window.c (window_memory_usage):
* window.c (window_objects_create):
* window.c (syms_of_window):
* window.c (vars_of_window):
* window.h:
Redo memory-usage mechanism, make it general; add way of dynamically
initializing Lisp object types -- OBJECT_HAS_METHOD(), similar to
CONSOLE_HAS_METHOD().
(1) Create OBJECT_HAS_METHOD(), OBJECT_HAS_PROPERTY() etc. for
specifying that a Lisp object type has a particular method or
property. Call such methods with OBJECT_METH, MAYBE_OBJECT_METH,
OBJECT_METH_OR_GIVEN; retrieve properties with OBJECT_PROPERTY.
Methods that formerly required a DEFINE_*GENERAL_LISP_OBJECT() to
specify them (getprop, putprop, remprop, plist, disksave) now
instead use the dynamic-method mechanism. The main benefit of
this is that new methods or properties can be added without
requiring that the declaration statements of all existing methods
be modified. We have to make the `struct lrecord_implementation'
non-const, but I don't think this should have any effect on speed --
the only possible method that's really speed-critical is the
mark method, and we already extract those out into a separate
(non-const) array for increased cache locality.
Object methods need to be reinitialized after pdump, so we put
them in separate functions such as face_objects_create(),
extent_objects_create() and call them appropriately from emacs.c
The only current object property (`memusage_stats_list') that
objects can specify is a Lisp object and gets staticpro()ed so it
only needs to be set during dump time, but because it references
symbols that might not exist in a syms_of_() function, we
initialize it in vars_of_(). There is also an object property
(`num_extra_memusage_stats') that is automatically initialized based
on `memusage_stats_list'; we do that in reinit_vars_of_alloc(),
which is called after all vars_of_() functions are called.
`disksaver' method was renamed `disksave' to correspond with the
name normally given to the function (e.g. disksave_lstream()).
(2) Generalize the memory-usage mechanism in `buffer-memory-usage',
`window-memory-usage', `charset-memory-usage' into an object-type-
specific mechanism called by a single function
`object-memory-usage'. (Former function `object-memory-usage'
renamed to `total-object-memory-usage'). Generalize the mechanism
of different "slices" so that we can have different "classes" of
memory described and different "slices" onto each class; `t'
separates classes, `nil' separates slices. Currently we have
three classes defined: the memory of an object itself,
non-Lisp-object memory associated with the object (e.g. arrays or
dynarrs stored as fields in the object), and Lisp-object memory
associated with the object (other internal Lisp objects stored in
the object). This isn't completely finished yet and we might need
to further separate the "other internal Lisp objects" class into
two classes.
The memory-usage mechanism uses a `struct usage_stats' (renamed
from `struct overhead_stats') to describe a malloc-view onto a set
of allocated memory (listing how much was requested and various
types of overhead) and a more general `struct generic_usage_stats'
(with a `struct usage_stats' in it) to hold all statistics about
object memory. `struct generic_usage_stats' contains an array of
32 Bytecounts, which are statistics of unspecified semantics. The
intention is that individual types declare a corresponding struct
(e.g. `struct window_stats') with the same structure but with
specific fields in place of the array, corresponding to specific
statistics. The number of such statistics is an object property
computed from the list of tags (Lisp symbols describing the
statistics) stored in `memusage_stats_list'. The idea here is to
allow particular object types to customize the number and
semantics of the statistics where completely avoiding consing.
This doesn't matter so much yet, but the intention is to have the
memory usage of all objects computed at the end of GC, at the same
time as other statistics are currently computed. The values for
all statistics for a single type would be added up to compute
aggregate values for all objects of a specific type. To make this
efficient, we can't allow any memory allocation at all.
(3) Create some additional functions for creating lists that
specify the elements directly as args rather than indirectly through
an array: listn() (number of args given), listu() (list terminated
by Qunbound).
(4) Delete a bit of remaining unused C window_config stuff, also
unused lrecord_type_popup_data.
author | Ben Wing <ben@xemacs.org> |
---|---|
date | Thu, 18 Mar 2010 10:50:06 -0500 |
parents | 6bff4f219697 |
children | 9e0b43d3095c |
files | lisp/ChangeLog lisp/diagnose.el src/ChangeLog src/alloc.c src/buffer.c src/console-impl.h src/dynarr.c src/emacs.c src/events.c src/extents.c src/extents.h src/faces.c src/faces.h src/general-slots.h src/glyphs.c src/glyphs.h src/lisp.h src/lrecord.h src/lstream.c src/marker.c src/mc-alloc.c src/mc-alloc.h src/mule-charset.c src/redisplay.c src/redisplay.h src/scrollbar-gtk.c src/scrollbar-msw.c src/scrollbar-x.c src/scrollbar.c src/scrollbar.h src/symbols.c src/symsinit.h src/ui-gtk.c src/unicode.c src/window.c src/window.h |
diffstat | 36 files changed, 1001 insertions(+), 522 deletions(-) [+] |
line wrap: on
line diff
--- a/lisp/ChangeLog Thu Mar 18 10:19:08 2010 -0500 +++ b/lisp/ChangeLog Thu Mar 18 10:50:06 2010 -0500 @@ -1,3 +1,8 @@ +2010-03-18 Ben Wing <ben@xemacs.org> + + * diagnose.el (show-memory-usage): + Rewrite to take into account API changes in memory-usage functions. + 2010-03-15 Ben Wing <ben@xemacs.org> * mule/mule-cmds.el:
--- a/lisp/diagnose.el Thu Mar 18 10:19:08 2010 -0500 +++ b/lisp/diagnose.el Thu Mar 18 10:50:06 2010 -0500 @@ -35,16 +35,25 @@ "Show statistics about memory usage of various sorts in XEmacs." (interactive) (garbage-collect) - (flet ((show-foo-stats (objtypename objlist memfun) + (flet ((show-foo-stats (objtypename cleanfun objlist) (let* ((hash (make-hash-table)) (first t) types fmt (objnamelen 25) (linelen objnamelen) (totaltotal 0)) - (dolist (obj objlist) + (loop for obj in objlist do (let ((total 0) - (stats (funcall memfun obj))) + (stats (object-memory-usage obj))) + ;; Pop off the slice describing the object itself's + ;; memory + (while (and stats (not (eq t (pop stats))))) + ;; Pop off the slice describing the associated + ;; non-Lisp-Object memory from the allocation + ;; perspective, so we can get to the slice describing + ;; the memory grouped by type + (while (and stats (pop stats))) + (loop for (type . num) in stats while type do (puthash type (+ num (or (gethash type hash) 0)) hash) (incf total num) @@ -68,7 +77,7 @@ (append types (list 'total)))) (princ (make-string linelen ?-)) (princ "\n")) - (let ((objname (format "%s" obj))) + (let ((objname (format "%s" (funcall cleanfun obj)))) (princ (apply 'format fmt (substring objname 0 (min (length objname) (1- objnamelen))) @@ -94,8 +103,8 @@ (when-fboundp 'charset-list (setq begin (point)) (incf grandtotal - (show-foo-stats 'charset (charset-list) - #'charset-memory-usage)) + (show-foo-stats 'charset 'charset-name + (mapcar 'get-charset (charset-list)))) (when-fboundp 'sort-numeric-fields (sort-numeric-fields -1 (save-excursion @@ -108,7 +117,7 @@ (princ "\n")) (setq begin (point)) (incf grandtotal - (show-foo-stats 'buffer (buffer-list) #'buffer-memory-usage)) + (show-foo-stats 'buffer 'buffer-name (buffer-list))) (when-fboundp 'sort-numeric-fields (sort-numeric-fields -1 (save-excursion @@ -121,10 +130,11 @@ (princ "\n") (setq begin (point)) (incf grandtotal - (show-foo-stats 'window (mapcan #'(lambda (fr) - (window-list fr t)) - (frame-list)) - #'window-memory-usage)) + (show-foo-stats 'window #'(lambda (x) + (buffer-name (window-buffer x))) + (mapcan #'(lambda (fr) + (window-list fr t)) + (frame-list)))) (when-fboundp #'sort-numeric-fields (sort-numeric-fields -1 (save-excursion
--- a/src/ChangeLog Thu Mar 18 10:19:08 2010 -0500 +++ b/src/ChangeLog Thu Mar 18 10:50:06 2010 -0500 @@ -1,3 +1,207 @@ +2010-03-18 Ben Wing <ben@xemacs.org> + + * alloc.c: + * alloc.c (disksave_object_finalization_1): + * alloc.c (lisp_object_storage_size): + * alloc.c (listu): + * alloc.c (listn): + * alloc.c (Fobject_memory_usage_stats): + * alloc.c (compute_memusage_stats_length): + * alloc.c (Fobject_memory_usage): + * alloc.c (Ftotal_object_memory_usage): + * alloc.c (malloced_storage_size): + * alloc.c (common_init_alloc_early): + * alloc.c (reinit_alloc_objects_early): + * alloc.c (reinit_alloc_early): + * alloc.c (init_alloc_once_early): + * alloc.c (syms_of_alloc): + * alloc.c (reinit_vars_of_alloc): + * buffer.c: + * buffer.c (struct buffer_stats): + * buffer.c (compute_buffer_text_usage): + * buffer.c (compute_buffer_usage): + * buffer.c (buffer_memory_usage): + * buffer.c (buffer_objects_create): + * buffer.c (syms_of_buffer): + * buffer.c (vars_of_buffer): + * console-impl.h (struct console_methods): + * dynarr.c (Dynarr_memory_usage): + * emacs.c (main_1): + * events.c (clear_event_resource): + * extents.c: + * extents.c (compute_buffer_extent_usage): + * extents.c (extent_objects_create): + * extents.h: + * faces.c: + * faces.c (compute_face_cachel_usage): + * faces.c (face_objects_create): + * faces.h: + * general-slots.h: + * glyphs.c: + * glyphs.c (compute_glyph_cachel_usage): + * glyphs.c (glyph_objects_create): + * glyphs.h: + * lisp.h: + * lisp.h (struct usage_stats): + * lrecord.h: + * lrecord.h (enum lrecord_type): + * lrecord.h (struct lrecord_implementation): + * lrecord.h (MC_ALLOC_CALL_FINALIZER_FOR_DISKSAVE): + * lrecord.h (DEFINE_DUMPABLE_LISP_OBJECT): + * lrecord.h (DEFINE_DUMPABLE_SIZABLE_LISP_OBJECT): + * lrecord.h (DEFINE_DUMPABLE_FROB_BLOCK_LISP_OBJECT): + * lrecord.h (DEFINE_DUMPABLE_FROB_BLOCK_SIZABLE_LISP_OBJECT): + * lrecord.h (DEFINE_DUMPABLE_INTERNAL_LISP_OBJECT): + * lrecord.h (DEFINE_DUMPABLE_SIZABLE_INTERNAL_LISP_OBJECT): + * lrecord.h (DEFINE_NODUMP_LISP_OBJECT): + * lrecord.h (DEFINE_NODUMP_SIZABLE_LISP_OBJECT): + * lrecord.h (DEFINE_NODUMP_FROB_BLOCK_LISP_OBJECT): + * lrecord.h (DEFINE_NODUMP_FROB_BLOCK_SIZABLE_LISP_OBJECT): + * lrecord.h (DEFINE_NODUMP_INTERNAL_LISP_OBJECT): + * lrecord.h (DEFINE_NODUMP_SIZABLE_INTERNAL_LISP_OBJECT): + * lrecord.h (MAKE_LISP_OBJECT): + * lrecord.h (DEFINE_DUMPABLE_MODULE_LISP_OBJECT): + * lrecord.h (DEFINE_DUMPABLE_MODULE_SIZABLE_LISP_OBJECT): + * lrecord.h (DEFINE_NODUMP_MODULE_LISP_OBJECT): + * lrecord.h (DEFINE_NODUMP_MODULE_SIZABLE_LISP_OBJECT): + * lrecord.h (MAKE_MODULE_LISP_OBJECT): + * lrecord.h (INIT_LISP_OBJECT): + * lrecord.h (INIT_MODULE_LISP_OBJECT): + * lrecord.h (UNDEF_LISP_OBJECT): + * lrecord.h (UNDEF_MODULE_LISP_OBJECT): + * lrecord.h (DECLARE_LISP_OBJECT): + * lrecord.h (DECLARE_MODULE_API_LISP_OBJECT): + * lrecord.h (DECLARE_MODULE_LISP_OBJECT): + * lstream.c: + * lstream.c (syms_of_lstream): + * lstream.c (vars_of_lstream): + * marker.c: + * marker.c (compute_buffer_marker_usage): + * mc-alloc.c (mc_alloced_storage_size): + * mc-alloc.h: + * mule-charset.c: + * mule-charset.c (struct charset_stats): + * mule-charset.c (compute_charset_usage): + * mule-charset.c (charset_memory_usage): + * mule-charset.c (mule_charset_objects_create): + * mule-charset.c (syms_of_mule_charset): + * mule-charset.c (vars_of_mule_charset): + * redisplay.c: + * redisplay.c (compute_rune_dynarr_usage): + * redisplay.c (compute_display_block_dynarr_usage): + * redisplay.c (compute_glyph_block_dynarr_usage): + * redisplay.c (compute_display_line_dynarr_usage): + * redisplay.c (compute_line_start_cache_dynarr_usage): + * redisplay.h: + * scrollbar-gtk.c (gtk_compute_scrollbar_instance_usage): + * scrollbar-msw.c (mswindows_compute_scrollbar_instance_usage): + * scrollbar-x.c (x_compute_scrollbar_instance_usage): + * scrollbar.c (compute_scrollbar_instance_usage): + * scrollbar.h: + * symbols.c: + * symbols.c (reinit_symbol_objects_early): + * symbols.c (init_symbols_once_early): + * symbols.c (reinit_symbols_early): + * symbols.c (defsymbol_massage_name_1): + * symsinit.h: + * ui-gtk.c: + * ui-gtk.c (emacs_gtk_object_getprop): + * ui-gtk.c (emacs_gtk_object_putprop): + * ui-gtk.c (ui_gtk_objects_create): + * unicode.c (compute_from_unicode_table_size_1): + * unicode.c (compute_to_unicode_table_size_1): + * unicode.c (compute_from_unicode_table_size): + * unicode.c (compute_to_unicode_table_size): + * window.c: + * window.c (struct window_stats): + * window.c (compute_window_mirror_usage): + * window.c (compute_window_usage): + * window.c (window_memory_usage): + * window.c (window_objects_create): + * window.c (syms_of_window): + * window.c (vars_of_window): + * window.h: + Redo memory-usage mechanism, make it general; add way of dynamically + initializing Lisp object types -- OBJECT_HAS_METHOD(), similar to + CONSOLE_HAS_METHOD(). + + (1) Create OBJECT_HAS_METHOD(), OBJECT_HAS_PROPERTY() etc. for + specifying that a Lisp object type has a particular method or + property. Call such methods with OBJECT_METH, MAYBE_OBJECT_METH, + OBJECT_METH_OR_GIVEN; retrieve properties with OBJECT_PROPERTY. + Methods that formerly required a DEFINE_*GENERAL_LISP_OBJECT() to + specify them (getprop, putprop, remprop, plist, disksave) now + instead use the dynamic-method mechanism. The main benefit of + this is that new methods or properties can be added without + requiring that the declaration statements of all existing methods + be modified. We have to make the `struct lrecord_implementation' + non-const, but I don't think this should have any effect on speed -- + the only possible method that's really speed-critical is the + mark method, and we already extract those out into a separate + (non-const) array for increased cache locality. + + Object methods need to be reinitialized after pdump, so we put + them in separate functions such as face_objects_create(), + extent_objects_create() and call them appropriately from emacs.c + The only current object property (`memusage_stats_list') that + objects can specify is a Lisp object and gets staticpro()ed so it + only needs to be set during dump time, but because it references + symbols that might not exist in a syms_of_() function, we + initialize it in vars_of_(). There is also an object property + (`num_extra_memusage_stats') that is automatically initialized based + on `memusage_stats_list'; we do that in reinit_vars_of_alloc(), + which is called after all vars_of_() functions are called. + + `disksaver' method was renamed `disksave' to correspond with the + name normally given to the function (e.g. disksave_lstream()). + + (2) Generalize the memory-usage mechanism in `buffer-memory-usage', + `window-memory-usage', `charset-memory-usage' into an object-type- + specific mechanism called by a single function + `object-memory-usage'. (Former function `object-memory-usage' + renamed to `total-object-memory-usage'). Generalize the mechanism + of different "slices" so that we can have different "classes" of + memory described and different "slices" onto each class; `t' + separates classes, `nil' separates slices. Currently we have + three classes defined: the memory of an object itself, + non-Lisp-object memory associated with the object (e.g. arrays or + dynarrs stored as fields in the object), and Lisp-object memory + associated with the object (other internal Lisp objects stored in + the object). This isn't completely finished yet and we might need + to further separate the "other internal Lisp objects" class into + two classes. + + The memory-usage mechanism uses a `struct usage_stats' (renamed + from `struct overhead_stats') to describe a malloc-view onto a set + of allocated memory (listing how much was requested and various + types of overhead) and a more general `struct generic_usage_stats' + (with a `struct usage_stats' in it) to hold all statistics about + object memory. `struct generic_usage_stats' contains an array of + 32 Bytecounts, which are statistics of unspecified semantics. The + intention is that individual types declare a corresponding struct + (e.g. `struct window_stats') with the same structure but with + specific fields in place of the array, corresponding to specific + statistics. The number of such statistics is an object property + computed from the list of tags (Lisp symbols describing the + statistics) stored in `memusage_stats_list'. The idea here is to + allow particular object types to customize the number and + semantics of the statistics where completely avoiding consing. + This doesn't matter so much yet, but the intention is to have the + memory usage of all objects computed at the end of GC, at the same + time as other statistics are currently computed. The values for + all statistics for a single type would be added up to compute + aggregate values for all objects of a specific type. To make this + efficient, we can't allow any memory allocation at all. + + (3) Create some additional functions for creating lists that + specify the elements directly as args rather than indirectly through + an array: listn() (number of args given), listu() (list terminated + by Qunbound). + + (4) Delete a bit of remaining unused C window_config stuff, also + unused lrecord_type_popup_data. + + 2010-03-18 Ben Wing <ben@xemacs.org> * tests.c:
--- a/src/alloc.c Thu Mar 18 10:19:08 2010 -0500 +++ b/src/alloc.c Thu Mar 18 10:50:06 2010 -0500 @@ -105,7 +105,7 @@ /* All the built-in lisp object types are enumerated in `enum lrecord_type'. Additional ones may be defined by a module (none yet). We leave some room in `lrecord_implementations_table' for such new lisp object types. */ -const struct lrecord_implementation *lrecord_implementations_table[(int)lrecord_type_last_built_in_type + MODULE_DEFINABLE_TYPE_COUNT]; +struct lrecord_implementation *lrecord_implementations_table[(int)lrecord_type_last_built_in_type + MODULE_DEFINABLE_TYPE_COUNT]; int lrecord_type_count = lrecord_type_last_built_in_type; /* This is just for use by the printer, to allow things to print uniquely. @@ -127,6 +127,12 @@ #endif +#ifdef MEMORY_USAGE_STATS +Lisp_Object Qobject_actually_requested, Qobject_malloc_overhead; +Lisp_Object Qother_memory_actually_requested, Qother_memory_malloc_overhead; +Lisp_Object Qother_memory_dynarr_overhead, Qother_memory_gap_overhead; +#endif /* MEMORY_USAGE_STATS */ + /* Very cheesy ways of figuring out how much memory is being used for data. #### Need better (system-dependent) ways. */ void *minimum_address_seen; @@ -760,8 +766,8 @@ debug_print (wrap_pointer_1 (header)); } #endif - if (imp->disksaver && !objh->free) - (imp->disksaver) (wrap_pointer_1 (header)); + if (imp->disksave && !objh->free) + (imp->disksave) (wrap_pointer_1 (header)); } #endif /* not NEW_GC */ } @@ -842,7 +848,7 @@ #ifdef MEMORY_USAGE_STATS Bytecount -lisp_object_storage_size (Lisp_Object obj, struct overhead_stats *ovstats) +lisp_object_storage_size (Lisp_Object obj, struct usage_stats *ustats) { #ifndef NEW_GC const struct lrecord_implementation *imp = @@ -851,20 +857,20 @@ Bytecount size = lisp_object_size (obj); #ifdef NEW_GC - return mc_alloced_storage_size (size, ovstats); + return mc_alloced_storage_size (size, ustats); #else if (imp->frob_block_p) { Bytecount overhead = fixed_type_block_overhead (size); - if (ovstats) + if (ustats) { - ovstats->was_requested += size; - ovstats->malloc_overhead += overhead; + ustats->was_requested += size; + ustats->malloc_overhead += overhead; } return size + overhead; } else - return malloced_storage_size (XPNTR (obj), size, ovstats); + return malloced_storage_size (XPNTR (obj), size, ustats); #endif } @@ -1480,6 +1486,46 @@ return Fcons (obj0, Fcons (obj1, Fcons (obj2, Fcons (obj3, Fcons (obj4, Fcons (obj5, Qnil)))))); } +/* Return a list of arbitrary length, terminated by Qunbound. */ + +Lisp_Object +listu (Lisp_Object first, ...) +{ + Lisp_Object obj = Qnil; + Lisp_Object val; + va_list va; + + va_start (va, first); + val = first; + while (!UNBOUNDP (val)) + { + obj = Fcons (val, obj); + val = va_arg (va, Lisp_Object); + } + va_end (va); + return Fnreverse (obj); +} + +/* Return a list of arbitrary length, with length specified and remaining + args making up the list. */ + +Lisp_Object +listn (int num_args, ...) +{ + int i; + Lisp_Object obj = Qnil; + va_list va; + + va_start (va, num_args); + for (i = 0; i < num_args; i++) + obj = Fcons (va_arg (va, Lisp_Object), obj); + va_end (va); + return Fnreverse (obj); +} + +/* Return a list of arbitrary length, with length specified and an array + of elements. */ + DEFUN ("make-list", Fmake_list, 2, 2, 0, /* Return a new list of length LENGTH, with each element being OBJECT. */ @@ -2434,16 +2480,11 @@ standard way to do finalization when using SWEEP_FIXED_TYPE_BLOCK(). */ -DEFINE_DUMPABLE_FROB_BLOCK_GENERAL_LISP_OBJECT ("string", string, - mark_string, print_string, - 0, string_equal, 0, - string_description, - string_getprop, - string_putprop, - string_remprop, - string_plist, - 0 /* no disksaver */, - Lisp_String); +DEFINE_DUMPABLE_FROB_BLOCK_LISP_OBJECT ("string", string, + mark_string, print_string, + 0, string_equal, 0, + string_description, + Lisp_String); #endif /* not NEW_GC */ #ifdef NEW_GC @@ -2484,17 +2525,9 @@ #endif /* not NEW_GC */ #ifdef NEW_GC -DEFINE_DUMPABLE_GENERAL_LISP_OBJECT ("string", string, - mark_string, print_string, - 0, - string_equal, 0, - string_description, - string_getprop, - string_putprop, - string_remprop, - string_plist, - 0 /* no disksaver */, - Lisp_String); +DEFINE_DUMPABLE_LISP_OBJECT ("string", string, mark_string, print_string, + 0, string_equal, 0, + string_description, Lisp_String); static const struct memory_description string_direct_data_description[] = { @@ -4748,7 +4781,7 @@ return pl; } -DEFUN("object-memory-usage-stats", Fobject_memory_usage_stats, 0, 0 ,"", /* +DEFUN ("object-memory-usage-stats", Fobject_memory_usage_stats, 0, 0, 0, /* Return statistics about memory usage of Lisp objects. */ ()) @@ -4758,6 +4791,127 @@ #endif /* ALLOC_TYPE_STATS */ +#ifdef MEMORY_USAGE_STATS + +/* Compute the number of extra memory-usage statistics associated with an + object. We can't compute this at the time INIT_LISP_OBJECT() is called + because the value of the `memusage_stats_list' property is generally + set afterwards. So we compute the values for all types of objects + after all objects have been initialized. */ + +static void +compute_memusage_stats_length (void) +{ + int i; + + for (i = 0; i < countof (lrecord_implementations_table); i++) + { + int len = 0; + struct lrecord_implementation *imp = lrecord_implementations_table[i]; + + if (!imp) + continue; + /* For some of the early objects, Qnil was not yet initialized at + the time of object initialization, so it came up as Qnull_pointer. + Fix that now. */ + if (EQ (imp->memusage_stats_list, Qnull_pointer)) + imp->memusage_stats_list = Qnil; + { + LIST_LOOP_2 (item, imp->memusage_stats_list) + { + if (!NILP (item) && !EQ (item, Qt)) + len++; + } + } + + imp->num_extra_memusage_stats = len; + } +} + +DEFUN ("object-memory-usage", Fobject_memory_usage, 1, 1, 0, /* +Return stats about the memory usage of OBJECT. +The values returned are in the form of an alist of usage types and byte +counts. The byte counts attempt to encompass all the memory used +by the object (separate from the memory logically associated with any +other object), including internal structures and any malloc() +overhead associated with them. In practice, the byte counts are +underestimated because certain memory usage is very hard to determine +\(e.g. the amount of memory used inside the Xt library or inside the +X server). + +Multiple slices of the total memory usage may be returned, separated +by a nil. Each slice represents a particular view of the memory, a +particular way of partitioning it into groups. Within a slice, there +is no overlap between the groups of memory, and each slice collectively +represents all the memory concerned. The rightmost slice typically +represents the total memory used plus malloc and dynarr overhead. + +Slices describing other Lisp objects logically associated with the +object may be included, separated from other slices by `t' and from +each other by nil if there is more than one. + +#### We have to figure out how to handle the memory used by the object +itself vs. the memory used by substructures. Probably the memory_usage +method should return info only about substructures and related Lisp +objects, since the caller can always find and all info about the object +itself. +*/ + (object)) +{ + struct generic_usage_stats gustats; + struct usage_stats object_stats; + int i; + Lisp_Object val = Qnil; + Lisp_Object stats_list = OBJECT_PROPERTY (object, memusage_stats_list); + + xzero (object_stats); + lisp_object_storage_size (object, &object_stats); + + val = acons (Qobject_actually_requested, + make_int (object_stats.was_requested), val); + val = acons (Qobject_malloc_overhead, + make_int (object_stats.malloc_overhead), val); + assert (!object_stats.dynarr_overhead); + assert (!object_stats.gap_overhead); + + if (!NILP (stats_list)) + { + xzero (gustats); + MAYBE_OBJECT_METH (object, memory_usage, (object, &gustats)); + + val = Fcons (Qt, val); + val = acons (Qother_memory_actually_requested, + make_int (gustats.u.was_requested), val); + val = acons (Qother_memory_malloc_overhead, + make_int (gustats.u.malloc_overhead), val); + if (gustats.u.dynarr_overhead) + val = acons (Qother_memory_dynarr_overhead, + make_int (gustats.u.dynarr_overhead), val); + if (gustats.u.gap_overhead) + val = acons (Qother_memory_gap_overhead, + make_int (gustats.u.gap_overhead), val); + val = Fcons (Qnil, val); + + i = 0; + { + LIST_LOOP_2 (item, stats_list) + { + if (NILP (item) || EQ (item, Qt)) + val = Fcons (item, val); + else + { + val = acons (item, make_int (gustats.othervals[i]), val); + i++; + } + } + } + } + + return Fnreverse (val); +} + +#endif /* MEMORY_USAGE_STATS */ + /* Debugging aids. */ DEFUN ("garbage-collect", Fgarbage_collect, 0, 0, "", /* @@ -4858,7 +5012,7 @@ } #ifdef ALLOC_TYPE_STATS -DEFUN ("object-memory-usage", Fobject_memory_usage, 0, 0, 0, /* +DEFUN ("total-object-memory-usage", Ftotal_object_memory_usage, 0, 0, 0, /* Return total number of bytes used for object storage in XEmacs. This may be helpful in debugging XEmacs's memory usage. See also `consing-since-gc' and `object-memory-usage-stats'. @@ -4950,7 +5104,7 @@ Bytecount malloced_storage_size (void * UNUSED (ptr), Bytecount claimed_size, - struct overhead_stats *stats) + struct usage_stats *stats) { Bytecount orig_claimed_size = claimed_size; @@ -5056,6 +5210,7 @@ #ifndef NEW_GC init_string_chars_alloc (); init_string_alloc (); + /* #### Is it intentional that this is called twice? --ben */ init_string_chars_alloc (); init_cons_alloc (); init_symbol_alloc (); @@ -5164,6 +5319,15 @@ #endif /* defined (__cplusplus) && defined (ERROR_CHECK_GC) */ } +static void +reinit_alloc_objects_early (void) +{ + OBJECT_HAS_METHOD (string, getprop); + OBJECT_HAS_METHOD (string, putprop); + OBJECT_HAS_METHOD (string, remprop); + OBJECT_HAS_METHOD (string, plist); +} + void reinit_alloc_early (void) { @@ -5171,6 +5335,7 @@ #ifndef NEW_GC init_lcrecord_lists (); #endif /* not NEW_GC */ + reinit_alloc_objects_early (); } void @@ -5186,18 +5351,6 @@ dump_add_opaque (lrecord_uid_counter, sizeof (lrecord_uid_counter)); - INIT_LISP_OBJECT (cons); - INIT_LISP_OBJECT (vector); - INIT_LISP_OBJECT (string); -#ifdef NEW_GC - INIT_LISP_OBJECT (string_indirect_data); - INIT_LISP_OBJECT (string_direct_data); -#endif /* NEW_GC */ -#ifndef NEW_GC - INIT_LISP_OBJECT (lcrecord_list); - INIT_LISP_OBJECT (free); -#endif /* not NEW_GC */ - staticpros = Dynarr_new2 (Lisp_Object_ptr_dynarr, Lisp_Object *); Dynarr_resize (staticpros, 1410); /* merely a small optimization */ dump_add_root_block_ptr (&staticpros, &staticpros_description); @@ -5221,6 +5374,21 @@ #else /* not NEW_GC */ init_lcrecord_lists (); #endif /* not NEW_GC */ + + INIT_LISP_OBJECT (cons); + INIT_LISP_OBJECT (vector); + INIT_LISP_OBJECT (string); + +#ifdef NEW_GC + INIT_LISP_OBJECT (string_indirect_data); + INIT_LISP_OBJECT (string_direct_data); +#endif /* NEW_GC */ +#ifndef NEW_GC + INIT_LISP_OBJECT (lcrecord_list); + INIT_LISP_OBJECT (free); +#endif /* not NEW_GC */ + + reinit_alloc_objects_early (); } void @@ -5228,6 +5396,15 @@ { DEFSYMBOL (Qgarbage_collecting); +#ifdef MEMORY_USAGE_STATS + DEFSYMBOL (Qobject_actually_requested); + DEFSYMBOL (Qobject_malloc_overhead); + DEFSYMBOL (Qother_memory_actually_requested); + DEFSYMBOL (Qother_memory_malloc_overhead); + DEFSYMBOL (Qother_memory_dynarr_overhead); + DEFSYMBOL (Qother_memory_gap_overhead); +#endif /* MEMORY_USAGE_STATS */ + DEFSUBR (Fcons); DEFSUBR (Flist); DEFSUBR (Fvector); @@ -5243,8 +5420,11 @@ DEFSUBR (Fpurecopy); #ifdef ALLOC_TYPE_STATS DEFSUBR (Fobject_memory_usage_stats); + DEFSUBR (Ftotal_object_memory_usage); +#endif /* ALLOC_TYPE_STATS */ +#ifdef MEMORY_USAGE_STATS DEFSUBR (Fobject_memory_usage); -#endif /* ALLOC_TYPE_STATS */ +#endif /* MEMORY_USAGE_STATS */ DEFSUBR (Fgarbage_collect); #if 0 DEFSUBR (Fmemory_limit); @@ -5258,6 +5438,14 @@ } void +reinit_vars_of_alloc (void) +{ +#ifdef MEMORY_USAGE_STATS + compute_memusage_stats_length (); +#endif /* MEMORY_USAGE_STATS */ +} + +void vars_of_alloc (void) { #ifdef DEBUG_XEMACS
--- a/src/buffer.c Thu Mar 18 10:19:08 2010 -0500 +++ b/src/buffer.c Thu Mar 18 10:50:06 2010 -0500 @@ -1752,76 +1752,40 @@ struct buffer_stats { - int text; - int markers; - int extents; - int other; + struct usage_stats u; + Bytecount text; + Bytecount markers; + Bytecount extents; }; static Bytecount -compute_buffer_text_usage (struct buffer *b, struct overhead_stats *ovstats) +compute_buffer_text_usage (struct buffer *b, struct usage_stats *ustats) { - int was_requested = b->text->z - 1; + Bytecount was_requested = b->text->z - 1; Bytecount gap = b->text->gap_size + b->text->end_gap_size; Bytecount malloc_use = malloced_storage_size (b->text->beg, was_requested + gap, 0); - ovstats->gap_overhead += gap; - ovstats->was_requested += was_requested; - ovstats->malloc_overhead += malloc_use - (was_requested + gap); + ustats->gap_overhead += gap; + ustats->was_requested += was_requested; + ustats->malloc_overhead += malloc_use - (was_requested + gap); return malloc_use; } static void compute_buffer_usage (struct buffer *b, struct buffer_stats *stats, - struct overhead_stats *ovstats) + struct usage_stats *ustats) { - xzero (*stats); - stats->other += lisp_object_storage_size (wrap_buffer (b), ovstats); - stats->text += compute_buffer_text_usage (b, ovstats); - stats->markers += compute_buffer_marker_usage (b, ovstats); - stats->extents += compute_buffer_extent_usage (b, ovstats); + stats->text += compute_buffer_text_usage (b, ustats); + stats->markers += compute_buffer_marker_usage (b, ustats); + stats->extents += compute_buffer_extent_usage (b, ustats); } -DEFUN ("buffer-memory-usage", Fbuffer_memory_usage, 1, 1, 0, /* -Return stats about the memory usage of buffer BUFFER. -The values returned are in the form of an alist of usage types and byte -counts. The byte counts attempt to encompass all the memory used -by the buffer (separate from the memory logically associated with a -buffer or frame), including internal structures and any malloc() -overhead associated with them. In practice, the byte counts are -underestimated because certain memory usage is very hard to determine -\(e.g. the amount of memory used inside the Xt library or inside the -X server) and because there is other stuff that might logically -be associated with a window, buffer, or frame (e.g. window configurations, -glyphs) but should not obviously be included in the usage counts. - -Multiple slices of the total memory usage may be returned, separated -by a nil. Each slice represents a particular view of the memory, a -particular way of partitioning it into groups. Within a slice, there -is no overlap between the groups of memory, and each slice collectively -represents all the memory concerned. -*/ - (buffer)) +static void +buffer_memory_usage (Lisp_Object buffer, struct generic_usage_stats *gustats) { - struct buffer_stats stats; - struct overhead_stats ovstats; - Lisp_Object val = Qnil; - - CHECK_BUFFER (buffer); /* dead buffers should be allowed, no? */ - xzero (ovstats); - compute_buffer_usage (XBUFFER (buffer), &stats, &ovstats); - - val = acons (Qtext, make_int (stats.text), val); - val = acons (Qmarkers, make_int (stats.markers), val); - val = acons (Qextents, make_int (stats.extents), val); - val = acons (Qother, make_int (stats.other), val); - val = Fcons (Qnil, val); - val = acons (Qactually_requested, make_int (ovstats.was_requested), val); - val = acons (Qmalloc_overhead, make_int (ovstats.malloc_overhead), val); - val = acons (Qgap_overhead, make_int (ovstats.gap_overhead), val); - val = acons (Qdynarr_overhead, make_int (ovstats.dynarr_overhead), val); - - return Fnreverse (val); + struct buffer_stats *stats = (struct buffer_stats *) gustats; + + compute_buffer_usage (XBUFFER (buffer), stats, &stats->u); } #endif /* MEMORY_USAGE_STATS */ @@ -1905,6 +1869,14 @@ void +buffer_objects_create (void) +{ +#ifdef MEMORY_USAGE_STATS + OBJECT_HAS_METHOD (buffer, memory_usage); +#endif +} + +void syms_of_buffer (void) { INIT_LISP_OBJECT (buffer); @@ -1969,9 +1941,6 @@ DEFSUBR (Fbarf_if_buffer_read_only); DEFSUBR (Fbury_buffer); DEFSUBR (Fkill_all_local_variables); -#ifdef MEMORY_USAGE_STATS - DEFSUBR (Fbuffer_memory_usage); -#endif #if defined (DEBUG_XEMACS) && defined (MULE) DEFSUBR (Fbuffer_char_byte_converion_info); DEFSUBR (Fstring_char_byte_converion_info); @@ -1994,6 +1963,11 @@ vars_of_buffer (void) { /* This function can GC */ +#ifdef MEMORY_USAGE_STATS + OBJECT_HAS_PROPERTY + (buffer, memusage_stats_list, list3 (Qtext, Qmarkers, Qextents)); +#endif /* MEMORY_USAGE_STATS */ + staticpro (&QSFundamental); staticpro (&QSscratch);
--- a/src/console-impl.h Thu Mar 18 10:19:08 2010 -0500 +++ b/src/console-impl.h Thu Mar 18 10:50:06 2010 -0500 @@ -292,7 +292,7 @@ #ifdef MEMORY_USAGE_STATS int (*compute_scrollbar_instance_usage_method) (struct device *, struct scrollbar_instance *, - struct overhead_stats *); + struct usage_stats *); #endif /* Paint the window's deadbox, a rectangle between window borders and two short edges of both scrollbars. */
--- a/src/dynarr.c Thu Mar 18 10:19:08 2010 -0500 +++ b/src/dynarr.c Thu Mar 18 10:50:06 2010 -0500 @@ -422,7 +422,7 @@ See the comment above the definition of this structure. */ Bytecount -Dynarr_memory_usage (void *d, struct overhead_stats *stats) +Dynarr_memory_usage (void *d, struct usage_stats *stats) { Bytecount total = 0; Dynarr *dy = (Dynarr *) d;
--- a/src/emacs.c Thu Mar 18 10:19:08 2010 -0500 +++ b/src/emacs.c Thu Mar 18 10:50:06 2010 -0500 @@ -1464,7 +1464,26 @@ /* Make sure that eistrings can be created. */ init_eistring_once_early (); - + } +#ifdef PDUMP + else if (!restart) /* after successful pdump_load() + (note, we are inside ifdef PDUMP) */ + { + reinit_alloc_early (); + reinit_gc_early (); + reinit_symbols_early (); +#ifndef NEW_GC + reinit_opaque_early (); +#endif /* not NEW_GC */ + reinit_eistring_early (); +#ifdef WITH_NUMBER_TYPES + reinit_vars_of_number (); +#endif + } +#endif /* PDUMP */ + + if (!initialized) + { /* Now declare all the symbols and define all the Lisp primitives. The *only* thing that the syms_of_*() functions are allowed to do @@ -1549,6 +1568,7 @@ syms_of_intl (); syms_of_keymap (); syms_of_lread (); + syms_of_lstream (); syms_of_macros (); syms_of_marker (); syms_of_md5 (); @@ -1732,7 +1752,28 @@ #if defined (HAVE_POSTGRESQL) && !defined (HAVE_SHLIB) syms_of_postgresql (); #endif - + } + + if (!initialized +#ifdef PDUMP + || !restart +#endif + ) + { + buffer_objects_create (); + extent_objects_create (); + face_objects_create (); + glyph_objects_create (); + lstream_objects_create (); + mule_charset_objects_create (); +#ifdef HAVE_GTK + ui_gtk_objects_create (); +#endif + window_objects_create (); + } + + if (!initialized) + { /* Now create the subtypes for the types that have them. We do this before the vars_*() because more symbols may get initialized here. */ @@ -1896,17 +1937,6 @@ else if (!restart) /* after successful pdump_load() (note, we are inside ifdef PDUMP) */ { - reinit_alloc_early (); - reinit_gc_early (); - reinit_symbols_early (); -#ifndef NEW_GC - reinit_opaque_early (); -#endif /* not NEW_GC */ - reinit_eistring_early (); -#ifdef WITH_NUMBER_TYPES - reinit_vars_of_number (); -#endif - reinit_console_type_create_stream (); #ifdef HAVE_TTY reinit_console_type_create_tty (); @@ -2305,6 +2335,7 @@ { /* Now do additional vars_of_*() initialization that happens both at dump time and after pdump load. */ + reinit_vars_of_alloc (); reinit_vars_of_buffer (); reinit_vars_of_bytecode (); reinit_vars_of_console ();
--- a/src/events.c Thu Mar 18 10:19:08 2010 -0500 +++ b/src/events.c Thu Mar 18 10:50:06 2010 -0500 @@ -62,7 +62,7 @@ /* definition of event object */ /************************************************************************/ -/* #### Ad-hoc hack. Should be part of DEFINE_*_GENERAL_LISP_OBJECT. */ +/* #### Ad-hoc hack. Should be an object method. */ void clear_event_resource (void) {
--- a/src/extents.c Thu Mar 18 10:19:08 2010 -0500 +++ b/src/extents.c Thu Mar 18 10:50:06 2010 -0500 @@ -3462,20 +3462,17 @@ return Fextent_properties (obj); } -DEFINE_DUMPABLE_FROB_BLOCK_GENERAL_LISP_OBJECT ("extent", extent, - mark_extent, - print_extent, - /* NOTE: If you declare a - finalization method here, - it will NOT be called. - Shaft city. */ - 0, - extent_equal, extent_hash, - extent_description, - extent_getprop, extent_putprop, - extent_remprop, extent_plist, - 0 /* no disksaver */, - struct extent); +DEFINE_DUMPABLE_FROB_BLOCK_LISP_OBJECT ("extent", extent, + mark_extent, + print_extent, + /* NOTE: If you declare a + finalization method here, + it will NOT be called. + Shaft city. */ + 0, + extent_equal, extent_hash, + extent_description, + struct extent); /************************************************************************/ /* basic extent accessors */ @@ -7419,7 +7416,7 @@ int compute_buffer_extent_usage (struct buffer *UNUSED (b), - struct overhead_stats *UNUSED (ovstats)) + struct usage_stats *UNUSED (ustats)) { /* #### not yet written */ return 0; @@ -7433,6 +7430,15 @@ /************************************************************************/ void +extent_objects_create (void) +{ + OBJECT_HAS_METHOD (extent, getprop); + OBJECT_HAS_METHOD (extent, putprop); + OBJECT_HAS_METHOD (extent, remprop); + OBJECT_HAS_METHOD (extent, plist); +} + +void syms_of_extents (void) { INIT_LISP_OBJECT (extent);
--- a/src/extents.h Thu Mar 18 10:19:08 2010 -0500 +++ b/src/extents.h Thu Mar 18 10:50:06 2010 -0500 @@ -238,7 +238,7 @@ #ifdef MEMORY_USAGE_STATS int compute_buffer_extent_usage (struct buffer *b, - struct overhead_stats *ovstats); + struct usage_stats *ustats); #endif #endif /* INCLUDED_extents_h_ */
--- a/src/faces.c Thu Mar 18 10:19:08 2010 -0500 +++ b/src/faces.c Thu Mar 18 10:50:06 2010 -0500 @@ -314,13 +314,10 @@ { XD_END } }; -DEFINE_DUMPABLE_GENERAL_LISP_OBJECT ("face", face, - mark_face, print_face, 0, face_equal, - face_hash, face_description, - face_getprop, - face_putprop, face_remprop, - face_plist, 0 /* no disksaver */, - Lisp_Face); +DEFINE_DUMPABLE_LISP_OBJECT ("face", face, + mark_face, print_face, 0, face_equal, + face_hash, face_description, + Lisp_Face); /************************************************************************/ /* face read syntax */ @@ -1652,7 +1649,7 @@ int compute_face_cachel_usage (face_cachel_dynarr *face_cachels, - struct overhead_stats *ovstats) + struct usage_stats *ustats) { int total = 0; @@ -1660,12 +1657,12 @@ { int i; - total += Dynarr_memory_usage (face_cachels, ovstats); + total += Dynarr_memory_usage (face_cachels, ustats); for (i = 0; i < Dynarr_length (face_cachels); i++) { int_dynarr *merged = Dynarr_at (face_cachels, i).merged_faces; if (merged) - total += Dynarr_memory_usage (merged, ovstats); + total += Dynarr_memory_usage (merged, ustats); } } @@ -2112,6 +2109,15 @@ void +face_objects_create (void) +{ + OBJECT_HAS_METHOD (face, getprop); + OBJECT_HAS_METHOD (face, putprop); + OBJECT_HAS_METHOD (face, remprop); + OBJECT_HAS_METHOD (face, plist); +} + +void syms_of_faces (void) { INIT_LISP_OBJECT (face);
--- a/src/faces.h Thu Mar 18 10:19:08 2010 -0500 +++ b/src/faces.h Thu Mar 18 10:50:06 2010 -0500 @@ -281,7 +281,7 @@ #ifdef MEMORY_USAGE_STATS int compute_face_cachel_usage (face_cachel_dynarr *face_cachels, - struct overhead_stats *ovstats); + struct usage_stats *ustats); #endif /* MEMORY_USAGE_STATS */ EXFUN (Fface_name, 1);
--- a/src/general-slots.h Thu Mar 18 10:19:08 2010 -0500 +++ b/src/general-slots.h Thu Mar 18 10:50:06 2010 -0500 @@ -1,6 +1,6 @@ /* Commonly-used symbols -- include file Copyright (C) 1995 Sun Microsystems. - Copyright (C) 1995, 1996, 2000, 2001, 2002, 2003 Ben Wing. + Copyright (C) 1995, 1996, 2000, 2001, 2002, 2003, 2010 Ben Wing. This file is part of XEmacs. @@ -46,7 +46,6 @@ SYMBOL (Qabort); SYMBOL_KEYWORD (Q_accelerator); SYMBOL_KEYWORD (Q_active); -SYMBOL (Qactually_requested); SYMBOL (Qafter); SYMBOL (Qall); SYMBOL_KEYWORD (Q_allow_other_keys); @@ -115,7 +114,6 @@ SYMBOL (Qdoc_string); SYMBOL (Qdocumentation); SYMBOL (Qduplex); -SYMBOL (Qdynarr_overhead); SYMBOL (Qemergency); SYMBOL (Qempty); SYMBOL (Qencode_as_utf_8); @@ -143,7 +141,6 @@ SYMBOL (Qfull_assoc); SYMBOL (Qfuncall); SYMBOL (Qfunction); -SYMBOL (Qgap_overhead); SYMBOL (Qgarbage_collection); SYMBOL (Qgeneric); SYMBOL (Qgeometry); @@ -193,7 +190,6 @@ SYMBOL (Qlocale); SYMBOL (Qlow); SYMBOL (Qmagic); -SYMBOL (Qmalloc_overhead); SYMBOL_KEYWORD (Q_margin_width); SYMBOL (Qmarkers); SYMBOL (Qmax);
--- a/src/glyphs.c Thu Mar 18 10:19:08 2010 -0500 +++ b/src/glyphs.c Thu Mar 18 10:50:06 2010 -0500 @@ -3818,14 +3818,11 @@ { XD_END } }; -DEFINE_DUMPABLE_GENERAL_LISP_OBJECT ("glyph", glyph, - mark_glyph, print_glyph, 0, - glyph_equal, glyph_hash, - glyph_description, - glyph_getprop, glyph_putprop, - glyph_remprop, glyph_plist, - 0 /* no disksaver */, - Lisp_Glyph); +DEFINE_DUMPABLE_LISP_OBJECT ("glyph", glyph, + mark_glyph, print_glyph, 0, + glyph_equal, glyph_hash, + glyph_description, + Lisp_Glyph); Lisp_Object allocate_glyph (enum glyph_type type, @@ -4477,12 +4474,12 @@ int compute_glyph_cachel_usage (glyph_cachel_dynarr *glyph_cachels, - struct overhead_stats *ovstats) + struct usage_stats *ustats) { int total = 0; if (glyph_cachels) - total += Dynarr_memory_usage (glyph_cachels, ovstats); + total += Dynarr_memory_usage (glyph_cachels, ustats); return total; } @@ -5187,6 +5184,15 @@ *****************************************************************************/ void +glyph_objects_create (void) +{ + OBJECT_HAS_METHOD (glyph, getprop); + OBJECT_HAS_METHOD (glyph, putprop); + OBJECT_HAS_METHOD (glyph, remprop); + OBJECT_HAS_METHOD (glyph, plist); +} + +void syms_of_glyphs (void) { INIT_LISP_OBJECT (glyph);
--- a/src/glyphs.h Thu Mar 18 10:19:08 2010 -0500 +++ b/src/glyphs.h Thu Mar 18 10:50:06 2010 -0500 @@ -1165,7 +1165,7 @@ #ifdef MEMORY_USAGE_STATS int compute_glyph_cachel_usage (glyph_cachel_dynarr *glyph_cachels, - struct overhead_stats *ovstats); + struct usage_stats *ustats); #endif /* MEMORY_USAGE_STATS */ /************************************************************************/
--- a/src/lisp.h Thu Mar 18 10:19:08 2010 -0500 +++ b/src/lisp.h Thu Mar 18 10:50:06 2010 -0500 @@ -1613,12 +1613,18 @@ the fields to 0, and add any existing values to whatever was there before; this way, you can get a cumulative effect. */ -struct overhead_stats +struct usage_stats { - int was_requested; - int malloc_overhead; - int dynarr_overhead; - int gap_overhead; + Bytecount was_requested; + Bytecount malloc_overhead; + Bytecount dynarr_overhead; + Bytecount gap_overhead; +}; + +struct generic_usage_stats +{ + struct usage_stats u; + Bytecount othervals[32]; }; #endif /* MEMORY_USAGE_STATS */ @@ -2175,8 +2181,8 @@ #define Dynarr_reset(d) Dynarr_set_lengthr (d, 0) #ifdef MEMORY_USAGE_STATS -struct overhead_stats; -Bytecount Dynarr_memory_usage (void *d, struct overhead_stats *stats); +struct usage_stats; +Bytecount Dynarr_memory_usage (void *d, struct usage_stats *stats); #endif /************* Adding/deleting elements to/from a dynarr *************/ @@ -4779,10 +4785,12 @@ MODULE_API Lisp_Object list3 (Lisp_Object, Lisp_Object, Lisp_Object); MODULE_API Lisp_Object list4 (Lisp_Object, Lisp_Object, Lisp_Object, Lisp_Object); -MODULE_API Lisp_Object list5 (Lisp_Object, Lisp_Object, Lisp_Object, Lisp_Object, - Lisp_Object); -MODULE_API Lisp_Object list6 (Lisp_Object, Lisp_Object, Lisp_Object, Lisp_Object, +MODULE_API Lisp_Object list5 (Lisp_Object, Lisp_Object, Lisp_Object, Lisp_Object, Lisp_Object); +MODULE_API Lisp_Object list6 (Lisp_Object, Lisp_Object, Lisp_Object, + Lisp_Object, Lisp_Object, Lisp_Object); +MODULE_API Lisp_Object listn (int numargs, ...); +MODULE_API Lisp_Object listu (Lisp_Object, ...); DECLARE_DOESNT_RETURN (memory_full (void)); void disksave_object_finalization (void); extern int purify_flag; @@ -4831,7 +4839,7 @@ void recompute_funcall_allocation_flag (void); #ifdef MEMORY_USAGE_STATS -Bytecount malloced_storage_size (void *, Bytecount, struct overhead_stats *); +Bytecount malloced_storage_size (void *, Bytecount, struct usage_stats *); Bytecount fixed_type_block_overhead (Bytecount); #endif @@ -5926,7 +5934,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 -int compute_buffer_marker_usage (struct buffer *, struct overhead_stats *); +int compute_buffer_marker_usage (struct buffer *, struct usage_stats *); #endif void init_buffer_markers (struct buffer *b); void uninit_buffer_markers (struct buffer *b); @@ -6601,9 +6609,9 @@ extern Lisp_Object Qutf_16, Qutf_8, Qucs_4, Qutf_7, Qutf_32; #ifdef MEMORY_USAGE_STATS Bytecount compute_from_unicode_table_size (Lisp_Object charset, - struct overhead_stats *stats); + struct usage_stats *stats); Bytecount compute_to_unicode_table_size (Lisp_Object charset, - struct overhead_stats *stats); + struct usage_stats *stats); #endif /* MEMORY_USAGE_STATS */ /* Defined in undo.c */
--- a/src/lrecord.h Thu Mar 18 10:19:08 2010 -0500 +++ b/src/lrecord.h Thu Mar 18 10:50:06 2010 -0500 @@ -364,9 +364,7 @@ lrecord_type_frame, lrecord_type_window, lrecord_type_window_mirror, - lrecord_type_window_configuration, lrecord_type_gui_item, - lrecord_type_popup_data, lrecord_type_toolbar_button, lrecord_type_scrollbar_instance, lrecord_type_color_instance, @@ -490,29 +488,6 @@ /* Data layout description for your object. See long comment below. */ const struct memory_description *description; - /* These functions allow any object type to have builtin property - lists that can be manipulated from the lisp level with - `get', `put', `remprop', and `object-plist'. */ - Lisp_Object (*getprop) (Lisp_Object obj, Lisp_Object prop); - int (*putprop) (Lisp_Object obj, Lisp_Object prop, Lisp_Object val); - int (*remprop) (Lisp_Object obj, Lisp_Object prop); - Lisp_Object (*plist) (Lisp_Object obj); - - /* `disksaver' is called at dump time. It is used for objects that - contain pointers or handles to objects created in external libraries, - such as window-system windows or file handles. Such external objects - cannot be dumped, so it is necessary to release them at dump time and - arrange somehow or other for them to be resurrected if necessary later - on. - - It seems that even non-dumpable objects may be around at dump time, - and a disksaver may be provided. (In fact, the only object currently - with a disksaver, lstream, is non-dumpable.) - - Objects rarely need to provide this method; most of the time it will - be NULL. */ - void (*disksaver) (Lisp_Object); - /* Only one of `static_size' and `size_in_bytes_method' is non-0. If `static_size' is 0, this type is not instantiable by ALLOC_NORMAL_LISP_OBJECT(). If both are 0 (this should never happen), @@ -530,6 +505,60 @@ is (usually) allocated in frob blocks. */ unsigned int frob_block_p :1; #endif /* not NEW_GC */ + + /**********************************************************************/ + /* Remaining stuff is not assignable statically using + DEFINE_*_LISP_OBJECT, but must be assigned with OBJECT_HAS_METHOD + or the like. */ + + /* These functions allow any object type to have builtin property + lists that can be manipulated from the lisp level with + `get', `put', `remprop', and `object-plist'. */ + Lisp_Object (*getprop) (Lisp_Object obj, Lisp_Object prop); + int (*putprop) (Lisp_Object obj, Lisp_Object prop, Lisp_Object val); + int (*remprop) (Lisp_Object obj, Lisp_Object prop); + Lisp_Object (*plist) (Lisp_Object obj); + + /* `disksave' is called at dump time. It is used for objects that + contain pointers or handles to objects created in external libraries, + such as window-system windows or file handles. Such external objects + cannot be dumped, so it is necessary to release them at dump time and + arrange somehow or other for them to be resurrected if necessary later + on. + + It seems that even non-dumpable objects may be around at dump time, + and a disksave may be provided. (In fact, the only object currently + with a disksave, lstream, is non-dumpable.) + + Objects rarely need to provide this method; most of the time it will + be NULL. */ + void (*disksave) (Lisp_Object); + +#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); + + /* 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; + + /* 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. + 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. */ + Lisp_Object memusage_stats_list; +#endif /* MEMORY_USAGE_STATS */ }; /* All the built-in lisp object types are enumerated in `enum lrecord_type'. @@ -537,7 +566,7 @@ room in `lrecord_implementations_table' for such new lisp object types. */ #define MODULE_DEFINABLE_TYPE_COUNT 32 -extern MODULE_API const struct lrecord_implementation * +extern MODULE_API struct lrecord_implementation * lrecord_implementations_table[lrecord_type_last_built_in_type + MODULE_DEFINABLE_TYPE_COUNT]; /* Given a Lisp object, return its implementation @@ -593,8 +622,8 @@ { \ const struct lrecord_implementation *MCACF_implementation \ = LHEADER_IMPLEMENTATION (MCACF_lheader); \ - if (MCACF_implementation && MCACF_implementation->disksaver) \ - MCACF_implementation->disksaver (MCACF_obj); \ + if (MCACF_implementation && MCACF_implementation->disksave) \ + MCACF_implementation->disksave (MCACF_obj); \ } \ } while (0) @@ -1271,12 +1300,6 @@ customize the print method, use the normal DEFINE_*_LISP_OBJECT mechanism for defining these objects. - DEFINE_*_GENERAL_LISP_OBJECT is for objects that need to provide one of - the less common methods that are omitted on most objects. These methods - include the methods supporting the unified property interface using - `get', `put', `remprop' and `object-plist', and (for dumpable objects - only) the `disksaver' method. - DEFINE_MODULE_* is for objects defined in an external module. MAKE_LISP_OBJECT and MAKE_MODULE_LISP_OBJECT are what underlies all of @@ -1294,133 +1317,128 @@ /********* The dumpable versions *********** */ #define DEFINE_DUMPABLE_LISP_OBJECT(name,c_name,marker,printer,nuker,equal,hash,desc,structtype) \ -DEFINE_DUMPABLE_GENERAL_LISP_OBJECT(name,c_name,marker,printer,nuker,equal,hash,desc,0,0,0,0,0,structtype) - -#define DEFINE_DUMPABLE_GENERAL_LISP_OBJECT(name,c_name,marker,printer,nuker,equal,hash,desc,getprop,putprop,remprop,plist,disksaver,structtype) \ -MAKE_LISP_OBJECT(name,c_name,1 /*dumpable*/,marker,printer,nuker,equal,hash,desc,getprop,putprop,remprop,plist,disksaver,sizeof (structtype),0,0,structtype) +MAKE_LISP_OBJECT(name,c_name,1 /*dumpable*/,marker,printer,nuker,equal,hash,desc,sizeof (structtype),0,0,structtype) #define DEFINE_DUMPABLE_SIZABLE_LISP_OBJECT(name,c_name,marker,printer,nuker,equal,hash,desc,sizer,structtype) \ -DEFINE_DUMPABLE_SIZABLE_GENERAL_LISP_OBJECT(name,c_name,marker,printer,nuker,equal,hash,desc,0,0,0,0,0,sizer,structtype) - -#define DEFINE_DUMPABLE_SIZABLE_GENERAL_LISP_OBJECT(name,c_name,marker,printer,nuker,equal,hash,desc,getprop,putprop,remprop,plist,disksaver,sizer,structtype) \ -MAKE_LISP_OBJECT(name,c_name,1 /*dumpable*/,marker,printer,nuker,equal,hash,desc,getprop,putprop,remprop,plist,disksaver,0,sizer,0,structtype) +MAKE_LISP_OBJECT(name,c_name,1 /*dumpable*/,marker,printer,nuker,equal,hash,desc,0,sizer,0,structtype) #define DEFINE_DUMPABLE_FROB_BLOCK_LISP_OBJECT(name,c_name,marker,printer,nuker,equal,hash,desc,structtype) \ -DEFINE_DUMPABLE_FROB_BLOCK_GENERAL_LISP_OBJECT(name,c_name,marker,printer,nuker,equal,hash,desc,0,0,0,0,0,structtype) - -#define DEFINE_DUMPABLE_FROB_BLOCK_GENERAL_LISP_OBJECT(name,c_name,marker,printer,nuker,equal,hash,desc,getprop,putprop,remprop,plist,disksaver,structtype) \ -MAKE_LISP_OBJECT(name,c_name,1 /*dumpable*/,marker,printer,nuker,equal,hash,desc,getprop,putprop,remprop,plist,disksaver,sizeof(structtype),0,1,structtype) +MAKE_LISP_OBJECT(name,c_name,1 /*dumpable*/,marker,printer,nuker,equal,hash,desc,sizeof(structtype),0,1,structtype) #define DEFINE_DUMPABLE_FROB_BLOCK_SIZABLE_LISP_OBJECT(name,c_name,marker,printer,nuker,equal,hash,desc,sizer,structtype) \ -MAKE_LISP_OBJECT(name,c_name,1 /*dumpable*/,marker,printer,nuker,equal,hash,desc,0,0,0,0,0,0,sizer,1,structtype) +MAKE_LISP_OBJECT(name,c_name,1 /*dumpable*/,marker,printer,nuker,equal,hash,desc,0,sizer,1,structtype) #define DEFINE_DUMPABLE_INTERNAL_LISP_OBJECT(name,c_name,marker,desc,structtype) \ -DEFINE_DUMPABLE_GENERAL_LISP_OBJECT(name,c_name,marker,internal_object_printer,0,0,0,desc,0,0,0,0,0,structtype) +DEFINE_DUMPABLE_LISP_OBJECT(name,c_name,marker,internal_object_printer,0,0,0,desc,structtype) #define DEFINE_DUMPABLE_SIZABLE_INTERNAL_LISP_OBJECT(name,c_name,marker,desc,sizer,structtype) \ -DEFINE_DUMPABLE_SIZABLE_GENERAL_LISP_OBJECT(name,c_name,marker,internal_object_printer,0,0,0,desc,0,0,0,0,0,sizer,structtype) +DEFINE_DUMPABLE_SIZABLE_LISP_OBJECT(name,c_name,marker,internal_object_printer,0,0,0,desc,sizer,structtype) /********* The non-dumpable versions *********** */ #define DEFINE_NODUMP_LISP_OBJECT(name,c_name,marker,printer,nuker,equal,hash,desc,structtype) \ -DEFINE_NODUMP_GENERAL_LISP_OBJECT(name,c_name,marker,printer,nuker,equal,hash,desc,0,0,0,0,0,structtype) - -#define DEFINE_NODUMP_GENERAL_LISP_OBJECT(name,c_name,marker,printer,nuker,equal,hash,desc,getprop,putprop,remprop,plist,disksaver,structtype) \ -MAKE_LISP_OBJECT(name,c_name,0 /*non-dumpable*/,marker,printer,nuker,equal,hash,desc,getprop,putprop,remprop,plist,disksaver,sizeof (structtype),0,0,structtype) +MAKE_LISP_OBJECT(name,c_name,0 /*non-dumpable*/,marker,printer,nuker,equal,hash,desc,sizeof (structtype),0,0,structtype) #define DEFINE_NODUMP_SIZABLE_LISP_OBJECT(name,c_name,marker,printer,nuker,equal,hash,desc,sizer,structtype) \ -DEFINE_NODUMP_SIZABLE_GENERAL_LISP_OBJECT(name,c_name,marker,printer,nuker,equal,hash,desc,0,0,0,0,0,sizer,structtype) - -#define DEFINE_NODUMP_SIZABLE_GENERAL_LISP_OBJECT(name,c_name,marker,printer,nuker,equal,hash,desc,getprop,putprop,remprop,plist,disksaver,sizer,structtype) \ -MAKE_LISP_OBJECT(name,c_name,0 /*non-dumpable*/,marker,printer,nuker,equal,hash,desc,getprop,putprop,remprop,plist,disksaver,0,sizer,0,structtype) +MAKE_LISP_OBJECT(name,c_name,0 /*non-dumpable*/,marker,printer,nuker,equal,hash,desc,0,sizer,0,structtype) #define DEFINE_NODUMP_FROB_BLOCK_LISP_OBJECT(name,c_name,marker,printer,nuker,equal,hash,desc,structtype) \ -DEFINE_NODUMP_FROB_BLOCK_GENERAL_LISP_OBJECT(name,c_name,marker,printer,nuker,equal,hash,desc,0,0,0,0,0,structtype) - -#define DEFINE_NODUMP_FROB_BLOCK_GENERAL_LISP_OBJECT(name,c_name,marker,printer,nuker,equal,hash,desc,getprop,putprop,remprop,plist,disksaver,structtype) \ -MAKE_LISP_OBJECT(name,c_name,0 /*non-dumpable*/,marker,printer,nuker,equal,hash,desc,getprop,putprop,remprop,plist,disksaver,sizeof(structtype),0,1,structtype) +MAKE_LISP_OBJECT(name,c_name,0 /*non-dumpable*/,marker,printer,nuker,equal,hash,desc,sizeof(structtype),0,1,structtype) #define DEFINE_NODUMP_FROB_BLOCK_SIZABLE_LISP_OBJECT(name,c_name,marker,printer,nuker,equal,hash,desc,sizer,structtype) \ -MAKE_LISP_OBJECT(name,c_name,0 /*non-dumpable*/,marker,printer,nuker,equal,hash,desc,0,0,0,0,0,0,sizer,1,structtype) +MAKE_LISP_OBJECT(name,c_name,0 /*non-dumpable*/,marker,printer,nuker,equal,hash,desc,0,sizer,1,structtype) #define DEFINE_NODUMP_INTERNAL_LISP_OBJECT(name,c_name,marker,desc,structtype) \ -DEFINE_NODUMP_GENERAL_LISP_OBJECT(name,c_name,marker,internal_object_printer,0,0,0,desc,0,0,0,0,0,structtype) +DEFINE_NODUMP_LISP_OBJECT(name,c_name,marker,internal_object_printer,0,0,0,desc,structtype) #define DEFINE_NODUMP_SIZABLE_INTERNAL_LISP_OBJECT(name,c_name,marker,desc,sizer,structtype) \ -DEFINE_NODUMP_SIZABLE_GENERAL_LISP_OBJECT(name,c_name,marker,internal_object_printer,0,0,0,desc,0,0,0,0,0,sizer,structtype) +DEFINE_NODUMP_SIZABLE_LISP_OBJECT(name,c_name,marker,internal_object_printer,0,0,0,desc,sizer,structtype) /********* MAKE_LISP_OBJECT, the underlying macro *********** */ #ifdef NEW_GC -#define MAKE_LISP_OBJECT(name,c_name,dumpable,marker,printer,nuker,equal,hash,desc,getprop,putprop,remprop,plist,disksaver,size,sizer,frob_block_p,structtype) \ +#define MAKE_LISP_OBJECT(name,c_name,dumpable,marker,printer,nuker, \ +equal,hash,desc,size,sizer,frob_block_p,structtype) \ DECLARE_ERROR_CHECK_TYPES(c_name, structtype) \ -const struct lrecord_implementation lrecord_##c_name = \ +struct lrecord_implementation lrecord_##c_name = \ { name, dumpable, marker, printer, nuker, equal, hash, desc, \ - getprop, putprop, remprop, plist, disksaver, size, sizer, \ - lrecord_type_##c_name } + size, sizer, lrecord_type_##c_name } #else /* not NEW_GC */ -#define MAKE_LISP_OBJECT(name,c_name,dumpable,marker,printer,nuker,equal,hash,desc,getprop,putprop,remprop,plist,disksaver,size,sizer,frob_block_p,structtype) \ +#define MAKE_LISP_OBJECT(name,c_name,dumpable,marker,printer,nuker,equal,hash,desc,size,sizer,frob_block_p,structtype) \ DECLARE_ERROR_CHECK_TYPES(c_name, structtype) \ -const struct lrecord_implementation lrecord_##c_name = \ +struct lrecord_implementation lrecord_##c_name = \ { name, dumpable, marker, printer, nuker, equal, hash, desc, \ - getprop, putprop, remprop, plist, disksaver, size, sizer, \ - lrecord_type_##c_name, frob_block_p } + size, sizer, lrecord_type_##c_name, frob_block_p } #endif /* not NEW_GC */ /********* The module dumpable versions *********** */ #define DEFINE_DUMPABLE_MODULE_LISP_OBJECT(name,c_name,dumpable,marker,printer,nuker,equal,hash,desc,structtype) \ -DEFINE_DUMPABLE_MODULE_GENERAL_LISP_OBJECT(name,c_name,dumpable,marker,printer,nuker,equal,hash,desc,0,0,0,0,0,structtype) - -#define DEFINE_DUMPABLE_MODULE_GENERAL_LISP_OBJECT(name,c_name,dumpable,marker,printer,nuker,equal,hash,desc,getprop,putprop,remprop,plist,disksaver,structtype) \ -MAKE_MODULE_LISP_OBJECT(name,c_name,1 /*dumpable*/,marker,printer,nuker,equal,hash,desc,getprop,putprop,remprop,plist,disksaver,sizeof (structtype),0,0,structtype) +MAKE_MODULE_LISP_OBJECT(name,c_name,1 /*dumpable*/,marker,printer,nuker,equal,hash,desc,sizeof (structtype),0,0,structtype) #define DEFINE_DUMPABLE_MODULE_SIZABLE_LISP_OBJECT(name,c_name,dumpable,marker,printer,nuker,equal,hash,desc,sizer,structtype) \ -DEFINE_DUMPABLE_MODULE_SIZABLE_GENERAL_LISP_OBJECT(name,c_name,dumpable,marker,printer,nuker,equal,hash,desc,0,0,0,0,0,sizer,structtype) - -#define DEFINE_DUMPABLE_MODULE_SIZABLE_GENERAL_LISP_OBJECT(name,c_name,dumpable,marker,printer,nuker,equal,hash,desc,getprop,putprop,remprop,plist,disksaver,sizer,structtype) \ -MAKE_MODULE_LISP_OBJECT(name,c_name,1 /*dumpable*/,marker,printer,nuker,equal,hash,desc,getprop,putprop,remprop,plist,disksaver,0,sizer,0,structtype) +MAKE_MODULE_LISP_OBJECT(name,c_name,1 /*dumpable*/,marker,printer,nuker,equal,hash,desc,0,sizer,0,structtype) /********* The module non-dumpable versions *********** */ -#define DEFINE_NODUMP_MODULE_LISP_OBJECT(name,c_name,dumpable,marker,printer,nuker,equal,hash,desc,structtype) \ -DEFINE_NODUMP_MODULE_GENERAL_LISP_OBJECT(name,c_name,dumpable,marker,printer,nuker,equal,hash,desc,0,0,0,0,0,structtype) - -#define DEFINE_NODUMP_MODULE_GENERAL_LISP_OBJECT(name,c_name,dumpable,marker,printer,nuker,equal,hash,desc,getprop,putprop,remprop,plist,disksaver,structtype) \ -MAKE_MODULE_LISP_OBJECT(name,c_name,0 /*non-dumpable*/,marker,printer,nuker,equal,hash,desc,getprop,putprop,remprop,plist,disksaver,sizeof (structtype),0,0,structtype) +#define DEFINE_NODUMP_MODULE_LISP_OBJECT(name,c_name,dumpable,marker, \ +printer,nuker,equal,hash,desc,structtype) \ +MAKE_MODULE_LISP_OBJECT(name,c_name,0 /*non-dumpable*/,marker,printer, \ +nuker,equal,hash,desc,sizeof (structtype),0,0,structtype) -#define DEFINE_NODUMP_MODULE_SIZABLE_LISP_OBJECT(name,c_name,dumpable,marker,printer,nuker,equal,hash,desc,sizer,structtype) \ -DEFINE_NODUMP_MODULE_SIZABLE_GENERAL_LISP_OBJECT(name,c_name,dumpable,marker,printer,nuker,equal,hash,desc,0,0,0,0,0,sizer,structtype) - -#define DEFINE_NODUMP_MODULE_SIZABLE_GENERAL_LISP_OBJECT(name,c_name,dumpable,marker,printer,nuker,equal,hash,desc,getprop,putprop,remprop,plist,disksaver,sizer,structtype) \ -MAKE_MODULE_LISP_OBJECT(name,c_name,0 /*non-dumpable*/,marker,printer,nuker,equal,hash,desc,getprop,putprop,remprop,plist,disksaver,0,sizer,0,structtype) +#define DEFINE_NODUMP_MODULE_SIZABLE_LISP_OBJECT(name,c_name,dumpable, \ +marker,printer,nuker,equal,hash,desc,sizer,structtype) \ +MAKE_MODULE_LISP_OBJECT(name,c_name,0 /*non-dumpable*/,marker,printer, \ +nuker,equal,hash,desc,0,sizer,0,structtype) /********* MAKE_MODULE_LISP_OBJECT, the underlying macro *********** */ #ifdef NEW_GC -#define MAKE_MODULE_LISP_OBJECT(name,c_name,dumpable,marker,printer,nuker,equal,hash,desc,getprop,putprop,remprop,plist,disksaver,size,sizer,frob_block_p,structtype) \ +#define MAKE_MODULE_LISP_OBJECT(name,c_name,dumpable,marker,printer, \ +nuker,equal,hash,desc,size,sizer,frob_block_p,structtype) \ +DECLARE_ERROR_CHECK_TYPES(c_name, structtype) \ +int lrecord_type_##c_name; \ +struct lrecord_implementation lrecord_##c_name = \ + { name, dumpable, marker, printer, nuker, equal, hash, desc, \ + size, sizer, lrecord_type_last_built_in_type } +#else /* not NEW_GC */ +#define MAKE_MODULE_LISP_OBJECT(name,c_name,dumpable,marker,printer, \ +nuker,equal,hash,desc,size,sizer,frob_block_p,structtype) \ DECLARE_ERROR_CHECK_TYPES(c_name, structtype) \ int lrecord_type_##c_name; \ struct lrecord_implementation lrecord_##c_name = \ { name, dumpable, marker, printer, nuker, equal, hash, desc, \ - getprop, putprop, remprop, plist, disksaver, size, sizer, \ - lrecord_type_last_built_in_type } -#else /* not NEW_GC */ -#define MAKE_MODULE_LISP_OBJECT(name,c_name,dumpable,marker,printer,nuker,equal,hash,desc,getprop,putprop,remprop,plist,disksaver,size,sizer,frob_block_p,structtype) \ -DECLARE_ERROR_CHECK_TYPES(c_name, structtype) \ -int lrecord_type_##c_name; \ -struct lrecord_implementation lrecord_##c_name = \ - { name, dumpable, marker, printer, nuker, equal, hash, desc, \ - getprop, putprop, remprop, plist, disksaver, size, sizer, \ - lrecord_type_last_built_in_type, frob_block_p } + size, sizer, lrecord_type_last_built_in_type, frob_block_p } #endif /* not NEW_GC */ +#ifdef MEMORY_USAGE_STATS +#define INIT_MEMORY_USAGE_STATS(type) \ +do \ +{ \ + lrecord_implementations_table[lrecord_type_##type]-> \ + memusage_stats_list = Qnil; \ + lrecord_implementations_table[lrecord_type_##type]-> \ + num_extra_memusage_stats = -1; \ + staticpro (&lrecord_implementations_table[lrecord_type_##type]-> \ + memusage_stats_list); \ +} while (0) +#else +#define INIT_MEMORY_USAGE_STATS(type) DO_NOTHING +#endif /* (not) MEMORY_USAGE_STATS */ + +#define INIT_LISP_OBJECT_BEGINNING(type) \ +do \ +{ \ + lrecord_implementations_table[lrecord_type_##type] = &lrecord_##type; \ + INIT_MEMORY_USAGE_STATS (type); \ +} while (0) + #ifdef USE_KKCC extern MODULE_API const struct memory_description *lrecord_memory_descriptions[]; -#define INIT_LISP_OBJECT(type) do { \ - lrecord_implementations_table[lrecord_type_##type] = &lrecord_##type; \ +#define INIT_LISP_OBJECT(type) do { \ + INIT_LISP_OBJECT_BEGINNING (type); \ lrecord_memory_descriptions[lrecord_type_##type] = \ lrecord_implementations_table[lrecord_type_##type]->description; \ } while (0) @@ -1428,16 +1446,16 @@ extern MODULE_API Lisp_Object (*lrecord_markers[]) (Lisp_Object); #define INIT_LISP_OBJECT(type) do { \ - lrecord_implementations_table[lrecord_type_##type] = &lrecord_##type; \ - lrecord_markers[lrecord_type_##type] = \ - lrecord_implementations_table[lrecord_type_##type]->marker; \ + INIT_LISP_OBJECT_BEGINNING (type); \ + lrecord_markers[lrecord_type_##type] = \ + lrecord_implementations_table[lrecord_type_##type]->marker; \ } while (0) #endif /* not USE_KKCC */ #define INIT_MODULE_LISP_OBJECT(type) do { \ - lrecord_type_##type = lrecord_type_count++; \ - lrecord_##type.lrecord_type_index = lrecord_type_##type; \ - INIT_LISP_OBJECT(type); \ + lrecord_type_##type = lrecord_type_count++; \ + lrecord_##type.lrecord_type_index = lrecord_type_##type; \ + INIT_LISP_OBJECT (type); \ } while (0) #ifdef HAVE_SHLIB @@ -1445,26 +1463,69 @@ #ifdef USE_KKCC #define UNDEF_LISP_OBJECT(type) do { \ - lrecord_implementations_table[lrecord_type_##type] = NULL; \ - lrecord_memory_descriptions[lrecord_type_##type] = NULL; \ + lrecord_implementations_table[lrecord_type_##type] = NULL; \ + lrecord_memory_descriptions[lrecord_type_##type] = NULL; \ } while (0) #else /* not USE_KKCC */ #define UNDEF_LISP_OBJECT(type) do { \ - lrecord_implementations_table[lrecord_type_##type] = NULL; \ - lrecord_markers[lrecord_type_##type] = NULL; \ + lrecord_implementations_table[lrecord_type_##type] = NULL; \ + lrecord_markers[lrecord_type_##type] = NULL; \ } while (0) #endif /* not USE_KKCC */ -#define UNDEF_MODULE_LISP_OBJECT(type) do { \ +#define UNDEF_MODULE_LISP_OBJECT(type) do { \ if (lrecord_##type.lrecord_type_index == lrecord_type_count - 1) { \ /* This is the most recently defined type. Clean up nicely. */ \ lrecord_type_##type = lrecord_type_count--; \ } /* Else we can't help leaving a hole with this implementation. */ \ - UNDEF_LISP_OBJECT(type); \ + UNDEF_LISP_OBJECT(type); \ } while (0) #endif /* HAVE_SHLIB */ +/*************** Macros for declaring that a Lisp object has a + particular method, or for calling such a method. ********/ + +/* Declare that object-type TYPE has method M; used in + initialization routines */ +#define OBJECT_HAS_METHOD(type, m) \ + (lrecord_##type.m = type##_##m) +/* Same but the method name come before the type */ +#define OBJECT_HAS_PREMETHOD(type, m) \ + (lrecord_##type.m = m##_##type) +/* Same but the name of the method is explicitly given */ +#define OBJECT_HAS_NAMED_METHOD(type, m, func) \ + (lrecord_##type.m = (func)) +/* Object type has a property with the given value. */ +#define OBJECT_HAS_PROPERTY(type, prop, val) \ + (lrecord_##type.prop = (val)) + +/* Does the given object method exist? */ +#define HAS_OBJECT_METH_P(obj, m) \ + (!!(XRECORD_LHEADER_IMPLEMENTATION (obj)->m)) +/* Call an object method. */ +#define OBJECT_METH(obj, m, args) \ + ((XRECORD_LHEADER_IMPLEMENTATION (obj)->m) args) + +/* Call an object method, if it exists. */ +#define MAYBE_OBJECT_METH(obj, m, args) \ +do \ +{ \ + const struct lrecord_implementation *_mom_imp = \ + XRECORD_LHEADER_IMPLEMENTATION (obj); \ + if (_mom_imp->m) \ + ((_mom_imp->m) args); \ +} while (0) + +/* Call an object method, if it exists, or return GIVEN. NOTE: + Multiply-evaluates OBJ. */ +#define OBJECT_METH_OR_GIVEN(obj, m, args, given) \ + (HAS_OBJECT_METH_P (obj, m) ? OBJECT_METH (obj, m, args) : (given)) + +#define OBJECT_PROPERTY(obj, prop) (XRECORD_LHEADER_IMPLEMENTATION (obj)->prop) + +/************** Other stuff **************/ + #define LRECORDP(a) (XTYPE (a) == Lisp_Type_Record) #define XRECORD_LHEADER(a) ((struct lrecord_header *) XPNTR (a)) @@ -1675,41 +1736,41 @@ #ifdef ERROR_CHECK_TYPES -# define DECLARE_LISP_OBJECT(c_name, structtype) \ -extern const struct lrecord_implementation lrecord_##c_name; \ -DECLARE_INLINE_HEADER ( \ -structtype * \ -error_check_##c_name (Lisp_Object obj, const Ascbyte *file, int line) \ -) \ -{ \ +# define DECLARE_LISP_OBJECT(c_name, structtype) \ +extern struct lrecord_implementation lrecord_##c_name; \ +DECLARE_INLINE_HEADER ( \ +structtype * \ +error_check_##c_name (Lisp_Object obj, const Ascbyte *file, int line) \ +) \ +{ \ assert_at_line (RECORD_TYPEP (obj, lrecord_type_##c_name), file, line); \ - return (structtype *) XPNTR (obj); \ -} \ + return (structtype *) XPNTR (obj); \ +} \ extern Lisp_Object Q##c_name##p -# define DECLARE_MODULE_API_LISP_OBJECT(c_name, structtype) \ -extern MODULE_API const struct lrecord_implementation lrecord_##c_name; \ -DECLARE_INLINE_HEADER ( \ -structtype * \ -error_check_##c_name (Lisp_Object obj, const Ascbyte *file, int line) \ -) \ -{ \ +# define DECLARE_MODULE_API_LISP_OBJECT(c_name, structtype) \ +extern MODULE_API struct lrecord_implementation lrecord_##c_name; \ +DECLARE_INLINE_HEADER ( \ +structtype * \ +error_check_##c_name (Lisp_Object obj, const Ascbyte *file, int line) \ +) \ +{ \ assert_at_line (RECORD_TYPEP (obj, lrecord_type_##c_name), file, line); \ - return (structtype *) XPNTR (obj); \ -} \ + return (structtype *) XPNTR (obj); \ +} \ extern MODULE_API Lisp_Object Q##c_name##p -# define DECLARE_MODULE_LISP_OBJECT(c_name, structtype) \ -extern int lrecord_type_##c_name; \ -extern struct lrecord_implementation lrecord_##c_name; \ -DECLARE_INLINE_HEADER ( \ -structtype * \ -error_check_##c_name (Lisp_Object obj, const Ascbyte *file, int line) \ -) \ -{ \ +# define DECLARE_MODULE_LISP_OBJECT(c_name, structtype) \ +extern int lrecord_type_##c_name; \ +extern struct lrecord_implementation lrecord_##c_name; \ +DECLARE_INLINE_HEADER ( \ +structtype * \ +error_check_##c_name (Lisp_Object obj, const Ascbyte *file, int line) \ +) \ +{ \ assert_at_line (RECORD_TYPEP (obj, lrecord_type_##c_name), file, line); \ - return (structtype *) XPNTR (obj); \ -} \ + return (structtype *) XPNTR (obj); \ +} \ extern Lisp_Object Q##c_name##p # define XRECORD(x, c_name, structtype) \ @@ -1734,10 +1795,10 @@ # define DECLARE_LISP_OBJECT(c_name, structtype) \ extern Lisp_Object Q##c_name##p; \ -extern const struct lrecord_implementation lrecord_##c_name +extern struct lrecord_implementation lrecord_##c_name # define DECLARE_MODULE_API_LISP_OBJECT(c_name, structtype) \ extern MODULE_API Lisp_Object Q##c_name##p; \ -extern MODULE_API const struct lrecord_implementation lrecord_##c_name +extern MODULE_API struct lrecord_implementation lrecord_##c_name # define DECLARE_MODULE_LISP_OBJECT(c_name, structtype) \ extern Lisp_Object Q##c_name##p; \ extern int lrecord_type_##c_name; \ @@ -1948,14 +2009,14 @@ return detagged_lisp_object_size (XRECORD_LHEADER (o)); } -struct overhead_stats; +struct usage_stats; MODULE_API void copy_lisp_object (Lisp_Object dst, Lisp_Object src); MODULE_API void zero_sized_lisp_object (Lisp_Object obj, Bytecount size); MODULE_API void zero_nonsized_lisp_object (Lisp_Object obj); #ifdef MEMORY_USAGE_STATS Bytecount lisp_object_storage_size (Lisp_Object obj, - struct overhead_stats *ovstats); + struct usage_stats *ustats); #endif /* MEMORY_USAGE_STATS */ void free_normal_lisp_object (Lisp_Object obj);
--- a/src/lstream.c Thu Mar 18 10:19:08 2010 -0500 +++ b/src/lstream.c Thu Mar 18 10:50:06 2010 -0500 @@ -144,14 +144,12 @@ 0, lstream_empty_extra_description_1 }; -DEFINE_NODUMP_SIZABLE_GENERAL_LISP_OBJECT ("stream", lstream, - mark_lstream, print_lstream, - finalize_lstream, - 0, 0, /* no equal or hash */ - lstream_description, - 0, 0, 0, 0, /* no property meths */ - disksave_lstream, - sizeof_lstream, Lstream); +DEFINE_NODUMP_SIZABLE_LISP_OBJECT ("stream", lstream, + mark_lstream, print_lstream, + finalize_lstream, + 0, 0, /* no equal or hash */ + lstream_description, + sizeof_lstream, Lstream); /* Change the buffering of a stream. See lstream.h. By default the @@ -1822,6 +1820,18 @@ /************************************************************************/ void +syms_of_lstream (void) +{ + INIT_LISP_OBJECT (lstream); +} + +void +lstream_objects_create (void) +{ + OBJECT_HAS_PREMETHOD (lstream, disksave); +} + +void lstream_type_create (void) { LSTREAM_HAS_METHOD (stdio, reader); @@ -1877,5 +1887,4 @@ void vars_of_lstream (void) { - INIT_LISP_OBJECT (lstream); }
--- a/src/marker.c Thu Mar 18 10:19:08 2010 -0500 +++ b/src/marker.c Thu Mar 18 10:50:06 2010 -0500 @@ -498,7 +498,7 @@ #ifdef MEMORY_USAGE_STATS int -compute_buffer_marker_usage (struct buffer *b, struct overhead_stats *ovstats) +compute_buffer_marker_usage (struct buffer *b, struct usage_stats *ustats) { Lisp_Marker *m; int total = 0; @@ -506,7 +506,7 @@ for (m = BUF_MARKERS (b); m; m = m->next) total += sizeof (Lisp_Marker); - ovstats->was_requested += total; + ustats->was_requested += total; #ifdef NEW_GC overhead = mc_alloced_storage_size (total, 0) - total; #else /* not NEW_GC */ @@ -514,7 +514,7 @@ #endif /* not NEW_GC */ /* #### claiming this is all malloc overhead is not really right, but it has to go somewhere. */ - ovstats->malloc_overhead += overhead; + ustats->malloc_overhead += overhead; return total + overhead; }
--- a/src/mc-alloc.c Thu Mar 18 10:19:08 2010 -0500 +++ b/src/mc-alloc.c Thu Mar 18 10:50:06 2010 -0500 @@ -964,7 +964,7 @@ #ifdef MEMORY_USAGE_STATS Bytecount -mc_alloced_storage_size (Bytecount claimed_size, struct overhead_stats *stats) +mc_alloced_storage_size (Bytecount claimed_size, struct usage_stats *stats) { size_t used_size = get_used_list_size_value (get_used_list_index (claimed_size));
--- a/src/mc-alloc.h Thu Mar 18 10:19:08 2010 -0500 +++ b/src/mc-alloc.h Thu Mar 18 10:50:06 2010 -0500 @@ -126,7 +126,7 @@ /* Returns the real size, including overhead, which is actually alloced for an object with given claimed_size. */ Bytecount mc_alloced_storage_size (Bytecount claimed_size, - struct overhead_stats *stats); + struct usage_stats *stats); #endif /* MEMORY_USAGE_STATS */
--- a/src/mule-charset.c Thu Mar 18 10:19:08 2010 -0500 +++ b/src/mule-charset.c Thu Mar 18 10:50:06 2010 -0500 @@ -990,57 +990,25 @@ struct charset_stats { - int from_unicode; - int to_unicode; - int other; + struct usage_stats u; + Bytecount from_unicode; + Bytecount to_unicode; }; static void compute_charset_usage (Lisp_Object charset, struct charset_stats *stats, - struct overhead_stats *ovstats) + struct usage_stats *ustats) { - xzero (*stats); - stats->other += lisp_object_storage_size (charset, ovstats); - stats->from_unicode += compute_from_unicode_table_size (charset, ovstats); - stats->to_unicode += compute_to_unicode_table_size (charset, ovstats); + stats->from_unicode += compute_from_unicode_table_size (charset, ustats); + stats->to_unicode += compute_to_unicode_table_size (charset, ustats); } -DEFUN ("charset-memory-usage", Fcharset_memory_usage, 1, 1, 0, /* -Return stats about the memory usage of charset CHARSET. -The values returned are in the form of an alist of usage types and -byte counts. The byte counts attempt to encompass all the memory used -by the charset (separate from the memory logically associated with a -charset or frame), including internal structures and any malloc() -overhead associated with them. In practice, the byte counts are -underestimated for various reasons, e.g. because certain memory usage -is very hard to determine \(e.g. the amount of memory used inside the -Xt library or inside the X server). +static void +charset_memory_usage (Lisp_Object charset, struct generic_usage_stats *gustats) +{ + struct charset_stats *stats = (struct charset_stats *) gustats; -Multiple slices of the total memory usage may be returned, separated -by a nil. Each slice represents a particular view of the memory, a -particular way of partitioning it into groups. Within a slice, there -is no overlap between the groups of memory, and each slice collectively -represents all the memory concerned. -*/ - (charset)) -{ - struct charset_stats stats; - struct overhead_stats ovstats; - Lisp_Object val = Qnil; - - charset = Fget_charset (charset); - xzero (ovstats); - compute_charset_usage (charset, &stats, &ovstats); - - val = acons (Qfrom_unicode, make_int (stats.from_unicode), val); - val = acons (Qto_unicode, make_int (stats.to_unicode), val); - val = Fcons (Qnil, val); - val = acons (Qactually_requested, make_int (ovstats.was_requested), val); - val = acons (Qmalloc_overhead, make_int (ovstats.malloc_overhead), val); - val = acons (Qgap_overhead, make_int (ovstats.gap_overhead), val); - val = acons (Qdynarr_overhead, make_int (ovstats.dynarr_overhead), val); - - return Fnreverse (val); + compute_charset_usage (charset, stats, &stats->u); } #endif /* MEMORY_USAGE_STATS */ @@ -1051,6 +1019,14 @@ /************************************************************************/ void +mule_charset_objects_create (void) +{ +#ifdef MEMORY_USAGE_STATS + OBJECT_HAS_METHOD (charset, memory_usage); +#endif +} + +void syms_of_mule_charset (void) { INIT_LISP_OBJECT (charset); @@ -1074,10 +1050,6 @@ DEFSUBR (Fset_charset_registries); DEFSUBR (Fcharsets_in_region); -#ifdef MEMORY_USAGE_STATS - DEFSUBR (Fcharset_memory_usage); -#endif - DEFSYMBOL (Qcharsetp); DEFSYMBOL (Qregistries); DEFSYMBOL (Qfinal); @@ -1126,6 +1098,11 @@ { int i, j, k; +#ifdef MEMORY_USAGE_STATS + OBJECT_HAS_PROPERTY + (charset, memusage_stats_list, list2 (Qfrom_unicode, Qto_unicode)); +#endif /* MEMORY_USAGE_STATS */ + chlook = xnew_and_zero (struct charset_lookup); /* zero for Purify. */ dump_add_root_block_ptr (&chlook, &charset_lookup_description);
--- a/src/redisplay.c Thu Mar 18 10:19:08 2010 -0500 +++ b/src/redisplay.c Thu Mar 18 10:50:06 2010 -0500 @@ -9665,50 +9665,50 @@ /***************************************************************************/ static int -compute_rune_dynarr_usage (rune_dynarr *dyn, struct overhead_stats *ovstats) -{ - return dyn ? Dynarr_memory_usage (dyn, ovstats) : 0; +compute_rune_dynarr_usage (rune_dynarr *dyn, struct usage_stats *ustats) +{ + return dyn ? Dynarr_memory_usage (dyn, ustats) : 0; } static int compute_display_block_dynarr_usage (display_block_dynarr *dyn, - struct overhead_stats *ovstats) + struct usage_stats *ustats) { int total, i; if (!dyn) return 0; - total = Dynarr_memory_usage (dyn, ovstats); + total = Dynarr_memory_usage (dyn, ustats); for (i = 0; i < Dynarr_largest (dyn); i++) - total += compute_rune_dynarr_usage (Dynarr_at (dyn, i).runes, ovstats); + total += compute_rune_dynarr_usage (Dynarr_at (dyn, i).runes, ustats); return total; } static int compute_glyph_block_dynarr_usage (glyph_block_dynarr *dyn, - struct overhead_stats *ovstats) -{ - return dyn ? Dynarr_memory_usage (dyn, ovstats) : 0; + struct usage_stats *ustats) +{ + return dyn ? Dynarr_memory_usage (dyn, ustats) : 0; } int compute_display_line_dynarr_usage (display_line_dynarr *dyn, - struct overhead_stats *ovstats) + struct usage_stats *ustats) { int total, i; if (!dyn) return 0; - total = Dynarr_memory_usage (dyn, ovstats); + total = Dynarr_memory_usage (dyn, ustats); for (i = 0; i < Dynarr_largest (dyn); i++) { struct display_line *dl = &Dynarr_at (dyn, i); - total += compute_display_block_dynarr_usage(dl->display_blocks, ovstats); - total += compute_glyph_block_dynarr_usage (dl->left_glyphs, ovstats); - total += compute_glyph_block_dynarr_usage (dl->right_glyphs, ovstats); + total += compute_display_block_dynarr_usage(dl->display_blocks, ustats); + total += compute_glyph_block_dynarr_usage (dl->left_glyphs, ustats); + total += compute_glyph_block_dynarr_usage (dl->right_glyphs, ustats); } return total; @@ -9716,9 +9716,9 @@ int compute_line_start_cache_dynarr_usage (line_start_cache_dynarr *dyn, - struct overhead_stats *ovstats) -{ - return dyn ? Dynarr_memory_usage (dyn, ovstats) : 0; + struct usage_stats *ustats) +{ + return dyn ? Dynarr_memory_usage (dyn, ustats) : 0; } #endif /* MEMORY_USAGE_STATS */
--- a/src/redisplay.h Thu Mar 18 10:19:08 2010 -0500 +++ b/src/redisplay.h Thu Mar 18 10:50:06 2010 -0500 @@ -777,9 +777,9 @@ #ifdef MEMORY_USAGE_STATS int compute_display_line_dynarr_usage (display_line_dynarr *dyn, - struct overhead_stats *ovstats); + struct usage_stats *ustats); int compute_line_start_cache_dynarr_usage (line_start_cache_dynarr *dyn, - struct overhead_stats *ovstats); + struct usage_stats *ustats); #endif
--- a/src/scrollbar-gtk.c Thu Mar 18 10:19:08 2010 -0500 +++ b/src/scrollbar-gtk.c Thu Mar 18 10:50:06 2010 -0500 @@ -477,7 +477,7 @@ static int gtk_compute_scrollbar_instance_usage (struct device *UNUSED (d), struct scrollbar_instance *inst, - struct overhead_stats *ovstats) + struct usage_stats *ustats) { int total = 0; @@ -486,7 +486,7 @@ struct gtk_scrollbar_data *data = (struct gtk_scrollbar_data *) inst->scrollbar_data; - total += malloced_storage_size (data, sizeof (*data), ovstats); + total += malloced_storage_size (data, sizeof (*data), ustats); inst = inst->next; }
--- a/src/scrollbar-msw.c Thu Mar 18 10:19:08 2010 -0500 +++ b/src/scrollbar-msw.c Thu Mar 18 10:50:06 2010 -0500 @@ -426,7 +426,7 @@ static int mswindows_compute_scrollbar_instance_usage (struct device *UNUSED (d), struct scrollbar_instance *inst, - struct overhead_stats *ovstats) + struct usage_stats *ustats) { int total = 0; @@ -435,7 +435,7 @@ struct mswindows_scrollbar_data *data = (struct mswindows_scrollbar_data *) inst->scrollbar_data; - total += malloced_storage_size (data, sizeof (*data), ovstats); + total += malloced_storage_size (data, sizeof (*data), ustats); inst = inst->next; }
--- a/src/scrollbar-x.c Thu Mar 18 10:19:08 2010 -0500 +++ b/src/scrollbar-x.c Thu Mar 18 10:50:06 2010 -0500 @@ -697,7 +697,7 @@ static int x_compute_scrollbar_instance_usage (struct device *UNUSED (d), struct scrollbar_instance *inst, - struct overhead_stats *ovstats) + struct usage_stats *ustats) { int total = 0; @@ -706,9 +706,9 @@ struct x_scrollbar_data *data = (struct x_scrollbar_data *) inst->scrollbar_data; - total += malloced_storage_size (data, sizeof (*data), ovstats); + total += malloced_storage_size (data, sizeof (*data), ustats); total += malloced_storage_size (data->name, 1 + strlen (data->name), - ovstats); + ustats); inst = inst->next; }
--- a/src/scrollbar.c Thu Mar 18 10:19:08 2010 -0500 +++ b/src/scrollbar.c Thu Mar 18 10:50:06 2010 -0500 @@ -260,17 +260,17 @@ int compute_scrollbar_instance_usage (struct device *d, struct scrollbar_instance *inst, - struct overhead_stats *ovstats) + struct usage_stats *ustats) { int total = 0; if (HAS_DEVMETH_P(d, compute_scrollbar_instance_usage)) - total += DEVMETH (d, compute_scrollbar_instance_usage, (d, inst, ovstats)); + total += DEVMETH (d, compute_scrollbar_instance_usage, (d, inst, ustats)); while (inst) { total += lisp_object_storage_size (wrap_scrollbar_instance (inst), - ovstats); + ustats); inst = inst->next; }
--- a/src/scrollbar.h Thu Mar 18 10:19:08 2010 -0500 +++ b/src/scrollbar.h Thu Mar 18 10:50:06 2010 -0500 @@ -67,7 +67,7 @@ #ifdef MEMORY_USAGE_STATS int compute_scrollbar_instance_usage (struct device *d, struct scrollbar_instance *inst, - struct overhead_stats *ovstats); + struct usage_stats *ustats); #endif extern Lisp_Object Vscrollbar_width, Vscrollbar_height;
--- a/src/symbols.c Thu Mar 18 10:19:08 2010 -0500 +++ b/src/symbols.c Thu Mar 18 10:50:06 2010 -0500 @@ -141,15 +141,10 @@ return external_remprop (&XSYMBOL (symbol)->plist, property, 0, ERROR_ME); } -DEFINE_DUMPABLE_FROB_BLOCK_GENERAL_LISP_OBJECT ("symbol", symbol, - mark_symbol, print_symbol, - 0, 0, 0, symbol_description, - symbol_getprop, - symbol_putprop, - symbol_remprop, - Fsymbol_plist, - 0 /* no disksaver */, - Lisp_Symbol); +DEFINE_DUMPABLE_FROB_BLOCK_LISP_OBJECT ("symbol", symbol, + mark_symbol, print_symbol, + 0, 0, 0, symbol_description, + Lisp_Symbol); /**********************************************************************/ /* Intern */ @@ -3527,6 +3522,15 @@ }; #endif /* not NEW_GC */ +static void +reinit_symbol_objects_early (void) +{ + OBJECT_HAS_METHOD (symbol, getprop); + OBJECT_HAS_METHOD (symbol, putprop); + OBJECT_HAS_METHOD (symbol, remprop); + OBJECT_HAS_NAMED_METHOD (symbol, plist, Fsymbol_plist); +} + void init_symbols_once_early (void) { @@ -3536,13 +3540,13 @@ INIT_LISP_OBJECT (symbol_value_lisp_magic); INIT_LISP_OBJECT (symbol_value_varalias); - reinit_symbols_early (); + reinit_symbol_objects_early (); /* Bootstrapping problem: Qnil isn't set when make_string_nocopy is called the first time. */ Qnil = Fmake_symbol (make_string_nocopy ((const Ibyte *) "nil", 3)); XSTRING_PLIST (XSYMBOL (Qnil)->name) = Qnil; - XSYMBOL (Qnil)->value = Qnil; /* Nihil ex nihil */ + XSYMBOL (Qnil)->value = Qnil; /* Nihil ex nihilo */ XSYMBOL (Qnil)->plist = Qnil; Vobarray = make_vector (OBARRAY_SIZE, Qzero); @@ -3591,6 +3595,7 @@ void reinit_symbols_early (void) { + reinit_symbol_objects_early (); } static void
--- a/src/symsinit.h Thu Mar 18 10:19:08 2010 -0500 +++ b/src/symsinit.h Thu Mar 18 10:50:06 2010 -0500 @@ -147,6 +147,7 @@ void syms_of_intl_x (void); void syms_of_keymap (void); void syms_of_lread (void); +void syms_of_lstream (void); void syms_of_macros (void); void syms_of_marker (void); void syms_of_mc_alloc (void); @@ -202,6 +203,19 @@ void syms_of_win32 (void); void syms_of_window (void); +/* Initialize dynamic properties of objects (i.e. those properties not + initialized statically through a DEFINE_*_LISP_OBJECT declaration). + Dump time and post-pdump-load-time. */ + +void buffer_objects_create (void); +void extent_objects_create (void); +void face_objects_create (void); +void glyph_objects_create (void); +void lstream_objects_create (void); +void mule_charset_objects_create (void); +void ui_gtk_objects_create (void); +void window_objects_create (void); + /* Initialize the console types (dump-time only for console_type_(), post-pdump-load-time only for reinit_). */ @@ -329,6 +343,7 @@ void vars_of_abbrev (void); void vars_of_alloc (void); +void reinit_vars_of_alloc (void); void vars_of_balloon_x (void); void vars_of_buffer (void); void reinit_vars_of_buffer (void);
--- a/src/ui-gtk.c Thu Mar 18 10:19:08 2010 -0500 +++ b/src/ui-gtk.c Thu Mar 18 10:50:06 2010 -0500 @@ -807,7 +807,7 @@ } static Lisp_Object -object_getprop (Lisp_Object obj, Lisp_Object prop) +emacs_gtk_object_getprop (Lisp_Object obj, Lisp_Object prop) { Lisp_Object rval = Qnil; Lisp_Object prop_name = Qnil; @@ -871,7 +871,7 @@ } static int -object_putprop (Lisp_Object obj, Lisp_Object prop, Lisp_Object value) +emacs_gtk_object_putprop (Lisp_Object obj, Lisp_Object prop, Lisp_Object value) { GtkArgInfo *info = NULL; Lisp_Object prop_name = Qnil; @@ -932,19 +932,14 @@ gtk_object_unref (data->object); } -DEFINE_NODUMP_GENERAL_LISP_OBJECT ("GtkObject", emacs_gtk_object, - mark_gtk_object_data, - emacs_gtk_object_printer, - emacs_gtk_object_finalizer, - 0, /* equality */ - 0, /* hash */ - gtk_object_data_description, - object_getprop, - object_putprop, - 0, /* rem prop */ - 0, /* plist */ - 0, /* disksaver */ - emacs_gtk_object_data); +DEFINE_NODUMP_LISP_OBJECT ("GtkObject", emacs_gtk_object, + mark_gtk_object_data, + emacs_gtk_object_printer, + emacs_gtk_object_finalizer, + 0, /* equality */ + 0, /* hash */ + gtk_object_data_description, + emacs_gtk_object_data); static emacs_gtk_object_data * allocate_emacs_gtk_object_data (void) @@ -1338,6 +1333,14 @@ void +ui_gtk_objects_create (void) +{ + OBJECT_HAS_METHOD (emacs_gtk_object, getprop); + OBJECT_HAS_METHOD (emacs_gtk_object, putprop); + /* #### No remprop or plist methods */ +} + +void syms_of_ui_gtk (void) { INIT_LISP_OBJECT (emacs_ffi);
--- a/src/unicode.c Thu Mar 18 10:19:08 2010 -0500 +++ b/src/unicode.c Thu Mar 18 10:50:06 2010 -0500 @@ -542,7 +542,7 @@ static Bytecount compute_from_unicode_table_size_1 (void *table, int level, - struct overhead_stats *stats) + struct usage_stats *stats) { int i; Bytecount size = 0; @@ -590,7 +590,7 @@ static Bytecount compute_to_unicode_table_size_1 (void *table, int level, - struct overhead_stats *stats) + struct usage_stats *stats) { Bytecount size = 0; @@ -615,7 +615,7 @@ Bytecount compute_from_unicode_table_size (Lisp_Object charset, - struct overhead_stats *stats) + struct usage_stats *stats) { return (compute_from_unicode_table_size_1 (XCHARSET_FROM_UNICODE_TABLE (charset), @@ -625,7 +625,7 @@ Bytecount compute_to_unicode_table_size (Lisp_Object charset, - struct overhead_stats *stats) + struct usage_stats *stats) { return (compute_to_unicode_table_size_1 (XCHARSET_TO_UNICODE_TABLE (charset),
--- a/src/window.c Thu Mar 18 10:19:08 2010 -0500 +++ b/src/window.c Thu Mar 18 10:50:06 2010 -0500 @@ -5158,101 +5158,63 @@ struct window_stats { - int face; - int glyph; + struct usage_stats u; + Bytecount face; + Bytecount glyph; + Bytecount line_start; + Bytecount other_redisplay; #ifdef HAVE_SCROLLBARS - int scrollbar; + Bytecount scrollbar; #endif - int line_start; - int other_redisplay; - int other; }; static void compute_window_mirror_usage (struct window_mirror *mir, struct window_stats *stats, - struct overhead_stats *ovstats) + struct usage_stats *ustats) { if (!mir) return; - stats->other += lisp_object_storage_size (wrap_window_mirror (mir), ovstats); #ifdef HAVE_SCROLLBARS { struct device *d = XDEVICE (FRAME_DEVICE (mir->frame)); stats->scrollbar += compute_scrollbar_instance_usage (d, mir->scrollbar_vertical_instance, - ovstats); + ustats); stats->scrollbar += compute_scrollbar_instance_usage (d, mir->scrollbar_horizontal_instance, - ovstats); + ustats); } #endif /* HAVE_SCROLLBARS */ stats->other_redisplay += - compute_display_line_dynarr_usage (mir->current_display_lines, ovstats); + compute_display_line_dynarr_usage (mir->current_display_lines, ustats); stats->other_redisplay += - compute_display_line_dynarr_usage (mir->desired_display_lines, ovstats); + compute_display_line_dynarr_usage (mir->desired_display_lines, ustats); } static void compute_window_usage (struct window *w, struct window_stats *stats, - struct overhead_stats *ovstats) + struct usage_stats *ustats) { - xzero (*stats); - stats->other += lisp_object_storage_size (wrap_window (w), ovstats); - stats->face += compute_face_cachel_usage (w->face_cachels, ovstats); - stats->glyph += compute_glyph_cachel_usage (w->glyph_cachels, ovstats); + stats->face += compute_face_cachel_usage (w->face_cachels, ustats); + stats->glyph += compute_glyph_cachel_usage (w->glyph_cachels, ustats); stats->line_start += - compute_line_start_cache_dynarr_usage (w->line_start_cache, ovstats); - compute_window_mirror_usage (find_window_mirror (w), stats, ovstats); + compute_line_start_cache_dynarr_usage (w->line_start_cache, ustats); + compute_window_mirror_usage (find_window_mirror (w), stats, ustats); } -DEFUN ("window-memory-usage", Fwindow_memory_usage, 1, 1, 0, /* -Return stats about the memory usage of window WINDOW. -The values returned are in the form of an alist of usage types and byte -counts. The byte counts attempt to encompass all the memory used -by the window (separate from the memory logically associated with a -buffer or frame), including internal structures and any malloc() -overhead associated with them. In practice, the byte counts are -underestimated because certain memory usage is very hard to determine -\(e.g. the amount of memory used inside the Xt library or inside the -X server) and because there is other stuff that might logically -be associated with a window, buffer, or frame (e.g. window configurations, -glyphs) but should not obviously be included in the usage counts. - -Multiple slices of the total memory usage may be returned, separated -by a nil. Each slice represents a particular view of the memory, a -particular way of partitioning it into groups. Within a slice, there -is no overlap between the groups of memory, and each slice collectively -represents all the memory concerned. -*/ - (window)) +static void +window_memory_usage (Lisp_Object window, struct generic_usage_stats *gustats) { - struct window_stats stats; - struct overhead_stats ovstats; - Lisp_Object val = Qnil; - - CHECK_WINDOW (window); /* dead windows should be allowed, no? */ - xzero (ovstats); - compute_window_usage (XWINDOW (window), &stats, &ovstats); - - val = acons (Qface_cache, make_int (stats.face), val); - val = acons (Qglyph_cache, make_int (stats.glyph), val); -#ifdef HAVE_SCROLLBARS - val = acons (Qscrollbar_instances, make_int (stats.scrollbar), val); -#endif - val = acons (Qline_start_cache, make_int (stats.line_start), val); - val = acons (Qother_redisplay, make_int (stats.other_redisplay), val); - val = acons (Qother, make_int (stats.other), val); - val = Fcons (Qnil, val); - val = acons (Qactually_requested, make_int (ovstats.was_requested), val); - val = acons (Qmalloc_overhead, make_int (ovstats.malloc_overhead), val); - val = acons (Qdynarr_overhead, make_int (ovstats.dynarr_overhead), val); - - return Fnreverse (val); + struct window_stats *stats = (struct window_stats *) gustats; + + compute_window_usage (XWINDOW (window), stats, &stats->u); } #endif /* MEMORY_USAGE_STATS */ + + /* Mark all subwindows of a window as deleted. The argument W is actually the subwindow tree of the window in question. */ @@ -5430,6 +5392,14 @@ /************************************************************************/ void +window_objects_create (void) +{ +#ifdef MEMORY_USAGE_STATS + OBJECT_HAS_METHOD (window, memory_usage); +#endif +} + +void syms_of_window (void) { INIT_LISP_OBJECT (window); @@ -5453,7 +5423,6 @@ DEFSYMBOL (Qscrollbar_instances); #endif DEFSYMBOL (Qother_redisplay); - /* Qother in general.c */ #endif DEFSYMBOL (Qtruncate_partial_width_windows); @@ -5531,9 +5500,6 @@ DEFSUBR (Fscroll_other_window); DEFSUBR (Fcenter_to_window_line); DEFSUBR (Fmove_to_window_line); -#ifdef MEMORY_USAGE_STATS - DEFSUBR (Fwindow_memory_usage); -#endif DEFSUBR (Fcurrent_pixel_column); DEFSUBR (Fcurrent_pixel_row); } @@ -5549,6 +5515,17 @@ void 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, +#ifdef HAVE_SCROLLBARS + Qscrollbar_instances, +#endif + Qunbound)); +#endif /* MEMORY_USAGE_STATS */ + DEFVAR_BOOL ("scroll-on-clipped-lines", &scroll_on_clipped_lines /* *Non-nil means to scroll if point lands on a line which is clipped. */ );
--- a/src/window.h Thu Mar 18 10:19:08 2010 -0500 +++ b/src/window.h Thu Mar 18 10:50:06 2010 -0500 @@ -88,8 +88,6 @@ #define CHECK_WINDOW_MIRROR(x) CHECK_RECORD (x, window_mirror) #define CONCHECK_WINDOW_MIRROR(x) CONCHECK_RECORD (x, window_mirror) -DECLARE_LISP_OBJECT (window_configuration, struct window_config); - EXFUN (Fget_buffer_window, 3); EXFUN (Fmove_to_window_line, 2); EXFUN (Frecenter, 2);