From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.io!.POSTED.blaine.gmane.org!not-for-mail From: Helmut Eller Newsgroups: gmane.emacs.devel Subject: MPS: marker-vector (was: Markers in a gap array) Date: Mon, 05 Aug 2024 21:54:42 +0200 Message-ID: <87a5hqsq2l.fsf_-_@gmail.com> References: <87ikxlqwu6.fsf@localhost> <87le2hp6ug.fsf@localhost> <87v81455iw.fsf@gmail.com> <87jzh8djdt.fsf@gmail.com> Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="=-=-=" Injection-Info: ciao.gmane.io; posting-host="blaine.gmane.org:116.202.254.214"; logging-data="14631"; mail-complaints-to="usenet@ciao.gmane.io" User-Agent: Gnus/5.13 (Gnus v5.13) Cc: Stefan Monnier , Pip Cet , Ihor Radchenko , emacs-devel@gnu.org To: Gerd =?utf-8?Q?M=C3=B6llmann?= Original-X-From: emacs-devel-bounces+ged-emacs-devel=m.gmane-mx.org@gnu.org Mon Aug 05 21:55:48 2024 Return-path: Envelope-to: ged-emacs-devel@m.gmane-mx.org Original-Received: from lists.gnu.org ([209.51.188.17]) by ciao.gmane.io with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1sb3o3-0003hB-Vs for ged-emacs-devel@m.gmane-mx.org; Mon, 05 Aug 2024 21:55:48 +0200 Original-Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1sb3nD-0004Lm-Bb; Mon, 05 Aug 2024 15:54:55 -0400 Original-Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1sb3n9-0004LD-TR for emacs-devel@gnu.org; Mon, 05 Aug 2024 15:54:52 -0400 Original-Received: from mail-ej1-x636.google.com ([2a00:1450:4864:20::636]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1sb3n5-0006Sk-W5; Mon, 05 Aug 2024 15:54:51 -0400 Original-Received: by mail-ej1-x636.google.com with SMTP id a640c23a62f3a-a7d26c2297eso1375224866b.2; Mon, 05 Aug 2024 12:54:46 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1722887685; x=1723492485; darn=gnu.org; h=mime-version:user-agent:message-id:date:references:in-reply-to :subject:cc:to:from:from:to:cc:subject:date:message-id:reply-to; bh=JCYEAbao5am2uE7cbqw5nQc3/Mom6Jg/fyAGHi7iT9w=; b=KmbMFA7jWgJ/e7TRfe4PRrk/q66Z5xHB7LjSP8SFaB4atWWmEnXnEsjucvCCNWAiRQ BqXMcYw6v3738QPD0gThBwofMJIdE94BBAERtzytwYnXduWlyxxcstk8d7ColIqnqfuk 4GK0NrnMkWZ6ggSg0Rb/bPQJbhBSAKe9sDOhWjJzfGCLCDBV0lG3U9L+YHGpZAjf/HY5 5bjiD49dRQL7ZyAJfVuWfvjb13SYFVLHRJKUeuEbf3s9bLBibLRTgudEDgcpk8meUJLT iLw9/CibUrP0iaiLBbwB2BKeCL1cAt6fzW54q2dPhPebYM2YkY0YsAfdtCEe6JKG2m30 XOpg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1722887685; x=1723492485; h=mime-version:user-agent:message-id:date:references:in-reply-to :subject:cc:to:from:x-gm-message-state:from:to:cc:subject:date :message-id:reply-to; bh=JCYEAbao5am2uE7cbqw5nQc3/Mom6Jg/fyAGHi7iT9w=; b=aCIDja4RoDQ2cTWSoV4lXqsgjuZmAfyHE46AG5TSXwGAgToN/DwKPVnfHIdXL0XyPk we5+54Zol1yGC7S+V5CpEhGn08Z+xOpBwoptdFUJNOACtbS5hdbz0e1vr8hQ7lpAYSVn bKUdJUDS1V2zRQcPfZWPwa1L5TGD6WTflWXihD3kK6P++Ymy5KHgT5Ii5irPIlVWgRXA WppDWNPk70bj/7CRuRdmxipYj7tAseTEEYeetGs6p+NaYFUA4OuMeVFy0ThB7ZN47XjS qtdCL3QR0x2KCUxNdFJp3u8MFDTs1LrtJsTn7g2m5HxVd5xQxmaQSRwl83FWhf9n2Qrd ZOZw== X-Forwarded-Encrypted: i=1; AJvYcCU+8hFZAK7BW4PKD4Vp7m+iJguwbkay+N+dS0xZizpCJ4Me+J4W3spGBrwHSe4VeBJaydmZvrpk66IOrFa20U+wEgqU X-Gm-Message-State: AOJu0YxsgHMsI8EOhv2krcr60LP2OSy5PYLM4L4yVuNR8Xrf6lUQuCrg qGGCzki4iVdgpmL1pSYSw1wKu9Mn5bhDPoJhecEmiUdxBBgZ6cY5hTPwZQ== X-Google-Smtp-Source: AGHT+IFVyUb5/AwqlFQr/zuVPhABSHMOTvp5WcobsR6SLaAaJzmTeqKEub3Tgk5TXAqh8j3F6A6lBQ== X-Received: by 2002:a17:907:97c9:b0:a7a:aa35:4089 with SMTP id a640c23a62f3a-a7dc4e87671mr1007874366b.24.1722887684728; Mon, 05 Aug 2024 12:54:44 -0700 (PDT) Original-Received: from caladan (dialin-234199.rol.raiffeisen.net. [195.254.234.199]) by smtp.gmail.com with ESMTPSA id a640c23a62f3a-a7dc9bcf044sm480813266b.7.2024.08.05.12.54.43 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 05 Aug 2024 12:54:44 -0700 (PDT) In-Reply-To: <87jzh8djdt.fsf@gmail.com> (Helmut Eller's message of "Fri, 26 Jul 2024 21:48:46 +0200") Received-SPF: pass client-ip=2a00:1450:4864:20::636; envelope-from=eller.helmut@gmail.com; helo=mail-ej1-x636.google.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, FREEMAIL_FROM=0.001, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: emacs-devel@gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: "Emacs development discussions." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: emacs-devel-bounces+ged-emacs-devel=m.gmane-mx.org@gnu.org Original-Sender: emacs-devel-bounces+ged-emacs-devel=m.gmane-mx.org@gnu.org Xref: news.gmane.io gmane.emacs.devel:322410 Archived-At: --=-=-= Content-Type: text/plain What would you think about changing the marker-vector-with-free-list to a mundane growable array like in the patch below? The main motivation for this would that we could then iterate in reverse, or more precisely, in an order that is more like the order used for the linked-list-of-markers. This is relevant for the heuristic in buf_charpos_to_bytepos that creates a temporary marker; it works better if those temporary markers are visited first. Using Stefan's elb-bytechar benchmark, I get for the linked-list-of-markers: | test || tot avg (s) | tot avg err (s) | |------------------------++-------------+-----------------| | bytechar || 11.80 | 0.00 | | bytechar-100k || 11.85 | 0.00 | | bytechar-100k-nolookup || 9.19 | 0.00 | | bytechar-100k-random || 16.73 | 0.02 | | bytechar-100k-rev || 11.86 | 0.00 | | bytechar-10k-random || 12.36 | 0.01 | | bytechar-1k-random || 11.93 | 0.00 | | bytechar-nolookup || 9.15 | 0.00 | |------------------------++-------------+-----------------| | total || 94.88 | 0.02 | for the vector-with-free-list: | test || tot avg (s) | tot avg err (s) | |------------------------++-------------+-----------------| | bytechar || 11.63 | 0.01 | | bytechar-100k || 11.91 | 0.37 | | bytechar-100k-nolookup || 8.80 | 0.01 | | bytechar-100k-random || 248.07 | 3.84 | | bytechar-100k-rev || 11.71 | 0.02 | | bytechar-10k-random || 35.24 | 0.53 | | bytechar-1k-random || 14.01 | 0.06 | | bytechar-nolookup || 8.69 | 0.13 | |------------------------++-------------+-----------------| | total || 350.06 | 3.89 | and for the growable array: | test || tot avg (s) | tot avg err (s) | |------------------------++-------------+-----------------| | bytechar || 11.34 | 0.08 | | bytechar-100k || 11.59 | 0.47 | | bytechar-100k-nolookup || 8.78 | 0.12 | | bytechar-100k-random || 16.17 | 0.33 | | bytechar-100k-rev || 11.31 | 0.03 | | bytechar-10k-random || 11.76 | 0.01 | | bytechar-1k-random || 11.34 | 0.08 | | bytechar-nolookup || 8.70 | 0.09 | |------------------------++-------------+-----------------| | total || 91.00 | 0.61 | So the results of the growable array and the linked-list-of-markers would be closer. A downside of the growable array is that it needs a bit of extra code for the dumper. I didn't try to port the gap array code, because it seems like it would require many more changes and would make it even harder to merge with master. --=-=-= Content-Type: text/x-diff Content-Disposition: attachment; filename=0001-Introduce-a-struct-marker_vector.patch >From f640e13343183f0ad04edcfdc8d1576b7714b0f7 Mon Sep 17 00:00:00 2001 From: Helmut Eller Date: Sat, 27 Jul 2024 19:42:00 +0200 Subject: [PATCH] Introduce a struct marker_vector This replaces the vector-with-free-list by a growable vector, i.e. the free entries are always kept at the end of the vector. This allows us to iterate in reverse more easily because we can skip over unused entries quickly. Iterating in reverse is useful because buf_charpos_to_bytepos creates "temporary" markers to speed up the translation; this heuristic works better if we visit those recently created temporary markers early, like the non-MPS code does with the linked-list-of-markers. * src/buffer.h (struct marker_vector): New struct. (struct buffer_text, struct marker_it): Use it. (marker_vector_swap_remove): New helper. (marker_it_init, marker_it_valid, marker_it_next, marker_it_marker): Iterate in reverse order. * src/buffer.c (Fget_buffer_create, Fset_buffer_multibyte): Use struct marker_vector. * src/marker.c (buf_bytepos_to_charpos): Use struct marker_vector. * src/pdumper.c (dump_marker_vector): New helper. (dump_buffer): Use it. * src/igc.c (fix_marker_vector, dflt_scan_obj, fix_marker_vector) (fix_buffer, alloc_marker_vector, larger_marker_vector, igc_add_marker) (igc_remove_marker, igc_remove_all_markers, igc_resurrect_markers): Update for new data structure. (is_in_weak_pool): Renamed from weak_vector_p. --- src/buffer.c | 8 +-- src/buffer.h | 87 ++++++++++++++++++++-------- src/igc.c | 156 ++++++++++++++++++++++---------------------------- src/marker.c | 5 -- src/pdumper.c | 52 ++++++++++++++--- 5 files changed, 178 insertions(+), 130 deletions(-) diff --git a/src/buffer.c b/src/buffer.c index eea0703c898..d879b2447cc 100644 --- a/src/buffer.c +++ b/src/buffer.c @@ -662,11 +662,7 @@ DEFUN ("get-buffer-create", Fget_buffer_create, Sget_buffer_create, 1, 2, 0, reset_buffer_local_variables (b, 1); bset_mark (b, Fmake_marker ()); -#ifdef HAVE_MPS - BUF_MARKERS (b) = Qnil; -#else BUF_MARKERS (b) = NULL; -#endif /* Put this in the alist of all live buffers. */ XSETBUFFER (buffer, b); Vbuffer_alist = nconc2 (Vbuffer_alist, list1 (Fcons (name, buffer))); @@ -2938,8 +2934,8 @@ DEFUN ("set-buffer-multibyte", Fset_buffer_multibyte, Sset_buffer_multibyte, #ifdef HAVE_MPS DO_MARKERS (current_buffer, tail) { - Lisp_Object buf_markers = BUF_MARKERS (current_buffer); - BUF_MARKERS (current_buffer) = Qnil; + struct marker_vector *buf_markers = BUF_MARKERS (current_buffer); + BUF_MARKERS (current_buffer) = NULL; tail->bytepos = advance_to_char_boundary (tail->bytepos); tail->charpos = BYTE_TO_CHAR (tail->bytepos); BUF_MARKERS (current_buffer) = buf_markers; diff --git a/src/buffer.h b/src/buffer.h index 1e1a65e339d..fe95a4ddc40 100644 --- a/src/buffer.h +++ b/src/buffer.h @@ -220,6 +220,21 @@ #define FETCH_BYTE(n) (*BYTE_POS_ADDR (n)) /* Define the actual buffer data structures. */ +#ifdef HAVE_MPS +/* A marker_vector is a growable vector. The capacity and the length + fields are encoded as fixnum to satisfy AWL pool constraints. + + FIXME: capacity is redundant; it's also stored in the gc_header. +*/ +struct marker_vector +{ + GC_HEADER + Lisp_Object capacity; + Lisp_Object length; + struct Lisp_Marker *data[]; +}; +#endif + /* This data structure describes the actual text contents of a buffer. It is shared between indirect buffers and their base buffer. */ @@ -272,7 +287,7 @@ #define FETCH_BYTE(n) (*BYTE_POS_ADDR (n)) INTERVAL intervals; # ifdef HAVE_MPS - Lisp_Object markers; + struct marker_vector *markers; # else /* The markers that refer to this buffer. This is actually a single marker --- @@ -715,57 +730,83 @@ #define BVAR(buf, field) ((buf)->field ## _) struct marker_it { #ifdef HAVE_MPS - Lisp_Object markers, obj; - ptrdiff_t i; -# else + struct marker_vector *markers; + struct Lisp_Marker *m; + size_t i; +#else struct Lisp_Marker *marker; #endif }; #ifdef HAVE_MPS +/* Remove the marker at position I by swapping it with the marker at the + last position. */ +INLINE void +marker_vector_swap_remove (struct marker_vector *v, size_t i) +{ + for (size_t last = XFIXNUM (v->length) - 1; true; last--) + { + if (last == i) + { + v->length = make_fixnum (last); + return; + } + struct Lisp_Marker *m = v->data[last]; + if (m) + { + v->data[i] = m; + m->index = i; + v->length = make_fixnum (last); + return; + } + } +} + INLINE struct marker_it marker_it_init (struct buffer *b) { - Lisp_Object v = BUF_MARKERS (b); - if (!VECTORP (v)) - return (struct marker_it){ .obj = Qnil }; + struct marker_vector *v = BUF_MARKERS (b); - Lisp_Object obj = Qnil; - for (ptrdiff_t i = 1; i < ASIZE (v); ++i) - { - obj = AREF (v, i); - if (MARKERP (obj)) - return (struct marker_it) { .i = i, .markers = v, .obj = obj }; - } + if (v) + while (XFIXNUM (v->length) != 0) + { + size_t i = XFIXNUM(v->length) - 1; + struct Lisp_Marker *m = v->data[i]; + if (m) + return (struct marker_it){ .i = i, .markers = v, .m = m }; + v->length = make_fixnum (i); + } - return (struct marker_it) { .obj = Qnil }; + return (struct marker_it){ .m = NULL }; } INLINE bool marker_it_valid (struct marker_it *it) { - return MARKERP (it->obj); + return (it->m != NULL); } INLINE void marker_it_next (struct marker_it *it) { - it->obj = Qnil; - for (++it->i; it->i < ASIZE (it->markers); ++it->i) + while (it->i > 0) { - Lisp_Object m = AREF (it->markers, it->i); - if (MARKERP (m)) + it->i--; + struct Lisp_Marker *m = it->markers->data[it->i]; + if (m) { - it->obj = m; - break; + it->m = m; + return; } + marker_vector_swap_remove (it->markers, it->i); } + it->m = NULL; } INLINE struct Lisp_Marker * marker_it_marker (struct marker_it *it) { - return XMARKER (it->obj); + return it->m; } # else diff --git a/src/igc.c b/src/igc.c index 52d52ca7a91..30bf63d22ed 100644 --- a/src/igc.c +++ b/src/igc.c @@ -1797,7 +1797,7 @@ fix_charset_table (mps_ss_t ss, struct charset *table, size_t nbytes) } static mps_res_t fix_vector (mps_ss_t ss, struct Lisp_Vector *v); -static mps_res_t fix_marker_vector (mps_ss_t ss, struct Lisp_Vector *v); +static mps_res_t fix_marker_vector (mps_ss_t ss, struct marker_vector *v); static mps_res_t fix_weak_hash_table_strong_part (mps_ss_t ss, struct Lisp_Weak_Hash_Table_Strong_Part *t); static mps_res_t fix_weak_hash_table_weak_part (mps_ss_t ss, struct Lisp_Weak_Hash_Table_Weak_Part *w); @@ -1889,7 +1889,7 @@ dflt_scan_obj (mps_ss_t ss, mps_addr_t base_start, mps_addr_t base_limit, break; case IGC_OBJ_MARKER_VECTOR: - IGC_FIX_CALL_FN (ss, struct Lisp_Vector, client, fix_marker_vector); + IGC_FIX_CALL_FN (ss, struct marker_vector, client, fix_marker_vector); break; case IGC_OBJ_ITREE_TREE: @@ -1978,24 +1978,10 @@ fix_vectorlike (mps_ss_t ss, struct Lisp_Vector *v) } static mps_res_t -fix_marker_vector (mps_ss_t ss, struct Lisp_Vector *v) +fix_marker_vector (mps_ss_t ss, struct marker_vector *v) { - MPS_SCAN_BEGIN (ss) - { - for (size_t i = 0, n = vector_size (v); i < n; ++i) - { - Lisp_Object old = v->contents[i]; - IGC_FIX12_OBJ (ss, &v->contents[i]); - /* FIXME/igc: this is right for marker vectors only. */ - if (NILP (v->contents[i]) && !NILP (old)) - { - v->contents[i] = v->contents[0]; - v->contents[0] = make_fixnum (i); - } - } - } - MPS_SCAN_END (ss); - return MPS_RES_OK; + size_t len = XFIXNUM (v->length); + return mps_scan_area (ss, &v->data[0], &v->data[len], NULL); } static mps_res_t @@ -2004,8 +1990,6 @@ fix_buffer (mps_ss_t ss, struct buffer *b) MPS_SCAN_BEGIN (ss) { IGC_FIX_CALL_FN (ss, struct Lisp_Vector, b, fix_vectorlike); - IGC_FIX12_HEADER (ss, &b->own_text.intervals); - IGC_FIX12_OBJ (ss, &b->own_text.markers); IGC_FIX12_HEADER (ss, &b->overlays); IGC_FIX12_OBJ (ss, &b->undo_list_); @@ -2013,7 +1997,11 @@ fix_buffer (mps_ss_t ss, struct buffer *b) if (b->base_buffer) b->text = &b->base_buffer->own_text; else - b->text = &b->own_text; + { + b->text = &b->own_text; + IGC_FIX12_HEADER (ss, &b->own_text.intervals); + IGC_FIX12_HEADER (ss, &b->own_text.markers); + } } MPS_SCAN_END (ss); return MPS_RES_OK; @@ -4185,61 +4173,52 @@ igc_valid_lisp_object_p (Lisp_Object obj) return 1; } -static Lisp_Object -alloc_marker_vector (ptrdiff_t len, Lisp_Object init) +static struct marker_vector * +alloc_marker_vector (size_t capacity) { - struct Lisp_Vector *v - = alloc (header_size + len * word_size, IGC_OBJ_MARKER_VECTOR); - v->header.size = len; - for (ptrdiff_t i = 0; i < len; ++i) - v->contents[i] = init; - return make_lisp_ptr (v, Lisp_Vectorlike); + struct marker_vector *v = alloc ((offsetof (struct marker_vector, data) + + capacity * sizeof (v->data[0])), + IGC_OBJ_MARKER_VECTOR); + v->capacity = make_fixnum (capacity); + v->length = make_fixnum (0); + return v; } -static Lisp_Object -larger_marker_vector (Lisp_Object v) -{ - igc_assert (NILP (v) || (VECTORP (v) && XFIXNUM (AREF (v, 0)) < 0)); - ptrdiff_t old_len = NILP (v) ? 0 : ASIZE (v); - ptrdiff_t new_len = max (2, 2 * old_len); - Lisp_Object new_v = alloc_marker_vector (new_len, Qnil); - ptrdiff_t i = 0; - if (VECTORP (v)) - for (i = 1; i < ASIZE (v); ++i) - ASET (new_v, i, AREF (v, i)); - for (; i < ASIZE (new_v) - 1; ++i) - ASET (new_v, i, make_fixnum (i + 1)); - ASET (new_v, i, make_fixnum (-1)); - ASET (new_v, 0, make_fixnum (NILP (v) ? 1 : ASIZE (v))); - return new_v; +static struct marker_vector * +larger_marker_vector (struct marker_vector *old) +{ + igc_assert (old->length == old->capacity); + size_t old_cap = XFIXNUM (old->capacity); + size_t new_cap = max (2, 2 * old_cap); + struct marker_vector *new = alloc_marker_vector (new_cap); + new->length = make_fixnum (old_cap); + memcpy (new->data, old->data, old_cap * sizeof (old->data[0])); + return new; } void igc_add_marker (struct buffer *b, struct Lisp_Marker *m) { - Lisp_Object v = BUF_MARKERS (b); - igc_assert (NILP (v) || VECTORP (v)); - ptrdiff_t next_free = NILP (v) ? -1 : XFIXNUM (AREF (v, 0)); - if (next_free < 0) - { - v = BUF_MARKERS (b) = larger_marker_vector (v); - next_free = XFIXNUM (AREF (v, 0)); - } - ASET (v, 0, AREF (v, next_free)); - ASET (v, next_free, make_lisp_ptr (m, Lisp_Vectorlike)); - m->index = next_free; + struct marker_vector *v = BUF_MARKERS (b); + if (!v) + v = BUF_MARKERS (b) = alloc_marker_vector (2); + if (v->length == v->capacity) + v = BUF_MARKERS (b) = larger_marker_vector (v); + size_t index = XFIXNUM (v->length); + v->data[index] = m; + v->length = make_fixnum (index + 1); + m->index = index; m->buffer = b; } void igc_remove_marker (struct buffer *b, struct Lisp_Marker *m) { - Lisp_Object v = BUF_MARKERS (b); - igc_assert (VECTORP (v)); - igc_assert (m->index >= 1 && m->index < ASIZE (v)); - igc_assert (MARKERP (AREF (v, m->index)) && XMARKER (AREF (v, m->index)) == m); - ASET (v, m->index, AREF (v, 0)); - ASET (v, 0, make_fixnum (m->index)); + struct marker_vector *v = BUF_MARKERS (b); + igc_assert (v); + igc_assert (m->index >= 0 && m->index < XFIXNUM (v->length)); + igc_assert (v->data[m->index] && v->data[m->index] == m); + marker_vector_swap_remove (v, m->index); m->index = -1; m->buffer = NULL; } @@ -4247,44 +4226,45 @@ igc_remove_marker (struct buffer *b, struct Lisp_Marker *m) void igc_remove_all_markers (struct buffer *b) { - Lisp_Object v = BUF_MARKERS (b); - if (VECTORP (v)) + struct marker_vector *v = BUF_MARKERS (b); + if (!v) + return; + for (size_t i = 0, len = XFIXNUM (v->length); i < len; ++i) { - for (ptrdiff_t i = 1; i < ASIZE (v); ++i) - if (MARKERP (AREF (v, i))) - XMARKER (AREF (v, i))->buffer = NULL; - BUF_MARKERS (b) = Qnil; + struct Lisp_Marker *m = v->data[i]; + if (m) + { + m->buffer = NULL; + m->index = -1; + } } + v->length = make_fixnum (0); + BUF_MARKERS (b) = NULL; } static bool -weak_vector_p (Lisp_Object x) +is_in_weak_pool (mps_addr_t addr) { - if (VECTORP (x)) - { - struct igc *igc = global_igc; - mps_pool_t pool = NULL; - if (!mps_addr_pool (&pool, igc->arena, XVECTOR (x))) - return false; - return pool == igc->weak_pool; - } - else - return false; + struct igc *igc = global_igc; + mps_pool_t pool = NULL; + mps_addr_pool (&pool, igc->arena, addr); + return pool == igc->weak_pool; } void igc_resurrect_markers (struct buffer *b) { - Lisp_Object old = BUF_MARKERS (b); - if (NILP (old)) + struct marker_vector *old = BUF_MARKERS (b); + if (!old) return; - igc_assert (!weak_vector_p (old)); - size_t len = ASIZE (old); - Lisp_Object new = alloc_marker_vector (len, Qnil); - memcpy (XVECTOR (new)->contents, XVECTOR (old)->contents, - len * sizeof (Lisp_Object)); + igc_assert (!is_in_weak_pool (old)); + size_t capacity = XFIXNUM (old->capacity); + struct marker_vector *new = alloc_marker_vector (capacity); + size_t nbytes = (offsetof (struct marker_vector, data) + + capacity * sizeof (old->data[0])); + memcpy (new, old, nbytes); BUF_MARKERS (b) = new; - igc_assert (weak_vector_p (BUF_MARKERS (b))); + igc_assert (is_in_weak_pool (new)); } static void diff --git a/src/marker.c b/src/marker.c index 5db46e599ae..005f66f6f24 100644 --- a/src/marker.c +++ b/src/marker.c @@ -413,13 +413,8 @@ buf_bytepos_to_charpos (struct buffer *b, ptrdiff_t bytepos) It will last until the next GC. But don't do it if BUF_MARKERS is nil; that is a signal from Fset_buffer_multibyte. */ -#ifdef HAVE_MPS - if (record && VECTORP (BUF_MARKERS (b))) - build_marker (b, best_above, best_above_byte); -#else if (record && BUF_MARKERS (b)) build_marker (b, best_above, best_above_byte); -#endif byte_char_debug_check (b, best_above, best_above_byte); cached_buffer = b; diff --git a/src/pdumper.c b/src/pdumper.c index a56e0a8bfff..d4f4a7d8b6e 100644 --- a/src/pdumper.c +++ b/src/pdumper.c @@ -2873,10 +2873,37 @@ dump_obarray (struct dump_context *ctx, Lisp_Object object) return offset; } +#ifdef HAVE_MPS +static dump_off +dump_marker_vector (struct dump_context *ctx, const struct marker_vector *v) +{ + size_t capacity = XFIXNUM (v->capacity); + size_t length = XFIXNUM (v->length); + size_t nbytes = (offsetof (struct marker_vector, data) + + capacity * sizeof (v->data[0])); + struct marker_vector *out = alloca (nbytes); + memset (out, 0, nbytes); + dump_align_output (ctx, DUMP_ALIGNMENT); + dump_off offset = ctx->offset; + dump_object_start (ctx, v, IGC_OBJ_MARKER_VECTOR, out, nbytes); + DUMP_FIELD_COPY (out, v, capacity); + DUMP_FIELD_COPY (out, v, length); + for (size_t i = 0; i < length; i++) + { + struct Lisp_Marker *m = v->data[i]; + if (m) + dump_field_lv_rawptr (ctx, out, v, &v->data[i], Lisp_Vectorlike, + WEIGHT_NORMAL); + } + dump_object_finish (ctx, out, nbytes); + return offset; +} +#endif + static dump_off dump_buffer (struct dump_context *ctx, const struct buffer *in_buffer) { -#if CHECK_STRUCTS && !defined HASH_buffer_text_07D802E2D4 +#if CHECK_STRUCTS && !defined HASH_buffer_text_66FD568A61 # error "buffer changed. See CHECK_STRUCTS comment in config.h." #endif struct buffer munged_buffer = *in_buffer; @@ -2948,8 +2975,7 @@ dump_buffer (struct dump_context *ctx, const struct buffer *in_buffer) if (buffer->own_text.intervals) dump_field_fixup_later (ctx, out, buffer, &buffer->own_text.intervals); #ifdef HAVE_MPS - dump_field_lv (ctx, out, buffer, &buffer->own_text.markers, - WEIGHT_NORMAL); + dump_field_fixup_later (ctx, out, buffer, &buffer->own_text.markers); #else dump_field_lv_rawptr (ctx, out, buffer, &buffer->own_text.markers, Lisp_Vectorlike, WEIGHT_NORMAL); @@ -3012,11 +3038,21 @@ dump_buffer (struct dump_context *ctx, const struct buffer *in_buffer) dump_field_lv (ctx, out, buffer, &buffer->undo_list_, WEIGHT_STRONG); dump_off offset = finish_dump_pvec (ctx, &out->header); - if (!buffer->base_buffer && buffer->own_text.intervals) - dump_remember_fixup_ptr_raw - (ctx, - offset + dump_offsetof (struct buffer, own_text.intervals), - dump_interval_tree (ctx, buffer->own_text.intervals, 0)); + if (!buffer->base_buffer) + { + if (buffer->own_text.intervals) + dump_remember_fixup_ptr_raw + (ctx, + offset + dump_offsetof (struct buffer, own_text.intervals), + dump_interval_tree (ctx, buffer->own_text.intervals, 0)); +#ifdef HAVE_MPS + if (buffer->own_text.markers) + dump_remember_fixup_ptr_raw + (ctx, + offset + dump_offsetof (struct buffer, own_text.markers), + dump_marker_vector (ctx, buffer->own_text.markers)); +#endif + } return offset; } -- 2.39.2 --=-=-=--