Subject: bug#71525: 30.0.50; Spin in delete-region/interval_deletion_adjustment Spin in delete-region/interval_deletion_adjustment)

From: Dmitry Gutov <[email-masked]>
Date: Fri, 14 Jun 2024 02:41:15 +0300

On 14/06/2024 00:47, Dmitry Gutov wrote:
> The thing is, decode_coding_c_string already calls 
> adjust_markers_for_insert through
> 
>    decode_coding_object->decode_coding->produce_chars->insert_from_gap
> 
> And the extra call moves the markers too far.
> 
> Unfortunately, it's called with BEFORE_MARKERS=nil, and the above call 
> chain makes it difficult to pass through the extra argument.

We can do it through the coding_system structure, though.

See attached. It fixes the freezes in my testing.

It seems like the least invasive possible fix, but better suggestions 
welcome.

diff --git a/src/coding.c b/src/coding.c
index 5e4e92ea6e2..138aaa22e6a 100644
--- a/src/coding.c
+++ b/src/coding.c
@@ -5698,6 +5698,7 @@ setup_coding_system (Lisp_Object coding_system, struct coding_system *coding)
   coding->default_char = XFIXNUM (CODING_ATTR_DEFAULT_CHAR (attrs));
   coding->carryover_bytes = 0;
   coding->raw_destination = 0;
+  coding->dst_before_markers = 0;
 
   coding_type = CODING_ATTR_TYPE (attrs);
   if (EQ (coding_type, Qundecided))
@@ -7209,7 +7210,7 @@ produce_chars (struct coding_system *coding, Lisp_Object translation_table,
 
   produced = dst - (coding->destination + coding->produced);
   if (BUFFERP (coding->dst_object) && produced_chars > 0)
-    insert_from_gap (produced_chars, produced, 0);
+    insert_from_gap (produced_chars, produced, 0, coding->dst_before_markers);
   coding->produced += produced;
   coding->produced_char += produced_chars;
   return carryover;
@@ -7814,7 +7815,7 @@ encode_coding (struct coding_system *coding)
   } while (coding->consumed_char < coding->src_chars);
 
   if (BUFFERP (coding->dst_object) && coding->produced_char > 0)
-    insert_from_gap (coding->produced_char, coding->produced, 0);
+    insert_from_gap (coding->produced_char, coding->produced, 0, coding->dst_before_markers);
 
   SAFE_FREE ();
 }
@@ -8008,7 +8009,7 @@ decode_coding_gap (struct coding_system *coding, ptrdiff_t bytes)
 	    }
 	  coding->produced = bytes;
 	  coding->produced_char = chars;
-	  insert_from_gap (chars, bytes, 1);
+	  insert_from_gap (chars, bytes, 1, coding->dst_before_markers);
 	  return;
 	}
     }
@@ -9980,7 +9981,7 @@ encode_string_utf_8 (Lisp_Object string, Lisp_Object buffer,
       struct buffer *oldb = current_buffer;
 
       current_buffer = XBUFFER (buffer);
-      insert_from_gap (outbytes, outbytes, false);
+      insert_from_gap (outbytes, outbytes, false, false);
       current_buffer = oldb;
     }
   return val;
@@ -10290,7 +10291,7 @@ #define UTF_8_SEQUENCE_LENGTH(c)	\
       struct buffer *oldb = current_buffer;
 
       current_buffer = XBUFFER (buffer);
-      insert_from_gap (outchars, outbytes, false);
+      insert_from_gap (outchars, outbytes, false, false);
       current_buffer = oldb;
     }
   return val;
diff --git a/src/coding.h b/src/coding.h
index 8905e36838d..2e031d8cc55 100644
--- a/src/coding.h
+++ b/src/coding.h
@@ -428,6 +428,9 @@ #define CODING_MODE_SAFE_ENCODING		0x10
   /* Set to true if charbuf contains an annotation.  */
   bool_bf annotated : 1;
 
+  /* True to insert before markers in the DST_OBJECT buffer.  */
+  bool_bf dst_before_markers : 1;
+
   /* Used internally in coding.c.  See the comment of detect_ascii.  */
   unsigned eol_seen : 3;
 
diff --git a/src/decompress.c b/src/decompress.c
index fcdbb40fc90..6c342e54355 100644
--- a/src/decompress.c
+++ b/src/decompress.c
@@ -310,7 +310,7 @@ DEFUN ("zlib-decompress-region", Fzlib_decompress_region,
       inflate_status = inflate (&stream, Z_NO_FLUSH);
       pos_byte += avail_in - stream.avail_in;
       decompressed = avail_out - stream.avail_out;
-      insert_from_gap (decompressed, decompressed, 0);
+      insert_from_gap (decompressed, decompressed, 0, false);
       unwind_data.nbytes += decompressed;
       maybe_quit ();
     }
diff --git a/src/insdel.c b/src/insdel.c
index fbf71e1e595..8f8e7b7d71d 100644
--- a/src/insdel.c
+++ b/src/insdel.c
@@ -1129,10 +1129,12 @@ insert_from_gap_1 (ptrdiff_t nchars, ptrdiff_t nbytes, bool text_at_gap_tail)
 
 /* Insert a sequence of NCHARS chars which occupy NBYTES bytes
    starting at GAP_END_ADDR - NBYTES (if text_at_gap_tail) and at
-   GPT_ADDR (if not text_at_gap_tail).  */
+   GPT_ADDR (if not text_at_gap_tail).
+
+  If BEFORE_MARKERS is true, insert before markers. */
 
 void
-insert_from_gap (ptrdiff_t nchars, ptrdiff_t nbytes, bool text_at_gap_tail)
+insert_from_gap (ptrdiff_t nchars, ptrdiff_t nbytes, bool text_at_gap_tail, bool before_markers)
 {
   ptrdiff_t ins_charpos = GPT, ins_bytepos = GPT_BYTE;
 
@@ -1151,7 +1153,7 @@ insert_from_gap (ptrdiff_t nchars, ptrdiff_t nbytes, bool text_at_gap_tail)
   insert_from_gap_1 (nchars, nbytes, text_at_gap_tail);
 
   adjust_markers_for_insert (ins_charpos, ins_bytepos,
-			     ins_charpos + nchars, ins_bytepos + nbytes, false);
+			     ins_charpos + nchars, ins_bytepos + nbytes, before_markers);
 
   if (buffer_intervals (current_buffer))
     {
diff --git a/src/lisp.h b/src/lisp.h
index 21dada59132..2c3c4e0ba87 100644
--- a/src/lisp.h
+++ b/src/lisp.h
@@ -4372,7 +4372,8 @@ verify (FLT_RADIX == 2 || FLT_RADIX == 16);
 extern void insert_1_both (const char *, ptrdiff_t, ptrdiff_t,
 			   bool, bool, bool);
 extern void insert_from_gap_1 (ptrdiff_t, ptrdiff_t, bool text_at_gap_tail);
-extern void insert_from_gap (ptrdiff_t, ptrdiff_t, bool text_at_gap_tail);
+extern void insert_from_gap (ptrdiff_t, ptrdiff_t, bool text_at_gap_tail,
+			     bool before_markers);
 extern void insert_from_string (Lisp_Object, ptrdiff_t, ptrdiff_t,
 				ptrdiff_t, ptrdiff_t, bool);
 extern void insert_from_buffer (struct buffer *, ptrdiff_t, ptrdiff_t, bool);
diff --git a/src/process.c b/src/process.c
index eb526311c53..7000b51775c 100644
--- a/src/process.c
+++ b/src/process.c
@@ -6415,6 +6415,7 @@ read_and_insert_process_output (struct Lisp_Process *p, char *buf,
       specpdl_ref count1 = SPECPDL_INDEX ();
 
       XSETBUFFER (curbuf, current_buffer);
+      process_coding->dst_before_markers = true;
       /* We cannot allow after-change-functions be run
 	 during decoding, because that might modify the
 	 buffer, while we rely on process_coding.produced to
@@ -6423,9 +6424,6 @@ read_and_insert_process_output (struct Lisp_Process *p, char *buf,
       specbind (Qinhibit_modification_hooks, Qt);
       decode_coding_c_string (process_coding,
 			      (unsigned char *) buf, nread, curbuf);
-      adjust_markers_for_insert (PT, PT_BYTE,
-				 PT + process_coding->produced_char,
-				 PT_BYTE + process_coding->produced, true);
       unbind_to (count1, Qnil);
 
       read_process_output_set_last_coding_system (p, process_coding);