aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPaul Eggert2020-03-08 00:20:57 -0800
committerPaul Eggert2020-03-08 00:20:57 -0800
commit4415534ef01309417e8f552eb4c075095603f2f3 (patch)
treeca55889bb9636c2b2d16e4a29fcc14b2d18e3fdc
parente4fb95fa18072cedb021a82f7aa0e79fa6ca387a (diff)
parent0a3682a566d5563e3d57defe49359cee236e0274 (diff)
downloademacs-4415534ef01309417e8f552eb4c075095603f2f3.tar.gz
emacs-4415534ef01309417e8f552eb4c075095603f2f3.zip
Merge from origin/emacs-27
0a3682a566 * src/timefns.c: Add comments. b16ba4041d ; lisp/emacs-lisp/seq.el: Explain why we don't use cl-lib ... 3cbf4cb796 Eliminate use of cl-concatenate in 'seq' package 363d927086 Fix bug with JIT stealth timers 818333c85a * doc/lispref/os.texi (time-subtract): Doc fix.
-rw-r--r--doc/lispref/os.texi5
-rw-r--r--lisp/emacs-lisp/cl-extra.el6
-rw-r--r--lisp/emacs-lisp/seq.el10
-rw-r--r--lisp/emacs-lisp/timer.el2
-rw-r--r--src/timefns.c32
5 files changed, 37 insertions, 18 deletions
diff --git a/doc/lispref/os.texi b/doc/lispref/os.texi
index cf4ef52abfb..e72858bbf1a 100644
--- a/doc/lispref/os.texi
+++ b/doc/lispref/os.texi
@@ -1979,10 +1979,9 @@ The result is @code{nil} if either argument is a NaN.
1979 1979
1980@defun time-subtract t1 t2 1980@defun time-subtract t1 t2
1981This returns the time difference @var{t1} @minus{} @var{t2} between 1981This returns the time difference @var{t1} @minus{} @var{t2} between
1982two time values, normally as a Lisp timestamp but as a float 1982two time values, as a Lisp time value. The result is exact and its clock
1983if either argument is infinite or a NaN@.
1984When the result is a timestamp, it is exact and its clock
1985resolution is no worse than the worse of its two arguments' resolutions. 1983resolution is no worse than the worse of its two arguments' resolutions.
1984The result is floating-point only if it is infinite or a NaN.
1986If you need the difference in units 1985If you need the difference in units
1987of elapsed seconds, you can convert it with @code{time-convert} or 1986of elapsed seconds, you can convert it with @code{time-convert} or
1988@code{float-time}. @xref{Time Conversion}. 1987@code{float-time}. @xref{Time Conversion}.
diff --git a/lisp/emacs-lisp/cl-extra.el b/lisp/emacs-lisp/cl-extra.el
index e3dabdfcef2..e9bfe8df5f2 100644
--- a/lisp/emacs-lisp/cl-extra.el
+++ b/lisp/emacs-lisp/cl-extra.el
@@ -556,11 +556,7 @@ too large if positive or too small if negative)."
556(defun cl-concatenate (type &rest sequences) 556(defun cl-concatenate (type &rest sequences)
557 "Concatenate, into a sequence of type TYPE, the argument SEQUENCEs. 557 "Concatenate, into a sequence of type TYPE, the argument SEQUENCEs.
558\n(fn TYPE SEQUENCE...)" 558\n(fn TYPE SEQUENCE...)"
559 (pcase type 559 (seq-concatenate type sequences))
560 ('vector (apply #'vconcat sequences))
561 ('string (apply #'concat sequences))
562 ('list (apply #'append (append sequences '(nil))))
563 (_ (error "Not a sequence type name: %S" type))))
564 560
565;;; List functions. 561;;; List functions.
566 562
diff --git a/lisp/emacs-lisp/seq.el b/lisp/emacs-lisp/seq.el
index 0b946dd7365..e3037a71901 100644
--- a/lisp/emacs-lisp/seq.el
+++ b/lisp/emacs-lisp/seq.el
@@ -58,6 +58,10 @@
58 58
59(eval-when-compile (require 'cl-generic)) 59(eval-when-compile (require 'cl-generic))
60 60
61;; We used to use some sequence functions from cl-lib, but this
62;; dependency was swapped around so that it will be easier to make
63;; seq.el preloaded in the future. See also Bug#39761#26.
64
61(defmacro seq-doseq (spec &rest body) 65(defmacro seq-doseq (spec &rest body)
62 "Loop over a sequence. 66 "Loop over a sequence.
63Evaluate BODY with VAR bound to each element of SEQUENCE, in turn. 67Evaluate BODY with VAR bound to each element of SEQUENCE, in turn.
@@ -285,7 +289,11 @@ sorted. FUNCTION must be a function of one argument."
285TYPE must be one of following symbols: vector, string or list. 289TYPE must be one of following symbols: vector, string or list.
286 290
287\n(fn TYPE SEQUENCE...)" 291\n(fn TYPE SEQUENCE...)"
288 (apply #'cl-concatenate type (seq-map #'seq-into-sequence sequences))) 292 (pcase type
293 ('vector (apply #'vconcat sequences))
294 ('string (apply #'concat sequences))
295 ('list (apply #'append (append sequences '(nil))))
296 (_ (error "Not a sequence type name: %S" type))))
289 297
290(cl-defgeneric seq-into-sequence (sequence) 298(cl-defgeneric seq-into-sequence (sequence)
291 "Convert SEQUENCE into a sequence. 299 "Convert SEQUENCE into a sequence.
diff --git a/lisp/emacs-lisp/timer.el b/lisp/emacs-lisp/timer.el
index 74a94957e73..9eb8feed0f1 100644
--- a/lisp/emacs-lisp/timer.el
+++ b/lisp/emacs-lisp/timer.el
@@ -378,7 +378,7 @@ This function returns a timer object which you can use in
378 (decoded-time-year now) 378 (decoded-time-year now)
379 (decoded-time-zone now))))))) 379 (decoded-time-zone now)))))))
380 380
381 (or (consp time) 381 (or (time-equal-p time time)
382 (error "Invalid time format")) 382 (error "Invalid time format"))
383 383
384 (let ((timer (timer-create))) 384 (let ((timer (timer-create)))
diff --git a/src/timefns.c b/src/timefns.c
index 41db1e68759..6dd6e1611a4 100644
--- a/src/timefns.c
+++ b/src/timefns.c
@@ -491,11 +491,14 @@ timespec_mpz (struct timespec t)
491static Lisp_Object 491static Lisp_Object
492timespec_ticks (struct timespec t) 492timespec_ticks (struct timespec t)
493{ 493{
494 /* For speed, use intmax_t arithmetic if it will do. */
494 intmax_t accum; 495 intmax_t accum;
495 if (FASTER_TIMEFNS 496 if (FASTER_TIMEFNS
496 && !INT_MULTIPLY_WRAPV (t.tv_sec, TIMESPEC_HZ, &accum) 497 && !INT_MULTIPLY_WRAPV (t.tv_sec, TIMESPEC_HZ, &accum)
497 && !INT_ADD_WRAPV (t.tv_nsec, accum, &accum)) 498 && !INT_ADD_WRAPV (t.tv_nsec, accum, &accum))
498 return make_int (accum); 499 return make_int (accum);
500
501 /* Fall back on bignum arithmetic. */
499 timespec_mpz (t); 502 timespec_mpz (t);
500 return make_integer_mpz (); 503 return make_integer_mpz ();
501} 504}
@@ -505,12 +508,17 @@ timespec_ticks (struct timespec t)
505static Lisp_Object 508static Lisp_Object
506lisp_time_hz_ticks (struct lisp_time t, Lisp_Object hz) 509lisp_time_hz_ticks (struct lisp_time t, Lisp_Object hz)
507{ 510{
511 /* For speed, just return TICKS if T is (TICKS . HZ). */
508 if (FASTER_TIMEFNS && EQ (t.hz, hz)) 512 if (FASTER_TIMEFNS && EQ (t.hz, hz))
509 return t.ticks; 513 return t.ticks;
514
515 /* Check HZ for validity. */
510 if (FIXNUMP (hz)) 516 if (FIXNUMP (hz))
511 { 517 {
512 if (XFIXNUM (hz) <= 0) 518 if (XFIXNUM (hz) <= 0)
513 invalid_hz (hz); 519 invalid_hz (hz);
520
521 /* For speed, use intmax_t arithmetic if it will do. */
514 intmax_t ticks; 522 intmax_t ticks;
515 if (FASTER_TIMEFNS && FIXNUMP (t.ticks) && FIXNUMP (t.hz) 523 if (FASTER_TIMEFNS && FIXNUMP (t.ticks) && FIXNUMP (t.hz)
516 && !INT_MULTIPLY_WRAPV (XFIXNUM (t.ticks), XFIXNUM (hz), &ticks)) 524 && !INT_MULTIPLY_WRAPV (XFIXNUM (t.ticks), XFIXNUM (hz), &ticks))
@@ -520,6 +528,7 @@ lisp_time_hz_ticks (struct lisp_time t, Lisp_Object hz)
520 else if (! (BIGNUMP (hz) && 0 < mpz_sgn (*xbignum_val (hz)))) 528 else if (! (BIGNUMP (hz) && 0 < mpz_sgn (*xbignum_val (hz))))
521 invalid_hz (hz); 529 invalid_hz (hz);
522 530
531 /* Fall back on bignum arithmetic. */
523 mpz_mul (mpz[0], 532 mpz_mul (mpz[0],
524 *bignum_integer (&mpz[0], t.ticks), 533 *bignum_integer (&mpz[0], t.ticks),
525 *bignum_integer (&mpz[1], hz)); 534 *bignum_integer (&mpz[1], hz));
@@ -533,9 +542,13 @@ lisp_time_seconds (struct lisp_time t)
533{ 542{
534 if (!FASTER_TIMEFNS) 543 if (!FASTER_TIMEFNS)
535 return lisp_time_hz_ticks (t, make_fixnum (1)); 544 return lisp_time_hz_ticks (t, make_fixnum (1));
545
546 /* For speed, use EMACS_INT arithmetic if it will do. */
536 if (FIXNUMP (t.ticks) && FIXNUMP (t.hz)) 547 if (FIXNUMP (t.ticks) && FIXNUMP (t.hz))
537 return make_fixnum (XFIXNUM (t.ticks) / XFIXNUM (t.hz) 548 return make_fixnum (XFIXNUM (t.ticks) / XFIXNUM (t.hz)
538 - (XFIXNUM (t.ticks) % XFIXNUM (t.hz) < 0)); 549 - (XFIXNUM (t.ticks) % XFIXNUM (t.hz) < 0));
550
551 /* For speed, inline what lisp_time_hz_ticks would do. */
539 mpz_fdiv_q (mpz[0], 552 mpz_fdiv_q (mpz[0],
540 *bignum_integer (&mpz[0], t.ticks), 553 *bignum_integer (&mpz[0], t.ticks),
541 *bignum_integer (&mpz[1], t.hz)); 554 *bignum_integer (&mpz[1], t.hz));
@@ -1122,21 +1135,22 @@ time_arith (Lisp_Object a, Lisp_Object b, bool subtract)
1122 (subtract ? mpz_submul : mpz_addmul) (*iticks, *fa, *nb); 1135 (subtract ? mpz_submul : mpz_addmul) (*iticks, *fa, *nb);
1123 1136
1124 /* Normalize iticks/ihz by dividing both numerator and 1137 /* Normalize iticks/ihz by dividing both numerator and
1125 denominator by ig = gcd (iticks, ihz). However, if that 1138 denominator by ig = gcd (iticks, ihz). For speed, though,
1126 would cause the denominator to become less than hzmin, 1139 skip this division if ihz = 1. */
1127 rescale the denominator upwards from its ordinary value by
1128 multiplying numerator and denominator so that the denominator
1129 becomes at least hzmin. This rescaling avoids returning a
1130 timestamp that is less precise than both a and b, or a
1131 timestamp that looks obsolete when that might be a problem. */
1132 mpz_t *ig = &mpz[3]; 1140 mpz_t *ig = &mpz[3];
1133 mpz_gcd (*ig, *iticks, *ihz); 1141 mpz_gcd (*ig, *iticks, *ihz);
1134
1135 if (!FASTER_TIMEFNS || mpz_cmp_ui (*ig, 1) > 0) 1142 if (!FASTER_TIMEFNS || mpz_cmp_ui (*ig, 1) > 0)
1136 { 1143 {
1137 mpz_divexact (*iticks, *iticks, *ig); 1144 mpz_divexact (*iticks, *iticks, *ig);
1138 mpz_divexact (*ihz, *ihz, *ig); 1145 mpz_divexact (*ihz, *ihz, *ig);
1139 1146
1147 /* However, if dividing the denominator by ig would cause the
1148 denominator to become less than hzmin, rescale the denominator
1149 upwards by multiplying the normalized numerator and denominator
1150 so that the resulting denominator becomes at least hzmin.
1151 This rescaling avoids returning a timestamp that is less precise
1152 than both a and b, or a timestamp that looks obsolete when that
1153 might be a problem. */
1140 if (!FASTER_TIMEFNS || mpz_cmp (*ihz, *hzmin) < 0) 1154 if (!FASTER_TIMEFNS || mpz_cmp (*ihz, *hzmin) < 0)
1141 { 1155 {
1142 /* Rescale straightforwardly. Although this might not 1156 /* Rescale straightforwardly. Although this might not
@@ -1150,6 +1164,8 @@ time_arith (Lisp_Object a, Lisp_Object b, bool subtract)
1150 mpz_mul (*ihz, *ihz, *rescale); 1164 mpz_mul (*ihz, *ihz, *rescale);
1151 } 1165 }
1152 } 1166 }
1167
1168 /* mpz[0] and iticks now correspond to the (HZ . TICKS) pair. */
1153 hz = make_integer_mpz (); 1169 hz = make_integer_mpz ();
1154 mpz_swap (mpz[0], *iticks); 1170 mpz_swap (mpz[0], *iticks);
1155 ticks = make_integer_mpz (); 1171 ticks = make_integer_mpz ();