Mercurial > hg > xemacs-beta
diff src/lrecord.h @ 5127:a9c41067dd88 ben-lisp-object
more cleanups, terminology clarification, lots of doc work
-------------------- ChangeLog entries follow: --------------------
man/ChangeLog addition:
2010-03-05 Ben Wing <ben@xemacs.org>
* internals/internals.texi (Introduction to Allocation):
* internals/internals.texi (Integers and Characters):
* internals/internals.texi (Allocation from Frob Blocks):
* internals/internals.texi (lrecords):
* internals/internals.texi (Low-level allocation):
Rewrite section on allocation of Lisp objects to reflect the new
reality. Remove references to nonexistent XSETINT and XSETCHAR.
modules/ChangeLog addition:
2010-03-05 Ben Wing <ben@xemacs.org>
* postgresql/postgresql.c (allocate_pgconn):
* postgresql/postgresql.c (allocate_pgresult):
* postgresql/postgresql.h (struct Lisp_PGconn):
* postgresql/postgresql.h (struct Lisp_PGresult):
* ldap/eldap.c (allocate_ldap):
* ldap/eldap.h (struct Lisp_LDAP):
Same changes as in src/ dir. See large log there in ChangeLog,
but basically:
ALLOC_LISP_OBJECT -> ALLOC_NORMAL_LISP_OBJECT
LISP_OBJECT_HEADER -> NORMAL_LISP_OBJECT_HEADER
../hlo/src/ChangeLog addition:
2010-03-05 Ben Wing <ben@xemacs.org>
* alloc.c:
* alloc.c (old_alloc_sized_lcrecord):
* alloc.c (very_old_free_lcrecord):
* alloc.c (copy_lisp_object):
* alloc.c (zero_sized_lisp_object):
* alloc.c (zero_nonsized_lisp_object):
* alloc.c (lisp_object_storage_size):
* alloc.c (free_normal_lisp_object):
* alloc.c (FREE_FIXED_TYPE_WHEN_NOT_IN_GC):
* alloc.c (ALLOC_FROB_BLOCK_LISP_OBJECT):
* alloc.c (Fcons):
* alloc.c (noseeum_cons):
* alloc.c (make_float):
* alloc.c (make_bignum):
* alloc.c (make_bignum_bg):
* alloc.c (make_ratio):
* alloc.c (make_ratio_bg):
* alloc.c (make_ratio_rt):
* alloc.c (make_bigfloat):
* alloc.c (make_bigfloat_bf):
* alloc.c (size_vector):
* alloc.c (make_compiled_function):
* alloc.c (Fmake_symbol):
* alloc.c (allocate_extent):
* alloc.c (allocate_event):
* alloc.c (make_key_data):
* alloc.c (make_button_data):
* alloc.c (make_motion_data):
* alloc.c (make_process_data):
* alloc.c (make_timeout_data):
* alloc.c (make_magic_data):
* alloc.c (make_magic_eval_data):
* alloc.c (make_eval_data):
* alloc.c (make_misc_user_data):
* alloc.c (Fmake_marker):
* alloc.c (noseeum_make_marker):
* alloc.c (size_string_direct_data):
* alloc.c (make_uninit_string):
* alloc.c (make_string_nocopy):
* alloc.c (mark_lcrecord_list):
* alloc.c (alloc_managed_lcrecord):
* alloc.c (free_managed_lcrecord):
* alloc.c (sweep_lcrecords_1):
* alloc.c (malloced_storage_size):
* buffer.c (allocate_buffer):
* buffer.c (compute_buffer_usage):
* buffer.c (DEFVAR_BUFFER_LOCAL_1):
* buffer.c (nuke_all_buffer_slots):
* buffer.c (common_init_complex_vars_of_buffer):
* buffer.h (struct buffer_text):
* buffer.h (struct buffer):
* bytecode.c:
* bytecode.c (make_compiled_function_args):
* bytecode.c (size_compiled_function_args):
* bytecode.h (struct compiled_function_args):
* casetab.c (allocate_case_table):
* casetab.h (struct Lisp_Case_Table):
* charset.h (struct Lisp_Charset):
* chartab.c (fill_char_table):
* chartab.c (Fmake_char_table):
* chartab.c (make_char_table_entry):
* chartab.c (copy_char_table_entry):
* chartab.c (Fcopy_char_table):
* chartab.c (put_char_table):
* chartab.h (struct Lisp_Char_Table_Entry):
* chartab.h (struct Lisp_Char_Table):
* console-gtk-impl.h (struct gtk_device):
* console-gtk-impl.h (struct gtk_frame):
* console-impl.h (struct console):
* console-msw-impl.h (struct Lisp_Devmode):
* console-msw-impl.h (struct mswindows_device):
* console-msw-impl.h (struct msprinter_device):
* console-msw-impl.h (struct mswindows_frame):
* console-msw-impl.h (struct mswindows_dialog_id):
* console-stream-impl.h (struct stream_console):
* console-stream.c (stream_init_console):
* console-tty-impl.h (struct tty_console):
* console-tty-impl.h (struct tty_device):
* console-tty.c (allocate_tty_console_struct):
* console-x-impl.h (struct x_device):
* console-x-impl.h (struct x_frame):
* console.c (allocate_console):
* console.c (nuke_all_console_slots):
* console.c (DEFVAR_CONSOLE_LOCAL_1):
* console.c (common_init_complex_vars_of_console):
* data.c (make_weak_list):
* data.c (make_weak_box):
* data.c (make_ephemeron):
* database.c:
* database.c (struct Lisp_Database):
* database.c (allocate_database):
* database.c (finalize_database):
* device-gtk.c (allocate_gtk_device_struct):
* device-impl.h (struct device):
* device-msw.c:
* device-msw.c (mswindows_init_device):
* device-msw.c (msprinter_init_device):
* device-msw.c (finalize_devmode):
* device-msw.c (allocate_devmode):
* device-tty.c (allocate_tty_device_struct):
* device-x.c (allocate_x_device_struct):
* device.c:
* device.c (nuke_all_device_slots):
* device.c (allocate_device):
* dialog-msw.c (handle_question_dialog_box):
* elhash.c:
* elhash.c (struct Lisp_Hash_Table):
* elhash.c (finalize_hash_table):
* elhash.c (make_general_lisp_hash_table):
* elhash.c (Fcopy_hash_table):
* elhash.h (htentry):
* emacs.c (main_1):
* eval.c:
* eval.c (size_multiple_value):
* event-stream.c (finalize_command_builder):
* event-stream.c (allocate_command_builder):
* event-stream.c (free_command_builder):
* event-stream.c (event_stream_generate_wakeup):
* event-stream.c (event_stream_resignal_wakeup):
* event-stream.c (event_stream_disable_wakeup):
* event-stream.c (event_stream_wakeup_pending_p):
* events.h (struct Lisp_Timeout):
* events.h (struct command_builder):
* extents-impl.h:
* extents-impl.h (struct extent_auxiliary):
* extents-impl.h (struct extent_info):
* extents-impl.h (set_extent_no_chase_aux_field):
* extents-impl.h (set_extent_no_chase_normal_field):
* extents.c:
* extents.c (gap_array_marker):
* extents.c (gap_array):
* extents.c (extent_list_marker):
* extents.c (extent_list):
* extents.c (stack_of_extents):
* extents.c (gap_array_make_marker):
* extents.c (extent_list_make_marker):
* extents.c (allocate_extent_list):
* extents.c (SLOT):
* extents.c (mark_extent_auxiliary):
* extents.c (allocate_extent_auxiliary):
* extents.c (attach_extent_auxiliary):
* extents.c (size_gap_array):
* extents.c (finalize_extent_info):
* extents.c (allocate_extent_info):
* extents.c (uninit_buffer_extents):
* extents.c (allocate_soe):
* extents.c (copy_extent):
* extents.c (vars_of_extents):
* extents.h:
* faces.c (allocate_face):
* faces.h (struct Lisp_Face):
* faces.h (struct face_cachel):
* file-coding.c:
* file-coding.c (finalize_coding_system):
* file-coding.c (sizeof_coding_system):
* file-coding.c (Fcopy_coding_system):
* file-coding.h (struct Lisp_Coding_System):
* file-coding.h (MARKED_SLOT):
* fns.c (size_bit_vector):
* font-mgr.c:
* font-mgr.c (finalize_fc_pattern):
* font-mgr.c (print_fc_pattern):
* font-mgr.c (Ffc_pattern_p):
* font-mgr.c (Ffc_pattern_create):
* font-mgr.c (Ffc_name_parse):
* font-mgr.c (Ffc_name_unparse):
* font-mgr.c (Ffc_pattern_duplicate):
* font-mgr.c (Ffc_pattern_add):
* font-mgr.c (Ffc_pattern_del):
* font-mgr.c (Ffc_pattern_get):
* font-mgr.c (fc_config_create_using):
* font-mgr.c (fc_strlist_to_lisp_using):
* font-mgr.c (fontset_to_list):
* font-mgr.c (Ffc_config_p):
* font-mgr.c (Ffc_config_up_to_date):
* font-mgr.c (Ffc_config_build_fonts):
* font-mgr.c (Ffc_config_get_cache):
* font-mgr.c (Ffc_config_get_fonts):
* font-mgr.c (Ffc_config_set_current):
* font-mgr.c (Ffc_config_get_blanks):
* font-mgr.c (Ffc_config_get_rescan_interval):
* font-mgr.c (Ffc_config_set_rescan_interval):
* font-mgr.c (Ffc_config_app_font_add_file):
* font-mgr.c (Ffc_config_app_font_add_dir):
* font-mgr.c (Ffc_config_app_font_clear):
* font-mgr.c (size):
* font-mgr.c (Ffc_config_substitute):
* font-mgr.c (Ffc_font_render_prepare):
* font-mgr.c (Ffc_font_match):
* font-mgr.c (Ffc_font_sort):
* font-mgr.c (finalize_fc_config):
* font-mgr.c (print_fc_config):
* font-mgr.h:
* font-mgr.h (struct fc_pattern):
* font-mgr.h (XFC_PATTERN):
* font-mgr.h (struct fc_config):
* font-mgr.h (XFC_CONFIG):
* frame-gtk.c (allocate_gtk_frame_struct):
* frame-impl.h (struct frame):
* frame-msw.c (mswindows_init_frame_1):
* frame-x.c (allocate_x_frame_struct):
* frame.c (nuke_all_frame_slots):
* frame.c (allocate_frame_core):
* gc.c:
* gc.c (GC_CHECK_NOT_FREE):
* glyphs.c (finalize_image_instance):
* glyphs.c (allocate_image_instance):
* glyphs.c (Fcolorize_image_instance):
* glyphs.c (allocate_glyph):
* glyphs.c (unmap_subwindow_instance_cache_mapper):
* glyphs.c (register_ignored_expose):
* glyphs.h (struct Lisp_Image_Instance):
* glyphs.h (struct Lisp_Glyph):
* glyphs.h (struct glyph_cachel):
* glyphs.h (struct expose_ignore):
* gui.c (allocate_gui_item):
* gui.h (struct Lisp_Gui_Item):
* keymap.c (struct Lisp_Keymap):
* keymap.c (make_keymap):
* lisp.h:
* lisp.h (struct Lisp_String_Direct_Data):
* lisp.h (struct Lisp_String_Indirect_Data):
* lisp.h (struct Lisp_Vector):
* lisp.h (struct Lisp_Bit_Vector):
* lisp.h (DECLARE_INLINE_LISP_BIT_VECTOR):
* lisp.h (struct weak_box):
* lisp.h (struct ephemeron):
* lisp.h (struct weak_list):
* lrecord.h:
* lrecord.h (struct lrecord_implementation):
* lrecord.h (MC_ALLOC_CALL_FINALIZER):
* lrecord.h (struct lcrecord_list):
* lstream.c (finalize_lstream):
* lstream.c (sizeof_lstream):
* lstream.c (Lstream_new):
* lstream.c (Lstream_delete):
* lstream.h (struct lstream):
* marker.c:
* marker.c (finalize_marker):
* marker.c (compute_buffer_marker_usage):
* mule-charset.c:
* mule-charset.c (make_charset):
* mule-charset.c (compute_charset_usage):
* objects-impl.h (struct Lisp_Color_Instance):
* objects-impl.h (struct Lisp_Font_Instance):
* objects-tty-impl.h (struct tty_color_instance_data):
* objects-tty-impl.h (struct tty_font_instance_data):
* objects-tty.c (tty_initialize_color_instance):
* objects-tty.c (tty_initialize_font_instance):
* objects.c (finalize_color_instance):
* objects.c (Fmake_color_instance):
* objects.c (finalize_font_instance):
* objects.c (Fmake_font_instance):
* objects.c (reinit_vars_of_objects):
* opaque.c:
* opaque.c (sizeof_opaque):
* opaque.c (make_opaque_ptr):
* opaque.c (free_opaque_ptr):
* opaque.h:
* opaque.h (Lisp_Opaque):
* opaque.h (Lisp_Opaque_Ptr):
* print.c (printing_unreadable_lcrecord):
* print.c (external_object_printer):
* print.c (debug_p4):
* process.c (finalize_process):
* process.c (make_process_internal):
* procimpl.h (struct Lisp_Process):
* rangetab.c (Fmake_range_table):
* rangetab.c (Fcopy_range_table):
* rangetab.h (struct Lisp_Range_Table):
* scrollbar.c:
* scrollbar.c (create_scrollbar_instance):
* scrollbar.c (compute_scrollbar_instance_usage):
* scrollbar.h (struct scrollbar_instance):
* specifier.c (finalize_specifier):
* specifier.c (sizeof_specifier):
* specifier.c (set_specifier_caching):
* specifier.h (struct Lisp_Specifier):
* specifier.h (struct specifier_caching):
* symeval.h:
* symeval.h (SYMBOL_VALUE_MAGIC_P):
* symeval.h (DEFVAR_SYMVAL_FWD):
* symsinit.h:
* syntax.c (init_buffer_syntax_cache):
* syntax.h (struct syntax_cache):
* toolbar.c:
* toolbar.c (allocate_toolbar_button):
* toolbar.c (update_toolbar_button):
* toolbar.h (struct toolbar_button):
* tooltalk.c (struct Lisp_Tooltalk_Message):
* tooltalk.c (make_tooltalk_message):
* tooltalk.c (struct Lisp_Tooltalk_Pattern):
* tooltalk.c (make_tooltalk_pattern):
* ui-gtk.c:
* ui-gtk.c (allocate_ffi_data):
* ui-gtk.c (emacs_gtk_object_finalizer):
* ui-gtk.c (allocate_emacs_gtk_object_data):
* ui-gtk.c (allocate_emacs_gtk_boxed_data):
* ui-gtk.h:
* window-impl.h (struct window):
* window-impl.h (struct window_mirror):
* window.c (finalize_window):
* window.c (allocate_window):
* window.c (new_window_mirror):
* window.c (mark_window_as_deleted):
* window.c (make_dummy_parent):
* window.c (compute_window_mirror_usage):
* window.c (compute_window_usage):
Overall point of this change and previous ones in this repository:
(1) Introduce new, clearer terminology: everything other than int
or char is a "record" object, which comes in two types: "normal
objects" and "frob-block objects". Fix up all places that
referred to frob-block objects as "simple", "basic", etc.
(2) Provide an advertised interface for doing operations on Lisp
objects, including creating new types, that is clean and
consistent in its naming, uses the above-referenced terms and
avoids referencing "lrecords", "old lcrecords", etc., which should
hide under the surface.
(3) Make the size_in_bytes and finalizer methods take a
Lisp_Object rather than a void * for consistency with other methods.
(4) Separate finalizer method into finalizer and disksaver, so
that normal finalize methods don't have to worry about disksaving.
Other specifics:
(1) Renaming:
LISP_OBJECT_HEADER -> NORMAL_LISP_OBJECT_HEADER
ALLOC_LISP_OBJECT -> ALLOC_NORMAL_LISP_OBJECT
implementation->basic_p -> implementation->frob_block_p
ALLOCATE_FIXED_TYPE_AND_SET_IMPL -> ALLOC_FROB_BLOCK_LISP_OBJECT
*FCCONFIG*, wrap_fcconfig -> *FC_CONFIG*, wrap_fc_config
*FCPATTERN*, wrap_fcpattern -> *FC_PATTERN*, wrap_fc_pattern
(the last two changes make the naming of these macros consistent
with the naming of all other macros, since the objects are named
fc-config and fc-pattern with a hyphen)
(2) Lots of documentation fixes in lrecord.h.
(3) Eliminate macros for copying, freeing, zeroing objects, getting
their storage size. Instead, new functions:
zero_sized_lisp_object()
zero_nonsized_lisp_object()
lisp_object_storage_size()
free_normal_lisp_object()
(copy_lisp_object() already exists)
LISP_OBJECT_FROB_BLOCK_P() (actually a macro)
Eliminated:
free_lrecord()
zero_lrecord()
copy_lrecord()
copy_sized_lrecord()
old_copy_lcrecord()
old_copy_sized_lcrecord()
old_zero_lcrecord()
old_zero_sized_lcrecord()
LISP_OBJECT_STORAGE_SIZE()
COPY_SIZED_LISP_OBJECT()
COPY_SIZED_LCRECORD()
COPY_LISP_OBJECT()
ZERO_LISP_OBJECT()
FREE_LISP_OBJECT()
(4) Catch the remaining places where lrecord stuff was used directly
and use the advertised interface, e.g. alloc_sized_lrecord() ->
ALLOC_SIZED_LISP_OBJECT().
(5) Make certain statically-declared pseudo-objects
(buffer_local_flags, console_local_flags) have their lheader
initialized correctly, so things like copy_lisp_object() can work
on them. Make extent_auxiliary_defaults a proper heap object
Vextent_auxiliary_defaults, and make extent auxiliaries dumpable
so that this object can be dumped. allocate_extent_auxiliary()
now just creates the object, and attach_extent_auxiliary()
creates an extent auxiliary and attaches to an extent, like the
old allocate_extent_auxiliary().
(6) Create EXTENT_AUXILIARY_SLOTS macro, similar to the foo-slots.h
files but in a macro instead of a file. The purpose is to avoid
duplication when iterating over all the slots in an extent auxiliary.
Use it.
(7) In lstream.c, don't zero out object after allocation because
allocation routines take care of this.
(8) In marker.c, fix a mistake in computing marker overhead.
(9) In print.c, clean up printing_unreadable_lcrecord(),
external_object_printer() to avoid lots of ifdef NEW_GC's.
(10) Separate toolbar-button allocation into a separate
allocate_toolbar_button() function for use in the example code
in lrecord.h.
author | Ben Wing <ben@xemacs.org> |
---|---|
date | Fri, 05 Mar 2010 04:08:17 -0600 |
parents | 2a462149bd6a |
children | 7be849cb8828 |
line wrap: on
line diff
--- a/src/lrecord.h Wed Feb 24 19:04:27 2010 -0600 +++ b/src/lrecord.h Fri Mar 05 04:08:17 2010 -0600 @@ -26,40 +26,136 @@ #ifndef INCLUDED_lrecord_h_ #define INCLUDED_lrecord_h_ -/* The "lrecord" type of Lisp object is used for all object types other - than a few simple ones (like char and int). This allows many types to be - implemented but only a few bits required in a Lisp object for type - information. (The tradeoff is that each object has its type marked in - it, thereby increasing its size.) All lrecords begin with a `struct - lrecord_header', which identifies the lisp object type, by providing an - index into a table of `struct lrecord_implementation', which describes - the behavior of the lisp object. It also contains some other data bits. +/* All objects other than char and int are implemented as structures and + passed by reference. Such objects are called "record objects" ("record" + is another term for "structure"). The "wrapped" value of such an object + (i.e. when stored in a variable of type Lisp_Object) is simply the raw + pointer coerced to an integral type the same size as the pointer + (usually `long'). + + Under old-GC (i.e. when NEW_GC is not defined), there are two kinds of + record objects: normal objects (those allocated on their own with + xmalloc()) and frob-block objects (those allocated as pieces of large, + usually 2K, chunks of memory known as "frob blocks"). Under NEW_GC, + there is only one type of record object. Stuff below that applies to + frob-block objects is assumed to apply to the same type of object as + normal objects under NEW_GC. + + Record objects have a header at the beginning of their structure, which + is used internally to identify the type of the object (so that an + object's type can be recovered from its pointer); in addition, it holds + a few flags and a "UID", which for most objects is shown when it is + printed, and is primarily useful for debugging purposes. The header of + a normal object is declared as NORMAL_LISP_OBJECT_HEADER and that of a + frob-block object FROB_BLOCK_LISP_OBJECT_HEADER. + + FROB_BLOCK_LISP_OBJECT_HEADER boils down to a `struct lrecord_header'. + This is a 32-bit value made up of bit fields, where 8 bits are used to + hold the type, 2 or 3 bits are used for flags associated with the + garbage collector, and the remaining 21 or 22 bits hold the UID. + + Under NEW_GC, NORMAL_LISP_OBJECT_HEADER also resolves to `struct + lrecord_header'. Under old-GC, however, NORMAL_LISP_OBJECT_HEADER + resolves to a `struct old_lcrecord_header' (note the `c'), which is a + larger structure -- on 32-bit machines it occupies 3 machine words + instead of 1. Such an object is known internally as an "lcrecord". The + first word of `struct old_lcrecord_header' is an embedded `struct + lrecord_header' with the same information as for frob-block objects; + that way, all objects can be cast to a `struct lrecord_header' to + determine their type or other info. The other words consist of a + pointer, used to thread all lcrecords together in one big linked list, + and a 32-bit structure that contains another UID field (#### which + should be deleted, as it is redundant; it dates back to the days when + the lrecord_header consisted of a pointer to an object's implementation + structure rather than an index). + + Under old-GC, normal objects (i.e. lcrecords) are allocated in + individual chunks using the underlying allocator (i.e. xmalloc(), which + is a thin wrapper around malloc()). Frob-block objects are more + efficient than normal objects, as they have a smaller header and don't + have the additional memory overhead associated with malloc() -- instead, + as mentioned above, they are carved out of 2K chunks of memory called + "frob blocks"). However, it is slightly more tricky to create such + objects, as they require special routines in alloc.c to create an object + of each such type and to sweep them during garbage collection. In + addition, there is currently no mechanism for handling variable-sized + frob-block objects (e.g. vectors), whereas variable-sized normal objects + are not a problem. Frob-block objects are typically used for basic + objects that exist in large numbers, such as `cons' or `string'. -#ifndef NEW_GC - Lrecords are of two types: straight lrecords, and lcrecords. - Straight lrecords are used for those types of objects that have - their own allocation routines (typically allocated out of 2K chunks - of memory called `frob blocks'). These objects have a `struct - lrecord_header' at the top, containing only the bits needed to find - the lrecord_implementation for the object. There are special - routines in alloc.c to create an object of each such type. + Note that strings are an apparent exception to the statement above that + variable-sized objects can't be handled. Under old-GC strings work as + follows. A string consists of two parts -- a fixed-size "string header" + that is allocated as a standard frob-block object, and a "string-chars" + structure that is allocated out of special 8K-sized frob blocks that + have a dedicated garbage-collection handler that compacts the blocks + during the sweep stage, relocating the string-chars data (but not the + string headers) to eliminate gaps. Strings larger than 8K are not + placed in frob blocks, but instead are stored as individually malloc()ed + blocks of memory. Strings larger than 8K are called "big strings" and + those smaller than 8K are called "small strings". + + Under new-GC, there is no difference between big and small strings, + just as there is no difference between normal and frob-block objects. + There is only one allocation method, which is capable of handling + variable-sized objects. This apparently allocates all objects in + frob blocks according to the size of the object. + + To create a new normal Lisp object, see the toolbar-button example + below. To create a new frob-block Lisp object, follow the lead of + one of the existing frob-block objects, such as extents or events. + Note that you do not need to supply all the methods (see below); + reasonable defaults are provided for many of them. Alternatively, if + you're just looking for a way of encapsulating data (which possibly + could contain Lisp_Objects in it), you may well be able to use the + opaque type. +*/ + +/* + How to declare a Lisp object: + + NORMAL_LISP_OBJECT_HEADER: + Header for normal objects + + FROB_BLOCK_LISP_OBJECT_HEADER: + Header for frob-block objects - Lcrecords are used for less common sorts of objects that don't do - their own allocation. Each such object is malloc()ed individually, - and the objects are chained together through a `next' pointer. - Lcrecords have a `struct old_lcrecord_header' at the top, which - contains a `struct lrecord_header' and a `next' pointer, and are - allocated using old_alloc_lcrecord_type() or its variants. -#endif + How to allocate a Lisp object: + + - For normal objects of a fixed size, simply call + ALLOC_NORMAL_LISP_OBJECT (type), where TYPE is the name of the type + (e.g. toolbar_button). Such objects can be freed manually using + free_normal_lisp_object. + + - For normal objects whose size can vary (and hence which have a + size_in_bytes_method rather than a static_size), call + ALLOC_SIZED_LISP_OBJECT (size, type), where TYPE is the + name of the type. NOTE: You cannot call free_normal_lisp_object() on such + on object! (At least when not NEW_GC) + + - For frob-block objects, use + ALLOC_FROB_BLOCK_LISP_OBJECT (type, lisp_type, var, lrec_ptr). + But these objects need special handling; if you don't understand this, + just ignore it. - Creating a new Lisp object type is fairly easy; just follow the - lead of some existing type (e.g. hash tables). Note that you - do not need to supply all the methods (see below); reasonable - defaults are provided for many of them. Alternatively, if you're - just looking for a way of encapsulating data (which possibly - could contain Lisp_Objects in it), you may well be able to use - the opaque type. -*/ + - Some lrecords, which are used totally internally, use the + noseeum-* functions for debugging reasons. + + Other operations: + + - copy_lisp_object (dst, src) + + - zero_nonsized_lisp_object (obj), zero_sized_lisp_object (obj, size): + BUT NOTE, it is not necessary to zero out newly allocated Lisp objects. + This happens automatically. + + - lisp_object_size (obj): Return the size of a Lisp object. NOTE: This + requires that the object is properly initialized. + + - lisp_object_storage_size (obj, stats): Return the storage size of a + Lisp objcet, including malloc or frob-block overhead; also, if STATS + is non-NULL, accumulate info about the size and overhead into STATS. + */ #ifdef NEW_GC /* @@ -74,46 +170,34 @@ object descriptions exist to indicate the size of these structures and the Lisp object pointers within them. - At least one definite issue is that under New-GC dumpable objects cannot - contain any finalizers (see pdump_register_object()). This means that any - substructures in dumpable objects that are allocated separately and - normally freed in a finalizer need instead to be made into actual Lisp - objects. If those structures are Dynarrs, they need to be made into - Dynarr Lisp objects (e.g. face-cachel-dynarr or glyph-cachel-dynarr), - which are created using Dynarr_lisp_new() or Dynarr_new_new2(). - Furthermore, the objects contained in the Dynarr also need to be Lisp - objects (e.g. face-cachel or glyph-cachel). + At least one definite issue is that under New-GC dumpable objects cannot + contain any finalizers (see pdump_register_object()). This means that + any substructures in dumpable objects that are allocated separately and + normally freed in a finalizer need instead to be made into actual Lisp + objects. If those structures are Dynarrs, they need to be made into + Dynarr Lisp objects (e.g. face-cachel-dynarr or glyph-cachel-dynarr), + which are created using Dynarr_lisp_new() or Dynarr_new_new2(). + Furthermore, the objects contained in the Dynarr also need to be Lisp + objects (e.g. face-cachel or glyph-cachel). --ben */ - #endif - - #ifdef NEW_GC -#define ALLOC_LISP_OBJECT(type) alloc_lrecord (&lrecord_##type) +#define ALLOC_NORMAL_LISP_OBJECT(type) alloc_lrecord (&lrecord_##type) #define ALLOC_SIZED_LISP_OBJECT(size, type) \ alloc_sized_lrecord (size, &lrecord_##type) -#define COPY_SIZED_LISP_OBJECT copy_sized_lrecord -#define COPY_LISP_OBJECT copy_lrecord -#define LISP_OBJECT_STORAGE_SIZE(ptr, size, stats) \ - mc_alloced_storage_size (size, stats) -#define ZERO_LISP_OBJECT zero_lrecord -#define LISP_OBJECT_HEADER struct lrecord_header +#define NORMAL_LISP_OBJECT_HEADER struct lrecord_header #define FROB_BLOCK_LISP_OBJECT_HEADER struct lrecord_header -#define FREE_LISP_OBJECT free_lrecord +#define LISP_OBJECT_FROB_BLOCK_P(obj) 0 #else /* not NEW_GC */ -#define ALLOC_LISP_OBJECT(type) alloc_automanaged_lcrecord (&lrecord_##type) +#define ALLOC_NORMAL_LISP_OBJECT(type) alloc_automanaged_lcrecord (&lrecord_##type) #define ALLOC_SIZED_LISP_OBJECT(size, type) \ old_alloc_sized_lcrecord (size, &lrecord_##type) -#define COPY_SIZED_LISP_OBJECT old_copy_sized_lcrecord -#define COPY_LISP_OBJECT old_copy_lcrecord -#define LISP_OBJECT_STORAGE_SIZE malloced_storage_size -#define ZERO_LISP_OBJECT old_zero_lcrecord -#define LISP_OBJECT_HEADER struct old_lcrecord_header +#define NORMAL_LISP_OBJECT_HEADER struct old_lcrecord_header #define FROB_BLOCK_LISP_OBJECT_HEADER struct lrecord_header -#define FREE_LISP_OBJECT old_free_lcrecord +#define LISP_OBJECT_FROB_BLOCK_P(obj) (XRECORD_LHEADER_IMPLEMENTATION(obj)->frob_block_p) #endif /* not NEW_GC */ BEGIN_C_DECLS @@ -393,7 +477,7 @@ memory or releasing pointers or handles to objects created in external libraries, such as window-system windows or file handles. This can be NULL, meaning no special finalization is necessary. */ - void (*finalizer) (void *header); + void (*finalizer) (Lisp_Object obj); /* This can be NULL, meaning compare objects with EQ(). */ int (*equal) (Lisp_Object obj1, Lisp_Object obj2, int depth, @@ -436,19 +520,20 @@ /* 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_LISP_OBJECT(). If both are 0 (this should never happen), this - object cannot be instantiated; you will get an abort() if you try.*/ + ALLOC_NORMAL_LISP_OBJECT(). If both are 0 (this should never happen), + this object cannot be instantiated; you will get an abort() if you + try.*/ Bytecount static_size; - Bytecount (*size_in_bytes_method) (const void *header); + Bytecount (*size_in_bytes_method) (Lisp_Object); /* The (constant) index into lrecord_implementations_table */ enum lrecord_type lrecord_type_index; #ifndef NEW_GC - /* A "basic" lrecord is any lrecord that's not an lcrecord, i.e. + /* A "frob-block" lrecord is any lrecord that's not an lcrecord, i.e. one that does not have an old_lcrecord_header at the front and which is (usually) allocated in frob blocks. */ - unsigned int basic_p :1; + unsigned int frob_block_p :1; #endif /* not NEW_GC */ }; @@ -460,6 +545,8 @@ extern MODULE_API const struct lrecord_implementation * lrecord_implementations_table[lrecord_type_last_built_in_type + MODULE_DEFINABLE_TYPE_COUNT]; +/* Given a Lisp object, return its implementation + (struct lrecord_implementation) */ #define XRECORD_LHEADER_IMPLEMENTATION(obj) \ LHEADER_IMPLEMENTATION (XRECORD_LHEADER (obj)) #define LHEADER_IMPLEMENTATION(lh) lrecord_implementations_table[(lh)->type] @@ -496,7 +583,7 @@ if (MCACF_implementation && MCACF_implementation->finalizer) \ { \ GC_STAT_FINALIZED; \ - MCACF_implementation->finalizer (ptr); \ + MCACF_implementation->finalizer (MCACF_obj); \ } \ } \ } while (0) @@ -769,7 +856,7 @@ struct Lisp_Hash_Table { - LISP_OBJECT_HEADER header; + NORMAL_LISP_OBJECT_HEADER header; Elemcount size; Elemcount count; Elemcount rehash_count; @@ -834,7 +921,7 @@ struct Lisp_Specifier { - LISP_OBJECT_HEADER header; + NORMAL_LISP_OBJECT_HEADER header; struct specifier_methods *methods; ... @@ -1396,7 +1483,7 @@ 1. Declare the struct for your object in a header file somewhere. Remember that it must begin with - LISP_OBJECT_HEADER header; + NORMAL_LISP_OBJECT_HEADER header; 2. Put the "standard junk" (DECLARE_LISP_OBJECT()/XFOO/etc.) below the struct definition -- see below. @@ -1429,121 +1516,156 @@ --ben -An example: + An example: ------------------------------ in toolbar.h ----------------------------- -struct toolbar_button -{ - LISP_OBJECT_HEADER header; - - Lisp_Object next; - Lisp_Object frame; - - Lisp_Object up_glyph; - Lisp_Object down_glyph; - Lisp_Object disabled_glyph; - - Lisp_Object cap_up_glyph; - Lisp_Object cap_down_glyph; - Lisp_Object cap_disabled_glyph; - - Lisp_Object callback; - Lisp_Object enabled_p; - Lisp_Object help_string; - - char enabled; - char down; - char pushright; - char blank; - - int x, y; - int width, height; - int dirty; - int vertical; - int border_width; -}; - -[[ the standard junk: ]] - -DECLARE_LISP_OBJECT (toolbar_button, struct toolbar_button); -#define XTOOLBAR_BUTTON(x) XRECORD (x, toolbar_button, struct toolbar_button) -#define wrap_toolbar_button(p) wrap_record (p, toolbar_button) -#define TOOLBAR_BUTTONP(x) RECORDP (x, toolbar_button) -#define CHECK_TOOLBAR_BUTTON(x) CHECK_RECORD (x, toolbar_button) -#define CONCHECK_TOOLBAR_BUTTON(x) CONCHECK_RECORD (x, toolbar_button) - + struct toolbar_button + { + NORMAL_LISP_OBJECT_HEADER header; + + Lisp_Object next; + Lisp_Object frame; + + Lisp_Object up_glyph; + Lisp_Object down_glyph; + Lisp_Object disabled_glyph; + + Lisp_Object cap_up_glyph; + Lisp_Object cap_down_glyph; + Lisp_Object cap_disabled_glyph; + + Lisp_Object callback; + Lisp_Object enabled_p; + Lisp_Object help_string; + + char enabled; + char down; + char pushright; + char blank; + + int x, y; + int width, height; + int dirty; + int vertical; + int border_width; + }; + + [[ the standard junk: ]] + + DECLARE_LISP_OBJECT (toolbar_button, struct toolbar_button); + #define XTOOLBAR_BUTTON(x) XRECORD (x, toolbar_button, struct toolbar_button) + #define wrap_toolbar_button(p) wrap_record (p, toolbar_button) + #define TOOLBAR_BUTTONP(x) RECORDP (x, toolbar_button) + #define CHECK_TOOLBAR_BUTTON(x) CHECK_RECORD (x, toolbar_button) + #define CONCHECK_TOOLBAR_BUTTON(x) CONCHECK_RECORD (x, toolbar_button) + ------------------------------ in toolbar.c ----------------------------- - -#include "toolbar.h" - -... + + #include "toolbar.h" + + ... + + static const struct memory_description toolbar_button_description [] = { + { XD_LISP_OBJECT, offsetof (struct toolbar_button, next) }, + { XD_LISP_OBJECT, offsetof (struct toolbar_button, frame) }, + { XD_LISP_OBJECT, offsetof (struct toolbar_button, up_glyph) }, + { XD_LISP_OBJECT, offsetof (struct toolbar_button, down_glyph) }, + { XD_LISP_OBJECT, offsetof (struct toolbar_button, disabled_glyph) }, + { XD_LISP_OBJECT, offsetof (struct toolbar_button, cap_up_glyph) }, + { XD_LISP_OBJECT, offsetof (struct toolbar_button, cap_down_glyph) }, + { XD_LISP_OBJECT, offsetof (struct toolbar_button, cap_disabled_glyph) }, + { XD_LISP_OBJECT, offsetof (struct toolbar_button, callback) }, + { XD_LISP_OBJECT, offsetof (struct toolbar_button, enabled_p) }, + { XD_LISP_OBJECT, offsetof (struct toolbar_button, help_string) }, + { XD_END } + }; + + static Lisp_Object + allocate_toolbar_button (struct frame *f, int pushright) + { + struct toolbar_button *tb; + + tb = XTOOLBAR_BUTTON (ALLOC_NORMAL_LISP_OBJECT (toolbar_button)); + tb->next = Qnil; + tb->frame = wrap_frame (f); + tb->up_glyph = Qnil; + tb->down_glyph = Qnil; + tb->disabled_glyph = Qnil; + tb->cap_up_glyph = Qnil; + tb->cap_down_glyph = Qnil; + tb->cap_disabled_glyph = Qnil; + tb->callback = Qnil; + tb->enabled_p = Qnil; + tb->help_string = Qnil; + + tb->pushright = pushright; + tb->x = tb->y = tb->width = tb->height = -1; + tb->dirty = 1; + + return wrap_toolbar_button (tb); + } + + static Lisp_Object + mark_toolbar_button (Lisp_Object obj) + { + struct toolbar_button *data = XTOOLBAR_BUTTON (obj); + mark_object (data->next); + mark_object (data->frame); + mark_object (data->up_glyph); + mark_object (data->down_glyph); + mark_object (data->disabled_glyph); + mark_object (data->cap_up_glyph); + mark_object (data->cap_down_glyph); + mark_object (data->cap_disabled_glyph); + mark_object (data->callback); + mark_object (data->enabled_p); + return data->help_string; + } + + DEFINE_NODUMP_LISP_OBJECT ("toolbar-button", toolbar_button, + mark_toolbar_button, + external_object_printer, 0, 0, 0, + toolbar_button_description, + struct toolbar_button); + + ... + + void + syms_of_toolbar (void) + { + INIT_LISP_OBJECT (toolbar_button); + + ...; + } + +------------------------------ in inline.c ----------------------------- + + #ifdef HAVE_TOOLBARS + #include "toolbar.h" + #endif + +------------------------------ in lrecord.h ----------------------------- + + enum lrecord_type + { + ... + lrecord_type_toolbar_button, + ... + }; -static const struct memory_description toolbar_button_description [] = { - { XD_LISP_OBJECT, offsetof (struct toolbar_button, next) }, - { XD_LISP_OBJECT, offsetof (struct toolbar_button, frame) }, - { XD_LISP_OBJECT, offsetof (struct toolbar_button, up_glyph) }, - { XD_LISP_OBJECT, offsetof (struct toolbar_button, down_glyph) }, - { XD_LISP_OBJECT, offsetof (struct toolbar_button, disabled_glyph) }, - { XD_LISP_OBJECT, offsetof (struct toolbar_button, cap_up_glyph) }, - { XD_LISP_OBJECT, offsetof (struct toolbar_button, cap_down_glyph) }, - { XD_LISP_OBJECT, offsetof (struct toolbar_button, cap_disabled_glyph) }, - { XD_LISP_OBJECT, offsetof (struct toolbar_button, callback) }, - { XD_LISP_OBJECT, offsetof (struct toolbar_button, enabled_p) }, - { XD_LISP_OBJECT, offsetof (struct toolbar_button, help_string) }, - { XD_END } -}; - -static Lisp_Object -mark_toolbar_button (Lisp_Object obj) -\{ - struct toolbar_button *data = XTOOLBAR_BUTTON (obj); - mark_object (data->next); - mark_object (data->frame); - mark_object (data->up_glyph); - mark_object (data->down_glyph); - mark_object (data->disabled_glyph); - mark_object (data->cap_up_glyph); - mark_object (data->cap_down_glyph); - mark_object (data->cap_disabled_glyph); - mark_object (data->callback); - mark_object (data->enabled_p); - return data->help_string; -} +------------------------------ in .gdbinit.in.in ----------------------------- -DEFINE_NODUMP_LISP_OBJECT ("toolbar-button", toolbar_button, - mark_toolbar_button, - external_object_printer, 0, 0, 0, - toolbar_button_description, - struct toolbar_button); - -... - -void -syms_of_toolbar (void) -{ - INIT_LISP_OBJECT (toolbar_button); - - ...; -} + ... + else + if $lrecord_type == lrecord_type_toolbar_button + pstructtype toolbar_button + ... + ... + ... + end ------------------------------- in inline.c ----------------------------- - -#ifdef HAVE_TOOLBARS -#include "toolbar.h" -#endif - ------------------------------- in lrecord.h ----------------------------- - -enum lrecord_type -{ - ... - lrecord_type_toolbar_button, - ... -}; - - ---ben + --ben */ @@ -1676,32 +1798,12 @@ dead_wrong_type_argument (predicate, x); \ } while (0) -/* How to allocate a Lisp object: - - - For most objects, simply call ALLOC_LISP_OBJECT (type), where TYPE is - the name of the type (e.g. toolbar_button). Such objects can be freed - manually using FREE_LISP_OBJECT. - - - For objects whose size can vary (and hence which have a - size_in_bytes_method rather than a static_size), call - ALLOC_SIZED_LISP_OBJECT (size, type), where TYPE is the - name of the type. NOTE: You cannot call FREE_LISP_OBJECT() on such - on object! (At least when not NEW_GC) - - - Basic lrecords (of which there are a limited number, which exist only - when not NEW_GC, and which have special handling in alloc.c) need - special handling; if you don't understand this, just ignore it. - - - Some lrecords, which are used totally internally, use the - noseeum-* functions for the reason of debugging. - */ - #ifndef NEW_GC /*-------------------------- lcrecord-list -----------------------------*/ struct lcrecord_list { - LISP_OBJECT_HEADER header; + NORMAL_LISP_OBJECT_HEADER header; Lisp_Object free; Elemcount size; const struct lrecord_implementation *implementation; @@ -1722,13 +1824,13 @@ lrecords. lcrecords themselves are divided into three types: (1) auto-managed, (2) hand-managed, and (3) unmanaged. "Managed" refers to using a special object called an lcrecord-list to keep track of freed - lcrecords, which can freed with FREE_LISP_OBJECT() or the like and later be - recycled when a new lcrecord is required, rather than requiring new - malloc(). Thus, allocation of lcrecords can be very + lcrecords, which can freed with free_normal_lisp_object() or the like + and later be recycled when a new lcrecord is required, rather than + requiring new malloc(). Thus, allocation of lcrecords can be very cheap. (Technically, the lcrecord-list manager could divide up large chunks of memory and allocate out of that, mimicking what happens with lrecords. At that point, however, we'd want to rethink the whole - division between lrecords and lcrecords.) + division between lrecords and lcrecords.) NOTE: There is a fundamental limitation of lcrecord-lists, which is that they only handle blocks of a particular, fixed size. Thus, objects that @@ -1736,9 +1838,9 @@ in particular dictate the various types of management: -- "Auto-managed" means that you just go ahead and allocate the lcrecord - whenever you want, using ALLOC_LISP_OBJECT(), and the appropriate + whenever you want, using ALLOC_NORMAL_LISP_OBJECT(), and the appropriate lcrecord-list manager is automatically created. To free, you just call - "FREE_LISP_OBJECT()" and the appropriate lcrecord-list manager is + "free_normal_lisp_object()" and the appropriate lcrecord-list manager is automatically located and called. The limitation here of course is that all your objects are of the same size. (#### Eventually we should have a more sophisticated system that tracks the sizes seen and creates one @@ -1816,24 +1918,6 @@ void old_free_lcrecord (Lisp_Object rec); - -/* Copy the data from one lcrecord structure into another, but don't - overwrite the header information. */ - -#define old_copy_sized_lcrecord(dst, src, size) \ - memcpy ((Rawbyte *) (dst) + sizeof (struct old_lcrecord_header), \ - (Rawbyte *) (src) + sizeof (struct old_lcrecord_header), \ - (size) - sizeof (struct old_lcrecord_header)) - -#define old_copy_lcrecord(dst, src) \ - old_copy_sized_lcrecord (dst, src, sizeof (*(dst))) - -#define old_zero_sized_lcrecord(lcr, size) \ - memset ((Rawbyte *) (lcr) + sizeof (struct old_lcrecord_header), 0, \ - (size) - sizeof (struct old_lcrecord_header)) - -#define old_zero_lcrecord(lcr) old_zero_sized_lcrecord (lcr, sizeof (*(lcr))) - #else /* NEW_GC */ MODULE_API Lisp_Object alloc_sized_lrecord (Bytecount size, @@ -1849,27 +1933,8 @@ int elemcount, const struct lrecord_implementation *imp); -void free_lrecord (Lisp_Object rec); - - -/* Copy the data from one lrecord structure into another, but don't - overwrite the header information. */ - -#define copy_sized_lrecord(dst, src, size) \ - memcpy ((char *) (dst) + sizeof (struct lrecord_header), \ - (char *) (src) + sizeof (struct lrecord_header), \ - (size) - sizeof (struct lrecord_header)) - -#define copy_lrecord(dst, src) copy_sized_lrecord (dst, src, sizeof (*(dst))) - #endif /* NEW_GC */ -#define zero_sized_lrecord(lcr, size) \ - memset ((char *) (lcr) + sizeof (struct lrecord_header), 0, \ - (size) - sizeof (struct lrecord_header)) - -#define zero_lrecord(lcr) zero_sized_lrecord (lcr, sizeof (*(lcr))) - DECLARE_INLINE_HEADER ( Bytecount detagged_lisp_object_size (const struct lrecord_header *h) @@ -1878,7 +1943,7 @@ const struct lrecord_implementation *imp = LHEADER_IMPLEMENTATION (h); return (imp->size_in_bytes_method ? - imp->size_in_bytes_method (h) : + imp->size_in_bytes_method (wrap_pointer_1 (h)) : imp->static_size); } @@ -1890,6 +1955,17 @@ return detagged_lisp_object_size (XRECORD_LHEADER (o)); } +struct overhead_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); +#endif /* MEMORY_USAGE_STATS */ +void free_normal_lisp_object (Lisp_Object obj); + /************************************************************************/ /* Dumping */