diff options
| author | Paul Eggert | 2017-01-25 20:27:45 -0800 |
|---|---|---|
| committer | Paul Eggert | 2017-01-25 21:25:37 -0800 |
| commit | 1392ec7420ee23238a1588b759c631d87a677483 (patch) | |
| tree | ca89387ce9acf91005465c7359dc4e212375c479 | |
| parent | 0dfd9a69186e12e53b8aa759c47b9747de92db43 (diff) | |
| download | emacs-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.c | 1 | ||||
| -rw-r--r-- | src/editfns.c | 14 | ||||
| -rw-r--r-- | src/eval.c | 11 | ||||
| -rw-r--r-- | src/fns.c | 132 | ||||
| -rw-r--r-- | src/keyboard.h | 2 | ||||
| -rw-r--r-- | src/lisp.h | 16 |
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); | |||
| 1450 | static bool maybe_call_debugger (Lisp_Object conditions, Lisp_Object sig, | 1450 | static bool maybe_call_debugger (Lisp_Object conditions, Lisp_Object sig, |
| 1451 | Lisp_Object data); | 1451 | Lisp_Object data); |
| 1452 | 1452 | ||
| 1453 | void | 1453 | static void |
| 1454 | process_quit_flag (void) | 1454 | process_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 | ||
| 1465 | void | ||
| 1466 | maybe_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 | |||
| 1465 | DEFUN ("signal", Fsignal, Ssignal, 2, 2, 0, | 1474 | DEFUN ("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. |
| 1467 | This function does not return. | 1476 | This function does not return. |
| @@ -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. */ | ||
| 88 | enum { QUIT_COUNT_HEURISTIC = 1 << 16 }; | 89 | enum { 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 | |||
| 95 | static void | ||
| 96 | rarely_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 | ||
| 92 | DEFUN ("length", Flength, Slength, 1, 1, 0, | 104 | DEFUN ("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, | |||
| 1387 | The value is actually the tail of LIST whose car is ELT. */) | 1401 | The 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, | |||
| 1403 | The value is actually the tail of LIST whose car is ELT. */) | 1418 | The 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. | |||
| 1440 | Elements of LIST that are not conses are ignored. */) | 1463 | Elements 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, | |||
| 1468 | The value is actually the first element of LIST whose car equals KEY. */) | 1493 | The 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, | |||
| 1502 | The value is actually the first element of LIST whose cdr is KEY. */) | 1528 | The 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, | |||
| 1518 | The value is actually the first element of LIST whose cdr equals KEY. */) | 1546 | The 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, | |||
| 2041 | otherwise the new PROP VAL pair is added. The new plist is returned; | 2073 | otherwise the new PROP VAL pair is added. The new plist is returned; |
| 2042 | use `(setq x (plist-put x prop val))' to be sure to use the new value. | 2074 | use `(setq x (plist-put x prop val))' to be sure to use the new value. |
| 2043 | The PLIST is modified by side effects. */) | 2075 | The 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 | |||
| 2085 | one of the properties on the list. */) | 2117 | one 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, | |||
| 2110 | otherwise the new PROP VAL pair is added. The new plist is returned; | 2142 | otherwise the new PROP VAL pair is added. The new plist is returned; |
| 2111 | use `(setq x (lax-plist-put x prop val))' to be sure to use the new value. | 2143 | use `(setq x (lax-plist-put x prop val))' to be sure to use the new value. |
| 2112 | The PLIST is modified by side effects. */) | 2144 | The 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. | |||
| 2394 | usage: (nconc &rest LISTS) */) | 2425 | usage: (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. | |||
| 2839 | The value is actually the tail of PLIST whose car is PROP. */) | 2872 | The 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); | |||
| 486 | extern void add_user_signal (int, const char *); | 486 | extern void add_user_signal (int, const char *); |
| 487 | 487 | ||
| 488 | extern int tty_read_avail_input (struct terminal *, struct input_event *); | 488 | extern int tty_read_avail_input (struct terminal *, struct input_event *); |
| 489 | extern bool volatile pending_signals; | ||
| 490 | extern void process_pending_signals (void); | ||
| 489 | extern struct timespec timer_check (void); | 491 | extern struct timespec timer_check (void); |
| 490 | extern void mark_kboards (void); | 492 | extern 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 | ||
| 3138 | extern void process_pending_signals (void); | 3138 | When not quitting, process any pending signals. */ |
| 3139 | extern bool volatile pending_signals; | ||
| 3140 | |||
| 3141 | extern 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 | ||
| 3140 | extern 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 | ||