Mercurial > hg > xemacs-beta
changeset 5159:cb303ff63e76
merge
author | Ben Wing <ben@xemacs.org> |
---|---|
date | Fri, 19 Mar 2010 17:02:11 -0500 |
parents | 9e0b43d3095c (diff) 45753d9a0dc4 (current diff) |
children | ab9ee10a53e4 |
files | ChangeLog src/ChangeLog src/alloc.c |
diffstat | 44 files changed, 1442 insertions(+), 556 deletions(-) [+] |
line wrap: on
line diff
--- a/CHANGES-beta Thu Mar 18 23:12:41 2010 -0500 +++ b/CHANGES-beta Fri Mar 19 17:02:11 2010 -0500 @@ -1,3 +1,133 @@ +to XEmacs 21.5.30 "harblegarble" + +by Ben Wing: + +debugging: + +-- make objects consistently print a UID, with a separate number space per + object type +-- add variable `debug-soe' for debugging stack-of-extents code in extents.c +-- correctly note pdumped objects in memory-usage stats returned by + `garbage-collect' and `object-memory-usage-stats'. +-- make VDB debugging functions (e.g. `test-segfault', which causes an + immediate crash!) conditional on `--with-debug' +-- rename `debug-xemacs-searches' -> `debug-searches' +-- Turn on "compiled-function annotation hack" so that compiled-function + objects print the function they are assigned to +-- Resurrect byte-metering code when --with-debug; enable with variables + `byte-code-meter', `byte-metering-on' +-- Add more checks for invalid byte code; when a byte-code-related crash + occurs, output the last 100 instructions processed + +documentation: + +-- fix to `previous/next-single[-char]-property-change' + +Lisp API: + +-- `set-frame-displayable-pixel-height' and friends had bugs in them, esp. + on MS Windows, where they didn't work; fixed +-- `frame-pixel-height', `set-frame-pixel-height' and friends will now + use updated values for frame size (as of next redisplay) when the frame + was previously resized but a redisplay has not yet happened +-- When `set-case-table' called with a length-256 vector, don't overwrite + existing case table; instead, populate a new table +-- Fix internal case comparisons to use the "canonical case mapping" so that + they always work even in the presence of complex case mappings (other + than just upper -> lower and lower -> upper) +-- In `scan-lists' and friends, when an error occurs, return a `scan-error' + along with two arguments specifying the range in which the error occurred, + for GNU compatibility + +Internals: + +-- reduce lcrecord header size from 3 words to 2 +-- major change to the way Lisp objects are defined and declared; introduce + a cleaner surface-layer API that eliminates references to "lrecords" and + "lcrecords", and uses "frob-block object" in place of "basic object"/ + "simple object"/etc. +-- new disksave method for Lisp objects, separated out from the finalize method +-- Lisp objects now must specify a print method; use either + internal_object_printer() or external_object_printer() as a default +-- equal method for Lisp objects has new `foldcase' param, to implement + case-folding comparison ala `equalp' +-- various changes to frame-geometry macros in frame-impl.h, gutter.h, etc., + and frame-sizing code in frame.c +-- Major rewrite, updated documentation to dynarr functions and macros +-- Major updates to internals manual and long comments in C files: + frame geometry, specifier authors, MS-Windows compilation flags, xlike + mechanism, ... +-- Rename LISP_TO_VOID -> STORE_LISP_IN_VOID, + VOID_TO_LISP -> GET_LISP_FROM_VOID; add STORE_VOID_IN_LISP, + GET_VOID_FROM_LISP +-- Convert various source files to UTF-8 +-- File renames: + select-common.h -> select-xlike-inc.c + xgccache.{ch} -> gccache-x.{ch} + toolbar-common.{ch} -> toolbar-xlike.{ch} +-- New files: + bytecode-ops.h + sysgtk.h, sysgdkx.h + keymap-buttons.h, keymap-slots.h +-- Deleted files: + event-gtk.h +-- Major reworking of DFC macros e.g. EXTERNAL_TO_C_STRING renamed to + EXTERNAL_TO_ITEXT; make them return their values when possible rather + than storing into a named variable +-- Eliminate unused second argument to xfree() +-- separate HAVE_XFT into HAVE_XFT and USE_XFT, to facilitate compiling + simultaneously with X and GTK +-- Move `equalp' to C + +Testing: + +-- Move test-harness.el to Lisp directory + +Building: + +-- Fix `--quick-build' so full rebuilds don't happen when changes are made + to files like lisp.h, config.h that are included by all C files +-- Fix C++ build on Cygwin when configured with --have-database + +User-Visible Bug Fixes: + +-- `escape-quoted' was failing to add escape quoting to Control-1 characters; + many potential byte-code-related crashes may have resulted from the old + behavior +-- Fix a redisplay bug where args to default_face_height_and_width() were + in wrong order +-- "speedy insert" code (to make `revert-buffer' preserve extents, markers, + etc. in unmodified sections of a reverted file) was broken with binary + files +-- File-locking code now names lock files .#FN# instead of .#FN, to avoid + problems with programs that e.g. try to process all .c or .h files +-- Fix a crash in frame creation due to lack of call to reset_glyph_cachels() +-- Fix long-standing bug: searching for Control-1 chars didn't work +-- Turn on `load-ignore-out-of-date-elc-files' by default + + + +by Didier Verna: + +Lisp API: + +-- new `background-placement' property of faces; with a value of `absolute', + the background pixmap is drawn relative to the root window, allowing + seamless integration with the desktop background + +by Jerry James: + +Lisp API: + +-- signal an error instead of crashing when encountering a ratio like 1/0 + +Internals: + +-- locate and add copyright notices to various files in preparation for + move to GPL v3 + + + to XEmacs 21.5.29 "garbanzo" Major Features and Backward Incompatible Changes
--- a/ChangeLog Thu Mar 18 23:12:41 2010 -0500 +++ b/ChangeLog Fri Mar 19 17:02:11 2010 -0500 @@ -1,3 +1,8 @@ +2010-03-18 Ben Wing <ben@xemacs.org> + + * CHANGES-beta: + Partially updated with last couple of months worth of changes. + 2010-03-18 Mike Sperber <mike@xemacs.org> * INSTALL: Reflect change from `lib' to `share'; also, document
--- a/lisp/ChangeLog Thu Mar 18 23:12:41 2010 -0500 +++ b/lisp/ChangeLog Fri Mar 19 17:02:11 2010 -0500 @@ -1,3 +1,14 @@ +2010-03-19 Ben Wing <ben@xemacs.org> + + * diagnose.el (show-object-memory-usage-stats): + Rewrite to take into account non-lisp-storage statistics + returned by garbage-collect-1 and friends. + +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 23:12:41 2010 -0500 +++ b/lisp/diagnose.el Fri Mar 19 17:02:11 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 @@ -176,26 +186,40 @@ (garbage-collect) (let ((buffer "*object memory usage statistics*") (plist (object-memory-usage-stats)) - (fmt "%-30s%10s%10s\n") + (fmt "%-30s%10s%10s%18s\n") (grandtotal 0) begin) (flet ((show-stats (match-string) - (princ (format fmt "object" "count" "storage")) - (princ (make-string 50 ?-)) + (princ (format fmt "object" "count" "storage" "non-Lisp storage")) + (princ (make-string 68 ?-)) (princ "\n") (let ((total-use 0) + (total-non-lisp-use 0) (total-use-overhead 0) (total-count 0)) (map-plist #'(lambda (stat num) - (when (string-match match-string - (symbol-name stat)) + (when (and (string-match match-string + (symbol-name stat)) + (let ((match (match-string + 1 (symbol-name stat)))) + (or (< (length match) 9) + (not (equal (substring match -9) + "-non-lisp"))))) (let ((storage-use num) (storage-use-overhead (plist-get plist (intern (concat (match-string 1 (symbol-name stat)) "-storage-including-overhead")))) + (non-lisp-storage + (or (plist-get + plist + (intern (concat (match-string 1 + (symbol-name stat)) + "-non-lisp-storage"))) + 0)) + (storage-count (or (loop for str in '("s-used" "es-used" "-used") for val = (plist-get @@ -218,19 +242,21 @@ (incf total-use-overhead (if storage-use-overhead storage-use-overhead storage-use)) + (incf total-non-lisp-use non-lisp-storage) (incf total-count (or storage-count 0)) (and (> storage-use 0) (princ (format fmt (match-string 1 (symbol-name stat)) (or storage-count "unknown") - storage-use)))))) + storage-use + non-lisp-storage)))))) plist) (princ "\n") (princ (format fmt "total" - total-count total-use-overhead)) + total-count total-use-overhead total-non-lisp-use)) (incf grandtotal total-use-overhead) (when-fboundp #'sort-numeric-fields - (sort-numeric-fields -1 + (sort-numeric-fields -2 (save-excursion (goto-char begin) (forward-line 3) @@ -242,7 +268,7 @@ (save-excursion (set-buffer buffer) (setq begin (point)) - (princ "Allocated with lisp allocator:\n") + (princ "Allocated with lisp allocator or related:\n") (show-stats "\\(.*\\)-storage$") (princ (format "\n\ngrand total: %s\n" grandtotal))) grandtotal))))
--- a/src/ChangeLog Thu Mar 18 23:12:41 2010 -0500 +++ b/src/ChangeLog Fri Mar 19 17:02:11 2010 -0500 @@ -1,3 +1,264 @@ +2010-03-19 Ben Wing <ben@xemacs.org> + + * alloc.c: + * alloc.c (struct): + * alloc.c (tick_lrecord_stats): + * alloc.c (gc_sweep_1): + * alloc.c (finish_object_memory_usage_stats): + * alloc.c (object_memory_usage_stats): + * alloc.c (compute_memusage_stats_length): + Call new memory-usage mechanism at sweep time to compute extra + memory utilization for all objects. Add up the values element-by- + element to get an aggregrate set of statistics, where each is the + sum of the values of a single statistic across different objects + of the same type. At end of sweep time, call + finish_object_memory_usage_stats() to add up all the aggreggrate + stats that are related to non-Lisp memory storage to compute + a single value, and add it to the list of values returned by + `garbage-collect' and `object-memory-usage-stats'. + + * buffer.c (compute_buffer_text_usage): + Don't crash on buffers without text (killed buffers?) and don't + double-count indirect buffers. + + * elhash.c: + * elhash.c (hash_table_objects_create): + * elhash.c (vars_of_elhash): + * symsinit.h: + Add memory-usage method to count the size of `hentries'. + + * emacs.c (main_1): + Call new functions in elhash.c, frame.c at init. + + * frame.c: + * frame.c (compute_frame_usage): + * frame.c (frame_memory_usage): + * frame.c (frame_objects_create): + * symsinit.h: + Add memory-usage method to count gutter display structures, + subwindow exposures. + + * gc.c (gc_finish): + * lisp.h: + Declare finish_object_memory_usage_stats(), call it in gc_finish(). + + * lrecord.h (struct lrecord_implementation): + * lrecord.h (INIT_MEMORY_USAGE_STATS): + New value in implementation struct to track number of non-Lisp-memory + statistics. Computed in alloc.c. + + +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: + * tests.c (Ftest_data_format_conversion): + Need to GCPRO newly created objects or we'll eventually get + a crash due to occurrence of call2(). + 2010-03-16 Ben Wing <ben@xemacs.org> * alloc.c (make_lcrecord_list): @@ -149,18 +410,6 @@ (7) Delete some custom print methods that were identical to external_object_printer(). -2010-03-15 Ben Wing <ben@xemacs.org> - - * extents.c: - * extents.c (soe_dump): - * extents.c (soe_insert): - * extents.c (soe_delete): - * extents.c (soe_move): - * extents.c (extent_fragment_update): - * extents.c (print_extent_1): - * extents.c (print_extent): - * extents.c (vars_of_extents): - 2010-03-12 Ben Wing <ben@xemacs.org> * lisp.h:
--- a/src/alloc.c Thu Mar 18 23:12:41 2010 -0500 +++ b/src/alloc.c Fri Mar 19 17:02:11 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[] = { @@ -3590,6 +3623,10 @@ int bytes_freed; int instances_on_free_list; int bytes_on_free_list; +#ifdef MEMORY_USAGE_STATS + Bytecount nonlisp_bytes_in_use; + struct generic_usage_stats stats; +#endif } lrecord_stats [countof (lrecord_implementations_table)]; void @@ -3604,6 +3641,22 @@ case ALLOC_IN_USE: lrecord_stats[type_index].instances_in_use++; lrecord_stats[type_index].bytes_in_use += sz; +#ifdef MEMORY_USAGE_STATS + { + struct generic_usage_stats stats; + Lisp_Object obj = wrap_pointer_1 (h); + if (HAS_OBJECT_METH_P (obj, memory_usage)) + { + int i; + int total_stats = OBJECT_PROPERTY (obj, num_extra_memusage_stats); + xzero (stats); + OBJECT_METH (obj, memory_usage, (obj, &stats)); + for (i = 0; i < total_stats; i++) + lrecord_stats[type_index].stats.othervals[i] += + stats.othervals[i]; + } + } +#endif break; case ALLOC_FREE: lrecord_stats[type_index].instances_freed++; @@ -4483,9 +4536,7 @@ sweep_eval_data (); sweep_misc_user_data (); #endif /* EVENT_DATA_AS_OBJECTS */ -#endif /* not NEW_GC */ - -#ifndef NEW_GC + #ifdef PDUMP pdump_objects_unmark (); #endif @@ -4625,6 +4676,25 @@ strcat (buf, suffix); } +void +finish_object_memory_usage_stats (void) +{ +#ifdef MEMORY_USAGE_STATS + int i; + for (i = 0; i < countof (lrecord_implementations_table); i++) + { + struct lrecord_implementation *imp = lrecord_implementations_table[i]; + if (imp && imp->num_extra_nonlisp_memusage_stats) + { + int j; + for (j = 0; j < imp->num_extra_nonlisp_memusage_stats; j++) + lrecord_stats[i].nonlisp_bytes_in_use += + lrecord_stats[i].stats.othervals[j]; + } + } +#endif /* MEMORY_USAGE_STATS */ +} + static Lisp_Object object_memory_usage_stats (int set_total_gc_usage) { @@ -4633,7 +4703,6 @@ EMACS_INT tgu_val = 0; #ifdef NEW_GC - for (i = 0; i < countof (lrecord_implementations_table); i++) { if (lrecord_stats[i].instances_in_use != 0) @@ -4708,6 +4777,13 @@ sprintf (buf, "%s-storage", name); pl = gc_plist_hack (buf, lrecord_stats[i].bytes_in_use, pl); tgu_val += lrecord_stats[i].bytes_in_use; + if (lrecord_stats[i].nonlisp_bytes_in_use) + { + sprintf (buf, "%s-non-lisp-storage", name); + pl = gc_plist_hack (buf, lrecord_stats[i].nonlisp_bytes_in_use, + pl); + tgu_val += lrecord_stats[i].nonlisp_bytes_in_use; + } pluralize_and_append (buf, name, "-freed"); if (lrecord_stats[i].instances_freed != 0) pl = gc_plist_hack (buf, lrecord_stats[i].instances_freed, pl); @@ -4747,7 +4823,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. */ ()) @@ -4757,6 +4833,137 @@ #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; + int nonlisp_len = 0; + int seen_break = 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++; + if (!seen_break) + nonlisp_len++; + } + else + seen_break++; + } + } + + imp->num_extra_memusage_stats = len; + imp->num_extra_nonlisp_memusage_stats = nonlisp_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, "", /* @@ -4857,7 +5064,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'. @@ -4949,7 +5156,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; @@ -5055,6 +5262,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 (); @@ -5163,6 +5371,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) { @@ -5170,6 +5387,7 @@ #ifndef NEW_GC init_lcrecord_lists (); #endif /* not NEW_GC */ + reinit_alloc_objects_early (); } void @@ -5185,18 +5403,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); @@ -5220,6 +5426,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 @@ -5227,6 +5448,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); @@ -5242,8 +5472,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); @@ -5257,6 +5490,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 23:12:41 2010 -0500 +++ b/src/buffer.c Fri Mar 19 17:02:11 2010 -0500 @@ -1752,76 +1752,51 @@ 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 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); + Bytecount was_requested, gap, malloc_use; + + /* Killed buffer? */ + if (!b->text) + return 0; + + /* Indirect buffer shares its text with someone else, so don't double- + count the text */ + if (b->base_buffer) + return 0; + + was_requested = b->text->z - 1; + gap = b->text->gap_size + b->text->end_gap_size; + malloc_use = malloced_storage_size (b->text->beg, was_requested + gap, 0); + + 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 +1880,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 +1952,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 +1974,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 23:12:41 2010 -0500 +++ b/src/console-impl.h Fri Mar 19 17:02:11 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 23:12:41 2010 -0500 +++ b/src/dynarr.c Fri Mar 19 17:02:11 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/elhash.c Thu Mar 18 23:12:41 2010 -0500 +++ b/src/elhash.c Fri Mar 19 17:02:11 2010 -0500 @@ -280,6 +280,28 @@ return XHASH_TABLE (hash_table)->count; } +#ifdef MEMORY_USAGE_STATS + +struct hash_table_stats +{ + struct usage_stats u; + Bytecount hentries; +}; + +static void +hash_table_memory_usage (Lisp_Object hashtab, + struct generic_usage_stats *gustats) +{ + Lisp_Hash_Table *ht = XHASH_TABLE (hashtab); + struct hash_table_stats *stats = (struct hash_table_stats *) gustats; + stats->hentries += + malloced_storage_size (ht->hentries, + sizeof (htentry) * (ht->size + 1), + &stats->u); +} + +#endif /* MEMORY_USAGE_STATS */ + /* Printing hash tables. @@ -1805,6 +1827,14 @@ /************************************************************************/ void +hash_table_objects_create (void) +{ +#ifdef MEMORY_USAGE_STATS + OBJECT_HAS_METHOD (hash_table, memory_usage); +#endif +} + +void syms_of_elhash (void) { DEFSUBR (Fhash_table_p); @@ -1854,6 +1884,15 @@ } void +vars_of_elhash (void) +{ +#ifdef MEMORY_USAGE_STATS + OBJECT_HAS_PROPERTY + (hash_table, memusage_stats_list, list1 (intern ("hash-entries"))); +#endif /* MEMORY_USAGE_STATS */ +} + +void init_elhash_once_early (void) { INIT_LISP_OBJECT (hash_table);
--- a/src/emacs.c Thu Mar 18 23:12:41 2010 -0500 +++ b/src/emacs.c Fri Mar 19 17:02:11 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,30 @@ #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 (); + frame_objects_create (); + glyph_objects_create (); + hash_table_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 +1939,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 (); @@ -2078,6 +2110,7 @@ vars_of_dragdrop (); #endif vars_of_editfns (); + vars_of_elhash (); vars_of_emacs (); vars_of_eval (); @@ -2305,6 +2338,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 23:12:41 2010 -0500 +++ b/src/events.c Fri Mar 19 17:02:11 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 23:12:41 2010 -0500 +++ b/src/extents.c Fri Mar 19 17:02:11 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 23:12:41 2010 -0500 +++ b/src/extents.h Fri Mar 19 17:02:11 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 23:12:41 2010 -0500 +++ b/src/faces.c Fri Mar 19 17:02:11 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 23:12:41 2010 -0500 +++ b/src/faces.h Fri Mar 19 17:02:11 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/frame.c Thu Mar 18 23:12:41 2010 -0500 +++ b/src/frame.c Fri Mar 19 17:02:11 2010 -0500 @@ -4064,6 +4064,53 @@ } +#ifdef MEMORY_USAGE_STATS + +struct frame_stats +{ + struct usage_stats u; + Bytecount gutter; + Bytecount expose_ignore; + Bytecount other; +}; + +static void +compute_frame_usage (struct frame *f, struct frame_stats *stats, + struct usage_stats *ustats) +{ + enum edge_pos edge; + EDGE_POS_LOOP (edge) + { + stats->gutter += + compute_display_line_dynarr_usage (f->current_display_lines[edge], + ustats); + stats->gutter += + compute_display_line_dynarr_usage (f->desired_display_lines[edge], + ustats); + } + { + struct expose_ignore *e; + + for (e = f->subwindow_exposures; e; e = e->next) + stats->expose_ignore += malloced_storage_size (e, sizeof (*e), ustats); + } + +#if 0 + stats->other += FRAMEMETH (f, frame_memory_usage, (f, ustats)); +#endif +} + +static void +frame_memory_usage (Lisp_Object frame, struct generic_usage_stats *gustats) +{ + struct frame_stats *stats = (struct frame_stats *) gustats; + + compute_frame_usage (XFRAME (frame), stats, &stats->u); +} + +#endif /* MEMORY_USAGE_STATS */ + + /***************************************************************************/ /* */ /* initialization */ @@ -4071,6 +4118,14 @@ /***************************************************************************/ void +frame_objects_create (void) +{ +#ifdef MEMORY_USAGE_STATS + OBJECT_HAS_METHOD (frame, memory_usage); +#endif +} + +void init_frame (void) { #ifndef PDUMP @@ -4216,6 +4271,12 @@ void vars_of_frame (void) { +#ifdef MEMORY_USAGE_STATS + OBJECT_HAS_PROPERTY + (frame, memusage_stats_list, list3 (Qgutter, intern ("expose-ignore"), + Qother)); +#endif /* MEMORY_USAGE_STATS */ + /* */ Vframe_being_created = Qnil; staticpro (&Vframe_being_created);
--- a/src/gc.c Thu Mar 18 23:12:41 2010 -0500 +++ b/src/gc.c Fri Mar 19 17:02:11 2010 -0500 @@ -1774,6 +1774,7 @@ #ifdef NEW_GC GC_SET_PHASE (FINISH_GC); #endif /* NEW_GC */ + finish_object_memory_usage_stats (); consing_since_gc = 0; #ifndef DEBUG_XEMACS /* Allow you to set it really fucking low if you really want ... */
--- a/src/general-slots.h Thu Mar 18 23:12:41 2010 -0500 +++ b/src/general-slots.h Fri Mar 19 17:02:11 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 23:12:41 2010 -0500 +++ b/src/glyphs.c Fri Mar 19 17:02:11 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 23:12:41 2010 -0500 +++ b/src/glyphs.h Fri Mar 19 17:02:11 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 23:12:41 2010 -0500 +++ b/src/lisp.h Fri Mar 19 17:02:11 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,12 +4785,15 @@ 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); +void finish_object_memory_usage_stats (void); extern int purify_flag; #ifndef NEW_GC extern EMACS_INT gc_generation_number[1]; @@ -4831,7 +4840,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 +5935,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 +6610,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 23:12:41 2010 -0500 +++ b/src/lrecord.h Fri Mar 19 17:02:11 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,66 @@ 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; + + /* Number of additional type-specific statistics related to + non-Lisp-Object memory usage for this object. Automatically + calculated (see compute_memusage_stats_length()) based on the value + placed in `memusage_stats_list'. */ + Elemcount num_extra_nonlisp_memusage_stats; + + /* 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 +572,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 +628,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 +1306,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 +1323,130 @@ /********* 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; \ + lrecord_implementations_table[lrecord_type_##type]-> \ + num_extra_nonlisp_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 +1454,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 +1471,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 +1744,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 +1803,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 +2017,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 23:12:41 2010 -0500 +++ b/src/lstream.c Fri Mar 19 17:02:11 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 23:12:41 2010 -0500 +++ b/src/marker.c Fri Mar 19 17:02:11 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 23:12:41 2010 -0500 +++ b/src/mc-alloc.c Fri Mar 19 17:02:11 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 23:12:41 2010 -0500 +++ b/src/mc-alloc.h Fri Mar 19 17:02:11 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 23:12:41 2010 -0500 +++ b/src/mule-charset.c Fri Mar 19 17:02:11 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 23:12:41 2010 -0500 +++ b/src/redisplay.c Fri Mar 19 17:02:11 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 23:12:41 2010 -0500 +++ b/src/redisplay.h Fri Mar 19 17:02:11 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 23:12:41 2010 -0500 +++ b/src/scrollbar-gtk.c Fri Mar 19 17:02:11 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 23:12:41 2010 -0500 +++ b/src/scrollbar-msw.c Fri Mar 19 17:02:11 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 23:12:41 2010 -0500 +++ b/src/scrollbar-x.c Fri Mar 19 17:02:11 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 23:12:41 2010 -0500 +++ b/src/scrollbar.c Fri Mar 19 17:02:11 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 23:12:41 2010 -0500 +++ b/src/scrollbar.h Fri Mar 19 17:02:11 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 23:12:41 2010 -0500 +++ b/src/symbols.c Fri Mar 19 17:02:11 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 23:12:41 2010 -0500 +++ b/src/symsinit.h Fri Mar 19 17:02:11 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,21 @@ 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 frame_objects_create (void); +void glyph_objects_create (void); +void hash_table_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 +345,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); @@ -366,6 +383,7 @@ void vars_of_dragdrop (void); void vars_of_editfns (void); EXTERN_C void vars_of_eldap (void); +void vars_of_elhash (void); void vars_of_emacs (void); void vars_of_eval (void); void reinit_vars_of_eval (void);
--- a/src/tests.c Thu Mar 18 23:12:41 2010 -0500 +++ b/src/tests.c Fri Mar 19 17:02:11 2010 -0500 @@ -49,7 +49,7 @@ ()) { void *ptr; Bytecount len; - Lisp_Object string, opaque, conversion_result = Qnil; + Lisp_Object string = Qnil, opaque = Qnil, conversion_result = Qnil; Ibyte int_foo[] = "\n\nfoo\nbar"; Extbyte ext_unix[]= "\n\nfoo\nbar"; @@ -72,6 +72,20 @@ Lisp_Object string_latin1 = make_string (int_latin1, sizeof (int_latin1) - 1); int autodetect_eol_p = !NILP (Fsymbol_value (intern ("eol-detection-enabled-p"))); + struct gcpro gcpro1, gcpro2, gcpro3, gcpro4, gcpro5; + struct gcpro ngcpro1, ngcpro2, ngcpro3; +#ifdef MULE + struct gcpro ngcpro4; +#endif + + /* DFC conversion inhibits GC, but we have a call2() below which calls + Lisp, which can trigger GC, so we need to GC-protect everything here. */ + GCPRO5 (string, opaque, conversion_result, opaque_dos, string_foo); +#ifdef MULE + NGCPRO4 (string_latin2, opaque_latin, opaque0_latin, string_latin1); +#else + NGCPRO3 (opaque_latin, opaque0_latin, string_latin1); +#endif /* Check for expected strings before and after conversion. Conversions depend on whether MULE is defined. */ @@ -541,6 +555,8 @@ Qbinary); DFC_CHECK_DATA (ptr, len, ext_dos, "DOS Lisp opaque, ALLOCA, binary"); + NUNGCPRO; + UNGCPRO; return conversion_result; }
--- a/src/ui-gtk.c Thu Mar 18 23:12:41 2010 -0500 +++ b/src/ui-gtk.c Fri Mar 19 17:02:11 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 23:12:41 2010 -0500 +++ b/src/unicode.c Fri Mar 19 17:02:11 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 23:12:41 2010 -0500 +++ b/src/window.c Fri Mar 19 17:02:11 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 23:12:41 2010 -0500 +++ b/src/window.h Fri Mar 19 17:02:11 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);
--- a/tests/ChangeLog Thu Mar 18 23:12:41 2010 -0500 +++ b/tests/ChangeLog Fri Mar 19 17:02:11 2010 -0500 @@ -1,3 +1,10 @@ +2010-03-18 Ben Wing <ben@xemacs.org> + + * automated/c-tests.el: + * automated/c-tests.el (when): + Use `with-temp-buffer' so results don't get written into source + file. + 2010-03-12 Ben Wing <ben@xemacs.org> * automated/base64-tests.el (bt-base64-encode-string):
--- a/tests/automated/c-tests.el Thu Mar 18 23:12:41 2010 -0500 +++ b/tests/automated/c-tests.el Fri Mar 19 17:02:11 2010 -0500 @@ -1,4 +1,5 @@ ;; Copyright (C) 2000 Martin Buchholz +;; Copyright (C) 2010 Ben Wing. ;; Author: Martin Buchholz <martin@xemacs.org> ;; Maintainer: Martin Buchholz <martin@xemacs.org> @@ -38,8 +39,9 @@ (push (file-name-directory load-file-name) load-path)) (require 'test-harness)))) -(when (boundp 'test-function-list) ; Only if configure --debug - (loop for fun in test-function-list do - ;; #### I hope there's no way we can signal ... - (loop for result in (funcall fun) do - (Assert (nth 1 result) (nth 2 result) (nth 0 result))))) +(with-temp-buffer + (when (boundp 'test-function-list) ; Only if configure --debug + (loop for fun in test-function-list do + ;; #### I hope there's no way we can signal ... + (loop for result in (funcall fun) do + (Assert (nth 1 result) (nth 2 result) (nth 0 result))))))