aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPaul Eggert2017-01-25 20:27:45 -0800
committerPaul Eggert2017-01-25 21:25:37 -0800
commit1392ec7420ee23238a1588b759c631d87a677483 (patch)
treeca89387ce9acf91005465c7359dc4e212375c479
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.
-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