aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorPaul Eggert2017-01-25 20:27:45 -0800
committerPaul Eggert2017-01-25 21:25:37 -0800
commit1392ec7420ee23238a1588b759c631d87a677483 (patch)
treeca89387ce9acf91005465c7359dc4e212375c479 /src
parent0dfd9a69186e12e53b8aa759c47b9747de92db43 (diff)
downloademacs-1392ec7420ee23238a1588b759c631d87a677483.tar.gz
emacs-1392ec7420ee23238a1588b759c631d87a677483.zip
A quicker check for quit
On some microbenchmarks this lets Emacs run 60% faster on my platform (AMD Phenom II X4 910e, Fedora 25 x86-64). * src/atimer.c: Include keyboard.h, for pending_signals. * src/editfns.c (Fcompare_buffer_substrings): * src/fns.c (Fnthcdr, Fmemq, Fmemql, Fassq, Frassq, Fplist_put) (Fnconc, Fplist_member): Set and clear immediate_quit before and after loop instead of executing QUIT each time through the loop. This is OK for loops that affect only locals. * src/eval.c (process_quit_flag): Now static. (maybe_quit): New function, containing QUIT’s old body. * src/fns.c (rarely_quit): New function. (Fmember, Fassoc, Frassoc, Fdelete, Fnreverse, Freverse) (Flax_plist_get, Flax_plist_put, internal_equal, Fnconc): Use it instead of QUIT, for speed in tight loops that might modify non-locals. * src/keyboard.h (pending_signals, process_pending_signals): These belong to keyboard.c, so move them here ... * src/lisp.h: ... from here. (QUIT): Redefine in terms of the new maybe_quit function, which contains this macro’s old definiens. This works well with branch prediction on processors with return stack buffers, e.g., x86 other than the original Pentium.
Diffstat (limited to 'src')
-rw-r--r--src/atimer.c1
-rw-r--r--src/editfns.c14
-rw-r--r--src/eval.c11
-rw-r--r--src/fns.c132
-rw-r--r--src/keyboard.h2
-rw-r--r--src/lisp.h16
6 files changed, 108 insertions, 68 deletions
diff --git a/src/atimer.c b/src/atimer.c
index 7f099809d3c..5feb1f6777d 100644
--- a/src/atimer.c
+++ b/src/atimer.c
@@ -20,6 +20,7 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
20#include <stdio.h> 20#include <stdio.h>
21 21
22#include "lisp.h" 22#include "lisp.h"
23#include "keyboard.h"
23#include "syssignal.h" 24#include "syssignal.h"
24#include "systime.h" 25#include "systime.h"
25#include "atimer.h" 26#include "atimer.h"
diff --git a/src/editfns.c b/src/editfns.c
index bee3bbc2cdd..634aa1f63b2 100644
--- a/src/editfns.c
+++ b/src/editfns.c
@@ -3053,6 +3053,7 @@ determines whether case is significant or ignored. */)
3053 i2 = begp2; 3053 i2 = begp2;
3054 i1_byte = buf_charpos_to_bytepos (bp1, i1); 3054 i1_byte = buf_charpos_to_bytepos (bp1, i1);
3055 i2_byte = buf_charpos_to_bytepos (bp2, i2); 3055 i2_byte = buf_charpos_to_bytepos (bp2, i2);
3056 immediate_quit = true;
3056 3057
3057 while (i1 < endp1 && i2 < endp2) 3058 while (i1 < endp1 && i2 < endp2)
3058 { 3059 {
@@ -3060,8 +3061,6 @@ determines whether case is significant or ignored. */)
3060 characters, not just the bytes. */ 3061 characters, not just the bytes. */
3061 int c1, c2; 3062 int c1, c2;
3062 3063
3063 QUIT;
3064
3065 if (! NILP (BVAR (bp1, enable_multibyte_characters))) 3064 if (! NILP (BVAR (bp1, enable_multibyte_characters)))
3066 { 3065 {
3067 c1 = BUF_FETCH_MULTIBYTE_CHAR (bp1, i1_byte); 3066 c1 = BUF_FETCH_MULTIBYTE_CHAR (bp1, i1_byte);
@@ -3093,14 +3092,17 @@ determines whether case is significant or ignored. */)
3093 c1 = char_table_translate (trt, c1); 3092 c1 = char_table_translate (trt, c1);
3094 c2 = char_table_translate (trt, c2); 3093 c2 = char_table_translate (trt, c2);
3095 } 3094 }
3096 if (c1 < c2) 3095 if (c1 != c2)
3097 return make_number (- 1 - chars); 3096 {
3098 if (c1 > c2) 3097 immediate_quit = false;
3099 return make_number (chars + 1); 3098 return make_number (c1 < c2 ? -1 - chars : chars + 1);
3099 }
3100 3100
3101 chars++; 3101 chars++;
3102 } 3102 }
3103 3103
3104 immediate_quit = false;
3105
3104 /* The strings match as far as they go. 3106 /* The strings match as far as they go.
3105 If one is shorter, that one is less. */ 3107 If one is shorter, that one is less. */
3106 if (chars < endp1 - begp1) 3108 if (chars < endp1 - begp1)
diff --git a/src/eval.c b/src/eval.c
index 01e3db44082..734f01d81ae 100644
--- a/src/eval.c
+++ b/src/eval.c
@@ -1450,7 +1450,7 @@ static Lisp_Object find_handler_clause (Lisp_Object, Lisp_Object);
1450static bool maybe_call_debugger (Lisp_Object conditions, Lisp_Object sig, 1450static bool maybe_call_debugger (Lisp_Object conditions, Lisp_Object sig,
1451 Lisp_Object data); 1451 Lisp_Object data);
1452 1452
1453void 1453static void
1454process_quit_flag (void) 1454process_quit_flag (void)
1455{ 1455{
1456 Lisp_Object flag = Vquit_flag; 1456 Lisp_Object flag = Vquit_flag;
@@ -1462,6 +1462,15 @@ process_quit_flag (void)
1462 quit (); 1462 quit ();
1463} 1463}
1464 1464
1465void
1466maybe_quit (void)
1467{
1468 if (!NILP (Vquit_flag) && NILP (Vinhibit_quit))
1469 process_quit_flag ();
1470 else if (pending_signals)
1471 process_pending_signals ();
1472}
1473
1465DEFUN ("signal", Fsignal, Ssignal, 2, 2, 0, 1474DEFUN ("signal", Fsignal, Ssignal, 2, 2, 0,
1466 doc: /* Signal an error. Args are ERROR-SYMBOL and associated DATA. 1475 doc: /* Signal an error. Args are ERROR-SYMBOL and associated DATA.
1467This function does not return. 1476This function does not return.
diff --git a/src/fns.c b/src/fns.c
index c65a731f325..c175dd935d3 100644
--- a/src/fns.c
+++ b/src/fns.c
@@ -84,9 +84,21 @@ See Info node `(elisp)Random Numbers' for more details. */)
84} 84}
85 85
86/* Heuristic on how many iterations of a tight loop can be safely done 86/* Heuristic on how many iterations of a tight loop can be safely done
87 before it's time to do a QUIT. This must be a power of 2. */ 87 before it's time to do a quit. This must be a power of 2. It
88 is nice but not necessary for it to equal USHRT_MAX + 1. */
88enum { QUIT_COUNT_HEURISTIC = 1 << 16 }; 89enum { QUIT_COUNT_HEURISTIC = 1 << 16 };
89 90
91/* Process a quit, but do it only rarely, for efficiency. "Rarely"
92 means once per QUIT_COUNT_HEURISTIC or per USHRT_MAX + 1 times,
93 whichever is smaller. Use *QUIT_COUNT to count this. */
94
95static void
96rarely_quit (unsigned short int *quit_count)
97{
98 if (! (++*quit_count & (QUIT_COUNT_HEURISTIC - 1)))
99 QUIT;
100}
101
90/* Random data-structure functions. */ 102/* Random data-structure functions. */
91 103
92DEFUN ("length", Flength, Slength, 1, 1, 0, 104DEFUN ("length", Flength, Slength, 1, 1, 0,
@@ -1348,16 +1360,18 @@ DEFUN ("nthcdr", Fnthcdr, Snthcdr, 2, 2, 0,
1348 CHECK_NUMBER (n); 1360 CHECK_NUMBER (n);
1349 EMACS_INT num = XINT (n); 1361 EMACS_INT num = XINT (n);
1350 Lisp_Object tail = list; 1362 Lisp_Object tail = list;
1363 immediate_quit = true;
1351 for (EMACS_INT i = 0; i < num; i++) 1364 for (EMACS_INT i = 0; i < num; i++)
1352 { 1365 {
1353 if (! CONSP (tail)) 1366 if (! CONSP (tail))
1354 { 1367 {
1368 immediate_quit = false;
1355 CHECK_LIST_END (tail, list); 1369 CHECK_LIST_END (tail, list);
1356 return Qnil; 1370 return Qnil;
1357 } 1371 }
1358 tail = XCDR (tail); 1372 tail = XCDR (tail);
1359 QUIT;
1360 } 1373 }
1374 immediate_quit = false;
1361 return tail; 1375 return tail;
1362} 1376}
1363 1377
@@ -1387,12 +1401,13 @@ DEFUN ("member", Fmember, Smember, 2, 2, 0,
1387The value is actually the tail of LIST whose car is ELT. */) 1401The value is actually the tail of LIST whose car is ELT. */)
1388 (Lisp_Object elt, Lisp_Object list) 1402 (Lisp_Object elt, Lisp_Object list)
1389{ 1403{
1404 unsigned short int quit_count = 0;
1390 Lisp_Object tail; 1405 Lisp_Object tail;
1391 for (tail = list; CONSP (tail); tail = XCDR (tail)) 1406 for (tail = list; CONSP (tail); tail = XCDR (tail))
1392 { 1407 {
1393 if (! NILP (Fequal (elt, XCAR (tail)))) 1408 if (! NILP (Fequal (elt, XCAR (tail))))
1394 return tail; 1409 return tail;
1395 QUIT; 1410 rarely_quit (&quit_count);
1396 } 1411 }
1397 CHECK_LIST_END (tail, list); 1412 CHECK_LIST_END (tail, list);
1398 return Qnil; 1413 return Qnil;
@@ -1403,13 +1418,17 @@ DEFUN ("memq", Fmemq, Smemq, 2, 2, 0,
1403The value is actually the tail of LIST whose car is ELT. */) 1418The value is actually the tail of LIST whose car is ELT. */)
1404 (Lisp_Object elt, Lisp_Object list) 1419 (Lisp_Object elt, Lisp_Object list)
1405{ 1420{
1421 immediate_quit = true;
1406 Lisp_Object tail; 1422 Lisp_Object tail;
1407 for (tail = list; CONSP (tail); tail = XCDR (tail)) 1423 for (tail = list; CONSP (tail); tail = XCDR (tail))
1408 { 1424 {
1409 if (EQ (XCAR (tail), elt)) 1425 if (EQ (XCAR (tail), elt))
1410 return tail; 1426 {
1411 QUIT; 1427 immediate_quit = false;
1428 return tail;
1429 }
1412 } 1430 }
1431 immediate_quit = false;
1413 CHECK_LIST_END (tail, list); 1432 CHECK_LIST_END (tail, list);
1414 return Qnil; 1433 return Qnil;
1415} 1434}
@@ -1422,14 +1441,18 @@ The value is actually the tail of LIST whose car is ELT. */)
1422 if (!FLOATP (elt)) 1441 if (!FLOATP (elt))
1423 return Fmemq (elt, list); 1442 return Fmemq (elt, list);
1424 1443
1444 immediate_quit = true;
1425 Lisp_Object tail; 1445 Lisp_Object tail;
1426 for (tail = list; CONSP (tail); tail = XCDR (tail)) 1446 for (tail = list; CONSP (tail); tail = XCDR (tail))
1427 { 1447 {
1428 Lisp_Object tem = XCAR (tail); 1448 Lisp_Object tem = XCAR (tail);
1429 if (FLOATP (tem) && internal_equal (elt, tem, 0, 0, Qnil)) 1449 if (FLOATP (tem) && internal_equal (elt, tem, 0, 0, Qnil))
1430 return tail; 1450 {
1431 QUIT; 1451 immediate_quit = false;
1452 return tail;
1453 }
1432 } 1454 }
1455 immediate_quit = false;
1433 CHECK_LIST_END (tail, list); 1456 CHECK_LIST_END (tail, list);
1434 return Qnil; 1457 return Qnil;
1435} 1458}
@@ -1440,13 +1463,15 @@ The value is actually the first element of LIST whose car is KEY.
1440Elements of LIST that are not conses are ignored. */) 1463Elements of LIST that are not conses are ignored. */)
1441 (Lisp_Object key, Lisp_Object list) 1464 (Lisp_Object key, Lisp_Object list)
1442{ 1465{
1466 immediate_quit = true;
1443 Lisp_Object tail; 1467 Lisp_Object tail;
1444 for (tail = list; CONSP (tail); tail = XCDR (tail)) 1468 for (tail = list; CONSP (tail); tail = XCDR (tail))
1445 { 1469 if (CONSP (XCAR (tail)) && EQ (XCAR (XCAR (tail)), key))
1446 if (CONSP (XCAR (tail)) && EQ (XCAR (XCAR (tail)), key)) 1470 {
1471 immediate_quit = false;
1447 return XCAR (tail); 1472 return XCAR (tail);
1448 QUIT; 1473 }
1449 } 1474 immediate_quit = true;
1450 CHECK_LIST_END (tail, list); 1475 CHECK_LIST_END (tail, list);
1451 return Qnil; 1476 return Qnil;
1452} 1477}
@@ -1468,6 +1493,7 @@ DEFUN ("assoc", Fassoc, Sassoc, 2, 2, 0,
1468The value is actually the first element of LIST whose car equals KEY. */) 1493The value is actually the first element of LIST whose car equals KEY. */)
1469 (Lisp_Object key, Lisp_Object list) 1494 (Lisp_Object key, Lisp_Object list)
1470{ 1495{
1496 unsigned short int quit_count = 0;
1471 Lisp_Object tail; 1497 Lisp_Object tail;
1472 for (tail = list; CONSP (tail); tail = XCDR (tail)) 1498 for (tail = list; CONSP (tail); tail = XCDR (tail))
1473 { 1499 {
@@ -1475,7 +1501,7 @@ The value is actually the first element of LIST whose car equals KEY. */)
1475 if (CONSP (car) 1501 if (CONSP (car)
1476 && (EQ (XCAR (car), key) || !NILP (Fequal (XCAR (car), key)))) 1502 && (EQ (XCAR (car), key) || !NILP (Fequal (XCAR (car), key))))
1477 return car; 1503 return car;
1478 QUIT; 1504 rarely_quit (&quit_count);
1479 } 1505 }
1480 CHECK_LIST_END (tail, list); 1506 CHECK_LIST_END (tail, list);
1481 return Qnil; 1507 return Qnil;
@@ -1502,13 +1528,15 @@ DEFUN ("rassq", Frassq, Srassq, 2, 2, 0,
1502The value is actually the first element of LIST whose cdr is KEY. */) 1528The value is actually the first element of LIST whose cdr is KEY. */)
1503 (Lisp_Object key, Lisp_Object list) 1529 (Lisp_Object key, Lisp_Object list)
1504{ 1530{
1531 immediate_quit = true;
1505 Lisp_Object tail; 1532 Lisp_Object tail;
1506 for (tail = list; CONSP (tail); tail = XCDR (tail)) 1533 for (tail = list; CONSP (tail); tail = XCDR (tail))
1507 { 1534 if (CONSP (XCAR (tail)) && EQ (XCDR (XCAR (tail)), key))
1508 if (CONSP (XCAR (tail)) && EQ (XCDR (XCAR (tail)), key)) 1535 {
1536 immediate_quit = false;
1509 return XCAR (tail); 1537 return XCAR (tail);
1510 QUIT; 1538 }
1511 } 1539 immediate_quit = true;
1512 CHECK_LIST_END (tail, list); 1540 CHECK_LIST_END (tail, list);
1513 return Qnil; 1541 return Qnil;
1514} 1542}
@@ -1518,6 +1546,7 @@ DEFUN ("rassoc", Frassoc, Srassoc, 2, 2, 0,
1518The value is actually the first element of LIST whose cdr equals KEY. */) 1546The value is actually the first element of LIST whose cdr equals KEY. */)
1519 (Lisp_Object key, Lisp_Object list) 1547 (Lisp_Object key, Lisp_Object list)
1520{ 1548{
1549 unsigned short int quit_count = 0;
1521 Lisp_Object tail; 1550 Lisp_Object tail;
1522 for (tail = list; CONSP (tail); tail = XCDR (tail)) 1551 for (tail = list; CONSP (tail); tail = XCDR (tail))
1523 { 1552 {
@@ -1525,7 +1554,7 @@ The value is actually the first element of LIST whose cdr equals KEY. */)
1525 if (CONSP (car) 1554 if (CONSP (car)
1526 && (EQ (XCDR (car), key) || !NILP (Fequal (XCDR (car), key)))) 1555 && (EQ (XCDR (car), key) || !NILP (Fequal (XCDR (car), key))))
1527 return car; 1556 return car;
1528 QUIT; 1557 rarely_quit (&quit_count);
1529 } 1558 }
1530 CHECK_LIST_END (tail, list); 1559 CHECK_LIST_END (tail, list);
1531 return Qnil; 1560 return Qnil;
@@ -1666,6 +1695,7 @@ changing the value of a sequence `foo'. */)
1666 } 1695 }
1667 else 1696 else
1668 { 1697 {
1698 unsigned short int quit_count = 0;
1669 Lisp_Object tail, prev; 1699 Lisp_Object tail, prev;
1670 1700
1671 for (tail = seq, prev = Qnil; CONSP (tail); tail = XCDR (tail)) 1701 for (tail = seq, prev = Qnil; CONSP (tail); tail = XCDR (tail))
@@ -1679,7 +1709,7 @@ changing the value of a sequence `foo'. */)
1679 } 1709 }
1680 else 1710 else
1681 prev = tail; 1711 prev = tail;
1682 QUIT; 1712 rarely_quit (&quit_count);
1683 } 1713 }
1684 CHECK_LIST_END (tail, seq); 1714 CHECK_LIST_END (tail, seq);
1685 } 1715 }
@@ -1699,11 +1729,12 @@ This function may destructively modify SEQ to produce the value. */)
1699 return Freverse (seq); 1729 return Freverse (seq);
1700 else if (CONSP (seq)) 1730 else if (CONSP (seq))
1701 { 1731 {
1732 unsigned short int quit_count = 0;
1702 Lisp_Object prev, tail, next; 1733 Lisp_Object prev, tail, next;
1703 1734
1704 for (prev = Qnil, tail = seq; CONSP (tail); tail = next) 1735 for (prev = Qnil, tail = seq; CONSP (tail); tail = next)
1705 { 1736 {
1706 QUIT; 1737 rarely_quit (&quit_count);
1707 next = XCDR (tail); 1738 next = XCDR (tail);
1708 Fsetcdr (tail, prev); 1739 Fsetcdr (tail, prev);
1709 prev = tail; 1740 prev = tail;
@@ -1749,9 +1780,10 @@ See also the function `nreverse', which is used more often. */)
1749 return Qnil; 1780 return Qnil;
1750 else if (CONSP (seq)) 1781 else if (CONSP (seq))
1751 { 1782 {
1783 unsigned short int quit_count = 0;
1752 for (new = Qnil; CONSP (seq); seq = XCDR (seq)) 1784 for (new = Qnil; CONSP (seq); seq = XCDR (seq))
1753 { 1785 {
1754 QUIT; 1786 rarely_quit (&quit_count);
1755 new = Fcons (XCAR (seq), new); 1787 new = Fcons (XCAR (seq), new);
1756 } 1788 }
1757 CHECK_LIST_END (seq, seq); 1789 CHECK_LIST_END (seq, seq);
@@ -2041,28 +2073,28 @@ If PROP is already a property on the list, its value is set to VAL,
2041otherwise the new PROP VAL pair is added. The new plist is returned; 2073otherwise the new PROP VAL pair is added. The new plist is returned;
2042use `(setq x (plist-put x prop val))' to be sure to use the new value. 2074use `(setq x (plist-put x prop val))' to be sure to use the new value.
2043The PLIST is modified by side effects. */) 2075The PLIST is modified by side effects. */)
2044 (Lisp_Object plist, register Lisp_Object prop, Lisp_Object val) 2076 (Lisp_Object plist, Lisp_Object prop, Lisp_Object val)
2045{ 2077{
2046 register Lisp_Object tail, prev; 2078 immediate_quit = true;
2047 Lisp_Object newcell; 2079 Lisp_Object prev = Qnil;
2048 prev = Qnil; 2080 for (Lisp_Object tail = plist; CONSP (tail) && CONSP (XCDR (tail));
2049 for (tail = plist; CONSP (tail) && CONSP (XCDR (tail));
2050 tail = XCDR (XCDR (tail))) 2081 tail = XCDR (XCDR (tail)))
2051 { 2082 {
2052 if (EQ (prop, XCAR (tail))) 2083 if (EQ (prop, XCAR (tail)))
2053 { 2084 {
2085 immediate_quit = false;
2054 Fsetcar (XCDR (tail), val); 2086 Fsetcar (XCDR (tail), val);
2055 return plist; 2087 return plist;
2056 } 2088 }
2057 2089
2058 prev = tail; 2090 prev = tail;
2059 QUIT;
2060 } 2091 }
2061 newcell = Fcons (prop, Fcons (val, NILP (prev) ? plist : XCDR (XCDR (prev)))); 2092 immediate_quit = true;
2093 Lisp_Object newcell
2094 = Fcons (prop, Fcons (val, NILP (prev) ? plist : XCDR (XCDR (prev))));
2062 if (NILP (prev)) 2095 if (NILP (prev))
2063 return newcell; 2096 return newcell;
2064 else 2097 Fsetcdr (XCDR (prev), newcell);
2065 Fsetcdr (XCDR (prev), newcell);
2066 return plist; 2098 return plist;
2067} 2099}
2068 2100
@@ -2085,6 +2117,7 @@ corresponding to the given PROP, or nil if PROP is not
2085one of the properties on the list. */) 2117one of the properties on the list. */)
2086 (Lisp_Object plist, Lisp_Object prop) 2118 (Lisp_Object plist, Lisp_Object prop)
2087{ 2119{
2120 unsigned short int quit_count = 0;
2088 Lisp_Object tail; 2121 Lisp_Object tail;
2089 2122
2090 for (tail = plist; 2123 for (tail = plist;
@@ -2093,8 +2126,7 @@ one of the properties on the list. */)
2093 { 2126 {
2094 if (! NILP (Fequal (prop, XCAR (tail)))) 2127 if (! NILP (Fequal (prop, XCAR (tail))))
2095 return XCAR (XCDR (tail)); 2128 return XCAR (XCDR (tail));
2096 2129 rarely_quit (&quit_count);
2097 QUIT;
2098 } 2130 }
2099 2131
2100 CHECK_LIST_END (tail, prop); 2132 CHECK_LIST_END (tail, prop);
@@ -2110,12 +2142,11 @@ If PROP is already a property on the list, its value is set to VAL,
2110otherwise the new PROP VAL pair is added. The new plist is returned; 2142otherwise the new PROP VAL pair is added. The new plist is returned;
2111use `(setq x (lax-plist-put x prop val))' to be sure to use the new value. 2143use `(setq x (lax-plist-put x prop val))' to be sure to use the new value.
2112The PLIST is modified by side effects. */) 2144The PLIST is modified by side effects. */)
2113 (Lisp_Object plist, register Lisp_Object prop, Lisp_Object val) 2145 (Lisp_Object plist, Lisp_Object prop, Lisp_Object val)
2114{ 2146{
2115 register Lisp_Object tail, prev; 2147 unsigned short int quit_count = 0;
2116 Lisp_Object newcell; 2148 Lisp_Object prev = Qnil;
2117 prev = Qnil; 2149 for (Lisp_Object tail = plist; CONSP (tail) && CONSP (XCDR (tail));
2118 for (tail = plist; CONSP (tail) && CONSP (XCDR (tail));
2119 tail = XCDR (XCDR (tail))) 2150 tail = XCDR (XCDR (tail)))
2120 { 2151 {
2121 if (! NILP (Fequal (prop, XCAR (tail)))) 2152 if (! NILP (Fequal (prop, XCAR (tail))))
@@ -2125,13 +2156,12 @@ The PLIST is modified by side effects. */)
2125 } 2156 }
2126 2157
2127 prev = tail; 2158 prev = tail;
2128 QUIT; 2159 rarely_quit (&quit_count);
2129 } 2160 }
2130 newcell = list2 (prop, val); 2161 Lisp_Object newcell = list2 (prop, val);
2131 if (NILP (prev)) 2162 if (NILP (prev))
2132 return newcell; 2163 return newcell;
2133 else 2164 Fsetcdr (XCDR (prev), newcell);
2134 Fsetcdr (XCDR (prev), newcell);
2135 return plist; 2165 return plist;
2136} 2166}
2137 2167
@@ -2204,8 +2234,9 @@ internal_equal (Lisp_Object o1, Lisp_Object o2, int depth, bool props,
2204 } 2234 }
2205 } 2235 }
2206 2236
2237 unsigned short int quit_count = 0;
2207 tail_recurse: 2238 tail_recurse:
2208 QUIT; 2239 rarely_quit (&quit_count);
2209 if (EQ (o1, o2)) 2240 if (EQ (o1, o2))
2210 return 1; 2241 return 1;
2211 if (XTYPE (o1) != XTYPE (o2)) 2242 if (XTYPE (o1) != XTYPE (o2))
@@ -2394,14 +2425,12 @@ Only the last argument is not altered, and need not be a list.
2394usage: (nconc &rest LISTS) */) 2425usage: (nconc &rest LISTS) */)
2395 (ptrdiff_t nargs, Lisp_Object *args) 2426 (ptrdiff_t nargs, Lisp_Object *args)
2396{ 2427{
2397 ptrdiff_t argnum; 2428 unsigned short int quit_count = 0;
2398 register Lisp_Object tail, tem, val; 2429 Lisp_Object val = Qnil;
2399 2430
2400 val = tail = Qnil; 2431 for (ptrdiff_t argnum = 0; argnum < nargs; argnum++)
2401
2402 for (argnum = 0; argnum < nargs; argnum++)
2403 { 2432 {
2404 tem = args[argnum]; 2433 Lisp_Object tem = args[argnum];
2405 if (NILP (tem)) continue; 2434 if (NILP (tem)) continue;
2406 2435
2407 if (NILP (val)) 2436 if (NILP (val))
@@ -2411,14 +2440,18 @@ usage: (nconc &rest LISTS) */)
2411 2440
2412 CHECK_CONS (tem); 2441 CHECK_CONS (tem);
2413 2442
2443 immediate_quit = true;
2444 Lisp_Object tail;
2414 do 2445 do
2415 { 2446 {
2416 tail = tem; 2447 tail = tem;
2417 tem = XCDR (tail); 2448 tem = XCDR (tail);
2418 QUIT;
2419 } 2449 }
2420 while (CONSP (tem)); 2450 while (CONSP (tem));
2421 2451
2452 immediate_quit = false;
2453 rarely_quit (&quit_count);
2454
2422 tem = args[argnum + 1]; 2455 tem = args[argnum + 1];
2423 Fsetcdr (tail, tem); 2456 Fsetcdr (tail, tem);
2424 if (NILP (tem)) 2457 if (NILP (tem))
@@ -2839,12 +2872,13 @@ property and a property with the value nil.
2839The value is actually the tail of PLIST whose car is PROP. */) 2872The value is actually the tail of PLIST whose car is PROP. */)
2840 (Lisp_Object plist, Lisp_Object prop) 2873 (Lisp_Object plist, Lisp_Object prop)
2841{ 2874{
2875 immediate_quit = true;
2842 while (CONSP (plist) && !EQ (XCAR (plist), prop)) 2876 while (CONSP (plist) && !EQ (XCAR (plist), prop))
2843 { 2877 {
2844 plist = XCDR (plist); 2878 plist = XCDR (plist);
2845 plist = CDR (plist); 2879 plist = CDR (plist);
2846 QUIT;
2847 } 2880 }
2881 immediate_quit = false;
2848 return plist; 2882 return plist;
2849} 2883}
2850 2884
diff --git a/src/keyboard.h b/src/keyboard.h
index 7cd41ae55b6..2219c011352 100644
--- a/src/keyboard.h
+++ b/src/keyboard.h
@@ -486,6 +486,8 @@ extern bool kbd_buffer_events_waiting (void);
486extern void add_user_signal (int, const char *); 486extern void add_user_signal (int, const char *);
487 487
488extern int tty_read_avail_input (struct terminal *, struct input_event *); 488extern int tty_read_avail_input (struct terminal *, struct input_event *);
489extern bool volatile pending_signals;
490extern void process_pending_signals (void);
489extern struct timespec timer_check (void); 491extern struct timespec timer_check (void);
490extern void mark_kboards (void); 492extern void mark_kboards (void);
491 493
diff --git a/src/lisp.h b/src/lisp.h
index 7e918249935..01a08a05f20 100644
--- a/src/lisp.h
+++ b/src/lisp.h
@@ -3133,20 +3133,12 @@ extern Lisp_Object memory_signal_data;
3133 and (in particular) cannot call arbitrary Lisp code. 3133 and (in particular) cannot call arbitrary Lisp code.
3134 3134
3135 If quit-flag is set to `kill-emacs' the SIGINT handler has received 3135 If quit-flag is set to `kill-emacs' the SIGINT handler has received
3136 a request to exit Emacs when it is safe to do. */ 3136 a request to exit Emacs when it is safe to do.
3137 3137
3138extern void process_pending_signals (void); 3138 When not quitting, process any pending signals. */
3139extern bool volatile pending_signals;
3140
3141extern void process_quit_flag (void);
3142#define QUIT \
3143 do { \
3144 if (!NILP (Vquit_flag) && NILP (Vinhibit_quit)) \
3145 process_quit_flag (); \
3146 else if (pending_signals) \
3147 process_pending_signals (); \
3148 } while (false)
3149 3139
3140extern void maybe_quit (void);
3141#define QUIT maybe_quit ()
3150 3142
3151/* True if ought to quit now. */ 3143/* True if ought to quit now. */
3152 3144