From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.org!.POSTED!not-for-mail From: Paul Eggert Newsgroups: gmane.emacs.bugs Subject: bug#32405: [PATCH] Turn misc objects into pseudovectors Date: Wed, 8 Aug 2018 19:58:52 -0700 Message-ID: <20180809025852.28874-1-eggert@cs.ucla.edu> NNTP-Posting-Host: blaine.gmane.org X-Trace: blaine.gmane.org 1533783504 15958 195.159.176.226 (9 Aug 2018 02:58:24 GMT) X-Complaints-To: usenet@blaine.gmane.org NNTP-Posting-Date: Thu, 9 Aug 2018 02:58:24 +0000 (UTC) Cc: Paul Eggert To: 32405@debbugs.gnu.org Original-X-From: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane.org@gnu.org Thu Aug 09 04:58:20 2018 Return-path: Envelope-to: geb-bug-gnu-emacs@m.gmane.org Original-Received: from lists.gnu.org ([208.118.235.17]) by blaine.gmane.org with esmtp (Exim 4.84_2) (envelope-from ) id 1fnb9V-0003wu-KH for geb-bug-gnu-emacs@m.gmane.org; Thu, 09 Aug 2018 04:58:18 +0200 Original-Received: from localhost ([::1]:46291 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fnbBa-0003EA-Fn for geb-bug-gnu-emacs@m.gmane.org; Wed, 08 Aug 2018 23:00:26 -0400 Original-Received: from eggs.gnu.org ([2001:4830:134:3::10]:56090) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fnbBK-0003DX-Mt for bug-gnu-emacs@gnu.org; Wed, 08 Aug 2018 23:00:18 -0400 Original-Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1fnbBD-0000Io-DL for bug-gnu-emacs@gnu.org; Wed, 08 Aug 2018 23:00:10 -0400 Original-Received: from debbugs.gnu.org ([208.118.235.43]:40390) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1fnbBD-0000Ia-7e for bug-gnu-emacs@gnu.org; Wed, 08 Aug 2018 23:00:03 -0400 Original-Received: from Debian-debbugs by debbugs.gnu.org with local (Exim 4.84_2) (envelope-from ) id 1fnbBC-0002Of-Vh for bug-gnu-emacs@gnu.org; Wed, 08 Aug 2018 23:00:03 -0400 X-Loop: help-debbugs@gnu.org Resent-From: Paul Eggert Original-Sender: "Debbugs-submit" Resent-CC: bug-gnu-emacs@gnu.org Resent-Date: Thu, 09 Aug 2018 03:00:02 +0000 Resent-Message-ID: Resent-Sender: help-debbugs@gnu.org X-GNU-PR-Message: report 32405 X-GNU-PR-Package: emacs X-GNU-PR-Keywords: patch X-Debbugs-Original-To: bug-gnu-emacs@gnu.org Original-Received: via spool by submit@debbugs.gnu.org id=B.15337835799148 (code B ref -1); Thu, 09 Aug 2018 03:00:02 +0000 Original-Received: (at submit) by debbugs.gnu.org; 9 Aug 2018 02:59:39 +0000 Original-Received: from localhost ([127.0.0.1]:45408 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1fnbAm-0002NS-K3 for submit@debbugs.gnu.org; Wed, 08 Aug 2018 22:59:38 -0400 Original-Received: from eggs.gnu.org ([208.118.235.92]:36750) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1fnbAj-0002ND-CH for submit@debbugs.gnu.org; Wed, 08 Aug 2018 22:59:35 -0400 Original-Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1fnbAW-0008LA-N3 for submit@debbugs.gnu.org; Wed, 08 Aug 2018 22:59:28 -0400 Original-Received: from lists.gnu.org ([2001:4830:134:3::11]:38808) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1fnbAW-0008Kz-Hk for submit@debbugs.gnu.org; Wed, 08 Aug 2018 22:59:20 -0400 Original-Received: from eggs.gnu.org ([2001:4830:134:3::10]:55917) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fnbAP-0002aI-Ak for bug-gnu-emacs@gnu.org; Wed, 08 Aug 2018 22:59:20 -0400 Original-Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1fnbAI-0008BF-JE for bug-gnu-emacs@gnu.org; Wed, 08 Aug 2018 22:59:13 -0400 Original-Received: from zimbra.cs.ucla.edu ([131.179.128.68]:35114) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1fnbAH-00089f-UN for bug-gnu-emacs@gnu.org; Wed, 08 Aug 2018 22:59:06 -0400 Original-Received: from localhost (localhost [127.0.0.1]) by zimbra.cs.ucla.edu (Postfix) with ESMTP id 79AB51610C6 for ; Wed, 8 Aug 2018 19:59:03 -0700 (PDT) Original-Received: from zimbra.cs.ucla.edu ([127.0.0.1]) by localhost (zimbra.cs.ucla.edu [127.0.0.1]) (amavisd-new, port 10032) with ESMTP id jlr4l3XUsWy8; Wed, 8 Aug 2018 19:58:58 -0700 (PDT) Original-Received: from localhost (localhost [127.0.0.1]) by zimbra.cs.ucla.edu (Postfix) with ESMTP id 41D6D1610A0; Wed, 8 Aug 2018 19:58:58 -0700 (PDT) X-Virus-Scanned: amavisd-new at zimbra.cs.ucla.edu Original-Received: from zimbra.cs.ucla.edu ([127.0.0.1]) by localhost (zimbra.cs.ucla.edu [127.0.0.1]) (amavisd-new, port 10026) with ESMTP id nd7cH_CI7jds; Wed, 8 Aug 2018 19:58:58 -0700 (PDT) Original-Received: from Penguin.CS.UCLA.EDU (Penguin.CS.UCLA.EDU [131.179.64.200]) by zimbra.cs.ucla.edu (Postfix) with ESMTPSA id 02FB4161050; Wed, 8 Aug 2018 19:58:58 -0700 (PDT) X-Mailer: git-send-email 2.17.1 X-detected-operating-system: by eggs.gnu.org: GNU/Linux 3.x [fuzzy] X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.6.x X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] X-Received-From: 208.118.235.43 X-BeenThere: bug-gnu-emacs@gnu.org List-Id: "Bug reports for GNU Emacs, the Swiss army knife of text editors" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane.org@gnu.org Original-Sender: "bug-gnu-emacs" Xref: news.gmane.org gmane.emacs.bugs:149368 Archived-At: Eliminate the category of miscellaneous objects, and turn all such objects into pseudovectors. The immediate motivation for this change is to free up an enum Lisp_Type tag value, a scarce resource that can be better used elsewhere. However, this change is worthwhile in its own right, as it improves performance slightly on my platform, 0.3% faster for 'make compile-always' on Fedora 28, and it simplifies the garbage collector and interpreter. * doc/lispref/internals.texi (Garbage Collection): * etc/NEWS: Document change to garbage-collect return value. * src/alloc.c (total_markers, total_free_markers): (union aligned_Lisp_Misc, MARKER_BLOCK_SIZE) (struct marker_block, marker_block, marker_block_index) (misc_free_list, allocate_misc, live_misc_holding) (live_misc_p, sweep_misc): * src/lisp.h (lisp_h_MARKERP, lisp_h_MISCP, MARKERP, MISCP) (Lisp_Misc, enum Lisp_Misc_Type, Lisp_Misc_Free) (Lisp_Misc_Marker, Lisp_Misc_Overlay, Lisp_Misc_Finalizer) (Lisp_Misc_Ptr, Lisp_Misc_User_Ptr, Lisp_Misc_Limit) (XSETMISC, struct Lisp_Misc_Any, XMISCANY, XMISCTYPE) (struct Lisp_Free, union Lisp_Misc, XMISC): Remove. All uses removed. (cleanup_vector): Clean up objects that were formerly misc and are now pseudovectors. (make_misc_ptr, build_overlay, Fmake_marker, build_marker) (make_user_ptr, Fmake_finalizer): Build as pseudovectors, not as misc objects. (mark_finalizer_list, queue_doomed_finalizers) (compact_undo_list, mark_overlay, mark_object) (unchain_dead_markers): Mark as vector-like objects, not as misc objects. (mark_maybe_object, mark_maybe_pointer, valid_lisp_object_p) (total_bytes_of_live_objects, survives_gc_p): * src/fns.c (sxhash): No need to worry about misc objects. (garbage_collect_1): Do not generate a 'misc' component. (syms_of_alloc): No need for 'misc' symbol. * src/buffer.c (overlays_at, overlays_in, overlay_touches_p) (overlay_strings, recenter_overlay_lists) (fix_start_end_in_overlays, fix_overlays_before) (Foverlay_lists, report_overlay_modification) (evaporate_overlays): * src/editfns.c (overlays_around): * src/data.c (Ftype_of): * src/fns.c (internal_equal): * src/lisp.h (mint_ptrp, xmint_pointer, FINALIZERP) (XFINALIZER, MARKERP, XMARKER, OVERLAYP, XOVERLAY, USER_PTRP) (XUSER_PTR): * src/print.c (print_vectorlike, print_object): * src/undo.c (record_marker_adjustments): * src/xdisp.c (load_overlay_strings): Formerly misc objects are now pseudovectors. * src/lisp.h (PVEC_MARKER, PVEC_OVERLAY, PVEC_FINALIZER) (PVEC_MISC_PTR, PVEC_USER_PTR): New constants, replacing their misc versions. All uses changed. (struct Lisp_Marker, struct Lisp_Overlay, struct Lisp_Misc_Ptr) (struct Lisp_User_Ptr, struct Lisp_Finalizer): Make usable as a pseudovector by using a pseudovector header, replacing any DIY components, and putting Lisp_Object members first. All uses changed. --- doc/lispref/internals.texi | 11 +- etc/NEWS | 4 + src/alloc.c | 349 ++++++++----------------------------- src/buffer.c | 250 ++++++++++++-------------- src/data.c | 24 +-- src/editfns.c | 31 ++-- src/fns.c | 44 ++--- src/lisp.h | 195 +++++---------------- src/print.c | 147 +++++++--------- src/undo.c | 14 +- src/xdisp.c | 45 +++-- 11 files changed, 360 insertions(+), 754 deletions(-) diff --git a/doc/lispref/internals.texi b/doc/lispref/internals.texi index 65752860bf..1dc5de0a69 100644 --- a/doc/lispref/internals.texi +++ b/doc/lispref/internals.texi @@ -318,7 +318,6 @@ Garbage Collection @example ((@code{conses} @var{cons-size} @var{used-conses} @var{free-conses}) (@code{symbols} @var{symbol-size} @var{used-symbols} @var{free-symbols}) - (@code{miscs} @var{misc-size} @var{used-miscs} @var{free-miscs}) (@code{strings} @var{string-size} @var{used-strings} @var{free-strings}) (@code{string-bytes} @var{byte-size} @var{used-bytes}) (@code{vectors} @var{vector-size} @var{used-vectors}) @@ -334,7 +333,7 @@ Garbage Collection @example (garbage-collect) @result{} ((conses 16 49126 8058) (symbols 48 14607 0) - (miscs 40 34 56) (strings 32 2942 2607) + (strings 32 2942 2607) (string-bytes 1 78607) (vectors 16 7247) (vector-slots 8 341609 29474) (floats 8 71 102) (intervals 56 27 26) (buffers 944 8) @@ -371,14 +370,6 @@ Garbage Collection @code{sizeof (union Lisp_Misc)}, which is a size of the largest type enumerated in @code{enum Lisp_Misc_Type}. -@item used-miscs -The number of miscellaneous objects in use. These include markers -and overlays, plus certain objects not visible to users. - -@item free-miscs -The number of miscellaneous objects for which space has been obtained -from the operating system, but that are not currently being used. - @item string-size Internal size of a string header, i.e., @code{sizeof (struct Lisp_String)}. diff --git a/etc/NEWS b/etc/NEWS index 21887f5bfd..54dcc7e873 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -811,6 +811,10 @@ is backwards-compatible with versions of Emacs in which the old function exists. See the node "Displaying Buffers in Side Windows" in the ELisp manual for more details. +** The 'garbage-collect' function no longer returns a 'misc' component +because garbage collection no longer treats miscellaneous objects +specially; they are now allocated like any other pseudovector. + * Lisp Changes in Emacs 27.1 diff --git a/src/alloc.c b/src/alloc.c index e4b54aba86..dcf11825bc 100644 --- a/src/alloc.c +++ b/src/alloc.c @@ -247,8 +247,8 @@ bool gc_in_progress; /* Number of live and free conses etc. */ -static EMACS_INT total_conses, total_markers, total_symbols, total_buffers; -static EMACS_INT total_free_conses, total_free_markers, total_free_symbols; +static EMACS_INT total_conses, total_symbols, total_buffers; +static EMACS_INT total_free_conses, total_free_symbols; static EMACS_INT total_free_floats, total_floats; /* Points to memory space allocated as "spare", to be freed if we run @@ -356,6 +356,7 @@ no_sanitize_memcpy (void *dest, void const *src, size_t size) #endif /* MAX_SAVE_STACK > 0 */ +static void unchain_finalizer (struct Lisp_Finalizer *); static void mark_terminals (void); static void gc_sweep (void); static Lisp_Object make_pure_vector (ptrdiff_t); @@ -3197,7 +3198,10 @@ static void cleanup_vector (struct Lisp_Vector *vector) { detect_suspicious_free (vector); - if (PSEUDOVECTOR_TYPEP (&vector->header, PVEC_FONT)) + + if (PSEUDOVECTOR_TYPEP (&vector->header, PVEC_FINALIZER)) + unchain_finalizer (PSEUDOVEC_STRUCT (vector, Lisp_Finalizer)); + else if (PSEUDOVECTOR_TYPEP (&vector->header, PVEC_FONT)) { if ((vector->header.size & PSEUDOVECTOR_SIZE_MASK) == FONT_OBJECT_MAX) { @@ -3220,6 +3224,19 @@ cleanup_vector (struct Lisp_Vector *vector) finalize_one_mutex (PSEUDOVEC_STRUCT (vector, Lisp_Mutex)); else if (PSEUDOVECTOR_TYPEP (&vector->header, PVEC_CONDVAR)) finalize_one_condvar (PSEUDOVEC_STRUCT (vector, Lisp_CondVar)); + else if (PSEUDOVECTOR_TYPEP (&vector->header, PVEC_MARKER)) + { + /* sweep_buffer should already have unchained this from its buffer. */ + eassert (! PSEUDOVEC_STRUCT (vector, Lisp_Marker)->buffer); + } +#ifdef HAVE_MODULES + else if (PSEUDOVECTOR_TYPEP (&vector->header, PVEC_USER_PTR)) + { + struct Lisp_User_Ptr *uptr = PSEUDOVEC_STRUCT (vector, Lisp_User_Ptr); + if (uptr->finalizer) + uptr->finalizer (uptr->p); + } +#endif } /* Reclaim space used by unmarked vectors. */ @@ -3650,96 +3667,27 @@ Its value is void, and its function definition and property list are nil. */) -/*********************************************************************** - Marker (Misc) Allocation - ***********************************************************************/ - -/* Like union Lisp_Misc, but padded so that its size is a multiple of - the required alignment. */ - -union aligned_Lisp_Misc -{ - union Lisp_Misc m; - unsigned char c[(sizeof (union Lisp_Misc) + LISP_ALIGNMENT - 1) - & -LISP_ALIGNMENT]; -}; - -/* Allocation of markers and other objects that share that structure. - Works like allocation of conses. */ - -#define MARKER_BLOCK_SIZE \ - ((1020 - sizeof (struct marker_block *)) / sizeof (union aligned_Lisp_Misc)) - -struct marker_block -{ - /* Place `markers' first, to preserve alignment. */ - union aligned_Lisp_Misc markers[MARKER_BLOCK_SIZE]; - struct marker_block *next; -}; - -static struct marker_block *marker_block; -static int marker_block_index = MARKER_BLOCK_SIZE; - -static union Lisp_Misc *misc_free_list; - -/* Return a newly allocated Lisp_Misc object of specified TYPE. */ - -static Lisp_Object -allocate_misc (enum Lisp_Misc_Type type) -{ - Lisp_Object val; - - MALLOC_BLOCK_INPUT; - - if (misc_free_list) - { - XSETMISC (val, misc_free_list); - misc_free_list = misc_free_list->u_free.chain; - } - else - { - if (marker_block_index == MARKER_BLOCK_SIZE) - { - struct marker_block *new = lisp_malloc (sizeof *new, MEM_TYPE_MISC); - new->next = marker_block; - marker_block = new; - marker_block_index = 0; - total_free_markers += MARKER_BLOCK_SIZE; - } - XSETMISC (val, &marker_block->markers[marker_block_index].m); - marker_block_index++; - } - - MALLOC_UNBLOCK_INPUT; - - --total_free_markers; - consing_since_gc += sizeof (union Lisp_Misc); - misc_objects_consed++; - XMISCANY (val)->type = type; - XMISCANY (val)->gcmarkbit = 0; - return val; -} - Lisp_Object make_misc_ptr (void *a) { - Lisp_Object val = allocate_misc (Lisp_Misc_Ptr); - XUNTAG (val, Lisp_Misc, struct Lisp_Misc_Ptr)->pointer = a; - return val; + struct Lisp_Misc_Ptr *p = ALLOCATE_PSEUDOVECTOR (struct Lisp_Misc_Ptr, pointer, + PVEC_MISC_PTR); + p->pointer = a; + return make_lisp_ptr (p, Lisp_Vectorlike); } -/* Return a Lisp_Misc_Overlay object with specified START, END and PLIST. */ +/* Return a new overlay with specified START, END and PLIST. */ Lisp_Object build_overlay (Lisp_Object start, Lisp_Object end, Lisp_Object plist) { - register Lisp_Object overlay; - - overlay = allocate_misc (Lisp_Misc_Overlay); + struct Lisp_Overlay *p = ALLOCATE_PSEUDOVECTOR (struct Lisp_Overlay, next, + PVEC_OVERLAY); + Lisp_Object overlay = make_lisp_ptr (p, Lisp_Vectorlike); OVERLAY_START (overlay) = start; OVERLAY_END (overlay) = end; set_overlay_plist (overlay, plist); - XOVERLAY (overlay)->next = NULL; + p->next = NULL; return overlay; } @@ -3747,18 +3695,15 @@ DEFUN ("make-marker", Fmake_marker, Smake_marker, 0, 0, 0, doc: /* Return a newly allocated marker which does not point at any place. */) (void) { - register Lisp_Object val; - register struct Lisp_Marker *p; - - val = allocate_misc (Lisp_Misc_Marker); - p = XMARKER (val); + struct Lisp_Marker *p = ALLOCATE_PSEUDOVECTOR (struct Lisp_Marker, buffer, + PVEC_MARKER); p->buffer = 0; p->bytepos = 0; p->charpos = 0; p->next = NULL; p->insertion_type = 0; p->need_adjustment = 0; - return val; + return make_lisp_ptr (p, Lisp_Vectorlike); } /* Return a newly allocated marker which points into BUF @@ -3767,17 +3712,14 @@ DEFUN ("make-marker", Fmake_marker, Smake_marker, 0, 0, 0, Lisp_Object build_marker (struct buffer *buf, ptrdiff_t charpos, ptrdiff_t bytepos) { - Lisp_Object obj; - struct Lisp_Marker *m; - /* No dead buffers here. */ eassert (BUFFER_LIVE_P (buf)); /* Every character is at least one byte. */ eassert (charpos <= bytepos); - obj = allocate_misc (Lisp_Misc_Marker); - m = XMARKER (obj); + struct Lisp_Marker *m = ALLOCATE_PSEUDOVECTOR (struct Lisp_Marker, buffer, + PVEC_MARKER); m->buffer = buf; m->charpos = charpos; m->bytepos = bytepos; @@ -3785,7 +3727,7 @@ build_marker (struct buffer *buf, ptrdiff_t charpos, ptrdiff_t bytepos) m->need_adjustment = 0; m->next = BUF_MARKERS (buf); BUF_MARKERS (buf) = m; - return obj; + return make_lisp_ptr (m, Lisp_Vectorlike); } @@ -3831,14 +3773,11 @@ make_event_array (ptrdiff_t nargs, Lisp_Object *args) Lisp_Object make_user_ptr (void (*finalizer) (void *), void *p) { - Lisp_Object obj; - struct Lisp_User_Ptr *uptr; - - obj = allocate_misc (Lisp_Misc_User_Ptr); - uptr = XUSER_PTR (obj); + struct Lisp_User_Ptr *uptr = ALLOCATE_PSEUDOVECTOR (struct Lisp_User_Ptr, + finalizer, PVEC_USER_PTR); uptr->finalizer = finalizer; uptr->p = p; - return obj; + return make_lisp_ptr (uptr, Lisp_Vectorlike); } #endif @@ -3881,7 +3820,7 @@ mark_finalizer_list (struct Lisp_Finalizer *head) finalizer != head; finalizer = finalizer->next) { - finalizer->base.gcmarkbit = true; + VECTOR_MARK (finalizer); mark_object (finalizer->function); } } @@ -3898,7 +3837,7 @@ queue_doomed_finalizers (struct Lisp_Finalizer *dest, while (finalizer != src) { struct Lisp_Finalizer *next = finalizer->next; - if (!finalizer->base.gcmarkbit && !NILP (finalizer->function)) + if (!VECTOR_MARKED_P (finalizer) && !NILP (finalizer->function)) { unchain_finalizer (finalizer); finalizer_insert (dest, finalizer); @@ -3934,7 +3873,6 @@ run_finalizers (struct Lisp_Finalizer *finalizers) while (finalizers->next != finalizers) { finalizer = finalizers->next; - eassert (finalizer->base.type == Lisp_Misc_Finalizer); unchain_finalizer (finalizer); function = finalizer->function; if (!NILP (function)) @@ -3954,12 +3892,12 @@ count as reachable for the purpose of deciding whether to run FUNCTION. FUNCTION will be run once per finalizer object. */) (Lisp_Object function) { - Lisp_Object val = allocate_misc (Lisp_Misc_Finalizer); - struct Lisp_Finalizer *finalizer = XFINALIZER (val); + struct Lisp_Finalizer *finalizer + = ALLOCATE_PSEUDOVECTOR (struct Lisp_Finalizer, prev, PVEC_FINALIZER); finalizer->function = function; finalizer->prev = finalizer->next = NULL; finalizer_insert (&finalizers, finalizer); - return val; + return make_lisp_ptr (finalizer, Lisp_Vectorlike); } @@ -4580,41 +4518,6 @@ live_float_p (struct mem_node *m, void *p) return 0; } - -/* If P is a pointer to a live Lisp Misc on the heap, return the object. - Otherwise, return nil. M is a pointer to the mem_block for P. */ - -static Lisp_Object -live_misc_holding (struct mem_node *m, void *p) -{ - if (m->type == MEM_TYPE_MISC) - { - struct marker_block *b = m->start; - char *cp = p; - ptrdiff_t offset = cp - (char *) &b->markers[0]; - - /* P must point into a Lisp_Misc, not be - one of the unused cells in the current misc block, - and not be on the free-list. */ - if (0 <= offset && offset < MARKER_BLOCK_SIZE * sizeof b->markers[0] - && (b != marker_block - || offset / sizeof b->markers[0] < marker_block_index)) - { - cp = ptr_bounds_copy (cp, b); - union Lisp_Misc *s = p = cp -= offset % sizeof b->markers[0]; - if (s->u_any.type != Lisp_Misc_Free) - return make_lisp_ptr (s, Lisp_Misc); - } - } - return Qnil; -} - -static bool -live_misc_p (struct mem_node *m, void *p) -{ - return !NILP (live_misc_holding (m, p)); -} - /* If P is a pointer to a live vector-like object, return the object. Otherwise, return nil. M is a pointer to the mem_block for P. */ @@ -4733,10 +4636,6 @@ mark_maybe_object (Lisp_Object obj) || EQ (obj, live_buffer_holding (m, po))); break; - case Lisp_Misc: - mark_p = EQ (obj, live_misc_holding (m, po)); - break; - default: break; } @@ -4818,10 +4717,6 @@ mark_maybe_pointer (void *p) obj = live_string_holding (m, p); break; - case MEM_TYPE_MISC: - obj = live_misc_holding (m, p); - break; - case MEM_TYPE_SYMBOL: obj = live_symbol_holding (m, p); break; @@ -5222,9 +5117,6 @@ valid_lisp_object_p (Lisp_Object obj) case MEM_TYPE_STRING: return live_string_p (m, p); - case MEM_TYPE_MISC: - return live_misc_p (m, p); - case MEM_TYPE_SYMBOL: return live_symbol_p (m, p); @@ -5644,7 +5536,6 @@ total_bytes_of_live_objects (void) size_t tot = 0; tot += total_conses * sizeof (struct Lisp_Cons); tot += total_symbols * sizeof (struct Lisp_Symbol); - tot += total_markers * sizeof (union Lisp_Misc); tot += total_string_bytes; tot += total_vector_slots * word_size; tot += total_floats * sizeof (struct Lisp_Float); @@ -5765,7 +5656,7 @@ compact_undo_list (Lisp_Object list) { if (CONSP (XCAR (tail)) && MARKERP (XCAR (XCAR (tail))) - && !XMARKER (XCAR (XCAR (tail)))->gcmarkbit) + && !VECTOR_MARKED_P (XMARKER (XCAR (XCAR (tail))))) *prev = XCDR (tail); else prev = xcdr_addr (tail); @@ -5992,9 +5883,6 @@ garbage_collect_1 (void *end) list4 (Qsymbols, make_number (sizeof (struct Lisp_Symbol)), bounded_number (total_symbols), bounded_number (total_free_symbols)), - list4 (Qmiscs, make_number (sizeof (union Lisp_Misc)), - bounded_number (total_markers), - bounded_number (total_free_markers)), list4 (Qstrings, make_number (sizeof (struct Lisp_String)), bounded_number (total_strings), bounded_number (total_free_strings)), @@ -6181,12 +6069,12 @@ mark_compiled (struct Lisp_Vector *ptr) static void mark_overlay (struct Lisp_Overlay *ptr) { - for (; ptr && !ptr->gcmarkbit; ptr = ptr->next) + for (; ptr && !VECTOR_MARKED_P (ptr); ptr = ptr->next) { - ptr->gcmarkbit = 1; + VECTOR_MARK (ptr); /* These two are always markers and can be marked fast. */ - XMARKER (ptr->start)->gcmarkbit = 1; - XMARKER (ptr->end)->gcmarkbit = 1; + VECTOR_MARK (XMARKER (ptr->start)); + VECTOR_MARK (XMARKER (ptr->end)); mark_object (ptr->plist); } } @@ -6487,11 +6375,28 @@ mark_object (Lisp_Object arg) mark_char_table (ptr, (enum pvec_type) pvectype); break; + case PVEC_MARKER: + /* DO NOT mark thru the marker's chain. + The buffer's markers chain does not preserve markers from gc; + instead, markers are removed from the chain when freed by gc. */ case PVEC_BOOL_VECTOR: - /* No Lisp_Objects to mark in a bool vector. */ + case PVEC_MISC_PTR: +#ifdef HAVE_MODULES + case PVEC_USER_PTR: +#endif + /* No Lisp_Objects to mark in these. */ VECTOR_MARK (ptr); break; + case PVEC_OVERLAY: + mark_overlay (XOVERLAY (obj)); + break; + + case PVEC_FINALIZER: + VECTOR_MARK (ptr); + mark_object (XFINALIZER (obj)->function); + break; + case PVEC_SUBR: break; @@ -6547,48 +6452,9 @@ mark_object (Lisp_Object arg) } break; - case Lisp_Misc: - CHECK_ALLOCATED_AND_LIVE (live_misc_p); - - if (XMISCANY (obj)->gcmarkbit) - break; - - switch (XMISCTYPE (obj)) - { - case Lisp_Misc_Marker: - /* DO NOT mark thru the marker's chain. - The buffer's markers chain does not preserve markers from gc; - instead, markers are removed from the chain when freed by gc. */ - XMISCANY (obj)->gcmarkbit = 1; - break; - - case Lisp_Misc_Ptr: - XMISCANY (obj)->gcmarkbit = true; - break; - - case Lisp_Misc_Overlay: - mark_overlay (XOVERLAY (obj)); - break; - - case Lisp_Misc_Finalizer: - XMISCANY (obj)->gcmarkbit = true; - mark_object (XFINALIZER (obj)->function); - break; - -#ifdef HAVE_MODULES - case Lisp_Misc_User_Ptr: - XMISCANY (obj)->gcmarkbit = true; - break; -#endif - - default: - emacs_abort (); - } - break; - case Lisp_Cons: { - register struct Lisp_Cons *ptr = XCONS (obj); + struct Lisp_Cons *ptr = XCONS (obj); if (CONS_MARKED_P (ptr)) break; CHECK_ALLOCATED_AND_LIVE (live_cons_p); @@ -6665,10 +6531,6 @@ survives_gc_p (Lisp_Object obj) survives_p = XSYMBOL (obj)->u.s.gcmarkbit; break; - case Lisp_Misc: - survives_p = XMISCANY (obj)->gcmarkbit; - break; - case Lisp_String: survives_p = STRING_MARKED_P (XSTRING (obj)); break; @@ -6945,79 +6807,6 @@ sweep_symbols (void) total_free_symbols = num_free; } -NO_INLINE /* For better stack traces. */ -static void -sweep_misc (void) -{ - register struct marker_block *mblk; - struct marker_block **mprev = &marker_block; - register int lim = marker_block_index; - EMACS_INT num_free = 0, num_used = 0; - - /* Put all unmarked misc's on free list. For a marker, first - unchain it from the buffer it points into. */ - - misc_free_list = 0; - - for (mblk = marker_block; mblk; mblk = *mprev) - { - register int i; - int this_free = 0; - - for (i = 0; i < lim; i++) - { - if (!mblk->markers[i].m.u_any.gcmarkbit) - { - if (mblk->markers[i].m.u_any.type == Lisp_Misc_Marker) - /* Make sure markers have been unchained from their buffer - in sweep_buffer before we collect them. */ - eassert (!mblk->markers[i].m.u_marker.buffer); - else if (mblk->markers[i].m.u_any.type == Lisp_Misc_Finalizer) - unchain_finalizer (&mblk->markers[i].m.u_finalizer); -#ifdef HAVE_MODULES - else if (mblk->markers[i].m.u_any.type == Lisp_Misc_User_Ptr) - { - struct Lisp_User_Ptr *uptr = &mblk->markers[i].m.u_user_ptr; - if (uptr->finalizer) - uptr->finalizer (uptr->p); - } -#endif - /* Set the type of the freed object to Lisp_Misc_Free. - We could leave the type alone, since nobody checks it, - but this might catch bugs faster. */ - mblk->markers[i].m.u_marker.type = Lisp_Misc_Free; - mblk->markers[i].m.u_free.chain = misc_free_list; - misc_free_list = &mblk->markers[i].m; - this_free++; - } - else - { - num_used++; - mblk->markers[i].m.u_any.gcmarkbit = 0; - } - } - lim = MARKER_BLOCK_SIZE; - /* If this block contains only free markers and we have already - seen more than two blocks worth of free markers then deallocate - this block. */ - if (this_free == MARKER_BLOCK_SIZE && num_free > MARKER_BLOCK_SIZE) - { - *mprev = mblk->next; - /* Unhook from the free list. */ - misc_free_list = mblk->markers[0].m.u_free.chain; - lisp_free (mblk); - } - else - { - num_free += this_free; - mprev = &mblk->next; - } - } - - total_markers = num_used; - total_free_markers = num_free; -} - /* Remove BUFFER's markers that are due to be swept. This is needed since we treat BUF_MARKERS and markers's `next' field as weak pointers. */ static void @@ -7026,7 +6815,7 @@ unchain_dead_markers (struct buffer *buffer) struct Lisp_Marker *this, **prev = &BUF_MARKERS (buffer); while ((this = *prev)) - if (this->gcmarkbit) + if (VECTOR_MARKED_P (this)) prev = &this->next; else { @@ -7074,7 +6863,6 @@ gc_sweep (void) sweep_intervals (); sweep_symbols (); sweep_buffers (); - sweep_misc (); sweep_vectors (); check_string_bytes (!noninteractive); } @@ -7449,7 +7237,6 @@ do hash-consing of the objects allocated to pure space. */); DEFSYM (Qconses, "conses"); DEFSYM (Qsymbols, "symbols"); - DEFSYM (Qmiscs, "miscs"); DEFSYM (Qstrings, "strings"); DEFSYM (Qvectors, "vectors"); DEFSYM (Qfloats, "floats"); diff --git a/src/buffer.c b/src/buffer.c index 244c1851fa..bfbb5eaba6 100644 --- a/src/buffer.c +++ b/src/buffer.c @@ -2789,8 +2789,6 @@ overlays_at (EMACS_INT pos, bool extend, Lisp_Object **vec_ptr, ptrdiff_t *len_ptr, ptrdiff_t *next_ptr, ptrdiff_t *prev_ptr, bool change_req) { - Lisp_Object overlay, start, end; - struct Lisp_Overlay *tail; ptrdiff_t idx = 0; ptrdiff_t len = *len_ptr; Lisp_Object *vec = *vec_ptr; @@ -2798,22 +2796,20 @@ overlays_at (EMACS_INT pos, bool extend, Lisp_Object **vec_ptr, ptrdiff_t prev = BEGV; bool inhibit_storing = 0; - for (tail = current_buffer->overlays_before; tail; tail = tail->next) + for (struct Lisp_Overlay *tail = current_buffer->overlays_before; + tail; tail = tail->next) { - ptrdiff_t startpos, endpos; - - XSETMISC (overlay, tail); - - start = OVERLAY_START (overlay); - end = OVERLAY_END (overlay); - endpos = OVERLAY_POSITION (end); + Lisp_Object overlay = make_lisp_ptr (tail, Lisp_Vectorlike); + Lisp_Object start = OVERLAY_START (overlay); + Lisp_Object end = OVERLAY_END (overlay); + ptrdiff_t endpos = OVERLAY_POSITION (end); if (endpos < pos) { if (prev < endpos) prev = endpos; break; } - startpos = OVERLAY_POSITION (start); + ptrdiff_t startpos = OVERLAY_POSITION (start); /* This one ends at or after POS so its start counts for PREV_PTR if it's before POS. */ if (prev < startpos && startpos < pos) @@ -2846,22 +2842,20 @@ overlays_at (EMACS_INT pos, bool extend, Lisp_Object **vec_ptr, next = startpos; } - for (tail = current_buffer->overlays_after; tail; tail = tail->next) + for (struct Lisp_Overlay *tail = current_buffer->overlays_after; + tail; tail = tail->next) { - ptrdiff_t startpos, endpos; - - XSETMISC (overlay, tail); - - start = OVERLAY_START (overlay); - end = OVERLAY_END (overlay); - startpos = OVERLAY_POSITION (start); + Lisp_Object overlay = make_lisp_ptr (tail, Lisp_Vectorlike); + Lisp_Object start = OVERLAY_START (overlay); + Lisp_Object end = OVERLAY_END (overlay); + ptrdiff_t startpos = OVERLAY_POSITION (start); if (pos < startpos) { if (startpos < next) next = startpos; break; } - endpos = OVERLAY_POSITION (end); + ptrdiff_t endpos = OVERLAY_POSITION (end); if (pos < endpos) { if (idx == len) @@ -2923,8 +2917,6 @@ overlays_in (EMACS_INT beg, EMACS_INT end, bool extend, Lisp_Object **vec_ptr, ptrdiff_t *len_ptr, ptrdiff_t *next_ptr, ptrdiff_t *prev_ptr) { - Lisp_Object overlay, ostart, oend; - struct Lisp_Overlay *tail; ptrdiff_t idx = 0; ptrdiff_t len = *len_ptr; Lisp_Object *vec = *vec_ptr; @@ -2933,22 +2925,20 @@ overlays_in (EMACS_INT beg, EMACS_INT end, bool extend, bool inhibit_storing = 0; bool end_is_Z = end == Z; - for (tail = current_buffer->overlays_before; tail; tail = tail->next) + for (struct Lisp_Overlay *tail = current_buffer->overlays_before; + tail; tail = tail->next) { - ptrdiff_t startpos, endpos; - - XSETMISC (overlay, tail); - - ostart = OVERLAY_START (overlay); - oend = OVERLAY_END (overlay); - endpos = OVERLAY_POSITION (oend); + Lisp_Object overlay = make_lisp_ptr (tail, Lisp_Vectorlike); + Lisp_Object ostart = OVERLAY_START (overlay); + Lisp_Object oend = OVERLAY_END (overlay); + ptrdiff_t endpos = OVERLAY_POSITION (oend); if (endpos < beg) { if (prev < endpos) prev = endpos; break; } - startpos = OVERLAY_POSITION (ostart); + ptrdiff_t startpos = OVERLAY_POSITION (ostart); /* Count an interval if it overlaps the range, is empty at the start of the range, or is empty at END provided END denotes the end of the buffer. */ @@ -2980,22 +2970,20 @@ overlays_in (EMACS_INT beg, EMACS_INT end, bool extend, next = startpos; } - for (tail = current_buffer->overlays_after; tail; tail = tail->next) + for (struct Lisp_Overlay *tail = current_buffer->overlays_after; + tail; tail = tail->next) { - ptrdiff_t startpos, endpos; - - XSETMISC (overlay, tail); - - ostart = OVERLAY_START (overlay); - oend = OVERLAY_END (overlay); - startpos = OVERLAY_POSITION (ostart); + Lisp_Object overlay = make_lisp_ptr (tail, Lisp_Vectorlike); + Lisp_Object ostart = OVERLAY_START (overlay); + Lisp_Object oend = OVERLAY_END (overlay); + ptrdiff_t startpos = OVERLAY_POSITION (ostart); if (end < startpos) { if (startpos < next) next = startpos; break; } - endpos = OVERLAY_POSITION (oend); + ptrdiff_t endpos = OVERLAY_POSITION (oend); /* Count an interval if it overlaps the range, is empty at the start of the range, or is empty at END provided END denotes the end of the buffer. */ @@ -3097,31 +3085,26 @@ disable_line_numbers_overlay_at_eob (void) bool overlay_touches_p (ptrdiff_t pos) { - Lisp_Object overlay; - struct Lisp_Overlay *tail; - - for (tail = current_buffer->overlays_before; tail; tail = tail->next) + for (struct Lisp_Overlay *tail = current_buffer->overlays_before; + tail; tail = tail->next) { - ptrdiff_t endpos; - - XSETMISC (overlay ,tail); + Lisp_Object overlay = make_lisp_ptr (tail, Lisp_Vectorlike); eassert (OVERLAYP (overlay)); - endpos = OVERLAY_POSITION (OVERLAY_END (overlay)); + ptrdiff_t endpos = OVERLAY_POSITION (OVERLAY_END (overlay)); if (endpos < pos) break; if (endpos == pos || OVERLAY_POSITION (OVERLAY_START (overlay)) == pos) return 1; } - for (tail = current_buffer->overlays_after; tail; tail = tail->next) + for (struct Lisp_Overlay *tail = current_buffer->overlays_after; + tail; tail = tail->next) { - ptrdiff_t startpos; - - XSETMISC (overlay, tail); + Lisp_Object overlay = make_lisp_ptr (tail, Lisp_Vectorlike); eassert (OVERLAYP (overlay)); - startpos = OVERLAY_POSITION (OVERLAY_START (overlay)); + ptrdiff_t startpos = OVERLAY_POSITION (OVERLAY_START (overlay)); if (pos < startpos) break; if (startpos == pos || OVERLAY_POSITION (OVERLAY_END (overlay)) == pos) @@ -3337,27 +3320,26 @@ record_overlay_string (struct sortstrlist *ssl, Lisp_Object str, ptrdiff_t overlay_strings (ptrdiff_t pos, struct window *w, unsigned char **pstr) { - Lisp_Object overlay, window, str; - struct Lisp_Overlay *ov; - ptrdiff_t startpos, endpos; bool multibyte = ! NILP (BVAR (current_buffer, enable_multibyte_characters)); overlay_heads.used = overlay_heads.bytes = 0; overlay_tails.used = overlay_tails.bytes = 0; - for (ov = current_buffer->overlays_before; ov; ov = ov->next) + for (struct Lisp_Overlay *ov = current_buffer->overlays_before; + ov; ov = ov->next) { - XSETMISC (overlay, ov); + Lisp_Object overlay = make_lisp_ptr (ov, Lisp_Vectorlike); eassert (OVERLAYP (overlay)); - startpos = OVERLAY_POSITION (OVERLAY_START (overlay)); - endpos = OVERLAY_POSITION (OVERLAY_END (overlay)); + ptrdiff_t startpos = OVERLAY_POSITION (OVERLAY_START (overlay)); + ptrdiff_t endpos = OVERLAY_POSITION (OVERLAY_END (overlay)); if (endpos < pos) break; if (endpos != pos && startpos != pos) continue; - window = Foverlay_get (overlay, Qwindow); + Lisp_Object window = Foverlay_get (overlay, Qwindow); if (WINDOWP (window) && XWINDOW (window) != w) continue; + Lisp_Object str; if (startpos == pos && (str = Foverlay_get (overlay, Qbefore_string), STRINGP (str))) record_overlay_string (&overlay_heads, str, @@ -3372,20 +3354,22 @@ overlay_strings (ptrdiff_t pos, struct window *w, unsigned char **pstr) Foverlay_get (overlay, Qpriority), endpos - startpos); } - for (ov = current_buffer->overlays_after; ov; ov = ov->next) + for (struct Lisp_Overlay *ov = current_buffer->overlays_after; + ov; ov = ov->next) { - XSETMISC (overlay, ov); + Lisp_Object overlay = make_lisp_ptr (ov, Lisp_Vectorlike); eassert (OVERLAYP (overlay)); - startpos = OVERLAY_POSITION (OVERLAY_START (overlay)); - endpos = OVERLAY_POSITION (OVERLAY_END (overlay)); + ptrdiff_t startpos = OVERLAY_POSITION (OVERLAY_START (overlay)); + ptrdiff_t endpos = OVERLAY_POSITION (OVERLAY_END (overlay)); if (startpos > pos) break; if (endpos != pos && startpos != pos) continue; - window = Foverlay_get (overlay, Qwindow); + Lisp_Object window = Foverlay_get (overlay, Qwindow); if (WINDOWP (window) && XWINDOW (window) != w) continue; + Lisp_Object str; if (startpos == pos && (str = Foverlay_get (overlay, Qbefore_string), STRINGP (str))) record_overlay_string (&overlay_heads, str, @@ -3460,8 +3444,7 @@ overlay_strings (ptrdiff_t pos, struct window *w, unsigned char **pstr) void recenter_overlay_lists (struct buffer *buf, ptrdiff_t pos) { - Lisp_Object overlay, beg, end; - struct Lisp_Overlay *prev, *tail, *next; + struct Lisp_Overlay *prev, *next; /* See if anything in overlays_before should move to overlays_after. */ @@ -3469,14 +3452,15 @@ recenter_overlay_lists (struct buffer *buf, ptrdiff_t pos) But we use it for symmetry and in case that should cease to be true with some future change. */ prev = NULL; - for (tail = buf->overlays_before; tail; prev = tail, tail = next) + for (struct Lisp_Overlay *tail = buf->overlays_before; + tail; prev = tail, tail = next) { next = tail->next; - XSETMISC (overlay, tail); + Lisp_Object overlay = make_lisp_ptr (tail, Lisp_Vectorlike); eassert (OVERLAYP (overlay)); - beg = OVERLAY_START (overlay); - end = OVERLAY_END (overlay); + Lisp_Object beg = OVERLAY_START (overlay); + Lisp_Object end = OVERLAY_END (overlay); if (OVERLAY_POSITION (end) > pos) { @@ -3495,12 +3479,10 @@ recenter_overlay_lists (struct buffer *buf, ptrdiff_t pos) for (other = buf->overlays_after; other; other_prev = other, other = other->next) { - Lisp_Object otherbeg, otheroverlay; - - XSETMISC (otheroverlay, other); + Lisp_Object otheroverlay = make_lisp_ptr (other, Lisp_Vectorlike); eassert (OVERLAYP (otheroverlay)); - otherbeg = OVERLAY_START (otheroverlay); + Lisp_Object otherbeg = OVERLAY_START (otheroverlay); if (OVERLAY_POSITION (otherbeg) >= where) break; } @@ -3522,14 +3504,15 @@ recenter_overlay_lists (struct buffer *buf, ptrdiff_t pos) /* See if anything in overlays_after should be in overlays_before. */ prev = NULL; - for (tail = buf->overlays_after; tail; prev = tail, tail = next) + for (struct Lisp_Overlay *tail = buf->overlays_after; + tail; prev = tail, tail = next) { next = tail->next; - XSETMISC (overlay, tail); + Lisp_Object overlay = make_lisp_ptr (tail, Lisp_Vectorlike); eassert (OVERLAYP (overlay)); - beg = OVERLAY_START (overlay); - end = OVERLAY_END (overlay); + Lisp_Object beg = OVERLAY_START (overlay); + Lisp_Object end = OVERLAY_END (overlay); /* Stop looking, when we know that nothing further can possibly end before POS. */ @@ -3553,12 +3536,10 @@ recenter_overlay_lists (struct buffer *buf, ptrdiff_t pos) for (other = buf->overlays_before; other; other_prev = other, other = other->next) { - Lisp_Object otherend, otheroverlay; - - XSETMISC (otheroverlay, other); + Lisp_Object otheroverlay = make_lisp_ptr (other, Lisp_Vectorlike); eassert (OVERLAYP (otheroverlay)); - otherend = OVERLAY_END (otheroverlay); + Lisp_Object otherend = OVERLAY_END (otheroverlay); if (OVERLAY_POSITION (otherend) <= where) break; } @@ -3613,7 +3594,6 @@ adjust_overlays_for_delete (ptrdiff_t pos, ptrdiff_t length) void fix_start_end_in_overlays (register ptrdiff_t start, register ptrdiff_t end) { - Lisp_Object overlay; struct Lisp_Overlay *before_list UNINIT; struct Lisp_Overlay *after_list UNINIT; /* These are either nil, indicating that before_list or after_list @@ -3623,8 +3603,7 @@ fix_start_end_in_overlays (register ptrdiff_t start, register ptrdiff_t end) /* 'Parent', likewise, indicates a cons cell or current_buffer->overlays_before or overlays_after, depending which loop we're in. */ - struct Lisp_Overlay *tail, *parent; - ptrdiff_t startpos, endpos; + struct Lisp_Overlay *parent; /* This algorithm shifts links around instead of consing and GCing. The loop invariant is that before_list (resp. after_list) is a @@ -3633,12 +3612,14 @@ fix_start_end_in_overlays (register ptrdiff_t start, register ptrdiff_t end) (after_list) if it is, is still uninitialized. So it's not a bug that before_list isn't initialized, although it may look strange. */ - for (parent = NULL, tail = current_buffer->overlays_before; tail;) + parent = NULL; + for (struct Lisp_Overlay *tail = current_buffer->overlays_before; + tail; tail = tail->next) { - XSETMISC (overlay, tail); + Lisp_Object overlay = make_lisp_ptr (tail, Lisp_Vectorlike); - endpos = OVERLAY_POSITION (OVERLAY_END (overlay)); - startpos = OVERLAY_POSITION (OVERLAY_START (overlay)); + ptrdiff_t endpos = OVERLAY_POSITION (OVERLAY_END (overlay)); + ptrdiff_t startpos = OVERLAY_POSITION (OVERLAY_START (overlay)); /* If the overlay is backwards, make it empty. */ if (endpos < startpos) @@ -3676,17 +3657,18 @@ fix_start_end_in_overlays (register ptrdiff_t start, register ptrdiff_t end) set_buffer_overlays_before (current_buffer, tail->next); else parent->next = tail->next; - tail = tail->next; } else - parent = tail, tail = parent->next; + parent = tail; } - for (parent = NULL, tail = current_buffer->overlays_after; tail;) + parent = NULL; + for (struct Lisp_Overlay *tail = current_buffer->overlays_after; + tail; tail = tail->next) { - XSETMISC (overlay, tail); + Lisp_Object overlay = make_lisp_ptr (tail, Lisp_Vectorlike); - startpos = OVERLAY_POSITION (OVERLAY_START (overlay)); - endpos = OVERLAY_POSITION (OVERLAY_END (overlay)); + ptrdiff_t startpos = OVERLAY_POSITION (OVERLAY_START (overlay)); + ptrdiff_t endpos = OVERLAY_POSITION (OVERLAY_END (overlay)); /* If the overlay is backwards, make it empty. */ if (endpos < startpos) @@ -3722,10 +3704,9 @@ fix_start_end_in_overlays (register ptrdiff_t start, register ptrdiff_t end) set_buffer_overlays_after (current_buffer, tail->next); else parent->next = tail->next; - tail = tail->next; } else - parent = tail, tail = parent->next; + parent = tail; } /* Splice the constructed (wrong) lists into the buffer's lists, @@ -3776,7 +3757,7 @@ fix_overlays_before (struct buffer *bp, ptrdiff_t prev, ptrdiff_t pos) overlay whose ending marker is after-insertion-marker if disorder exists). */ while (tail - && (XSETMISC (tem, tail), + && (tem = make_lisp_ptr (tail, Lisp_Vectorlike), (end = OVERLAY_POSITION (OVERLAY_END (tem))) >= pos)) { parent = tail; @@ -3801,7 +3782,7 @@ fix_overlays_before (struct buffer *bp, ptrdiff_t prev, ptrdiff_t pos) overlays are in correct order. */ while (tail) { - XSETMISC (tem, tail); + tem = make_lisp_ptr (tail, Lisp_Vectorlike); end = OVERLAY_POSITION (OVERLAY_END (tem)); if (end == pos) @@ -4308,19 +4289,14 @@ The lists you get are copies, so that changing them has no effect. However, the overlays you get are the real objects that the buffer uses. */) (void) { - struct Lisp_Overlay *ol; - Lisp_Object before = Qnil, after = Qnil, tmp; + Lisp_Object before = Qnil, after = Qnil; - for (ol = current_buffer->overlays_before; ol; ol = ol->next) - { - XSETMISC (tmp, ol); - before = Fcons (tmp, before); - } - for (ol = current_buffer->overlays_after; ol; ol = ol->next) - { - XSETMISC (tmp, ol); - after = Fcons (tmp, after); - } + for (struct Lisp_Overlay *ol = current_buffer->overlays_before; + ol; ol = ol->next) + before = Fcons (make_lisp_ptr (ol, Lisp_Vectorlike), before); + for (struct Lisp_Overlay *ol = current_buffer->overlays_after; + ol; ol = ol->next) + after = Fcons (make_lisp_ptr (ol, Lisp_Vectorlike), after); return Fcons (Fnreverse (before), Fnreverse (after)); } @@ -4439,14 +4415,9 @@ void report_overlay_modification (Lisp_Object start, Lisp_Object end, bool after, Lisp_Object arg1, Lisp_Object arg2, Lisp_Object arg3) { - Lisp_Object prop, overlay; - struct Lisp_Overlay *tail; /* True if this change is an insertion. */ bool insertion = (after ? XFASTINT (arg3) == 0 : EQ (start, end)); - overlay = Qnil; - tail = NULL; - /* We used to run the functions as soon as we found them and only register them in last_overlay_modification_hooks for the purpose of the `after' case. But running elisp code as we traverse the list of overlays is @@ -4460,12 +4431,13 @@ report_overlay_modification (Lisp_Object start, Lisp_Object end, bool after, /* We are being called before a change. Scan the overlays to find the functions to call. */ last_overlay_modification_hooks_used = 0; - for (tail = current_buffer->overlays_before; tail; tail = tail->next) + for (struct Lisp_Overlay *tail = current_buffer->overlays_before; + tail; tail = tail->next) { ptrdiff_t startpos, endpos; Lisp_Object ostart, oend; - XSETMISC (overlay, tail); + Lisp_Object overlay = make_lisp_ptr (tail, Lisp_Vectorlike); ostart = OVERLAY_START (overlay); oend = OVERLAY_END (overlay); @@ -4476,14 +4448,14 @@ report_overlay_modification (Lisp_Object start, Lisp_Object end, bool after, if (insertion && (XFASTINT (start) == startpos || XFASTINT (end) == startpos)) { - prop = Foverlay_get (overlay, Qinsert_in_front_hooks); + Lisp_Object prop = Foverlay_get (overlay, Qinsert_in_front_hooks); if (!NILP (prop)) add_overlay_mod_hooklist (prop, overlay); } if (insertion && (XFASTINT (start) == endpos || XFASTINT (end) == endpos)) { - prop = Foverlay_get (overlay, Qinsert_behind_hooks); + Lisp_Object prop = Foverlay_get (overlay, Qinsert_behind_hooks); if (!NILP (prop)) add_overlay_mod_hooklist (prop, overlay); } @@ -4491,18 +4463,19 @@ report_overlay_modification (Lisp_Object start, Lisp_Object end, bool after, for both insertion and deletion. */ if (XFASTINT (end) > startpos && XFASTINT (start) < endpos) { - prop = Foverlay_get (overlay, Qmodification_hooks); + Lisp_Object prop = Foverlay_get (overlay, Qmodification_hooks); if (!NILP (prop)) add_overlay_mod_hooklist (prop, overlay); } } - for (tail = current_buffer->overlays_after; tail; tail = tail->next) + for (struct Lisp_Overlay *tail = current_buffer->overlays_after; + tail; tail = tail->next) { ptrdiff_t startpos, endpos; Lisp_Object ostart, oend; - XSETMISC (overlay, tail); + Lisp_Object overlay = make_lisp_ptr (tail, Lisp_Vectorlike); ostart = OVERLAY_START (overlay); oend = OVERLAY_END (overlay); @@ -4513,14 +4486,14 @@ report_overlay_modification (Lisp_Object start, Lisp_Object end, bool after, if (insertion && (XFASTINT (start) == startpos || XFASTINT (end) == startpos)) { - prop = Foverlay_get (overlay, Qinsert_in_front_hooks); + Lisp_Object prop = Foverlay_get (overlay, Qinsert_in_front_hooks); if (!NILP (prop)) add_overlay_mod_hooklist (prop, overlay); } if (insertion && (XFASTINT (start) == endpos || XFASTINT (end) == endpos)) { - prop = Foverlay_get (overlay, Qinsert_behind_hooks); + Lisp_Object prop = Foverlay_get (overlay, Qinsert_behind_hooks); if (!NILP (prop)) add_overlay_mod_hooklist (prop, overlay); } @@ -4528,7 +4501,7 @@ report_overlay_modification (Lisp_Object start, Lisp_Object end, bool after, for both insertion and deletion. */ if (XFASTINT (end) > startpos && XFASTINT (start) < endpos) { - prop = Foverlay_get (overlay, Qmodification_hooks); + Lisp_Object prop = Foverlay_get (overlay, Qmodification_hooks); if (!NILP (prop)) add_overlay_mod_hooklist (prop, overlay); } @@ -4596,16 +4569,13 @@ call_overlay_mod_hooks (Lisp_Object list, Lisp_Object overlay, bool after, void evaporate_overlays (ptrdiff_t pos) { - Lisp_Object overlay, hit_list; - struct Lisp_Overlay *tail; - - hit_list = Qnil; + Lisp_Object hit_list = Qnil; if (pos <= current_buffer->overlay_center) - for (tail = current_buffer->overlays_before; tail; tail = tail->next) + for (struct Lisp_Overlay *tail = current_buffer->overlays_before; + tail; tail = tail->next) { - ptrdiff_t endpos; - XSETMISC (overlay, tail); - endpos = OVERLAY_POSITION (OVERLAY_END (overlay)); + Lisp_Object overlay = make_lisp_ptr (tail, Lisp_Vectorlike); + ptrdiff_t endpos = OVERLAY_POSITION (OVERLAY_END (overlay)); if (endpos < pos) break; if (endpos == pos && OVERLAY_POSITION (OVERLAY_START (overlay)) == pos @@ -4613,11 +4583,11 @@ evaporate_overlays (ptrdiff_t pos) hit_list = Fcons (overlay, hit_list); } else - for (tail = current_buffer->overlays_after; tail; tail = tail->next) + for (struct Lisp_Overlay *tail = current_buffer->overlays_after; + tail; tail = tail->next) { - ptrdiff_t startpos; - XSETMISC (overlay, tail); - startpos = OVERLAY_POSITION (OVERLAY_START (overlay)); + Lisp_Object overlay = make_lisp_ptr (tail, Lisp_Vectorlike); + ptrdiff_t startpos = OVERLAY_POSITION (OVERLAY_START (overlay)); if (startpos > pos) break; if (startpos == pos && OVERLAY_POSITION (OVERLAY_END (overlay)) == pos diff --git a/src/data.c b/src/data.c index aaccb67518..2cef50fe76 100644 --- a/src/data.c +++ b/src/data.c @@ -221,27 +221,16 @@ for example, (type-of 1) returns `integer'. */) case Lisp_Cons: return Qcons; - case Lisp_Misc: - switch (XMISCTYPE (object)) - { - case Lisp_Misc_Marker: - return Qmarker; - case Lisp_Misc_Overlay: - return Qoverlay; - case Lisp_Misc_Finalizer: - return Qfinalizer; -#ifdef HAVE_MODULES - case Lisp_Misc_User_Ptr: - return Quser_ptr; -#endif - default: - emacs_abort (); - } - case Lisp_Vectorlike: switch (PSEUDOVECTOR_TYPE (XVECTOR (object))) { case PVEC_NORMAL_VECTOR: return Qvector; + case PVEC_MARKER: return Qmarker; + case PVEC_OVERLAY: return Qoverlay; + case PVEC_FINALIZER: return Qfinalizer; +#ifdef HAVE_MODULES + case PVEC_USER_PTR: return Quser_ptr; +#endif case PVEC_WINDOW_CONFIGURATION: return Qwindow_configuration; case PVEC_PROCESS: return Qprocess; case PVEC_WINDOW: return Qwindow; @@ -277,6 +266,7 @@ for example, (type-of 1) returns `integer'. */) case PVEC_MODULE_FUNCTION: return Qmodule_function; /* "Impossible" cases. */ + case PVEC_MISC_PTR: case PVEC_XWIDGET: case PVEC_OTHER: case PVEC_XWIDGET_VIEW: diff --git a/src/editfns.c b/src/editfns.c index 0fbc5aad8c..f3e6adb002 100644 --- a/src/editfns.c +++ b/src/editfns.c @@ -484,21 +484,18 @@ If you set the marker not to point anywhere, the buffer will have no mark. */) static ptrdiff_t overlays_around (EMACS_INT pos, Lisp_Object *vec, ptrdiff_t len) { - Lisp_Object overlay, start, end; - struct Lisp_Overlay *tail; - ptrdiff_t startpos, endpos; ptrdiff_t idx = 0; - for (tail = current_buffer->overlays_before; tail; tail = tail->next) + for (struct Lisp_Overlay *tail = current_buffer->overlays_before; + tail; tail = tail->next) { - XSETMISC (overlay, tail); - - end = OVERLAY_END (overlay); - endpos = OVERLAY_POSITION (end); + Lisp_Object overlay = make_lisp_ptr (tail, Lisp_Vectorlike); + Lisp_Object end = OVERLAY_END (overlay); + ptrdiff_t endpos = OVERLAY_POSITION (end); if (endpos < pos) break; - start = OVERLAY_START (overlay); - startpos = OVERLAY_POSITION (start); + Lisp_Object start = OVERLAY_START (overlay); + ptrdiff_t startpos = OVERLAY_POSITION (start); if (startpos <= pos) { if (idx < len) @@ -508,16 +505,16 @@ overlays_around (EMACS_INT pos, Lisp_Object *vec, ptrdiff_t len) } } - for (tail = current_buffer->overlays_after; tail; tail = tail->next) + for (struct Lisp_Overlay *tail = current_buffer->overlays_after; + tail; tail = tail->next) { - XSETMISC (overlay, tail); - - start = OVERLAY_START (overlay); - startpos = OVERLAY_POSITION (start); + Lisp_Object overlay = make_lisp_ptr (tail, Lisp_Vectorlike); + Lisp_Object start = OVERLAY_START (overlay); + ptrdiff_t startpos = OVERLAY_POSITION (start); if (pos < startpos) break; - end = OVERLAY_END (overlay); - endpos = OVERLAY_POSITION (end); + Lisp_Object end = OVERLAY_END (overlay); + ptrdiff_t endpos = OVERLAY_POSITION (end); if (pos <= endpos) { if (idx < len) diff --git a/src/fns.c b/src/fns.c index 5247140ead..1e23a78c4b 100644 --- a/src/fns.c +++ b/src/fns.c @@ -2285,7 +2285,7 @@ internal_equal (Lisp_Object o1, Lisp_Object o2, enum equal_kind equal_kind, ht = CALLN (Fmake_hash_table, QCtest, Qeq); switch (XTYPE (o1)) { - case Lisp_Cons: case Lisp_Misc: case Lisp_Vectorlike: + case Lisp_Cons: case Lisp_Vectorlike: { struct Lisp_Hash_Table *h = XHASH_TABLE (ht); EMACS_UINT hash; @@ -2342,29 +2342,6 @@ internal_equal (Lisp_Object o1, Lisp_Object o2, enum equal_kind equal_kind, depth++; goto tail_recurse; - case Lisp_Misc: - if (XMISCTYPE (o1) != XMISCTYPE (o2)) - return false; - if (OVERLAYP (o1)) - { - if (!internal_equal (OVERLAY_START (o1), OVERLAY_START (o2), - equal_kind, depth + 1, ht) - || !internal_equal (OVERLAY_END (o1), OVERLAY_END (o2), - equal_kind, depth + 1, ht)) - return false; - o1 = XOVERLAY (o1)->plist; - o2 = XOVERLAY (o2)->plist; - depth++; - goto tail_recurse; - } - if (MARKERP (o1)) - { - return (XMARKER (o1)->buffer == XMARKER (o2)->buffer - && (XMARKER (o1)->buffer == 0 - || XMARKER (o1)->bytepos == XMARKER (o2)->bytepos)); - } - break; - case Lisp_Vectorlike: { register int i; @@ -2374,6 +2351,24 @@ internal_equal (Lisp_Object o1, Lisp_Object o2, enum equal_kind equal_kind, same size. */ if (ASIZE (o2) != size) return false; + if (OVERLAYP (o1)) + { + if (!internal_equal (OVERLAY_START (o1), OVERLAY_START (o2), + equal_kind, depth + 1, ht) + || !internal_equal (OVERLAY_END (o1), OVERLAY_END (o2), + equal_kind, depth + 1, ht)) + return false; + o1 = XOVERLAY (o1)->plist; + o2 = XOVERLAY (o2)->plist; + depth++; + goto tail_recurse; + } + if (MARKERP (o1)) + { + return (XMARKER (o1)->buffer == XMARKER (o2)->buffer + && (XMARKER (o1)->buffer == 0 + || XMARKER (o1)->bytepos == XMARKER (o2)->bytepos)); + } /* Boolvectors are compared much like strings. */ if (BOOL_VECTOR_P (o1)) { @@ -4451,7 +4446,6 @@ sxhash (Lisp_Object obj, int depth) hash = XUINT (obj); break; - case Lisp_Misc: case Lisp_Symbol: hash = XHASH (obj); break; diff --git a/src/lisp.h b/src/lisp.h index bdece817bd..c559377288 100644 --- a/src/lisp.h +++ b/src/lisp.h @@ -360,8 +360,6 @@ typedef EMACS_INT Lisp_Word; #define lisp_h_EQ(x, y) (XLI (x) == XLI (y)) #define lisp_h_FLOATP(x) (XTYPE (x) == Lisp_Float) #define lisp_h_INTEGERP(x) ((XTYPE (x) & (Lisp_Int0 | ~Lisp_Int1)) == Lisp_Int0) -#define lisp_h_MARKERP(x) (MISCP (x) && XMISCTYPE (x) == Lisp_Misc_Marker) -#define lisp_h_MISCP(x) (XTYPE (x) == Lisp_Misc) #define lisp_h_NILP(x) EQ (x, Qnil) #define lisp_h_SET_SYMBOL_VAL(sym, v) \ (eassert ((sym)->u.s.redirect == SYMBOL_PLAINVAL), \ @@ -425,8 +423,6 @@ typedef EMACS_INT Lisp_Word; # define EQ(x, y) lisp_h_EQ (x, y) # define FLOATP(x) lisp_h_FLOATP (x) # define INTEGERP(x) lisp_h_INTEGERP (x) -# define MARKERP(x) lisp_h_MARKERP (x) -# define MISCP(x) lisp_h_MISCP (x) # define NILP(x) lisp_h_NILP (x) # define SET_SYMBOL_VAL(sym, v) lisp_h_SET_SYMBOL_VAL (sym, v) # define SYMBOL_CONSTANT_P(sym) lisp_h_SYMBOL_CONSTANT_P (sym) @@ -477,10 +473,6 @@ enum Lisp_Type /* Symbol. XSYMBOL (object) points to a struct Lisp_Symbol. */ Lisp_Symbol = 0, - /* Miscellaneous. XMISC (object) points to a union Lisp_Misc, - whose first member indicates the subtype. */ - Lisp_Misc = 1, - /* Integer. XINT (obj) is the integer value. */ Lisp_Int0 = 2, Lisp_Int1 = USE_LSB_TAG ? 6 : 3, @@ -501,25 +493,6 @@ enum Lisp_Type Lisp_Float = 7 }; -/* This is the set of data types that share a common structure. - The first member of the structure is a type code from this set. - The enum values are arbitrary, but we'll use large numbers to make it - more likely that we'll spot the error if a random word in memory is - mistakenly interpreted as a Lisp_Misc. */ -enum Lisp_Misc_Type - { - Lisp_Misc_Free = 0x5eab, - Lisp_Misc_Marker, - Lisp_Misc_Overlay, - Lisp_Misc_Finalizer, - Lisp_Misc_Ptr, -#ifdef HAVE_MODULES - Lisp_Misc_User_Ptr, -#endif - /* This is not a type code. It is for range checking. */ - Lisp_Misc_Limit - }; - /* These are the types of forwarding objects used in the value slot of symbols for special built-in variables whose value is stored in C variables. */ @@ -533,14 +506,12 @@ enum Lisp_Fwd_Type }; /* If you want to define a new Lisp data type, here are some - instructions. See the thread at - https://lists.gnu.org/r/emacs-devel/2012-10/msg00561.html - for more info. + instructions. First, there are already a couple of Lisp types that can be used if your new type does not need to be exposed to Lisp programs nor - displayed to users. These are Lisp_Misc_Ptr, a Lisp_Misc - subtype; and PVEC_OTHER, a kind of vectorlike object. The former + displayed to users. These are Lisp_Misc_Ptr and PVEC_OTHER, + which are both vectorlike objects. The former is suitable for stashing a pointer in a Lisp object; the pointer might be to some low-level C object that contains auxiliary information. The latter is useful for vector-like Lisp objects @@ -551,30 +522,14 @@ enum Lisp_Fwd_Type These two types don't look pretty when printed, so they are unsuitable for Lisp objects that can be exposed to users. - To define a new data type, add one more Lisp_Misc subtype or one - more pseudovector subtype. Pseudovectors are more suitable for - objects with several slots that need to support fast random access, - while Lisp_Misc types are for everything else. A pseudovector object - provides one or more slots for Lisp objects, followed by struct - members that are accessible only from C. A Lisp_Misc object is a - wrapper for a C struct that can contain anything you like. + To define a new data type, add a pseudovector subtype by extending + the pvec_type enumeration. A pseudovector provides one or more + slots for Lisp objects, followed by struct members that are + accessible only from C. There is no way to explicitly free a Lisp Object; only the garbage collector frees them. - To add a new pseudovector type, extend the pvec_type enumeration; - to add a new Lisp_Misc, extend the Lisp_Misc_Type enumeration. - - For a Lisp_Misc, you will also need to add your entry to union - Lisp_Misc, but make sure the first word has the same structure as - the others, starting with a 16-bit member of the Lisp_Misc_Type - enumeration and a 1-bit GC markbit. Also make sure the overall - size of the union is not increased by your addition. The latter - requirement is to keep Lisp_Misc objects small enough, so they - are handled faster: since all Lisp_Misc types use the same space, - enlarging any of them will affect all the rest. If you really - need a larger object, it is best to use Lisp_Vectorlike instead. - For a new pseudovector, it's highly desirable to limit the size of your data type by VBLOCK_BYTES_MAX bytes (defined in alloc.c). Otherwise you will need to change sweep_vectors (also in alloc.c). @@ -967,6 +922,13 @@ enum pvec_type { PVEC_NORMAL_VECTOR, PVEC_FREE, + PVEC_MARKER, + PVEC_OVERLAY, + PVEC_FINALIZER, + PVEC_MISC_PTR, +#ifdef HAVE_MODULES + PVEC_USER_PTR, +#endif PVEC_PROCESS, PVEC_FRAME, PVEC_WINDOW, @@ -1167,7 +1129,6 @@ INLINE bool #define XSETSTRING(a, b) ((a) = make_lisp_ptr (b, Lisp_String)) #define XSETSYMBOL(a, b) ((a) = make_lisp_symbol (b)) #define XSETFLOAT(a, b) ((a) = make_lisp_ptr (b, Lisp_Float)) -#define XSETMISC(a, b) ((a) = make_lisp_ptr (b, Lisp_Misc)) /* Pseudovector types. */ @@ -2267,46 +2228,10 @@ SXHASH_REDUCE (EMACS_UINT x) return (x ^ x >> (EMACS_INT_WIDTH - FIXNUM_BITS)) & INTMASK; } -/* These structures are used for various misc types. */ - -struct Lisp_Misc_Any /* Supertype of all Misc types. */ -{ - ENUM_BF (Lisp_Misc_Type) type : 16; /* = Lisp_Misc_??? */ - bool_bf gcmarkbit : 1; - unsigned spacer : 15; -}; - -INLINE bool -(MISCP) (Lisp_Object x) -{ - return lisp_h_MISCP (x); -} - -INLINE struct Lisp_Misc_Any * -XMISCANY (Lisp_Object a) -{ - eassert (MISCP (a)); - return XUNTAG (a, Lisp_Misc, struct Lisp_Misc_Any); -} - -INLINE enum Lisp_Misc_Type -XMISCTYPE (Lisp_Object a) -{ - return XMISCANY (a)->type; -} - struct Lisp_Marker { - ENUM_BF (Lisp_Misc_Type) type : 16; /* = Lisp_Misc_Marker */ - bool_bf gcmarkbit : 1; - unsigned spacer : 13; - /* This flag is temporarily used in the functions - decode/encode_coding_object to record that the marker position - must be adjusted after the conversion. */ - bool_bf need_adjustment : 1; - /* True means normal insertion at the marker's position - leaves the marker after the inserted text. */ - bool_bf insertion_type : 1; + union vectorlike_header header; + /* This is the buffer that the marker points into, or 0 if it points nowhere. Note: a chain of markers can contain markers pointing into different buffers (the chain is per buffer_text rather than per buffer, so it's @@ -2319,6 +2244,14 @@ struct Lisp_Marker */ struct buffer *buffer; + /* This flag is temporarily used in the functions + decode/encode_coding_object to record that the marker position + must be adjusted after the conversion. */ + bool_bf need_adjustment : 1; + /* True means normal insertion at the marker's position + leaves the marker after the inserted text. */ + bool_bf insertion_type : 1; + /* The remaining fields are meaningless in a marker that does not point anywhere. */ @@ -2351,20 +2284,16 @@ struct Lisp_Overlay I.e. 9words plus 2 bits, 3words of which are for external linked lists. */ { - ENUM_BF (Lisp_Misc_Type) type : 16; /* = Lisp_Misc_Overlay */ - bool_bf gcmarkbit : 1; - unsigned spacer : 15; - struct Lisp_Overlay *next; + union vectorlike_header header; Lisp_Object start; Lisp_Object end; Lisp_Object plist; + struct Lisp_Overlay *next; }; struct Lisp_Misc_Ptr { - ENUM_BF (Lisp_Misc_Type) type : 16; /* = Lisp_Misc_Ptr */ - bool_bf gcmarkbit : 1; - unsigned spacer : 15; + union vectorlike_header header; void *pointer; }; @@ -2382,7 +2311,7 @@ extern Lisp_Object make_misc_ptr (void *); C code, it should not be given a mint_ptr generated from Lisp code as that would allow Lisp code to coin pointers from integers and could lead to crashes. To package a C pointer into a Lisp-visible - object you can put the pointer into a Lisp_Misc object instead; see + object you can put the pointer into a pseudovector instead; see Lisp_User_Ptr for an example. */ INLINE Lisp_Object @@ -2395,7 +2324,7 @@ make_mint_ptr (void *a) INLINE bool mint_ptrp (Lisp_Object x) { - return INTEGERP (x) || (MISCP (x) && XMISCTYPE (x) == Lisp_Misc_Ptr); + return INTEGERP (x) || PSEUDOVECTORP (x, PVEC_MISC_PTR); } INLINE void * @@ -2404,16 +2333,13 @@ xmint_pointer (Lisp_Object a) eassert (mint_ptrp (a)); if (INTEGERP (a)) return XINTPTR (a); - return XUNTAG (a, Lisp_Misc, struct Lisp_Misc_Ptr)->pointer; + return XUNTAG (a, Lisp_Vectorlike, struct Lisp_Misc_Ptr)->pointer; } #ifdef HAVE_MODULES struct Lisp_User_Ptr { - ENUM_BF (Lisp_Misc_Type) type : 16; /* = Lisp_Misc_User_Ptr */ - bool_bf gcmarkbit : 1; - unsigned spacer : 15; - + union vectorlike_header header; void (*finalizer) (void *); void *p; }; @@ -2422,100 +2348,69 @@ struct Lisp_User_Ptr /* A finalizer sentinel. */ struct Lisp_Finalizer { - struct Lisp_Misc_Any base; - - /* Circular list of all active weak references. */ - struct Lisp_Finalizer *prev; - struct Lisp_Finalizer *next; + union vectorlike_header header; /* Call FUNCTION when the finalizer becomes unreachable, even if FUNCTION contains a reference to the finalizer; i.e., call FUNCTION when it is reachable _only_ through finalizers. */ Lisp_Object function; + + /* Circular list of all active weak references. */ + struct Lisp_Finalizer *prev; + struct Lisp_Finalizer *next; }; INLINE bool FINALIZERP (Lisp_Object x) { - return MISCP (x) && XMISCTYPE (x) == Lisp_Misc_Finalizer; + return PSEUDOVECTORP (x, PVEC_FINALIZER); } INLINE struct Lisp_Finalizer * XFINALIZER (Lisp_Object a) { eassert (FINALIZERP (a)); - return XUNTAG (a, Lisp_Misc, struct Lisp_Finalizer); -} - -/* A miscellaneous object, when it's on the free list. */ -struct Lisp_Free - { - ENUM_BF (Lisp_Misc_Type) type : 16; /* = Lisp_Misc_Free */ - bool_bf gcmarkbit : 1; - unsigned spacer : 15; - union Lisp_Misc *chain; - }; - -/* To get the type field of a union Lisp_Misc, use XMISCTYPE. - It uses one of these struct subtypes to get the type field. */ - -union Lisp_Misc - { - struct Lisp_Misc_Any u_any; /* Supertype of all Misc types. */ - struct Lisp_Free u_free; - struct Lisp_Marker u_marker; - struct Lisp_Overlay u_overlay; - struct Lisp_Finalizer u_finalizer; - struct Lisp_Misc_Ptr u_misc_ptr; -#ifdef HAVE_MODULES - struct Lisp_User_Ptr u_user_ptr; -#endif - }; - -INLINE union Lisp_Misc * -XMISC (Lisp_Object a) -{ - return XUNTAG (a, Lisp_Misc, union Lisp_Misc); + return XUNTAG (a, Lisp_Vectorlike, struct Lisp_Finalizer); } INLINE bool -(MARKERP) (Lisp_Object x) +MARKERP (Lisp_Object x) { - return lisp_h_MARKERP (x); + return PSEUDOVECTORP (x, PVEC_MARKER); } INLINE struct Lisp_Marker * XMARKER (Lisp_Object a) { eassert (MARKERP (a)); - return XUNTAG (a, Lisp_Misc, struct Lisp_Marker); + return XUNTAG (a, Lisp_Vectorlike, struct Lisp_Marker); } INLINE bool OVERLAYP (Lisp_Object x) { - return MISCP (x) && XMISCTYPE (x) == Lisp_Misc_Overlay; + return PSEUDOVECTORP (x, PVEC_OVERLAY); } INLINE struct Lisp_Overlay * XOVERLAY (Lisp_Object a) { eassert (OVERLAYP (a)); - return XUNTAG (a, Lisp_Misc, struct Lisp_Overlay); + return XUNTAG (a, Lisp_Vectorlike, struct Lisp_Overlay); } #ifdef HAVE_MODULES INLINE bool USER_PTRP (Lisp_Object x) { - return MISCP (x) && XMISCTYPE (x) == Lisp_Misc_User_Ptr; + return PSEUDOVECTORP (x, PVEC_USER_PTR); } INLINE struct Lisp_User_Ptr * XUSER_PTR (Lisp_Object a) { eassert (USER_PTRP (a)); - return XUNTAG (a, Lisp_Misc, struct Lisp_User_Ptr); + return XUNTAG (a, Lisp_Vectorlike, struct Lisp_User_Ptr); } #endif diff --git a/src/print.c b/src/print.c index 34c7fa12b6..cb35abfbfc 100644 --- a/src/print.c +++ b/src/print.c @@ -1367,6 +1367,67 @@ print_vectorlike (Lisp_Object obj, Lisp_Object printcharfun, bool escapeflag, { switch (PSEUDOVECTOR_TYPE (XVECTOR (obj))) { + case PVEC_MARKER: + print_c_string ("#insertion_type != 0) + print_c_string ("(moves after insertion) ", printcharfun); + if (! XMARKER (obj)->buffer) + print_c_string ("in no buffer", printcharfun); + else + { + int len = sprintf (buf, "at %"pD"d in ", marker_position (obj)); + strout (buf, len, len, printcharfun); + print_string (BVAR (XMARKER (obj)->buffer, name), printcharfun); + } + printchar ('>', printcharfun); + break; + + case PVEC_OVERLAY: + print_c_string ("#buffer) + print_c_string ("in no buffer", printcharfun); + else + { + int len = sprintf (buf, "from %"pD"d to %"pD"d in ", + marker_position (OVERLAY_START (obj)), + marker_position (OVERLAY_END (obj))); + strout (buf, len, len, printcharfun); + print_string (BVAR (XMARKER (OVERLAY_START (obj))->buffer, name), + printcharfun); + } + printchar ('>', printcharfun); + break; + +#ifdef HAVE_MODULES + case PVEC_USER_PTR: + { + print_c_string ("#p, + XUSER_PTR (obj)->finalizer); + strout (buf, i, i, printcharfun); + printchar ('>', printcharfun); + } + break; +#endif + + case PVEC_FINALIZER: + print_c_string ("#function)) + print_c_string (" used", printcharfun); + printchar ('>', printcharfun); + break; + + case PVEC_MISC_PTR: + { + /* This shouldn't happen in normal usage, but let's + print it anyway for the benefit of the debugger. */ + int i = sprintf (buf, "#", xmint_pointer (obj)); + strout (buf, i, i, printcharfun); + } + break; + case PVEC_PROCESS: if (escapeflag) { @@ -2096,94 +2157,16 @@ print_object (Lisp_Object obj, Lisp_Object printcharfun, bool escapeflag) break; case Lisp_Vectorlike: - if (! print_vectorlike (obj, printcharfun, escapeflag, buf)) - goto badtype; - break; - - case Lisp_Misc: - switch (XMISCTYPE (obj)) - { - case Lisp_Misc_Marker: - print_c_string ("#insertion_type != 0) - print_c_string ("(moves after insertion) ", printcharfun); - if (! XMARKER (obj)->buffer) - print_c_string ("in no buffer", printcharfun); - else - { - int len = sprintf (buf, "at %"pD"d in ", marker_position (obj)); - strout (buf, len, len, printcharfun); - print_string (BVAR (XMARKER (obj)->buffer, name), printcharfun); - } - printchar ('>', printcharfun); - break; - - case Lisp_Misc_Overlay: - print_c_string ("#buffer) - print_c_string ("in no buffer", printcharfun); - else - { - int len = sprintf (buf, "from %"pD"d to %"pD"d in ", - marker_position (OVERLAY_START (obj)), - marker_position (OVERLAY_END (obj))); - strout (buf, len, len, printcharfun); - print_string (BVAR (XMARKER (OVERLAY_START (obj))->buffer, name), - printcharfun); - } - printchar ('>', printcharfun); - break; - -#ifdef HAVE_MODULES - case Lisp_Misc_User_Ptr: - { - print_c_string ("#p, - XUSER_PTR (obj)->finalizer); - strout (buf, i, i, printcharfun); - printchar ('>', printcharfun); - break; - } -#endif - - case Lisp_Misc_Finalizer: - print_c_string ("#function)) - print_c_string (" used", printcharfun); - printchar ('>', printcharfun); - break; - - /* Remaining cases shouldn't happen in normal usage, but let's - print them anyway for the benefit of the debugger. */ - - case Lisp_Misc_Free: - print_c_string ("#", printcharfun); - break; - - case Lisp_Misc_Ptr: - { - int i = sprintf (buf, "#", xmint_pointer (obj)); - strout (buf, i, i, printcharfun); - } - break; - - default: - goto badtype; - } - break; - + if (print_vectorlike (obj, printcharfun, escapeflag, buf)) + break; + FALLTHROUGH; default: - badtype: { int len; /* We're in trouble if this happens! Probably should just emacs_abort (). */ print_c_string ("#next) + for (struct Lisp_Marker *m = BUF_MARKERS (current_buffer); m; m = m->next) { - charpos = m->charpos; + ptrdiff_t charpos = m->charpos; eassert (charpos <= Z); if (from <= charpos && charpos <= to) @@ -146,11 +142,11 @@ record_marker_adjustments (ptrdiff_t from, ptrdiff_t to) insertion_type t markers will automatically move forward upon re-inserting the deleted text, so we have to arrange for them to move backward to the correct position. */ - adjustment = (m->insertion_type ? to : from) - charpos; + ptrdiff_t adjustment = (m->insertion_type ? to : from) - charpos; if (adjustment) { - XSETMISC (marker, m); + Lisp_Object marker = make_lisp_ptr (m, Lisp_Vectorlike); bset_undo_list (current_buffer, Fcons (Fcons (marker, make_number (adjustment)), diff --git a/src/xdisp.c b/src/xdisp.c index 956535c2db..3f51b9c315 100644 --- a/src/xdisp.c +++ b/src/xdisp.c @@ -5819,11 +5819,7 @@ compare_overlay_entries (const void *e1, const void *e2) static void load_overlay_strings (struct it *it, ptrdiff_t charpos) { - Lisp_Object overlay, window, str, invisible; - struct Lisp_Overlay *ov; - ptrdiff_t start, end; - ptrdiff_t n = 0, i, j; - int invis; + ptrdiff_t n = 0; struct overlay_entry entriesbuf[20]; ptrdiff_t size = ARRAYELTS (entriesbuf); struct overlay_entry *entries = entriesbuf; @@ -5859,12 +5855,13 @@ load_overlay_strings (struct it *it, ptrdiff_t charpos) while (false) /* Process overlay before the overlay center. */ - for (ov = current_buffer->overlays_before; ov; ov = ov->next) + for (struct Lisp_Overlay *ov = current_buffer->overlays_before; + ov; ov = ov->next) { - XSETMISC (overlay, ov); + Lisp_Object overlay = make_lisp_ptr (ov, Lisp_Vectorlike); eassert (OVERLAYP (overlay)); - start = OVERLAY_POSITION (OVERLAY_START (overlay)); - end = OVERLAY_POSITION (OVERLAY_END (overlay)); + ptrdiff_t start = OVERLAY_POSITION (OVERLAY_START (overlay)); + ptrdiff_t end = OVERLAY_POSITION (OVERLAY_END (overlay)); if (end < charpos) break; @@ -5875,17 +5872,18 @@ load_overlay_strings (struct it *it, ptrdiff_t charpos) continue; /* Skip this overlay if it doesn't apply to IT->w. */ - window = Foverlay_get (overlay, Qwindow); + Lisp_Object window = Foverlay_get (overlay, Qwindow); if (WINDOWP (window) && XWINDOW (window) != it->w) continue; /* If the text ``under'' the overlay is invisible, both before- and after-strings from this overlay are visible; start and end position are indistinguishable. */ - invisible = Foverlay_get (overlay, Qinvisible); - invis = TEXT_PROP_MEANS_INVISIBLE (invisible); + Lisp_Object invisible = Foverlay_get (overlay, Qinvisible); + int invis = TEXT_PROP_MEANS_INVISIBLE (invisible); /* If overlay has a non-empty before-string, record it. */ + Lisp_Object str; if ((start == charpos || (end == charpos && invis != 0)) && (str = Foverlay_get (overlay, Qbefore_string), STRINGP (str)) && SCHARS (str)) @@ -5899,12 +5897,13 @@ load_overlay_strings (struct it *it, ptrdiff_t charpos) } /* Process overlays after the overlay center. */ - for (ov = current_buffer->overlays_after; ov; ov = ov->next) + for (struct Lisp_Overlay *ov = current_buffer->overlays_after; + ov; ov = ov->next) { - XSETMISC (overlay, ov); + Lisp_Object overlay = make_lisp_ptr (ov, Lisp_Vectorlike); eassert (OVERLAYP (overlay)); - start = OVERLAY_POSITION (OVERLAY_START (overlay)); - end = OVERLAY_POSITION (OVERLAY_END (overlay)); + ptrdiff_t start = OVERLAY_POSITION (OVERLAY_START (overlay)); + ptrdiff_t end = OVERLAY_POSITION (OVERLAY_END (overlay)); if (start > charpos) break; @@ -5915,16 +5914,17 @@ load_overlay_strings (struct it *it, ptrdiff_t charpos) continue; /* Skip this overlay if it doesn't apply to IT->w. */ - window = Foverlay_get (overlay, Qwindow); + Lisp_Object window = Foverlay_get (overlay, Qwindow); if (WINDOWP (window) && XWINDOW (window) != it->w) continue; /* If the text ``under'' the overlay is invisible, it has a zero dimension, and both before- and after-strings apply. */ - invisible = Foverlay_get (overlay, Qinvisible); - invis = TEXT_PROP_MEANS_INVISIBLE (invisible); + Lisp_Object invisible = Foverlay_get (overlay, Qinvisible); + int invis = TEXT_PROP_MEANS_INVISIBLE (invisible); /* If overlay has a non-empty before-string, record it. */ + Lisp_Object str; if ((start == charpos || (end == charpos && invis != 0)) && (str = Foverlay_get (overlay, Qbefore_string), STRINGP (str)) && SCHARS (str)) @@ -5950,12 +5950,11 @@ load_overlay_strings (struct it *it, ptrdiff_t charpos) /* IT->current.overlay_string_index is the number of overlay strings that have already been consumed by IT. Copy some of the remaining overlay strings to IT->overlay_strings. */ - i = 0; - j = it->current.overlay_string_index; - while (i < OVERLAY_STRING_CHUNK_SIZE && j < n) + ptrdiff_t j = it->current.overlay_string_index; + for (ptrdiff_t i = 0; i < OVERLAY_STRING_CHUNK_SIZE && j < n; i++, j++) { it->overlay_strings[i] = entries[j].string; - it->string_overlays[i++] = entries[j++].overlay; + it->string_overlays[i] = entries[j].overlay; } CHECK_IT (it); -- 2.17.1