comparison src/lrecord.h @ 1204:e22b0213b713

[xemacs-hg @ 2003-01-12 11:07:58 by michaels] modules/ChangeLog: 2002-12-16 Ben Wing <ben@xemacs.org> * postgresql/postgresql.c: remove ifdef USE_KKCC. src/ChangeLog: 2003-01-08 Mike Sperber <mike@xemacs.org> * console.h (CDFW_CONSOLE): Don't lead to a crash if we're dealing with a dead window/frame/device/console. 2002-12-20 Mike Sperber <mike@xemacs.org> * ui-gtk.c: Fix typo from Ben's patch: emacs_ffi_data is a typedef, not a struct. emacs_gtk_object_data is a typedef, not a struct. * gtk-glue.c (gdk_event_to_emacs_event): Fix typos from Ben's patch: le -> emacs_event + rearrange the code. * event-gtk.c (gtk_event_to_emacs_event): Fix typos from Ben's patch: ..._UNDERLYING_GDK_EVENT -> ..._GDK_EVENT, ev -> key_event. * device-gtk.c: Fix typo from Ben's patch: x_keysym_map_hash_table -> x_keysym_map_hashtable. 2002-12-19 Mike Sperber <mike@xemacs.org> * menubar-x.c (set_frame_menubar): Initialize protect_me field of popup_data. 2002-12-16 Ben Wing <ben@xemacs.org> Major cleanup of KKCC, etc. KKCC, pdump-related: -- descriptions are written for all objects. this required some changes in the format of some objects, e.g. extents, popup-data, coding system, lstream, lcrecord-list. -- KKCC now handles weakness in markers, hash tables, elsewhere correctly (formerly, you'd eventually get a stack overflow due to endlessly expanding markers). -- textual changes: lrecord_description -> memory_description, struct_description -> sized_memory_description. -- extensive comment describing descriptions and pdump. -- redo XD_UNION so it works inline and change its format to provide sufficient info for pdump. implement XD_UNION in pdump. also add XD_UNION_DYNAMIC_SIZE, which works like XD_UNION except for when auto-computing structure sizes. -- add support for XD_INDIRECT in description offsets (used by extents). -- add support for "description maps", allowing for indirect descriptions that are retrieved from an object at run-time. this generalizes XD_CODING_SYSTEM_END, XD_SPECIFIER_END, etc., which have now been eliminated. -- add a fifth field "flags" to memory_description, to support flags that can be specified for this particular line. Currently defined flags are XD_FLAG_NO_KKCC (KKCC should ignore this entry; useful for the weakness above in markers, etc.), XD_FLAG_NO_PDUMP (pdump should ignore this entry), XD_FLAG_UNION_DEFAULT_ENTRY (in union maps, this specifies a "default" entry for all remaining values), and XD_FLAG_FREE_LISP_OBJECT (for use with lcrecord-lists). -- clean up the kkcc-itis in events, so that the differences between event data as separate objects and as a union are now minimized to a small number of places. with the new XD_UNION, we no longer need event data as separate objects, so this code is no longer ifdef USE_KKCC, but instead ifdef EVENT_DATA_AS_OBJECTS, not used by default. make sure that we explicitly free the separate event data objects when no longer in use, to maintain the invariant the event processing causes no consing. -- also remove other USE_KKCC ifdefs when not necessary. -- allow for KKCC compilation under MS Windows. -- fix README.kkcc. -- dump_add_root_object -> dump_add_root_lisp_object. -- implement dump_add_root_block and use this to handle dump_add_opaque. -- factor out some code duplicated in kkcc and pdump. Other allocation/object-related: -- change various *slots.h so MARKED_SLOT() call no longer includes semicolon. -- free_marker() takes a Lisp_Object not a direct pointer. -- make bit vectors lcrecords, like vectors, and eliminate code that essentially duplicated the lcrecord handling. -- additional asserts in FREE_FIXED_TYPE, formerly duplicated in the various callers of this. -- all lcrecord allocation functions now zero out the returned lcrecords. unnecessary calls to zero_lcrecord removed. add long comment describing these functions. -- extract out process and coding system slots, like for buffers, frames, etc. -- lcrecords now set the type of items sitting on the free list to lcrecord_type_free. -- changes to the way that gap arrays are allocated, for kkcc's benefit -- now, one single memory block with a stretchy array on the end, instead of a separate block holding the array. Error-checking-related: -- now can compile with C++ under MS Windows. clean up compile errors discovered that way. (a few were real problems) -- add C++ error-checking code to verify problems with mismatched GCPRO/UNGCPRO. (there were a few in the kkcc code.) add long comment about how to catch insufficient GCPRO (yes, it's possible using C++). -- add debug_p4(), a simple object printer, when debug_print() doesn't work. -- add dp() and db() as short synonyms of debug_print(), debug_backtrace(). -- `print' tries EXTREMELY hard to avoid core dumping when printing when crashing or from debug_print(), and tries as hard as it reasonably can in other situations. -- Correct the message output upon crashing to be more up-to-date. Event-related: -- document event-matches-key-specifier-p better. -- generalize the dispatch queues formerly duplicated in the various event implementations. add event methods to drain pending events. generalize and clean up QUIT handling, removing event-specific quit processing. allow arbitrary keystrokes, not just ASCII, to be the QUIT char. among other things, this should fix some longstanding bugs in X quit handling. long comment describing the various event queues. -- implement delaying of XFlush() if there are pending expose events. SOMEONE PLEASE TRY THIS OUT. -- Fix `xemacs -batch -l dunnet' under Cygwin. Try to fix under MS Windows but not quite there yet. Other: -- class -> class_ and no more C++ games with this item. new -> new_ in the lwlib code, so far not elsewhere. -- use `struct htentry' not `struct hentry' in elhash.c to avoid debugger confusion with hash.c. -- new macros ALIST_LOOP_3, ALIST_LOOP_4. * README.kkcc: * alloc.c: * alloc.c (deadbeef_memory): * alloc.c (allocate_lisp_storage): * alloc.c (copy_lisp_object): * alloc.c (ALLOCATE_FIXED_TYPE_1): * alloc.c (FREE_FIXED_TYPE): * alloc.c (make_vector_internal): * alloc.c (make_bit_vector_internal): * 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 (struct string_chars_block): * alloc.c (mark_lcrecord_list): * alloc.c (make_lcrecord_list): * alloc.c (alloc_managed_lcrecord): * alloc.c (free_managed_lcrecord): * alloc.c (alloc_automanaged_lcrecord): * alloc.c (staticpro_1): * alloc.c (staticpro): * alloc.c (lispdesc_indirect_count_1): * alloc.c (lispdesc_indirect_description_1): * alloc.c (lispdesc_one_description_line_size): * alloc.c (lispdesc_structure_size): * alloc.c (mark_object_maybe_checking_free): * alloc.c (mark_with_description): * alloc.c (mark_struct_contents): * alloc.c (mark_object): * alloc.c (tick_lcrecord_stats): * alloc.c (free_cons): * alloc.c (free_key_data): * alloc.c (free_button_data): * alloc.c (free_motion_data): * alloc.c (free_process_data): * alloc.c (free_timeout_data): * alloc.c (free_magic_data): * alloc.c (free_magic_eval_data): * alloc.c (free_eval_data): * alloc.c (free_misc_user_data): * alloc.c (free_marker): * alloc.c (compact_string_chars): * alloc.c (gc_sweep): * alloc.c (garbage_collect_1): * alloc.c (Fgarbage_collect): * alloc.c (common_init_alloc_early): * alloc.c (init_alloc_early): * alloc.c (init_alloc_once_early): * buffer.c: * buffer.c (mark_buffer): * buffer.c (MARKED_SLOT): * buffer.c (cleanup_buffer_undo_lists): * buffer.c (Fget_file_buffer): * buffer.h (MARKED_SLOT): * bufslots.h: * bytecode.c: * callint.c: * casetab.c: * chartab.c: * chartab.c (symbol_to_char_table_type): * cmdloop.c: * cmdloop.c (Fcommand_loop_1): * config.h.in (new): * conslots.h: * console-gtk-impl.h (struct gtk_frame): * console-impl.h: * console-impl.h (struct console): * console-impl.h (MARKED_SLOT): * console-impl.h (CONSOLE_QUIT_EVENT): * console-msw-impl.h (XM_BUMPQUEUE): * console-msw.c (write_string_to_mswindows_debugging_output): * console-msw.h: * console-stream-impl.h: * console-stream-impl.h (struct stream_console): * console-stream.c: * console-stream.c (stream_init_console): * console-stream.h: * console-tty.c: * console-tty.h: * console-x.h: * console.c: * console.c (mark_console): * console.c (MARKED_SLOT): * console.c (allocate_console): * console.c (get_console_variant): * console.c (create_console): * console.c (delete_console_internal): * console.c (Fset_input_mode): * console.c (Fcurrent_input_mode): * console.c (common_init_complex_vars_of_console): * console.h: * console.h (console_variant): * console.h (device_metrics): * data.c: * data.c (Faref): * data.c (Faset): * data.c (decode_weak_list_type): * database.c: * debug.c (xemacs_debug_loop): * debug.c (FROB): * debug.c (Fadd_debug_class_to_check): * debug.c (Fdelete_debug_class_to_check): * debug.c (Fset_debug_classes_to_check): * debug.c (Fset_debug_class_types_to_check): * debug.c (Fdebug_types_being_checked): * debug.h (DASSERT): * device-gtk.c: * device-impl.h (struct device): * device-impl.h (MARKED_SLOT): * device-msw.c: * device-x.c: * device-x.c (x_init_device_class): * device-x.c (x_comp_visual_info): * device-x.c (x_try_best_visual_class): * device-x.c (x_init_device): * device-x.c (construct_name_list): * device-x.c (x_get_resource_prefix): * device-x.c (Fx_get_resource): * device-x.c (Fx_display_visual_class): * device.c: * device.c (MARKED_SLOT): * device.c (allocate_device): * device.c (Fmake_device): * device.c (delete_device_internal): * device.c (Fset_device_class): * device.h: * devslots.h: * devslots.h (MARKED_SLOT): * dialog-msw.c: * dired-msw.c (mswindows_ls_sort_fcn): * dired-msw.c (mswindows_get_files): * dired-msw.c (mswindows_format_file): * doprnt.c (parse_doprnt_spec): * dumper.c: * dumper.c (struct): * dumper.c (dump_add_root_block): * dumper.c (dump_add_root_struct_ptr): * dumper.c (dump_add_root_lisp_object): * dumper.c (pdump_struct_list_elt): * dumper.c (pdump_get_entry_list): * dumper.c (pdump_backtrace): * dumper.c (pdump_bump_depth): * dumper.c (pdump_register_sub): * dumper.c (pdump_register_object): * dumper.c (pdump_register_struct_contents): * dumper.c (pdump_register_struct): * dumper.c (pdump_store_new_pointer_offsets): * dumper.c (pdump_dump_data): * dumper.c (pdump_reloc_one): * dumper.c (pdump_allocate_offset): * dumper.c (pdump_scan_by_alignment): * dumper.c (pdump_dump_root_blocks): * dumper.c (pdump_dump_rtables): * dumper.c (pdump_dump_root_lisp_objects): * dumper.c (pdump): * dumper.c (pdump_load_finish): * dumper.c (pdump_file_get): * dumper.c (pdump_resource_get): * dumper.c (pdump_load): * editfns.c (save_excursion_restore): * editfns.c (user_login_name): * editfns.c (save_restriction_restore): * elhash.c: * elhash.c (htentry): * elhash.c (struct Lisp_Hash_Table): * elhash.c (HTENTRY_CLEAR_P): * elhash.c (LINEAR_PROBING_LOOP): * elhash.c (check_hash_table_invariants): * elhash.c (mark_hash_table): * elhash.c (hash_table_equal): * elhash.c (print_hash_table_data): * elhash.c (free_hentries): * elhash.c (make_general_lisp_hash_table): * elhash.c (decode_hash_table_weakness): * elhash.c (decode_hash_table_test): * elhash.c (Fcopy_hash_table): * elhash.c (resize_hash_table): * elhash.c (pdump_reorganize_hash_table): * elhash.c (find_htentry): * elhash.c (Fgethash): * elhash.c (Fputhash): * elhash.c (remhash_1): * elhash.c (Fremhash): * elhash.c (Fclrhash): * elhash.c (copy_compress_hentries): * elhash.c (elisp_maphash_unsafe): * elhash.c (finish_marking_weak_hash_tables): * elhash.c (prune_weak_hash_tables): * elhash.h: * emacs.c: * emacs.c (main_1): * emacs.c (main): * emacs.c (shut_down_emacs): * emodules.h (dump_add_root_lisp_object): * eval.c: * eval.c (unwind_to_catch): * eval.c (maybe_signal_error_1): * eval.c (maybe_signal_continuable_error_1): * eval.c (maybe_signal_error): * eval.c (maybe_signal_continuable_error): * eval.c (maybe_signal_error_2): * eval.c (maybe_signal_continuable_error_2): * eval.c (maybe_signal_ferror): * eval.c (maybe_signal_continuable_ferror): * eval.c (maybe_signal_ferror_with_frob): * eval.c (maybe_signal_continuable_ferror_with_frob): * eval.c (maybe_syntax_error): * eval.c (maybe_sferror): * eval.c (maybe_invalid_argument): * eval.c (maybe_invalid_constant): * eval.c (maybe_invalid_operation): * eval.c (maybe_invalid_change): * eval.c (maybe_invalid_state): * eval.c (Feval): * eval.c (call_trapping_problems): * eval.c (call_with_suspended_errors): * eval.c (warn_when_safe_lispobj): * eval.c (warn_when_safe): * eval.c (vars_of_eval): * event-Xt.c: * event-Xt.c (maybe_define_x_key_as_self_inserting_character): * event-Xt.c (x_to_emacs_keysym): * event-Xt.c (x_event_to_emacs_event): * event-Xt.c (emacs_Xt_enqueue_focus_event): * event-Xt.c (emacs_Xt_format_magic_event): * event-Xt.c (emacs_Xt_compare_magic_event): * event-Xt.c (emacs_Xt_hash_magic_event): * event-Xt.c (emacs_Xt_handle_magic_event): * event-Xt.c (Xt_timeout_to_emacs_event): * event-Xt.c (Xt_process_to_emacs_event): * event-Xt.c (signal_special_Xt_user_event): * event-Xt.c (emacs_Xt_next_event): * event-Xt.c (emacs_Xt_event_handler): * event-Xt.c (emacs_Xt_drain_queue): * event-Xt.c (emacs_Xt_event_pending_p): * event-Xt.c (check_if_pending_expose_event): * event-Xt.c (reinit_vars_of_event_Xt): * event-Xt.c (vars_of_event_Xt): * event-gtk.c: * event-gtk.c (IS_MODIFIER_KEY): * event-gtk.c (emacs_gtk_format_magic_event): * event-gtk.c (emacs_gtk_compare_magic_event): * event-gtk.c (emacs_gtk_hash_magic_event): * event-gtk.c (emacs_gtk_handle_magic_event): * event-gtk.c (gtk_to_emacs_keysym): * event-gtk.c (gtk_timeout_to_emacs_event): * event-gtk.c (gtk_process_to_emacs_event): * event-gtk.c (dragndrop_data_received): * event-gtk.c (signal_special_gtk_user_event): * event-gtk.c (emacs_gtk_next_event): * event-gtk.c (gtk_event_to_emacs_event): * event-gtk.c (generic_event_handler): * event-gtk.c (emacs_shell_event_handler): * event-gtk.c (emacs_gtk_drain_queue): * event-gtk.c (emacs_gtk_event_pending_p): * event-gtk.c (reinit_vars_of_event_gtk): * event-gtk.c (vars_of_event_gtk): * event-msw.c: * event-msw.c (struct winsock_stream): * event-msw.c (winsock_reader): * event-msw.c (winsock_writer): * event-msw.c (mswindows_enqueue_dispatch_event): * event-msw.c (mswindows_enqueue_misc_user_event): * event-msw.c (mswindows_enqueue_magic_event): * event-msw.c (mswindows_enqueue_process_event): * event-msw.c (mswindows_enqueue_mouse_button_event): * event-msw.c (mswindows_enqueue_keypress_event): * event-msw.c (mswindows_dequeue_dispatch_event): * event-msw.c (emacs_mswindows_drain_queue): * event-msw.c (mswindows_need_event_in_modal_loop): * event-msw.c (mswindows_need_event): * event-msw.c (mswindows_wm_timer_callback): * event-msw.c (dde_eval_string): * event-msw.c (Fdde_alloc_advise_item): * event-msw.c (mswindows_dde_callback): * event-msw.c (mswindows_wnd_proc): * event-msw.c (remove_timeout_mapper): * event-msw.c (emacs_mswindows_remove_timeout): * event-msw.c (emacs_mswindows_event_pending_p): * event-msw.c (emacs_mswindows_format_magic_event): * event-msw.c (emacs_mswindows_compare_magic_event): * event-msw.c (emacs_mswindows_hash_magic_event): * event-msw.c (emacs_mswindows_handle_magic_event): * event-msw.c (emacs_mswindows_select_console): * event-msw.c (emacs_mswindows_unselect_console): * event-msw.c (reinit_vars_of_event_mswindows): * event-msw.c (vars_of_event_mswindows): * event-stream.c: * event-stream.c (mark_command_builder): * event-stream.c (reset_command_builder_event_chain): * event-stream.c (allocate_command_builder): * event-stream.c (copy_command_builder): * event-stream.c (command_builder_append_event): * event-stream.c (event_stream_event_pending_p): * event-stream.c (event_stream_force_event_pending): * event-stream.c (maybe_read_quit_event): * event-stream.c (event_stream_drain_queue): * event-stream.c (remove_quit_p_event): * event-stream.c (event_stream_quit_p): * event-stream.c (echo_key_event): * event-stream.c (maybe_kbd_translate): * event-stream.c (execute_help_form): * event-stream.c (event_stream_generate_wakeup): * event-stream.c (enqueue_dispatch_event): * event-stream.c (enqueue_magic_eval_event): * event-stream.c (Fenqueue_eval_event): * event-stream.c (enqueue_misc_user_event): * event-stream.c (enqueue_misc_user_event_pos): * event-stream.c (next_event_internal): * event-stream.c (Fnext_event): * event-stream.c (Faccept_process_output): * event-stream.c (execute_internal_event): * event-stream.c (munge_keymap_translate): * event-stream.c (command_builder_find_leaf_no_mule_processing): * event-stream.c (command_builder_find_leaf): * event-stream.c (lookup_command_event): * event-stream.c (is_scrollbar_event): * event-stream.c (execute_command_event): * event-stream.c (Fdispatch_event): * event-stream.c (Fread_key_sequence): * event-stream.c (dribble_out_event): * event-stream.c (vars_of_event_stream): * event-tty.c (tty_timeout_to_emacs_event): * event-tty.c (emacs_tty_next_event): * event-tty.c (emacs_tty_drain_queue): * event-tty.c (reinit_vars_of_event_tty): * event-unixoid.c: * event-unixoid.c (find_tty_or_stream_console_from_fd): * event-unixoid.c (read_event_from_tty_or_stream_desc): * event-unixoid.c (drain_tty_devices): * event-unixoid.c (poll_fds_for_input): * events.c: * events.c (deinitialize_event): * events.c (zero_event): * events.c (mark_event): * events.c (print_event_1): * events.c (print_event): * events.c (event_equal): * events.c (event_hash): * events.c (Fmake_event): * events.c (Fdeallocate_event): * events.c (Fcopy_event): * events.c (map_event_chain_remove): * events.c (character_to_event): * events.c (event_to_character): * events.c (Fevent_to_character): * events.c (format_event_object): * events.c (upshift_event): * events.c (downshift_event): * events.c (event_upshifted_p): * events.c (Fevent_live_p): * events.c (Fevent_type): * events.c (Fevent_timestamp): * events.c (CHECK_EVENT_TYPE): * events.c (CHECK_EVENT_TYPE2): * events.c (CHECK_EVENT_TYPE3): * events.c (Fevent_key): * events.c (Fevent_button): * events.c (Fevent_modifier_bits): * events.c (event_x_y_pixel_internal): * events.c (event_pixel_translation): * events.c (Fevent_process): * events.c (Fevent_function): * events.c (Fevent_object): * events.c (Fevent_properties): * events.c (syms_of_events): * events.c (vars_of_events): * events.h: * events.h (struct event_stream): * events.h (struct Lisp_Key_Data): * events.h (KEY_DATA_KEYSYM): * events.h (EVENT_KEY_KEYSYM): * events.h (struct Lisp_Button_Data): * events.h (EVENT_BUTTON_BUTTON): * events.h (struct Lisp_Motion_Data): * events.h (EVENT_MOTION_X): * events.h (struct Lisp_Process_Data): * events.h (EVENT_PROCESS_PROCESS): * events.h (struct Lisp_Timeout_Data): * events.h (EVENT_TIMEOUT_INTERVAL_ID): * events.h (struct Lisp_Eval_Data): * events.h (EVENT_EVAL_FUNCTION): * events.h (struct Lisp_Misc_User_Data): * events.h (EVENT_MISC_USER_FUNCTION): * events.h (struct Lisp_Magic_Eval_Data): * events.h (EVENT_MAGIC_EVAL_INTERNAL_FUNCTION): * events.h (struct Lisp_Magic_Data): * events.h (EVENT_MAGIC_UNDERLYING): * events.h (EVENT_MAGIC_GDK_EVENT): * events.h (struct Lisp_Event): * events.h (XEVENT_CHANNEL): * events.h (SET_EVENT_TIMESTAMP_ZERO): * events.h (SET_EVENT_CHANNEL): * events.h (SET_EVENT_NEXT): * events.h (XSET_EVENT_TYPE): * events.h (struct command_builder): * extents.c: * extents.c (gap_array_adjust_markers): * extents.c (gap_array_recompute_derived_values): * extents.c (gap_array_move_gap): * extents.c (gap_array_make_gap): * extents.c (gap_array_insert_els): * extents.c (gap_array_delete_els): * extents.c (gap_array_make_marker): * extents.c (gap_array_delete_marker): * extents.c (gap_array_move_marker): * extents.c (make_gap_array): * extents.c (free_gap_array): * extents.c (extent_list_num_els): * extents.c (extent_list_insert): * extents.c (mark_extent_auxiliary): * extents.c (allocate_extent_auxiliary): * extents.c (decode_extent_at_flag): * extents.c (verify_extent_mapper): * extents.c (symbol_to_glyph_layout): * extents.c (syms_of_extents): * faces.c: * file-coding.c: * file-coding.c (struct_detector_category_description =): * file-coding.c (detector_category_dynarr_description_1): * file-coding.c (struct_detector_description =): * file-coding.c (detector_dynarr_description_1): * file-coding.c (MARKED_SLOT): * file-coding.c (mark_coding_system): * file-coding.c (coding_system_extra_description_map): * file-coding.c (coding_system_description): * file-coding.c (allocate_coding_system): * file-coding.c (symbol_to_eol_type): * file-coding.c (Fcoding_system_aliasee): * file-coding.c (set_coding_stream_coding_system): * file-coding.c (struct convert_eol_coding_system): * file-coding.c (struct undecided_coding_system): * file-coding.c (undecided_mark_coding_stream): * file-coding.c (coding_category_symbol_to_id): * file-coding.c (struct gzip_coding_system): * file-coding.c (coding_system_type_create): * file-coding.h: * file-coding.h (struct Lisp_Coding_System): * file-coding.h (CODING_SYSTEM_SLOT_DECLARATION): * file-coding.h (coding_system_variant): * file-coding.h (struct coding_system_methods): * file-coding.h (DEFINE_CODING_SYSTEM_TYPE_WITH_DATA): * file-coding.h (INITIALIZE_CODING_SYSTEM_TYPE_WITH_DATA): * file-coding.h (struct coding_stream): * fileio.c (Fsubstitute_in_file_name): * floatfns.c: * fns.c: * fns.c (base64_encode_1): * frame-gtk.c: * frame-gtk.c (Fgtk_start_drag_internal): * frame-impl.h (struct frame): * frame-impl.h (MARKED_SLOT): * frame-msw.c: * frame-x.c: * frame-x.c (Fcde_start_drag_internal): * frame-x.c (Foffix_start_drag_internal): * frame.c: * frame.c (MARKED_SLOT): * frame.c (allocate_frame_core): * frame.c (delete_frame_internal): * frame.c (Fmouse_position_as_motion_event): * frameslots.h: * frameslots.h (MARKED_SLOT_ARRAY): * free-hook.c: * glyphs-msw.c (mswindows_widget_instantiate): * glyphs-x.c: * glyphs-x.c (convert_EImage_to_XImage): * glyphs.c: * glyphs.c (process_image_string_instantiator): * glyphs.c (mark_image_instance): * glyphs.c (allocate_image_instance): * glyphs.c (unmap_subwindow): * glyphs.c (map_subwindow): * glyphs.c (syms_of_glyphs): * glyphs.c (specifier_type_create_image): * glyphs.h: * glyphs.h (struct text_image_instance): * glyphs.h (struct Lisp_Image_Instance): * gmalloc.c: * gmalloc.c ("C"): * gpmevent.c (Freceive_gpm_event): * gpmevent.c (gpm_next_event_cb): * gpmevent.c (vars_of_gpmevent): * gtk-glue.c (gdk_event_to_emacs_event): * gtk-xemacs.c (gtk_xemacs_class_init): * gui-msw.c: * gui-msw.c (mswindows_handle_gui_wm_command): * gui-msw.c (mswindows_translate_menu_or_dialog_item): * gui-x.c: * gui-x.c (mark_popup_data): * gui-x.c (snarf_widget_value_mapper): * gui-x.c (gcpro_popup_callbacks): * gui-x.c (ungcpro_popup_callbacks): * gui-x.c (free_popup_widget_value_tree): * gui-x.c (popup_selection_callback): * gui-x.h: * gui-x.h (struct popup_data): * gui.c: * gui.c (allocate_gui_item): * gutter.c (decode_gutter_position): * hash.c (NULL_ENTRY): * indent.c (vmotion_1): * indent.c (vmotion_pixels): * input-method-motif.c (res): * input-method-xlib.c (IMInstantiateCallback): * input-method-xlib.c (XIM_init_device): * input-method-xlib.c (res): * intl-encap-win32.c: * intl-encap-win32.c (qxeSHGetDataFromIDList): * intl-win32.c: * intl-win32.c (mswindows_multibyte_cp_type): * intl-win32.c (struct mswindows_multibyte_coding_system): * keymap.c: * keymap.c (make_key_description): * keymap.c (keymap_store): * keymap.c (get_keyelt): * keymap.c (keymap_lookup_1): * keymap.c (define_key_parser): * keymap.c (key_desc_list_to_event): * keymap.c (event_matches_key_specifier_p): * keymap.c (meta_prefix_char_p): * keymap.c (ensure_meta_prefix_char_keymapp): * keymap.c (Fdefine_key): * keymap.c (struct raw_lookup_key_mapper_closure): * keymap.c (raw_lookup_key): * keymap.c (raw_lookup_key_mapper): * keymap.c (lookup_keys): * keymap.c (lookup_events): * keymap.c (Flookup_key): * keymap.c (struct map_keymap_unsorted_closure): * keymap.c (map_keymap_unsorted_mapper): * keymap.c (map_keymap_sorted): * keymap.c (map_keymap_mapper): * keymap.c (map_keymap): * keymap.c (accessible_keymaps_mapper_1): * keymap.c (Faccessible_keymaps): * keymap.c (Fsingle_key_description): * keymap.c (raw_keys_to_keys): * keymap.c (format_raw_keys): * keymap.c (where_is_recursive_mapper): * keymap.c (where_is_internal): * keymap.c (describe_map_mapper_shadow_search): * keymap.c (keymap_lookup_inherited_mapper): * keymap.c (describe_map_mapper): * keymap.h (event_matches_key_specifier_p): * lisp.h: * lisp.h (this): * lisp.h (RETURN_NOT_REACHED): * lisp.h (struct Lisp_Vector): * lisp.h (struct Lisp_Bit_Vector): * lisp.h (UNGCPRO_1): * lisp.h (NUNGCPRO): * lisp.h (NNUNGCPRO): * lisp.h (DECLARE_INLINE_HEADER): * lrecord.h: * lrecord.h (struct lrecord_header): * lrecord.h (struct lcrecord_header): * lrecord.h (lrecord_type): * lrecord.h (struct lrecord_implementation): * lrecord.h (RECORD_DUMPABLE): * lrecord.h (memory_description_type): * lrecord.h (data_description_entry_flags): * lrecord.h (struct memory_description): * lrecord.h (struct sized_memory_description): * lrecord.h (XD_INDIRECT): * lrecord.h (XD_IS_INDIRECT): * lrecord.h (XD_DYNARR_DESC): * lrecord.h (DEFINE_BASIC_LRECORD_IMPLEMENTATION): * lrecord.h (MAKE_LRECORD_IMPLEMENTATION): * lrecord.h (MAKE_EXTERNAL_LRECORD_IMPLEMENTATION): * lrecord.h (alloc_lcrecord_type): * lstream.c: * lstream.c (Lstream_new): * lstream.c (lisp_buffer_marker): * lstream.h: * lstream.h (lstream_implementation): * lstream.h (DEFINE_LSTREAM_IMPLEMENTATION): * lstream.h (DEFINE_LSTREAM_IMPLEMENTATION_WITH_DATA): * marker.c: * marker.c (copy_marker_1): * mem-limits.h: * menubar-gtk.c: * menubar-gtk.c (gtk_popup_menu): * menubar-msw.c: * menubar-msw.c (mswindows_popup_menu): * menubar-x.c (make_dummy_xbutton_event): * menubar-x.c (command_builder_operate_menu_accelerator): * menubar-x.c (menu_accelerator_safe_compare): * menubar-x.c (menu_accelerator_safe_mod_compare): * mule-charset.c: * mule-charset.c (make_charset): * mule-charset.c (Fcharset_property): * mule-coding.c: * mule-coding.c (ccs_description_1): * mule-coding.c (ccs_description =): * mule-coding.c (ccsd_description_1): * mule-coding.c (ccsd_description =): * nt.c (getpwnam): * nt.c (init_mswindows_environment): * nt.c (get_cached_volume_information): * nt.c (mswindows_is_executable): * nt.c (read_unc_volume): * nt.c (mswindows_access): * nt.c (mswindows_link): * nt.c (mswindows_fstat): * nt.c (mswindows_stat): * nt.c (mswindows_executable_type): * nt.c (Fmswindows_short_file_name): * nt.c (Fmswindows_long_file_name): * objects-impl.h (struct Lisp_Color_Instance): * objects-impl.h (struct Lisp_Font_Instance): * objects-tty.c: * objects-x.c (allocate_nearest_color): * objects.c: * objects.c (Fmake_color_instance): * objects.c (Fmake_font_instance): * objects.c (font_instantiate): * opaque.c: * opaque.c (make_opaque): * opaque.c (make_opaque_ptr): * opaque.c (reinit_opaque_early): * opaque.c (init_opaque_once_early): * print.c: * print.c (printing_badness): * print.c (printing_major_badness): * print.c (print_internal): * print.c (debug_p4): * print.c (dp): * print.c (debug_backtrace): * process-nt.c (nt_create_process): * process-nt.c (get_internet_address): * process-unix.c: * process-unix.c (struct unix_process_data): * process-unix.c (get_internet_address): * process-unix.c (unix_alloc_process_data): * process-unix.c (unix_create_process): * process-unix.c (try_to_initialize_subtty): * process-unix.c (unix_kill_child_process): * process-unix.c (process_type_create_unix): * process.c: * process.c (mark_process): * process.c (MARKED_SLOT): * process.c (make_process_internal): * process.c (Fprocess_tty_name): * process.c (decode_signal): * process.h: * procimpl.h: * procimpl.h (struct process_methods): * procimpl.h (struct Lisp_Process): * rangetab.c: * realpath.c (readlink_and_correct_case): * redisplay-x.c (x_window_output_end): * redisplay-x.c (x_redraw_exposed_area): * redisplay-x.c (x_clear_frame): * redisplay.c: * redisplay.h: * redisplay.h (struct rune_dglyph): * redisplay.h (struct rune): * scrollbar.c: * scrollbar.c (create_scrollbar_instance): * specifier.c: * specifier.c (specifier_empty_extra_description_1): * specifier.c (make_specifier_internal): * specifier.c (decode_locale_type): * specifier.c (decode_how_to_add_specification): * specifier.h: * specifier.h (struct specifier_methods): * specifier.h (DEFINE_SPECIFIER_TYPE_WITH_DATA): * specifier.h (INITIALIZE_SPECIFIER_TYPE_WITH_DATA): * symbols.c: * symbols.c (Fsetplist): * symbols.c (default_value): * symbols.c (decode_magic_handler_type): * symbols.c (handler_type_from_function_symbol): * symbols.c (Fdefvaralias): * symbols.c (init_symbols_once_early): * symbols.c (reinit_symbols_early): * symsinit.h: * sysdep.c (sys_subshell): * sysdep.c (tty_init_sys_modes_on_device): * syswindows.h: * text.c (dfc_convert_to_external_format): * text.c (dfc_convert_to_internal_format): * text.c (reinit_eistring_early): * text.c (init_eistring_once_early): * text.c (reinit_vars_of_text): * text.h: * text.h (INC_IBYTEPTR_FMT): * text.h (DEC_IBYTEPTR_FMT): * toolbar.c: * toolbar.c (decode_toolbar_position): * tooltalk.c: * ui-gtk.c: * unexnt.c: * unexnt.c (_start): * unexnt.c (unexec): * unexnt.c (get_section_info): * unicode.c: * unicode.c (vars_of_unicode): * window.c: * window.c (allocate_window): * window.c (new_window_mirror): * window.c (update_mirror_internal): * winslots.h:
author michaels
date Sun, 12 Jan 2003 11:08:22 +0000
parents 25e260cb7994
children 4542b72c005e
comparison
equal deleted inserted replaced
1203:5f2f8dcbfb3e 1204:e22b0213b713
38 Straight lrecords are used for those types of objects that have 38 Straight lrecords are used for those types of objects that have
39 their own allocation routines (typically allocated out of 2K chunks 39 their own allocation routines (typically allocated out of 2K chunks
40 of memory called `frob blocks'). These objects have a `struct 40 of memory called `frob blocks'). These objects have a `struct
41 lrecord_header' at the top, containing only the bits needed to find 41 lrecord_header' at the top, containing only the bits needed to find
42 the lrecord_implementation for the object. There are special 42 the lrecord_implementation for the object. There are special
43 routines in alloc.c to deal with each such object type. 43 routines in alloc.c to create an object of each such type.
44 44
45 Lcrecords are used for less common sorts of objects that don't do 45 Lcrecords are used for less common sorts of objects that don't do
46 their own allocation. Each such object is malloc()ed individually, 46 their own allocation. Each such object is malloc()ed individually,
47 and the objects are chained together through a `next' pointer. 47 and the objects are chained together through a `next' pointer.
48 Lcrecords have a `struct lcrecord_header' at the top, which 48 Lcrecords have a `struct lcrecord_header' at the top, which
49 contains a `struct lrecord_header' and a `next' pointer, and are 49 contains a `struct lrecord_header' and a `next' pointer, and are
50 allocated using alloc_lcrecord(). 50 allocated using alloc_lcrecord_type() or its variants.
51 51
52 Creating a new lcrecord type is fairly easy; just follow the 52 Creating a new lcrecord type is fairly easy; just follow the
53 lead of some existing type (e.g. hash tables). Note that you 53 lead of some existing type (e.g. hash tables). Note that you
54 do not need to supply all the methods (see below); reasonable 54 do not need to supply all the methods (see below); reasonable
55 defaults are provided for many of them. Alternatively, if you're 55 defaults are provided for many of them. Alternatively, if you're
56 just looking for a way of encapsulating data (which possibly 56 just looking for a way of encapsulating data (which possibly
57 could contain Lisp_Objects in it), you may well be able to use 57 could contain Lisp_Objects in it), you may well be able to use
58 the opaque type. */ 58 the opaque type. --ben
59 */
59 60
60 struct lrecord_header 61 struct lrecord_header
61 { 62 {
62 /* index into lrecord_implementations_table[] */ 63 /* Index into lrecord_implementations_table[]. Objects that have been
64 explicitly freed using e.g. free_cons() have lrecord_type_free in this
65 field. */
63 unsigned int type :8; 66 unsigned int type :8;
64 67
65 /* If `mark' is 0 after the GC mark phase, the object will be freed 68 /* If `mark' is 0 after the GC mark phase, the object will be freed
66 during the GC sweep phase. There are 2 ways that `mark' can be 1: 69 during the GC sweep phase. There are 2 ways that `mark' can be 1:
67 - by being referenced from other objects during the GC mark phase 70 - by being referenced from other objects during the GC mark phase
95 { 98 {
96 struct lrecord_header lheader; 99 struct lrecord_header lheader;
97 100
98 /* The `next' field is normally used to chain all lcrecords together 101 /* The `next' field is normally used to chain all lcrecords together
99 so that the GC can find (and free) all of them. 102 so that the GC can find (and free) all of them.
100 `alloc_lcrecord' threads lcrecords together. 103 `basic_alloc_lcrecord' threads lcrecords together.
101 104
102 The `next' field may be used for other purposes as long as some 105 The `next' field may be used for other purposes as long as some
103 other mechanism is provided for letting the GC do its work. 106 other mechanism is provided for letting the GC do its work.
104 107
105 For example, the event and marker object types allocate members 108 For example, the event and marker object types allocate members
132 enum lrecord_type 135 enum lrecord_type
133 { 136 {
134 /* Symbol value magic types come first to make SYMBOL_VALUE_MAGIC_P fast. 137 /* Symbol value magic types come first to make SYMBOL_VALUE_MAGIC_P fast.
135 #### This should be replaced by a symbol_value_magic_p flag 138 #### This should be replaced by a symbol_value_magic_p flag
136 in the Lisp_Symbol lrecord_header. */ 139 in the Lisp_Symbol lrecord_header. */
137 lrecord_type_symbol_value_forward, 140 lrecord_type_symbol_value_forward, /* 0 */
138 lrecord_type_symbol_value_varalias, 141 lrecord_type_symbol_value_varalias, /* 1 */
139 lrecord_type_symbol_value_lisp_magic, 142 lrecord_type_symbol_value_lisp_magic, /* 2 */
140 lrecord_type_symbol_value_buffer_local, 143 lrecord_type_symbol_value_buffer_local, /* 3 */
141 lrecord_type_max_symbol_value_magic = lrecord_type_symbol_value_buffer_local, 144 lrecord_type_max_symbol_value_magic = lrecord_type_symbol_value_buffer_local,
142 145
143 lrecord_type_symbol, 146 lrecord_type_symbol, /* 4 */
144 lrecord_type_subr, 147 lrecord_type_subr, /* 5 */
145 lrecord_type_cons, 148 lrecord_type_cons, /* 6 */
146 lrecord_type_vector, 149 lrecord_type_vector,
147 lrecord_type_string, 150 lrecord_type_string,
148 lrecord_type_lcrecord_list, 151 lrecord_type_lcrecord_list,
149 lrecord_type_compiled_function, 152 lrecord_type_compiled_function,
150 lrecord_type_weak_list, 153 lrecord_type_weak_list,
164 lrecord_type_extent, 167 lrecord_type_extent,
165 lrecord_type_extent_info, 168 lrecord_type_extent_info,
166 lrecord_type_extent_auxiliary, 169 lrecord_type_extent_auxiliary,
167 lrecord_type_marker, 170 lrecord_type_marker,
168 lrecord_type_event, 171 lrecord_type_event,
169 #ifdef USE_KKCC 172 #ifdef EVENT_DATA_AS_OBJECTS
170 lrecord_type_key_data, 173 lrecord_type_key_data,
171 lrecord_type_button_data, 174 lrecord_type_button_data,
172 lrecord_type_motion_data, 175 lrecord_type_motion_data,
173 lrecord_type_process_data, 176 lrecord_type_process_data,
174 lrecord_type_timeout_data, 177 lrecord_type_timeout_data,
175 lrecord_type_eval_data, 178 lrecord_type_eval_data,
176 lrecord_type_misc_user_data, 179 lrecord_type_misc_user_data,
177 lrecord_type_magic_eval_data, 180 lrecord_type_magic_eval_data,
178 lrecord_type_magic_data, 181 lrecord_type_magic_data,
179 #endif /* USE_KKCC */ 182 #endif /* EVENT_DATA_AS_OBJECTS */
180 lrecord_type_keymap, 183 lrecord_type_keymap,
181 lrecord_type_command_builder, 184 lrecord_type_command_builder,
182 lrecord_type_timeout, 185 lrecord_type_timeout,
183 lrecord_type_specifier, 186 lrecord_type_specifier,
184 lrecord_type_console, 187 lrecord_type_console,
231 the return value is non-nil, it should be a Lisp_Object to be 234 the return value is non-nil, it should be a Lisp_Object to be
232 marked (don't call the mark_object function explicitly on it, 235 marked (don't call the mark_object function explicitly on it,
233 because the GC routines will do this). Doing it this way reduces 236 because the GC routines will do this). Doing it this way reduces
234 recursion, so the object returned should preferably be the one 237 recursion, so the object returned should preferably be the one
235 with the deepest level of Lisp_Object pointers. This function 238 with the deepest level of Lisp_Object pointers. This function
236 can be NULL, meaning no GC marking is necessary. */ 239 can be NULL, meaning no GC marking is necessary.
240
241 NOTE NOTE NOTE: This is not used by KKCC (which uses the data
242 description below instead), unless the data description is missing.
243 Yes, this currently means there is logic duplication. Eventually the
244 mark methods will be removed. */
237 Lisp_Object (*marker) (Lisp_Object); 245 Lisp_Object (*marker) (Lisp_Object);
238 246
239 /* `printer' converts the object to a printed representation. 247 /* `printer' converts the object to a printed representation.
240 This can be NULL; in this case default_object_printer() will be 248 This can be NULL; in this case default_object_printer() will be
241 used instead. */ 249 used instead. */
261 hash to the same value in order for hash tables to work properly. 269 hash to the same value in order for hash tables to work properly.
262 This means that `hash' can be NULL only if the `equal' method is 270 This means that `hash' can be NULL only if the `equal' method is
263 also NULL. */ 271 also NULL. */
264 unsigned long (*hash) (Lisp_Object, int); 272 unsigned long (*hash) (Lisp_Object, int);
265 273
266 /* External data layout description */ 274 /* Data layout description for your object. See long comment below. */
267 const struct lrecord_description *description; 275 const struct memory_description *description;
268 276
269 /* These functions allow any object type to have builtin property 277 /* These functions allow any object type to have builtin property
270 lists that can be manipulated from the lisp level with 278 lists that can be manipulated from the lisp level with
271 `get', `put', `remprop', and `object-plist'. */ 279 `get', `put', `remprop', and `object-plist'. */
272 Lisp_Object (*getprop) (Lisp_Object obj, Lisp_Object prop); 280 Lisp_Object (*getprop) (Lisp_Object obj, Lisp_Object prop);
273 int (*putprop) (Lisp_Object obj, Lisp_Object prop, Lisp_Object val); 281 int (*putprop) (Lisp_Object obj, Lisp_Object prop, Lisp_Object val);
274 int (*remprop) (Lisp_Object obj, Lisp_Object prop); 282 int (*remprop) (Lisp_Object obj, Lisp_Object prop);
275 Lisp_Object (*plist) (Lisp_Object obj); 283 Lisp_Object (*plist) (Lisp_Object obj);
276 284
277 /* Only one of `static_size' and `size_in_bytes_method' is non-0. 285 /* Only one of `static_size' and `size_in_bytes_method' is non-0.
278 If both are 0, this type is not instantiable by alloc_lcrecord(). */ 286 If both are 0, this type is not instantiable by basic_alloc_lcrecord(). */
279 Bytecount static_size; 287 Bytecount static_size;
280 Bytecount (*size_in_bytes_method) (const void *header); 288 Bytecount (*size_in_bytes_method) (const void *header);
281 289
282 /* The (constant) index into lrecord_implementations_table */ 290 /* The (constant) index into lrecord_implementations_table */
283 enum lrecord_type lrecord_type_index; 291 enum lrecord_type lrecord_type_index;
284 292
285 /* A "basic" lrecord is any lrecord that's not an lcrecord, i.e. 293 /* A "basic" lrecord is any lrecord that's not an lcrecord, i.e.
286 one that does not have an lcrecord_header at the front and which 294 one that does not have an lcrecord_header at the front and which
287 is (usually) allocated in frob blocks. We only use this flag for 295 is (usually) allocated in frob blocks. */
288 some consistency checking, and that only when error-checking is
289 enabled. */
290 unsigned int basic_p :1; 296 unsigned int basic_p :1;
291 }; 297 };
292 298
293 /* All the built-in lisp object types are enumerated in `enum lrecord_type'. 299 /* All the built-in lisp object types are enumerated in `enum lrecord_type'.
294 Additional ones may be defined by a module (none yet). We leave some 300 Additional ones may be defined by a module (none yet). We leave some
318 } while (0) 324 } while (0)
319 #define SET_LISP_READONLY_RECORD_HEADER(lheader) \ 325 #define SET_LISP_READONLY_RECORD_HEADER(lheader) \
320 ((void) ((lheader)->lisp_readonly = 1)) 326 ((void) ((lheader)->lisp_readonly = 1))
321 #define RECORD_MARKER(lheader) lrecord_markers[(lheader)->type] 327 #define RECORD_MARKER(lheader) lrecord_markers[(lheader)->type]
322 328
323 #ifdef USE_KKCC
324 #define RECORD_DUMPABLE(lheader) (lrecord_implementations_table[(lheader)->type])->dumpable 329 #define RECORD_DUMPABLE(lheader) (lrecord_implementations_table[(lheader)->type])->dumpable
325 #endif /* USE_KKCC */ 330
326 331 /* Data description stuff
327 /* External description stuff 332
328 333 Data layout descriptions describe blocks of memory (in particular, Lisp
329 PLEASE NOTE: Both lrecord_description and struct_description are 334 objects and other objects on the heap, and global objects with pointers
330 badly misnamed. In reality, an lrecord_description is nothing more 335 to such heap objects), including their size and a list of the elements
331 than a list of the elements in a block of memory that need 336 that need relocating, marking or other special handling. They are
332 relocating or other special handling, and a struct_description is 337 currently used in two places: by pdump [the new, portable dumper] and
333 no more than an lrecord_description plus the size of the block of 338 KKCC [the new garbage collector]. The two subsystems use the
334 memory. (In fact, a struct_description can now have its size given 339 descriptions in different ways, and as a result some of the descriptions
335 as zero, i.e. unspecified, meaning that the last element in the 340 are appropriate only for one or the other, when it is known that only
336 structure is noted in the list and the size of the block can 341 that subsystem will use the description. (This is particularly the case
337 therefore be computed from it.) The names stem from the fact 342 with objects that can't be dumped, because pdump needs more info than
338 lrecord_descriptions are used to describe lrecords (the size of the 343 KKCC.) However, properly written descriptions are appropriate for both,
339 lrecord is elsewhere in its description, attached to its methods, 344 and you should strive to write your descriptions that way, since the
340 so it does not need to be given here), while struct_descriptions 345 dumpable status of an object may change and new uses for the
341 are used to describe C structs; but both are used in various 346 descriptions may be created. (An example that comes to mind is a
342 additional ways. Much better terms would be memory_description and 347 facility for determining the memory usage of XEmacs data structures --
343 sized_memory_description. 348 like `buffer-memory-usage', `window-memory-usage', etc. but more
344 349 general.)
345 An lrecord_description is an array of values. (This is actually 350
351 More specifically:
352
353 Pdump (the portable dumper) needs to write out all objects in heap
354 space, and later on (in another invocation of XEmacs) load them back
355 into the heap, relocating all pointers to the heap objects in the global
356 data space. ("Heap" means anything malloc()ed, including all Lisp
357 objects, and "global data" means anything declared globally or
358 `static'.) Pdump, then, needs to be told about the location of all
359 global pointers to heap objects, all the description of all such
360 objects, including their size and any pointers to other heap (aka
361 "relocatable") objects. (Pdump assumes that the heap may occur in
362 different places in different invocations -- therefore, it is not enough
363 simply to write out the entire heap and later reload it at the same
364 location -- but that global data is always in the same place, and hence
365 pointers to it do not need to be relocated. This assumption holds true
366 in general for modern operating systems, but would be broken, for
367 example, in a system without virtual memory, or when dealing with shared
368 libraries. Also, unlike unexec, pdump does not usually write out or
369 restore objects in the global data space, and thus they need to be
370 initialized every time XEmacs is loaded. This is the purpose of the
371 reinit_*() functions throughout XEmacs. [It's possible, however, to make
372 pdump restore global data. This must be done, of course, for heap
373 pointers, but is also done for other values that are not easy to
374 recompute -- in particular, values established by the Lisp code loaded
375 at dump time.]) Note that the data type `Lisp_Object' is basically just
376 a relocatable pointer disguised as a long, and in general pdump treats
377 the Lisp_Object values and pointers to Lisp objects (e.g. Lisp_Object
378 vs. `struct frame *') identically. (NOTE: This equivalence depends
379 crucially on the current "minimal tagbits" implementation of Lisp_Object
380 pointers.)
381
382 Descriptions are used by pdump in three places: (a) descriptions of Lisp
383 objects, referenced in the DEFINE_*LRECORD_*IMPLEMENTATION*() call; (b)
384 descriptions of global objects to be dumped, registered by
385 dump_add_root_block(); (c) descriptions of global pointers to
386 non-Lisp_Object heap objects, registered by dump_add_root_struct_ptr().
387 The descriptions need to tell pdump which elements of your structure are
388 Lisp_Objects or structure pointers, plus the descriptions in turn of the
389 non-Lisp_Object structures pointed to. If these structures are you own
390 private ones, you will have to write these recursive descriptions
391 yourself; otherwise, you are reusing a structure already in existence
392 elsewhere and there is probably already a description for it.
393
394 Pdump does not care about Lisp objects that cannot be dumped (the
395 dumpable flag to DEFINE_*LRECORD_*IMPLEMENTATION*() is 0).
396
397 KKCC also uses data layout descriptions, but differently. It cares
398 about all objects, dumpable or not, but specifically only wants to know
399 about Lisp_Objects in your object and in structures pointed to. Thus,
400 it doesn't care about things like pointers to structures ot other blocks
401 of memory with no Lisp Objects in them, which pdump would care a lot
402 about.
403
404 Technically, then, you could write your description differently
405 depending on whether your object is dumpable -- the full pdump
406 description if so, the abbreviated KKCC description if not. In fact,
407 some descriptions are written this way. This is dangerous, though,
408 because another use might come along for the data descriptions, that
409 doesn't care about the dumper flag and makes use of some of the stuff
410 normally omitted from the "abbreviated" description -- see above.
411
412 A memory_description is an array of values. (This is actually
346 misnamed, in that it does not just describe lrecords, but any 413 misnamed, in that it does not just describe lrecords, but any
347 blocks of memory.) The first value of each line is a type, the 414 blocks of memory.) The first value of each line is a type, the
348 second the offset in the lrecord structure. The third and 415 second the offset in the lrecord structure. The third and
349 following elements are parameters; their presence, type and number 416 following elements are parameters; their presence, type and number
350 is type-dependent. 417 is type-dependent.
351 418
352 The description ends with a "XD_END", "XD_SPECIFIER_END" or 419 The description ends with an "XD_END" record.
353 "XD_CODING_SYSTEM_END" record.
354 420
355 The top-level description of an lrecord or lcrecord does not need 421 The top-level description of an lrecord or lcrecord does not need
356 to describe every element, just the ones that need to be relocated, 422 to describe every element, just the ones that need to be relocated,
357 since the size of the lrecord is known. (The same goes for nested 423 since the size of the lrecord is known. (The same goes for nested
358 structures, whenever the structure size is given, rather than being 424 structures, whenever the structure size is given, rather than being
359 defaulted by specifying 0 for the size.) 425 defaulted by specifying 0 for the size.)
360 426
361 A struct_description is used for describing nested "structures". (Again 427 A sized_memory_description is a memory_description plus the size of the
362 a misnomer, since it can be used for any blocks of memory, not just 428 block of memory. The size field in a sized_memory_description can be
363 structures.) It just contains a size for the memory block, a pointer to 429 given as zero, i.e. unspecified, meaning that the last element in the
364 an lrecord_description, and (for unions only) a union constant, 430 structure is described in the description and the size of the block can
365 described below. The size can be 0, in which case the size will be 431 therefore be computed from it. (This is useful for stretchy arrays.)
366 determined from the largest offset logically referenced (i.e. last 432
367 offset mentioned + size of that object). This is useful for stretchy 433 memory_descriptions are used to describe lrecords (the size of the
368 arrays. 434 lrecord is elsewhere in its description, attached to its methods, so it
435 does not need to be given here) and global objects, where the size is an
436 argument to the call to dump_add_root_block().
437 sized_memory_descriptions are used for pointers and arrays in
438 memory_descriptions and for calls to dump_add_root_struct_ptr(). (####
439 It is not obvious why this is so in the latter case. Probably, calls to
440 dump_add_root_struct_ptr() should use plain memory_descriptions and have
441 the size be an argument to the call.)
442
443 NOTE: Anywhere that a sized_memory_description occurs inside of a plain
444 memory_description, a "description map" can be substituted. Rather than
445 being an actual description, this describes how to find the description
446 by looking inside of the object being described. This is a convenient
447 way to describe Lisp objects with subtypes and corresponding
448 type-specific data.
369 449
370 Some example descriptions : 450 Some example descriptions :
371 451
372 struct Lisp_String 452 struct Lisp_String
373 { 453 {
375 Bytecount size; 455 Bytecount size;
376 Ibyte *data; 456 Ibyte *data;
377 Lisp_Object plist; 457 Lisp_Object plist;
378 }; 458 };
379 459
380 static const struct lrecord_description cons_description[] = { 460 static const struct memory_description cons_description[] = {
381 { XD_LISP_OBJECT, offsetof (Lisp_Cons, car) }, 461 { XD_LISP_OBJECT, offsetof (Lisp_Cons, car) },
382 { XD_LISP_OBJECT, offsetof (Lisp_Cons, cdr) }, 462 { XD_LISP_OBJECT, offsetof (Lisp_Cons, cdr) },
383 { XD_END } 463 { XD_END }
384 }; 464 };
385 465
386 Which means "two lisp objects starting at the 'car' and 'cdr' elements" 466 Which means "two lisp objects starting at the 'car' and 'cdr' elements"
387 467
388 static const struct lrecord_description string_description[] = { 468 static const struct memory_description string_description[] = {
389 { XD_BYTECOUNT, offsetof (Lisp_String, size) }, 469 { XD_BYTECOUNT, offsetof (Lisp_String, size) },
390 { XD_OPAQUE_DATA_PTR, offsetof (Lisp_String, data), XD_INDIRECT(0, 1) }, 470 { XD_OPAQUE_DATA_PTR, offsetof (Lisp_String, data), XD_INDIRECT (0, 1) },
391 { XD_LISP_OBJECT, offsetof (Lisp_String, plist) }, 471 { XD_LISP_OBJECT, offsetof (Lisp_String, plist) },
392 { XD_END } 472 { XD_END }
393 }; 473 };
394 474
395 "A pointer to string data at 'data', the size of the pointed array being 475 "A pointer to string data at 'data', the size of the pointed array being
406 ...; 486 ...;
407 } 487 }
408 488
409 You'd use XD_STRUCT_PTR, something like: 489 You'd use XD_STRUCT_PTR, something like:
410 490
411 static const struct lrecord_description lo_description_1[] = { 491 static const struct memory_description foo_description[] = {
492 ...
493 { XD_INT, offsetof (Lisp_Foo, count) },
494 { XD_STRUCT_PTR, offsetof (Lisp_Foo, objects),
495 XD_INDIRECT (0, 0), &lisp_object_description },
496 ...
497 };
498
499 lisp_object_description is declared in alloc.c, like this:
500
501 static const struct memory_description lisp_object_description_1[] = {
412 { XD_LISP_OBJECT, 0 }, 502 { XD_LISP_OBJECT, 0 },
413 { XD_END } 503 { XD_END }
414 }; 504 };
415 505
416 static const struct struct_description lo_description = { 506 const struct sized_memory_description lisp_object_description = {
417 sizeof (Lisp_Object), 507 sizeof (Lisp_Object),
418 lo_description_1 508 lisp_object_description_1
419 }; 509 };
420 510
421 static const struct lrecord_description foo_description[] = {
422 ...
423 { XD_INT, offsetof (Lisp_Foo, count) },
424 { XD_STRUCT_PTR, offsetof (Lisp_Foo, objects),
425 XD_INDIRECT (0, 0), &lo_description },
426 ...
427 };
428
429
430 Another example of XD_STRUCT_PTR: 511 Another example of XD_STRUCT_PTR:
431 512
432 typedef struct hentry 513 typedef struct htentry
433 { 514 {
434 Lisp_Object key; 515 Lisp_Object key;
435 Lisp_Object value; 516 Lisp_Object value;
436 } hentry; 517 } htentry;
437 518
438 struct Lisp_Hash_Table 519 struct Lisp_Hash_Table
439 { 520 {
440 struct lcrecord_header header; 521 struct lcrecord_header header;
441 Elemcount size; 522 Elemcount size;
444 double rehash_size; 525 double rehash_size;
445 double rehash_threshold; 526 double rehash_threshold;
446 Elemcount golden_ratio; 527 Elemcount golden_ratio;
447 hash_table_hash_function_t hash_function; 528 hash_table_hash_function_t hash_function;
448 hash_table_test_function_t test_function; 529 hash_table_test_function_t test_function;
449 hentry *hentries; 530 htentry *hentries;
450 enum hash_table_weakness weakness; 531 enum hash_table_weakness weakness;
451 Lisp_Object next_weak; // Used to chain together all of the weak 532 Lisp_Object next_weak; // Used to chain together all of the weak
452 // hash tables. Don't mark through this. 533 // hash tables. Don't mark through this.
453 }; 534 };
454 535
455 static const struct lrecord_description hentry_description_1[] = { 536 static const struct memory_description htentry_description_1[] = {
456 { XD_LISP_OBJECT, offsetof (hentry, key) }, 537 { XD_LISP_OBJECT, offsetof (htentry, key) },
457 { XD_LISP_OBJECT, offsetof (hentry, value) }, 538 { XD_LISP_OBJECT, offsetof (htentry, value) },
458 { XD_END } 539 { XD_END }
459 }; 540 };
460 541
461 static const struct struct_description hentry_description = { 542 static const struct sized_memory_description htentry_description = {
462 sizeof (hentry), 543 sizeof (htentry),
463 hentry_description_1 544 htentry_description_1
464 }; 545 };
465 546
466 const struct lrecord_description hash_table_description[] = { 547 const struct memory_description hash_table_description[] = {
467 { XD_ELEMCOUNT, offsetof (Lisp_Hash_Table, size) }, 548 { XD_ELEMCOUNT, offsetof (Lisp_Hash_Table, size) },
468 { XD_STRUCT_PTR, offsetof (Lisp_Hash_Table, hentries), XD_INDIRECT(0, 1), 549 { XD_STRUCT_PTR, offsetof (Lisp_Hash_Table, hentries), XD_INDIRECT (0, 1),
469 &hentry_description }, 550 &htentry_description },
470 { XD_LO_LINK, offsetof (Lisp_Hash_Table, next_weak) }, 551 { XD_LO_LINK, offsetof (Lisp_Hash_Table, next_weak) },
471 { XD_END } 552 { XD_END }
472 }; 553 };
473 554
474 Note that we don't need to declare all the elements in the structure, just 555 Note that we don't need to declare all the elements in the structure, just
475 the ones that need to be relocated (Lisp_Objects and structures) or that 556 the ones that need to be relocated (Lisp_Objects and structures) or that
476 need to be referenced as counts for relocated objects. 557 need to be referenced as counts for relocated objects.
477 558
559 A description map looks like this:
560
561 static const struct sized_memory_description specifier_extra_description_map [] = {
562 { offsetof (Lisp_Specifier, methods) },
563 { offsetof (struct specifier_methods, extra_description) },
564 { -1 }
565 };
566
567 const struct memory_description specifier_description[] = {
568 ...
569 { XD_STRUCT_ARRAY, offset (Lisp_Specifier, data), 1,
570 specifier_extra_description_map },
571 ...
572 { XD_END }
573 };
574
575 This would be appropriate for an object that looks like this:
576
577 struct specifier_methods
578 {
579 ...
580 const struct sized_memory_description *extra_description;
581 ...
582 };
583
584 struct Lisp_Specifier
585 {
586 struct lcrecord_header header;
587 struct specifier_methods *methods;
588
589 ...
590 // type-specific extra data attached to a specifier
591 max_align_t data[1];
592 };
593
594 The description map means "retrieve a pointer into the object at offset
595 `offsetof (Lisp_Specifier, methods)' , then in turn retrieve a pointer
596 into that object at offset `offsetof (struct specifier_methods,
597 extra_description)', and that is the sized_memory_description to use."
598 There can be any number of indirections, which can be either into
599 straight pointers or Lisp_Objects. The way that description maps are
600 distinguished from normal sized_memory_descriptions is that in the
601 former, the memory_description pointer is NULL.
602
603 --ben
604
478 605
479 The existing types : 606 The existing types :
480 607
481 608
482 XD_LISP_OBJECT 609 XD_LISP_OBJECT
483 A Lisp object. This is also the type to use for pointers to other lrecords. 610
611 A Lisp object. This is also the type to use for pointers to other lrecords
612 (e.g. struct frame *).
484 613
485 XD_LISP_OBJECT_ARRAY 614 XD_LISP_OBJECT_ARRAY
615
486 An array of Lisp objects or (equivalently) pointers to lrecords. 616 An array of Lisp objects or (equivalently) pointers to lrecords.
487 The parameter (i.e. third element) is the count. This would be declared 617 The parameter (i.e. third element) is the count. This would be declared
488 as Lisp_Object foo[666]. For something declared as Lisp_Object *foo, 618 as Lisp_Object foo[666]. For something declared as Lisp_Object *foo,
489 use XD_STRUCT_PTR, whose description parameter is a struct_description 619 use XD_STRUCT_PTR, whose description parameter is a sized_memory_description
490 consisting of only XD_LISP_OBJECT and XD_END. 620 consisting of only XD_LISP_OBJECT and XD_END.
491 621
492 XD_LO_LINK 622 XD_LO_LINK
623
493 Weak link in a linked list of objects of the same type. This is a 624 Weak link in a linked list of objects of the same type. This is a
494 link that does NOT generate a GC reference. Thus the pdumper will 625 link that does NOT generate a GC reference. Thus the pdumper will
495 not automatically add the referenced object to the table of all 626 not automatically add the referenced object to the table of all
496 objects to be dumped, and when storing and loading the dumped data 627 objects to be dumped, and when storing and loading the dumped data
497 will automatically prune unreferenced objects in the chain and link 628 will automatically prune unreferenced objects in the chain and link
499 many links away. We also need to special handling of a similar 630 many links away. We also need to special handling of a similar
500 nature for the root of the chain, which will be a staticpro()ed 631 nature for the root of the chain, which will be a staticpro()ed
501 object. 632 object.
502 633
503 XD_OPAQUE_PTR 634 XD_OPAQUE_PTR
635
504 Pointer to undumpable data. Must be NULL when dumping. 636 Pointer to undumpable data. Must be NULL when dumping.
505 637
506 XD_STRUCT_PTR 638 XD_STRUCT_PTR
639
507 Pointer to block of described memory. (This is misnamed: It is NOT 640 Pointer to block of described memory. (This is misnamed: It is NOT
508 necessarily a pointer to a struct foo.) Parameters are number of 641 necessarily a pointer to a struct foo.) Parameters are number of
509 contiguous blocks and struct_description. 642 contiguous blocks and sized_memory_description.
510 643
511 XD_STRUCT_ARRAY 644 XD_STRUCT_ARRAY
645
512 Array of blocks of described memory. Parameters are number of 646 Array of blocks of described memory. Parameters are number of
513 structures and struct_description. This differs from XD_STRUCT_PTR 647 structures and sized_memory_description. This differs from XD_STRUCT_PTR
514 in that the parameter is declared as struct foo[666] instead of 648 in that the parameter is declared as struct foo[666] instead of
515 struct *foo. In other words, the block of memory holding the 649 struct *foo. In other words, the block of memory holding the
516 structures is within the containing structure, rather than being 650 structures is within the containing structure, rather than being
517 elsewhere, with a pointer in the containing structure. 651 elsewhere, with a pointer in the containing structure.
518 652
653 NOTE NOTE NOTE: Be sure that you understand the difference between
654 XD_STRUCT_PTR and XD_STRUCT_ARRAY:
655 - struct foo bar[666], i.e. 666 inline struct foos
656 --> XD_STRUCT_ARRAY, argument 666, pointing to a description of
657 struct foo
658 - struct foo *bar, i.e. pointer to a block of 666 struct foos
659 --> XD_STRUCT_PTR, argument 666, pointing to a description of
660 struct foo
661 - struct foo *bar[666], i.e. 666 pointers to separate blocks of struct foos
662 --> XD_STRUCT_ARRAY, argument 666, pointing to a description of
663 a single pointer to struct foo; the description is a single
664 XD_STRUCT_PTR, argument 1, which in turn points to a description
665 of struct foo.
666
519 XD_OPAQUE_DATA_PTR 667 XD_OPAQUE_DATA_PTR
668
520 Pointer to dumpable opaque data. Parameter is the size of the data. 669 Pointer to dumpable opaque data. Parameter is the size of the data.
521 Pointed data must be relocatable without changes. 670 Pointed data must be relocatable without changes.
522 671
523 XD_UNION 672 XD_UNION
524 Union of two or more different types of data. Parameters are a 673
525 constant which determines which type the data is (this is usually an 674 Union of two or more different types of data. Parameters are a constant
526 XD_INDIRECT, referring to one of the fields in the structure), and 675 which determines which type the data is (this is usually an XD_INDIRECT,
527 an array of struct_descriptions, whose values are used as follows, 676 referring to one of the fields in the structure), and a "sizing lobby" (a
528 which is *DIFFERENT* from their usage in XD_STRUCT_PTR: the first 677 sized_memory_description, which points to a memory_description and
529 field is a constant, which is compared to the first parameter of the 678 indicates its size). The size field in the sizing lobby describes the
530 XD_UNION descriptor to determine if this description applies to the 679 size of the union field in the object, and the memory_description in it
531 data at the given offset, and the second is a pointer to a *SINGLE* 680 is referred to as a "union map" and has a special interpretation: The
532 lrecord_description structure, describing the data being pointed at 681 offset field is replaced by a constant, which is compared to the first
533 when the associated constant matches. You can go ahead and create 682 parameter of the XD_UNION descriptor to determine if this description
534 an array of lrecord_description structures and put an XD_END on it, 683 applies to the union data, and XD_INDIRECT references refer to the
535 but only the first one is used. If the data being pointed at is a 684 containing object and description. Note that the description applies
536 structure, you *MAY NOT* substitute an array of lrecord_description 685 "inline" to the union data, like XD_STRUCT_ARRAY and not XD_STRUCT_PTR.
537 structures describing the structure; instead, use a single 686 If the union data is a pointer to different types of structures, each
538 lrecord_description structure with an XD_STRUCT_PTR in it, and point 687 element in the memory_description should be an XD_STRUCT_PTR. See
539 it in turn to the description of the structure. See charset.h for a 688 unicode.c, redisplay.c and objects.c for examples of XD_UNION.
540 description of how to use XD_UNION. (In other words, if the constant 689
541 matches, the lrecord_description pointed at will in essence be 690 XD_UNION_DYNAMIC_SIZE
542 substituted for the XD_UNION declaration.) 691
692 Same as XD_UNION except that this is used for objects where the size of
693 the object containing the union varies depending on the particular value
694 of the union constant. That is, an object with plain XD_UNION typically
695 has the union declared as `union foo' or as `void *', where an object
696 with XD_UNION_DYNAMIC_SIZE typically has the union as the last element,
697 and declared as something like char foo[1]. With plain XD_UNION, the
698 object is (usually) of fixed size and always contains enough space for
699 the data associated with all possible union constants, and thus the union
700 constant can potentially change during the lifetime of the object. With
701 XD_UNION_DYNAMIC_SIZE, however, the union constant is fixed at the time
702 of creation of the object, and the size of the object is computed
703 dynamically at creation time based on the size of the data associated
704 with the union constant. Currently, the only difference between XD_UNION
705 and XD_UNION_DYNAMIC_SIZE is how the size of the union data is
706 calculated, when (a) the structure containing the union has no size
707 given; (b) the union occurs as the last element in the structure; and (c)
708 the union has no size given (in the first-level sized_memory_description
709 pointed to). In this circumstance, the size of XD_UNION comes from the
710 max size of the data associated with all possible union constants,
711 whereas the size of XD_UNION_DYNAMIC_SIZE comes from the size of the data
712 associated with the currently specified (and unchangeable) union
713 constant.
543 714
544 XD_C_STRING 715 XD_C_STRING
716
545 Pointer to a C string. 717 Pointer to a C string.
546 718
547 XD_DOC_STRING 719 XD_DOC_STRING
720
548 Pointer to a doc string (C string if positive, opaque value if negative) 721 Pointer to a doc string (C string if positive, opaque value if negative)
549 722
550 XD_INT_RESET 723 XD_INT_RESET
724
551 An integer which will be reset to a given value in the dump file. 725 An integer which will be reset to a given value in the dump file.
552 726
553
554 XD_ELEMCOUNT 727 XD_ELEMCOUNT
728
555 Elemcount value. Used for counts. 729 Elemcount value. Used for counts.
556 730
557 XD_BYTECOUNT 731 XD_BYTECOUNT
732
558 Bytecount value. Used for counts. 733 Bytecount value. Used for counts.
559 734
560 XD_HASHCODE 735 XD_HASHCODE
736
561 Hashcode value. Used for the results of hashing functions. 737 Hashcode value. Used for the results of hashing functions.
562 738
563 XD_INT 739 XD_INT
740
564 int value. Used for counts. 741 int value. Used for counts.
565 742
566 XD_LONG 743 XD_LONG
744
567 long value. Used for counts. 745 long value. Used for counts.
568 746
569 XD_BYTECOUNT 747 XD_BYTECOUNT
748
570 bytecount value. Used for counts. 749 bytecount value. Used for counts.
571 750
572 XD_END 751 XD_END
752
573 Special type indicating the end of the array. 753 Special type indicating the end of the array.
574 754
575 XD_SPECIFIER_END
576 Special type indicating the end of the array for a specifier. Extra
577 description, describing the specifier-type-specific data at the end
578 of the specifier object, is going to be fetched from the specifier
579 methods. This should occur exactly once, in the description of the
580 specifier object, and the dump code knows how to special-case this
581 by fetching the specifier_methods pointer from the appropriate place
582 in the memory block (which will, of course, be a struct
583 Lisp_Specifier), fetching the description of the
584 specifier-type-specific data from this, and continuing processing
585 the memory block.
586
587 XD_CODING_SYSTEM_END
588 Special type indicating the end of the array for a coding system.
589 Extra description is going to be fetched from the coding system
590 methods. Works just like XD_SPECIFIER_END.
591
592 755
593 Special macros: 756 Special macros:
594 XD_INDIRECT(line, delta) 757
595 Usable where a "count" or "size" is requested. Gives the value of 758 XD_INDIRECT (line, delta)
596 the element which is at line number 'line' in the description (count 759 Usable where a count, size, offset or union constant is requested. Gives
597 starts at zero) and adds delta to it. 760 the value of the element which is at line number 'line' in the
761 description (count starts at zero) and adds delta to it, which must
762 (currently) be positive.
598 */ 763 */
599 764
600 enum lrecord_description_type 765 enum memory_description_type
601 { 766 {
602 XD_LISP_OBJECT_ARRAY, 767 XD_LISP_OBJECT_ARRAY,
603 XD_LISP_OBJECT, 768 XD_LISP_OBJECT,
604 XD_LO_LINK, 769 XD_LO_LINK,
605 XD_OPAQUE_PTR, 770 XD_OPAQUE_PTR,
606 XD_STRUCT_PTR, 771 XD_STRUCT_PTR,
607 XD_STRUCT_ARRAY, 772 XD_STRUCT_ARRAY,
608 XD_OPAQUE_DATA_PTR, 773 XD_OPAQUE_DATA_PTR,
609 XD_UNION, 774 XD_UNION,
775 XD_UNION_DYNAMIC_SIZE,
610 XD_C_STRING, 776 XD_C_STRING,
611 XD_DOC_STRING, 777 XD_DOC_STRING,
612 XD_INT_RESET, 778 XD_INT_RESET,
613 XD_BYTECOUNT, 779 XD_BYTECOUNT,
614 XD_ELEMCOUNT, 780 XD_ELEMCOUNT,
615 XD_HASHCODE, 781 XD_HASHCODE,
616 XD_INT, 782 XD_INT,
617 XD_LONG, 783 XD_LONG,
618 XD_END, 784 XD_END
619 XD_SPECIFIER_END,
620 XD_CODING_SYSTEM_END
621 }; 785 };
622 786
623 struct lrecord_description 787 enum data_description_entry_flags
624 { 788 {
625 enum lrecord_description_type type; 789 /* If set, KKCC does not process this entry.
626 int offset; 790
791 (1) One obvious use is with things that pdump saves but which do not get
792 marked normally -- for example the next and prev fields in a marker. The
793 marker chain is weak, with its entries removed when they are finalized.
794
795 (2) This can be set on structures not containing any Lisp objects, or (more
796 usefully) on structures that contain Lisp objects but where the objects
797 always occur in another structure as well. For example, the extent lists
798 kept by a buffer keep the extents in two lists, one sorted by the start
799 of the extent and the other by the end. There's no point in marking
800 both, since each contains the same objects as the other; but when dumping
801 (if we were to dump such a structure), when computing memory size, etc.,
802 it's crucial to tag both sides.
803 */
804 XD_FLAG_NO_KKCC = 1,
805 /* If set, pdump does not process this entry. */
806 XD_FLAG_NO_PDUMP = 2,
807 /* Indicates that this is a "default" entry in a union map. */
808 XD_FLAG_UNION_DEFAULT_ENTRY = 4,
809 /* Indicates that this is a free Lisp object we're marking.
810 Only relevant for ERROR_CHECK_GC. This occurs when we're marking
811 lcrecord-lists, where the objects have had their type changed to
812 lrecord_type_free and also have had their free bit set, but we mark
813 them as normal. */
814 XD_FLAG_FREE_LISP_OBJECT = 8,
815 #if 0
816 /* Suggestions for other possible flags: */
817
818 /* Eliminate XD_UNION_DYNAMIC_SIZE and replace it with a flag, like this. */
819 XD_FLAG_UNION_DYNAMIC_SIZE = 16,
820 /* Require that everyone who uses a description map has to flag it, so
821 that it's easy to tell, when looking through the code, where the
822 description maps are and who's using them. This might also become
823 necessary if for some reason the format of the description map is
824 expanded and we need to stick a pointer in the second slot (although
825 we could still ensure that the second slot in the first entry was NULL
826 or <0). */
827 XD_FLAG_DESCRIPTION_MAP = 32,
828 #endif
829 };
830
831 struct memory_description
832 {
833 enum memory_description_type type;
834 Bytecount offset;
627 EMACS_INT data1; 835 EMACS_INT data1;
628 const struct struct_description *data2; 836 const struct sized_memory_description *data2;
837 /* Indicates which subsystems process this entry, plus (potentially) other
838 flags that apply to this entry. */
839 int flags;
629 }; 840 };
630 841
631 struct struct_description 842 struct sized_memory_description
632 { 843 {
633 Bytecount size; 844 Bytecount size;
634 const struct lrecord_description *description; 845 const struct memory_description *description;
635 }; 846 };
636 847
637 #define XD_INDIRECT(val, delta) (-1-((val)|(delta<<8))) 848 extern const struct sized_memory_description lisp_object_description;
638 849
639 #define XD_IS_INDIRECT(code) (code<0) 850 #define XD_INDIRECT(val, delta) (-1 - (Bytecount) ((val) | ((delta) << 8)))
640 #define XD_INDIRECT_VAL(code) ((-1-code) & 255) 851
641 #define XD_INDIRECT_DELTA(code) (((-1-code)>>8) & 255) 852 #define XD_IS_INDIRECT(code) ((code) < 0)
642 853 #define XD_INDIRECT_VAL(code) ((-1 - (code)) & 255)
643 #define XD_DYNARR_DESC(base_type, sub_desc) \ 854 #define XD_INDIRECT_DELTA(code) ((-1 - (code)) >> 8)
855
856 #define XD_DYNARR_DESC(base_type, sub_desc) \
644 { XD_STRUCT_PTR, offsetof (base_type, base), XD_INDIRECT(1, 0), sub_desc }, \ 857 { XD_STRUCT_PTR, offsetof (base_type, base), XD_INDIRECT(1, 0), sub_desc }, \
645 { XD_INT, offsetof (base_type, cur) }, \ 858 { XD_INT, offsetof (base_type, cur) }, \
646 { XD_INT_RESET, offsetof (base_type, max), XD_INDIRECT(1, 0) } 859 { XD_INT_RESET, offsetof (base_type, max), XD_INDIRECT(1, 0) } \
860
647 861
648 /* DEFINE_LRECORD_IMPLEMENTATION is for objects with constant size. 862 /* DEFINE_LRECORD_IMPLEMENTATION is for objects with constant size.
649 DEFINE_LRECORD_SEQUENCE_IMPLEMENTATION is for objects whose size varies. 863 DEFINE_LRECORD_SEQUENCE_IMPLEMENTATION is for objects whose size varies.
650 */ 864 */
651 865
654 #else 868 #else
655 # define DECLARE_ERROR_CHECK_TYPES(c_name, structtype) 869 # define DECLARE_ERROR_CHECK_TYPES(c_name, structtype)
656 #endif 870 #endif
657 871
658 872
659 #ifdef USE_KKCC
660 #define DEFINE_BASIC_LRECORD_IMPLEMENTATION(name,c_name,dumpable,marker,printer,nuker,equal,hash,desc,structtype) \ 873 #define DEFINE_BASIC_LRECORD_IMPLEMENTATION(name,c_name,dumpable,marker,printer,nuker,equal,hash,desc,structtype) \
661 DEFINE_BASIC_LRECORD_IMPLEMENTATION_WITH_PROPS(name,c_name,dumpable,marker,printer,nuker,equal,hash,desc,0,0,0,0,structtype) 874 DEFINE_BASIC_LRECORD_IMPLEMENTATION_WITH_PROPS(name,c_name,dumpable,marker,printer,nuker,equal,hash,desc,0,0,0,0,structtype)
662 875
663 #define DEFINE_BASIC_LRECORD_IMPLEMENTATION_WITH_PROPS(name,c_name,dumpable,marker,printer,nuker,equal,hash,desc,getprop,putprop,remprop,plist,structtype) \ 876 #define DEFINE_BASIC_LRECORD_IMPLEMENTATION_WITH_PROPS(name,c_name,dumpable,marker,printer,nuker,equal,hash,desc,getprop,putprop,remprop,plist,structtype) \
664 MAKE_LRECORD_IMPLEMENTATION(name,c_name,dumpable,marker,printer,nuker,equal,hash,desc,getprop,putprop,remprop,plist,sizeof(structtype),0,1,structtype) 877 MAKE_LRECORD_IMPLEMENTATION(name,c_name,dumpable,marker,printer,nuker,equal,hash,desc,getprop,putprop,remprop,plist,sizeof(structtype),0,1,structtype)
677 890
678 #define DEFINE_LRECORD_SEQUENCE_IMPLEMENTATION_WITH_PROPS(name,c_name,dumpable,marker,printer,nuker,equal,hash,desc,getprop,putprop,remprop,plist,sizer,structtype) \ 891 #define DEFINE_LRECORD_SEQUENCE_IMPLEMENTATION_WITH_PROPS(name,c_name,dumpable,marker,printer,nuker,equal,hash,desc,getprop,putprop,remprop,plist,sizer,structtype) \
679 MAKE_LRECORD_IMPLEMENTATION(name,c_name,dumpable,marker,printer,nuker,equal,hash,desc,getprop,putprop,remprop,plist,0,sizer,0,structtype) 892 MAKE_LRECORD_IMPLEMENTATION(name,c_name,dumpable,marker,printer,nuker,equal,hash,desc,getprop,putprop,remprop,plist,0,sizer,0,structtype)
680 893
681 #define MAKE_LRECORD_IMPLEMENTATION(name,c_name,dumpable,marker,printer,nuker,equal,hash,desc,getprop,putprop,remprop,plist,size,sizer,basic_p,structtype) \ 894 #define MAKE_LRECORD_IMPLEMENTATION(name,c_name,dumpable,marker,printer,nuker,equal,hash,desc,getprop,putprop,remprop,plist,size,sizer,basic_p,structtype) \
682 DECLARE_ERROR_CHECK_TYPES(c_name, structtype) \ 895 DECLARE_ERROR_CHECK_TYPES(c_name, structtype) \
683 const struct lrecord_implementation lrecord_##c_name = \ 896 const struct lrecord_implementation lrecord_##c_name = \
684 { name, dumpable, marker, printer, nuker, equal, hash, desc, \ 897 { name, dumpable, marker, printer, nuker, equal, hash, desc, \
685 getprop, putprop, remprop, plist, size, sizer, \ 898 getprop, putprop, remprop, plist, size, sizer, \
686 lrecord_type_##c_name, basic_p } 899 lrecord_type_##c_name, basic_p }
687 900
696 909
697 #define DEFINE_EXTERNAL_LRECORD_SEQUENCE_IMPLEMENTATION_WITH_PROPS(name,c_name,dumpable,marker,printer,nuker,equal,hash,desc,getprop,putprop,remprop,plist,sizer,structtype) \ 910 #define DEFINE_EXTERNAL_LRECORD_SEQUENCE_IMPLEMENTATION_WITH_PROPS(name,c_name,dumpable,marker,printer,nuker,equal,hash,desc,getprop,putprop,remprop,plist,sizer,structtype) \
698 MAKE_EXTERNAL_LRECORD_IMPLEMENTATION(name,c_name,dumpable,marker,printer,nuker,equal,hash,desc,getprop,putprop,remprop,plist,0,sizer,0,structtype) 911 MAKE_EXTERNAL_LRECORD_IMPLEMENTATION(name,c_name,dumpable,marker,printer,nuker,equal,hash,desc,getprop,putprop,remprop,plist,0,sizer,0,structtype)
699 912
700 #define MAKE_EXTERNAL_LRECORD_IMPLEMENTATION(name,c_name,dumpable,marker,printer,nuker,equal,hash,desc,getprop,putprop,remprop,plist,size,sizer,basic_p,structtype) \ 913 #define MAKE_EXTERNAL_LRECORD_IMPLEMENTATION(name,c_name,dumpable,marker,printer,nuker,equal,hash,desc,getprop,putprop,remprop,plist,size,sizer,basic_p,structtype) \
701 DECLARE_ERROR_CHECK_TYPES(c_name, structtype) \ 914 DECLARE_ERROR_CHECK_TYPES(c_name, structtype) \
702 int lrecord_type_##c_name; \ 915 int lrecord_type_##c_name; \
703 struct lrecord_implementation lrecord_##c_name = \ 916 struct lrecord_implementation lrecord_##c_name = \
704 { name, dumpable, marker, printer, nuker, equal, hash, desc, \ 917 { name, dumpable, marker, printer, nuker, equal, hash, desc, \
705 getprop, putprop, remprop, plist, size, sizer, \ 918 getprop, putprop, remprop, plist, size, sizer, \
706 lrecord_type_last_built_in_type, basic_p } 919 lrecord_type_last_built_in_type, basic_p }
707
708 #else /* not USE_KKCC */
709
710 #define DEFINE_BASIC_LRECORD_IMPLEMENTATION(name,c_name,marker,printer,nuker,equal,hash,desc,structtype) \
711 DEFINE_BASIC_LRECORD_IMPLEMENTATION_WITH_PROPS(name,c_name,marker,printer,nuker,equal,hash,desc,0,0,0,0,structtype)
712
713 #define DEFINE_BASIC_LRECORD_IMPLEMENTATION_WITH_PROPS(name,c_name,marker,printer,nuker,equal,hash,desc,getprop,putprop,remprop,plist,structtype) \
714 MAKE_LRECORD_IMPLEMENTATION(name,c_name,0,marker,printer,nuker,equal,hash,desc,getprop,putprop,remprop,plist,sizeof(structtype),0,1,structtype)
715
716 #define DEFINE_LRECORD_IMPLEMENTATION(name,c_name,marker,printer,nuker,equal,hash,desc,structtype) \
717 DEFINE_LRECORD_IMPLEMENTATION_WITH_PROPS(name,c_name,marker,printer,nuker,equal,hash,desc,0,0,0,0,structtype)
718
719 #define DEFINE_LRECORD_IMPLEMENTATION_WITH_PROPS(name,c_name,marker,printer,nuker,equal,hash,desc,getprop,putprop,remprop,plist,structtype) \
720 MAKE_LRECORD_IMPLEMENTATION(name,c_name,0,marker,printer,nuker,equal,hash,desc,getprop,putprop,remprop,plist,sizeof (structtype),0,0,structtype)
721
722 #define DEFINE_LRECORD_SEQUENCE_IMPLEMENTATION(name,c_name,marker,printer,nuker,equal,hash,desc,sizer,structtype) \
723 DEFINE_LRECORD_SEQUENCE_IMPLEMENTATION_WITH_PROPS(name,c_name,marker,printer,nuker,equal,hash,desc,0,0,0,0,sizer,structtype)
724
725 #define DEFINE_BASIC_LRECORD_SEQUENCE_IMPLEMENTATION(name,c_name,marker,printer,nuker,equal,hash,desc,sizer,structtype) \
726 MAKE_LRECORD_IMPLEMENTATION(name,c_name,0,marker,printer,nuker,equal,hash,desc,0,0,0,0,0,sizer,1,structtype)
727
728 #define DEFINE_LRECORD_SEQUENCE_IMPLEMENTATION_WITH_PROPS(name,c_name,marker,printer,nuker,equal,hash,desc,getprop,putprop,remprop,plist,sizer,structtype) \
729 MAKE_LRECORD_IMPLEMENTATION(name,c_name,0,marker,printer,nuker,equal,hash,desc,getprop,putprop,remprop,plist,0,sizer,0,structtype)
730
731 #define MAKE_LRECORD_IMPLEMENTATION(name,c_name,dumpable,marker,printer,nuker,equal,hash,desc,getprop,putprop,remprop,plist,size,sizer,basic_p,structtype) \
732 DECLARE_ERROR_CHECK_TYPES(c_name, structtype) \
733 const struct lrecord_implementation lrecord_##c_name = \
734 { name, dumpable, marker, printer, nuker, equal, hash, desc, \
735 getprop, putprop, remprop, plist, size, sizer, \
736 lrecord_type_##c_name, basic_p }
737
738 #define DEFINE_EXTERNAL_LRECORD_IMPLEMENTATION(name,c_name,marker,printer,nuker,equal,hash,desc,structtype) \
739 DEFINE_EXTERNAL_LRECORD_IMPLEMENTATION_WITH_PROPS(name,c_name,marker,printer,nuker,equal,hash,desc,0,0,0,0,structtype)
740
741 #define DEFINE_EXTERNAL_LRECORD_IMPLEMENTATION_WITH_PROPS(name,c_name,marker,printer,nuker,equal,hash,desc,getprop,putprop,remprop,plist,structtype) \
742 MAKE_EXTERNAL_LRECORD_IMPLEMENTATION(name,c_name,0,marker,printer,nuker,equal,hash,desc,getprop,putprop,remprop,plist,sizeof (structtype),0,0,structtype)
743
744 #define DEFINE_EXTERNAL_LRECORD_SEQUENCE_IMPLEMENTATION(name,c_name,marker,printer,nuker,equal,hash,desc,sizer,structtype) \
745 DEFINE_EXTERNAL_LRECORD_SEQUENCE_IMPLEMENTATION_WITH_PROPS(name,c_name,marker,printer,nuker,equal,hash,desc,0,0,0,0,sizer,structtype)
746
747 #define DEFINE_EXTERNAL_LRECORD_SEQUENCE_IMPLEMENTATION_WITH_PROPS(name,c_name,marker,printer,nuker,equal,hash,desc,getprop,putprop,remprop,plist,sizer,structtype) \
748 MAKE_EXTERNAL_LRECORD_IMPLEMENTATION(name,c_name,0,marker,printer,nuker,equal,hash,desc,getprop,putprop,remprop,plist,0,sizer,0,structtype)
749
750 #define MAKE_EXTERNAL_LRECORD_IMPLEMENTATION(name,c_name,dumpable,marker,printer,nuker,equal,hash,desc,getprop,putprop,remprop,plist,size,sizer,basic_p,structtype) \
751 DECLARE_ERROR_CHECK_TYPES(c_name, structtype) \
752 int lrecord_type_##c_name; \
753 struct lrecord_implementation lrecord_##c_name = \
754 { name, dumpable, marker, printer, nuker, equal, hash, desc, \
755 getprop, putprop, remprop, plist, size, sizer, \
756 lrecord_type_last_built_in_type, basic_p }
757 #endif /* not USE_KKCC */
758 920
759 extern Lisp_Object (*lrecord_markers[]) (Lisp_Object); 921 extern Lisp_Object (*lrecord_markers[]) (Lisp_Object);
760 922
761 #define INIT_LRECORD_IMPLEMENTATION(type) do { \ 923 #define INIT_LRECORD_IMPLEMENTATION(type) do { \
762 lrecord_implementations_table[lrecord_type_##type] = &lrecord_##type; \ 924 lrecord_implementations_table[lrecord_type_##type] = &lrecord_##type; \
807 3. Add this header file to inline.c. 969 3. Add this header file to inline.c.
808 970
809 4. Create the methods for your object. Note that technically you don't 971 4. Create the methods for your object. Note that technically you don't
810 need any, but you will almost always want at least a mark method. 972 need any, but you will almost always want at least a mark method.
811 973
812 5. Define your object with DEFINE_LRECORD_IMPLEMENTATION() or some 974 4. Create the data layout description for your object. See
975 toolbar_button_description below; the comment above in `struct lrecord',
976 describing the purpose of the descriptions; and comments elsewhere in
977 this file describing the exact syntax of the description structures.
978
979 6. Define your object with DEFINE_LRECORD_IMPLEMENTATION() or some
813 variant. 980 variant.
814 981
815 6. Include the header file in the .c file where you defined the object. 982 7. Include the header file in the .c file where you defined the object.
816 983
817 7. Put a call to INIT_LRECORD_IMPLEMENTATION() for the object in the 984 8. Put a call to INIT_LRECORD_IMPLEMENTATION() for the object in the
818 .c file's syms_of_foo() function. 985 .c file's syms_of_foo() function.
819 986
820 8. Add a type enum for the object to enum lrecord_type, earlier in this 987 9. Add a type enum for the object to enum lrecord_type, earlier in this
821 file. 988 file.
989
990 --ben
822 991
823 An example: 992 An example:
824 993
825 ------------------------------ in toolbar.h ----------------------------- 994 ------------------------------ in toolbar.h -----------------------------
826 995
868 1037
869 #include "toolbar.h" 1038 #include "toolbar.h"
870 1039
871 ... 1040 ...
872 1041
1042 static const struct memory_description toolbar_button_description [] = {
1043 { XD_LISP_OBJECT, offsetof (struct toolbar_button, next) },
1044 { XD_LISP_OBJECT, offsetof (struct toolbar_button, frame) },
1045 { XD_LISP_OBJECT, offsetof (struct toolbar_button, up_glyph) },
1046 { XD_LISP_OBJECT, offsetof (struct toolbar_button, down_glyph) },
1047 { XD_LISP_OBJECT, offsetof (struct toolbar_button, disabled_glyph) },
1048 { XD_LISP_OBJECT, offsetof (struct toolbar_button, cap_up_glyph) },
1049 { XD_LISP_OBJECT, offsetof (struct toolbar_button, cap_down_glyph) },
1050 { XD_LISP_OBJECT, offsetof (struct toolbar_button, cap_disabled_glyph) },
1051 { XD_LISP_OBJECT, offsetof (struct toolbar_button, callback) },
1052 { XD_LISP_OBJECT, offsetof (struct toolbar_button, enabled_p) },
1053 { XD_LISP_OBJECT, offsetof (struct toolbar_button, help_string) },
1054 { XD_END }
1055 };
1056
873 static Lisp_Object 1057 static Lisp_Object
874 mark_toolbar_button (Lisp_Object obj) 1058 mark_toolbar_button (Lisp_Object obj)
875 { 1059 \{
876 struct toolbar_button *data = XTOOLBAR_BUTTON (obj); 1060 struct toolbar_button *data = XTOOLBAR_BUTTON (obj);
877 mark_object (data->next); 1061 mark_object (data->next);
878 mark_object (data->frame); 1062 mark_object (data->frame);
879 mark_object (data->up_glyph); 1063 mark_object (data->up_glyph);
880 mark_object (data->down_glyph); 1064 mark_object (data->down_glyph);
889 1073
890 [[ If your object should never escape to Lisp, declare its print method 1074 [[ If your object should never escape to Lisp, declare its print method
891 as internal_object_printer instead of 0. ]] 1075 as internal_object_printer instead of 0. ]]
892 1076
893 DEFINE_LRECORD_IMPLEMENTATION ("toolbar-button", toolbar_button, 1077 DEFINE_LRECORD_IMPLEMENTATION ("toolbar-button", toolbar_button,
894 mark_toolbar_button, 0, 1078 0, mark_toolbar_button, 0, 0, 0, 0,
895 0, 0, 0, 0, struct toolbar_button); 1079 toolbar_button_description,
1080 struct toolbar_button);
896 1081
897 ... 1082 ...
898 1083
899 void 1084 void
900 syms_of_toolbar (void) 1085 syms_of_toolbar (void)
916 { 1101 {
917 ... 1102 ...
918 lrecord_type_toolbar_button, 1103 lrecord_type_toolbar_button,
919 ... 1104 ...
920 }; 1105 };
1106
1107
1108 --ben
921 1109
922 */ 1110 */
923 1111
924 /* 1112 /*
925 1113
1049 #define CHECK_NONRECORD(x, lisp_enum, predicate) do { \ 1237 #define CHECK_NONRECORD(x, lisp_enum, predicate) do { \
1050 if (XTYPE (x) != lisp_enum) \ 1238 if (XTYPE (x) != lisp_enum) \
1051 dead_wrong_type_argument (predicate, x); \ 1239 dead_wrong_type_argument (predicate, x); \
1052 } while (0) 1240 } while (0)
1053 1241
1242 /*-------------------------- lcrecord-list -----------------------------*/
1243
1244 struct lcrecord_list
1245 {
1246 struct lcrecord_header header;
1247 Lisp_Object free;
1248 Elemcount size;
1249 const struct lrecord_implementation *implementation;
1250 };
1251
1252 DECLARE_LRECORD (lcrecord_list, struct lcrecord_list);
1253 #define XLCRECORD_LIST(x) XRECORD (x, lcrecord_list, struct lcrecord_list)
1254 #define wrap_lcrecord_list(p) wrap_record (p, lcrecord_list)
1255 #define LCRECORD_LISTP(x) RECORDP (x, lcrecord_list)
1256 /* #define CHECK_LCRECORD_LIST(x) CHECK_RECORD (x, lcrecord_list)
1257 Lcrecord lists should never escape to the Lisp level, so
1258 functions should not be doing this. */
1259
1054 /* Various ways of allocating lcrecords. All bytes (except lcrecord 1260 /* Various ways of allocating lcrecords. All bytes (except lcrecord
1055 header) are zeroed in returned structure. */ 1261 header) are zeroed in returned structure.
1056 1262
1057 void *alloc_lcrecord (Bytecount size, 1263 See above for a discussion of the difference between plain lrecords and
1058 const struct lrecord_implementation *); 1264 lrecords. lcrecords themselves are divided into three types: (1)
1059 1265 auto-managed, (2) hand-managed, and (3) unmanaged. "Managed" refers to
1266 using a special object called an lcrecord-list to keep track of freed
1267 lcrecords, which can freed with free_lcrecord() or the like and later be
1268 recycled when a new lcrecord is required, rather than requiring new
1269 malloc(). Thus, allocation of lcrecords can be very
1270 cheap. (Technically, the lcrecord-list manager could divide up large
1271 chunks of memory and allocate out of that, mimicking what happens with
1272 lrecords. At that point, however, we'd want to rethink the whole
1273 division between lrecords and lcrecords.)
1274
1275 NOTE: There is a fundamental limitation of lcrecord-lists, which is that
1276 they only handle blocks of a particular, fixed size. Thus, objects that
1277 can be of varying sizes need to do various tricks. These considerations
1278 in particular dictate the various types of management:
1279
1280 -- "Auto-managed" means that you just go ahead and allocate the lcrecord
1281 whenever you want, using alloc_lcrecord_type(), and the appropriate
1282 lcrecord-list manager is automatically created. To free, you just call
1283 "free_lcrecord()" and the appropriate lcrecord-list manager is
1284 automatically located and called. The limitation here of course is that
1285 all your objects are of the same size. (#### Eventually we should have a
1286 more sophisticated system that tracks the sizes seen and creates one
1287 lcrecord list per size, indexed in a hash table. Usually there are only
1288 a limited number of sizes, so this works well.)
1289
1290 -- "Hand-managed" exists because we haven't yet written the more
1291 sophisticated scheme for auto-handling different-sized lcrecords, as
1292 described in the end of the last paragraph. In this model, you go ahead
1293 and create the lcrecord-list objects yourself for the sizes you will
1294 need, using make_lcrecord_list(). Then, create lcrecords using
1295 alloc_managed_lcrecord(), passing in the lcrecord-list you created, and
1296 free them with free_managed_lcrecord().
1297
1298 -- "Unmanaged" means you simply allocate lcrecords, period. No
1299 lcrecord-lists, no way to free them. This may be suitable when the
1300 lcrecords are variable-sized and (a) you're too lazy to write the code
1301 to hand-manage them, or (b) the objects you create are always or almost
1302 always Lisp-visible, and thus there's no point in freeing them (and it
1303 wouldn't be safe to do so). You just create them with
1304 basic_alloc_lcrecord(), and that's it.
1305
1306 --ben
1307
1308 Here is an in-depth look at the steps required to create a allocate an
1309 lcrecord using the hand-managed style. Since this is the most
1310 complicated, you will learn a lot about the other styles as well. In
1311 addition, there is useful general information about what freeing an
1312 lcrecord really entails, and what are the precautions:
1313
1314 1) Create an lcrecord-list object using make_lcrecord_list(). This is
1315 often done at initialization. Remember to staticpro_nodump() this
1316 object! The arguments to make_lcrecord_list() are the same as would be
1317 passed to basic_alloc_lcrecord().
1318
1319 2) Instead of calling basic_alloc_lcrecord(), call alloc_managed_lcrecord()
1320 and pass the lcrecord-list earlier created.
1321
1322 3) When done with the lcrecord, call free_managed_lcrecord(). The
1323 standard freeing caveats apply: ** make sure there are no pointers to
1324 the object anywhere! **
1325
1326 4) Calling free_managed_lcrecord() is just like kissing the
1327 lcrecord goodbye as if it were garbage-collected. This means:
1328 -- the contents of the freed lcrecord are undefined, and the
1329 contents of something produced by alloc_managed_lcrecord()
1330 are undefined, just like for basic_alloc_lcrecord().
1331 -- the mark method for the lcrecord's type will *NEVER* be called
1332 on freed lcrecords.
1333 -- the finalize method for the lcrecord's type will be called
1334 at the time that free_managed_lcrecord() is called.
1335 */
1336
1337 /* UNMANAGED MODEL: */
1338 void *basic_alloc_lcrecord (Bytecount size,
1339 const struct lrecord_implementation *);
1340
1341 /* HAND-MANAGED MODEL: */
1342 Lisp_Object make_lcrecord_list (Elemcount size,
1343 const struct lrecord_implementation
1344 *implementation);
1345 Lisp_Object alloc_managed_lcrecord (Lisp_Object lcrecord_list);
1346 void free_managed_lcrecord (Lisp_Object lcrecord_list, Lisp_Object lcrecord);
1347
1348 /* AUTO-MANAGED MODEL: */
1060 void *alloc_automanaged_lcrecord (Bytecount size, 1349 void *alloc_automanaged_lcrecord (Bytecount size,
1061 const struct lrecord_implementation *); 1350 const struct lrecord_implementation *);
1062
1063 #define alloc_unmanaged_lcrecord_type(type, lrecord_implementation) \
1064 ((type *) alloc_lcrecord (sizeof (type), lrecord_implementation))
1065
1066 #define alloc_lcrecord_type(type, lrecord_implementation) \ 1351 #define alloc_lcrecord_type(type, lrecord_implementation) \
1067 ((type *) alloc_automanaged_lcrecord (sizeof (type), lrecord_implementation)) 1352 ((type *) alloc_automanaged_lcrecord (sizeof (type), lrecord_implementation))
1068
1069 void free_lcrecord (Lisp_Object rec); 1353 void free_lcrecord (Lisp_Object rec);
1070 1354
1071 1355
1072 /* Copy the data from one lcrecord structure into another, but don't 1356 /* Copy the data from one lcrecord structure into another, but don't
1073 overwrite the header information. */ 1357 overwrite the header information. */
1081 1365
1082 #define zero_sized_lcrecord(lcr, size) \ 1366 #define zero_sized_lcrecord(lcr, size) \
1083 memset ((char *) (lcr) + sizeof (struct lcrecord_header), 0, \ 1367 memset ((char *) (lcr) + sizeof (struct lcrecord_header), 0, \
1084 (size) - sizeof (struct lcrecord_header)) 1368 (size) - sizeof (struct lcrecord_header))
1085 1369
1086 #define zero_lcrecord(lcr) zero_sized_lcrecord(lcr, sizeof (*(lcr))) 1370 #define zero_lcrecord(lcr) zero_sized_lcrecord (lcr, sizeof (*(lcr)))
1371
1372 DECLARE_INLINE_HEADER (
1373 Bytecount
1374 detagged_lisp_object_size (const struct lrecord_header *h)
1375 )
1376 {
1377 const struct lrecord_implementation *imp = LHEADER_IMPLEMENTATION (h);
1378
1379 return (imp->size_in_bytes_method ?
1380 imp->size_in_bytes_method (h) :
1381 imp->static_size);
1382 }
1383
1384 DECLARE_INLINE_HEADER (
1385 Bytecount
1386 lisp_object_size (Lisp_Object o)
1387 )
1388 {
1389 return detagged_lisp_object_size (XRECORD_LHEADER (o));
1390 }
1391
1392
1393 /************************************************************************/
1394 /* Dumping */
1395 /************************************************************************/
1396
1397 /* dump_add_root_struct_ptr (&var, &desc) dumps the structure pointed to by
1398 `var'. This is for a single relocatable pointer located in the data
1399 segment (i.e. the block pointed to is in the heap). */
1400 #ifdef PDUMP
1401 void dump_add_root_struct_ptr (void *, const struct sized_memory_description *);
1402 #else
1403 #define dump_add_root_struct_ptr(varaddr,descaddr) DO_NOTHING
1404 #endif
1405
1406 /* dump_add_opaque (&var, size) dumps the opaque static structure `var'.
1407 This is for a static block of memory (in the data segment, not the
1408 heap), with no relocatable pointers in it. */
1409 #ifdef PDUMP
1410 #define dump_add_opaque(varaddr,size) dump_add_root_block (varaddr, size, NULL)
1411 #else
1412 #define dump_add_opaque(varaddr,size) DO_NOTHING
1413 #endif
1414
1415 /* dump_add_root_block (ptr, size, desc) dumps the static structure
1416 located at `var' of size SIZE and described by DESC. This is for a
1417 static block of memory (in the data segment, not the heap), with
1418 relocatable pointers in it. */
1419 #ifdef PDUMP
1420 void dump_add_root_block (const void *ptraddress, Bytecount size,
1421 const struct memory_description *desc);
1422 #else
1423 #define dump_add_root_block(ptraddress,desc) DO_NOTHING
1424 #endif
1425
1426 /* Call dump_add_opaque_int (&int_var) to dump `int_var', of type `int'. */
1427 #ifdef PDUMP
1428 #define dump_add_opaque_int(int_varaddr) do { \
1429 int *dao_ = (int_varaddr); /* type check */ \
1430 dump_add_opaque (dao_, sizeof (*dao_)); \
1431 } while (0)
1432 #else
1433 #define dump_add_opaque_int(int_varaddr) DO_NOTHING
1434 #endif
1435
1436 /* Call dump_add_opaque_fixnum (&fixnum_var) to dump `fixnum_var', of type
1437 `Fixnum'. */
1438 #ifdef PDUMP
1439 #define dump_add_opaque_fixnum(fixnum_varaddr) do { \
1440 Fixnum *dao_ = (fixnum_varaddr); /* type check */ \
1441 dump_add_opaque (dao_, sizeof (*dao_)); \
1442 } while (0)
1443 #else
1444 #define dump_add_opaque_fixnum(fixnum_varaddr) DO_NOTHING
1445 #endif
1446
1447 /* Call dump_add_root_lisp_object (&var) to ensure that var is properly
1448 updated after pdump. */
1449 #ifdef PDUMP
1450 void dump_add_root_lisp_object (Lisp_Object *);
1451 #else
1452 #define dump_add_root_lisp_object(varaddr) DO_NOTHING
1453 #endif
1454
1455 /* Call dump_add_weak_lisp_object (&var) to ensure that var is properly
1456 updated after pdump. var must point to a linked list of objects out of
1457 which some may not be dumped */
1458 #ifdef PDUMP
1459 void dump_add_weak_object_chain (Lisp_Object *);
1460 #else
1461 #define dump_add_weak_object_chain(varaddr) DO_NOTHING
1462 #endif
1463
1464 /* Nonzero means Emacs has already been initialized.
1465 Used during startup to detect startup of dumped Emacs. */
1466 extern int initialized;
1467
1468 #ifdef PDUMP
1469
1470 void pdump_objects_unmark (void);
1471 void pdump (void);
1472 int pdump_load (const char *argv0);
1473 void pdump_backtrace (void);
1474 extern unsigned int dump_id;
1475 extern char *pdump_start, *pdump_end;
1476
1477 #define DUMPEDP(adr) ((((char *)(adr)) < pdump_end) && (((char *)(adr)) >= pdump_start))
1478
1479 #else
1480 #define DUMPEDP(adr) 0
1481 #endif
1482
1483 /***********************************************************************/
1484 /* data descriptions */
1485 /***********************************************************************/
1486
1487
1488 #if defined (USE_KKCC) || defined (PDUMP)
1489
1490 extern int in_pdump;
1491
1492 EMACS_INT lispdesc_indirect_count_1 (EMACS_INT code,
1493 const struct memory_description *idesc,
1494 const void *idata);
1495 const struct sized_memory_description *lispdesc_indirect_description_1
1496 (const void *obj, const struct sized_memory_description *sdesc);
1497 Bytecount lispdesc_structure_size (const void *obj,
1498 const struct sized_memory_description *
1499 sdesc);
1500
1501 DECLARE_INLINE_HEADER (
1502 EMACS_INT
1503 lispdesc_indirect_count (EMACS_INT code,
1504 const struct memory_description *idesc,
1505 const void *idata)
1506 )
1507 {
1508 if (XD_IS_INDIRECT (code))
1509 code = lispdesc_indirect_count_1 (code, idesc, idata);
1510 return code;
1511 }
1512
1513 DECLARE_INLINE_HEADER (
1514 const struct sized_memory_description *
1515 lispdesc_indirect_description (const void *obj,
1516 const struct sized_memory_description *sdesc)
1517 )
1518 {
1519 if (sdesc->description)
1520 return sdesc;
1521 else
1522 return lispdesc_indirect_description_1 (obj, sdesc);
1523 }
1524
1525
1526 /* Do standard XD_UNION processing. DESC1 is an entry in DESC, which
1527 describes the entire data structure. Returns NULL (do nothing, nothing
1528 matched), or a new value for DESC1. In the latter case, assign to DESC1
1529 in your function and goto union_switcheroo. */
1530
1531 DECLARE_INLINE_HEADER (
1532 const struct memory_description *
1533 lispdesc_process_xd_union (const struct memory_description *desc1,
1534 const struct memory_description *desc,
1535 const void *data)
1536 )
1537 {
1538 int count = 0;
1539 EMACS_INT variant = lispdesc_indirect_count (desc1->data1, desc,
1540 data);
1541 desc1 =
1542 lispdesc_indirect_description (data, desc1->data2)->description;
1543
1544 for (count = 0; desc1[count].type != XD_END; count++)
1545 {
1546 if ((desc1[count].flags & XD_FLAG_UNION_DEFAULT_ENTRY) ||
1547 desc1[count].offset == variant)
1548 {
1549 return &desc1[count];
1550 }
1551 }
1552
1553 return NULL;
1554 }
1555
1556 #endif /* defined (USE_KKCC) || defined (PDUMP) */
1087 1557
1088 #endif /* INCLUDED_lrecord_h_ */ 1558 #endif /* INCLUDED_lrecord_h_ */