From 818333c85a513dc2d0ae9ee00ecde983c4fe0269 Mon Sep 17 00:00:00 2001 From: Paul Eggert Date: Sat, 7 Mar 2020 09:30:19 -0800 Subject: [PATCH 1/5] * doc/lispref/os.texi (time-subtract): Doc fix. --- doc/lispref/os.texi | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/doc/lispref/os.texi b/doc/lispref/os.texi index 201ca18c1e4..92aaf24b851 100644 --- a/doc/lispref/os.texi +++ b/doc/lispref/os.texi @@ -1978,10 +1978,9 @@ The result is @code{nil} if either argument is a NaN. @defun time-subtract t1 t2 This returns the time difference @var{t1} @minus{} @var{t2} between -two time values, normally as a Lisp timestamp but as a float -if either argument is infinite or a NaN@. -When the result is a timestamp, it is exact and its clock +two time values, as a Lisp time value. The result is exact and its clock resolution is no worse than the worse of its two arguments' resolutions. +The result is floating-point only if it is infinite or a NaN. If you need the difference in units of elapsed seconds, you can convert it with @code{time-convert} or @code{float-time}. @xref{Time Conversion}. From 363d927086dbdc4e5073393889b76eb0470785f4 Mon Sep 17 00:00:00 2001 From: Paul Eggert Date: Sat, 7 Mar 2020 09:47:03 -0800 Subject: [PATCH 2/5] Fix bug with JIT stealth timers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * lisp/emacs-lisp/timer.el (run-at-time): Don’t assume that Lisp time values must be conses (Bug#39944). --- lisp/emacs-lisp/timer.el | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 (decoded-time-year now) (decoded-time-zone now))))))) - (or (consp time) + (or (time-equal-p time time) (error "Invalid time format")) (let ((timer (timer-create))) From 3cbf4cb79600ade39a186f31448e56e0e6fdd364 Mon Sep 17 00:00:00 2001 From: Andrew Eggenberger Date: Thu, 27 Feb 2020 21:43:47 -0600 Subject: [PATCH 3/5] Eliminate use of cl-concatenate in 'seq' package Fixes (Bug#39761) by making cl-extra dependent on seq rather than vice versa. * lisp/emacs-lisp/seq.el (seq-concatenate): Move cl-concatenate's code here instead of calling it. * lisp/emacs-lisp/cl-extra.el (cl-concatenate): Use cl-concatenate. Copyright-paperwork-exempt: yes --- lisp/emacs-lisp/cl-extra.el | 6 +----- lisp/emacs-lisp/seq.el | 6 +++++- 2 files changed, 6 insertions(+), 6 deletions(-) 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)." (defun cl-concatenate (type &rest sequences) "Concatenate, into a sequence of type TYPE, the argument SEQUENCEs. \n(fn TYPE SEQUENCE...)" - (pcase type - ('vector (apply #'vconcat sequences)) - ('string (apply #'concat sequences)) - ('list (apply #'append (append sequences '(nil)))) - (_ (error "Not a sequence type name: %S" type)))) + (seq-concatenate type sequences)) ;;; List functions. diff --git a/lisp/emacs-lisp/seq.el b/lisp/emacs-lisp/seq.el index 0b946dd7365..629a7a5fb30 100644 --- a/lisp/emacs-lisp/seq.el +++ b/lisp/emacs-lisp/seq.el @@ -285,7 +285,11 @@ sorted. FUNCTION must be a function of one argument." TYPE must be one of following symbols: vector, string or list. \n(fn TYPE SEQUENCE...)" - (apply #'cl-concatenate type (seq-map #'seq-into-sequence sequences))) + (pcase type + ('vector (apply #'vconcat sequences)) + ('string (apply #'concat sequences)) + ('list (apply #'append (append sequences '(nil)))) + (_ (error "Not a sequence type name: %S" type)))) (cl-defgeneric seq-into-sequence (sequence) "Convert SEQUENCE into a sequence. From b16ba4041db928826df5f58e9bfac9fb38208145 Mon Sep 17 00:00:00 2001 From: Noam Postavsky Date: Sat, 7 Mar 2020 18:45:23 -0500 Subject: [PATCH 4/5] ; lisp/emacs-lisp/seq.el: Explain why we don't use cl-lib here --- lisp/emacs-lisp/seq.el | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/lisp/emacs-lisp/seq.el b/lisp/emacs-lisp/seq.el index 629a7a5fb30..e3037a71901 100644 --- a/lisp/emacs-lisp/seq.el +++ b/lisp/emacs-lisp/seq.el @@ -58,6 +58,10 @@ (eval-when-compile (require 'cl-generic)) +;; We used to use some sequence functions from cl-lib, but this +;; dependency was swapped around so that it will be easier to make +;; seq.el preloaded in the future. See also Bug#39761#26. + (defmacro seq-doseq (spec &rest body) "Loop over a sequence. Evaluate BODY with VAR bound to each element of SEQUENCE, in turn. From 0a3682a566d5563e3d57defe49359cee236e0274 Mon Sep 17 00:00:00 2001 From: Paul Eggert Date: Sun, 8 Mar 2020 00:16:17 -0800 Subject: [PATCH 5/5] * src/timefns.c: Add comments. --- src/timefns.c | 32 ++++++++++++++++++++++++-------- 1 file changed, 24 insertions(+), 8 deletions(-) diff --git a/src/timefns.c b/src/timefns.c index a08d3b816ff..8e2bb214ed8 100644 --- a/src/timefns.c +++ b/src/timefns.c @@ -491,11 +491,14 @@ timespec_mpz (struct timespec t) static Lisp_Object timespec_ticks (struct timespec t) { + /* For speed, use intmax_t arithmetic if it will do. */ intmax_t accum; if (FASTER_TIMEFNS && !INT_MULTIPLY_WRAPV (t.tv_sec, TIMESPEC_HZ, &accum) && !INT_ADD_WRAPV (t.tv_nsec, accum, &accum)) return make_int (accum); + + /* Fall back on bignum arithmetic. */ timespec_mpz (t); return make_integer_mpz (); } @@ -505,12 +508,17 @@ timespec_ticks (struct timespec t) static Lisp_Object lisp_time_hz_ticks (struct lisp_time t, Lisp_Object hz) { + /* For speed, just return TICKS if T is (TICKS . HZ). */ if (FASTER_TIMEFNS && EQ (t.hz, hz)) return t.ticks; + + /* Check HZ for validity. */ if (FIXNUMP (hz)) { if (XFIXNUM (hz) <= 0) invalid_hz (hz); + + /* For speed, use intmax_t arithmetic if it will do. */ intmax_t ticks; if (FASTER_TIMEFNS && FIXNUMP (t.ticks) && FIXNUMP (t.hz) && !INT_MULTIPLY_WRAPV (XFIXNUM (t.ticks), XFIXNUM (hz), &ticks)) @@ -520,6 +528,7 @@ lisp_time_hz_ticks (struct lisp_time t, Lisp_Object hz) else if (! (BIGNUMP (hz) && 0 < mpz_sgn (*xbignum_val (hz)))) invalid_hz (hz); + /* Fall back on bignum arithmetic. */ mpz_mul (mpz[0], *bignum_integer (&mpz[0], t.ticks), *bignum_integer (&mpz[1], hz)); @@ -533,9 +542,13 @@ lisp_time_seconds (struct lisp_time t) { if (!FASTER_TIMEFNS) return lisp_time_hz_ticks (t, make_fixnum (1)); + + /* For speed, use EMACS_INT arithmetic if it will do. */ if (FIXNUMP (t.ticks) && FIXNUMP (t.hz)) return make_fixnum (XFIXNUM (t.ticks) / XFIXNUM (t.hz) - (XFIXNUM (t.ticks) % XFIXNUM (t.hz) < 0)); + + /* For speed, inline what lisp_time_hz_ticks would do. */ mpz_fdiv_q (mpz[0], *bignum_integer (&mpz[0], t.ticks), *bignum_integer (&mpz[1], t.hz)); @@ -1116,21 +1129,22 @@ time_arith (Lisp_Object a, Lisp_Object b, bool subtract) (subtract ? mpz_submul : mpz_addmul) (*iticks, *fa, *nb); /* Normalize iticks/ihz by dividing both numerator and - denominator by ig = gcd (iticks, ihz). However, if that - would cause the denominator to become less than hzmin, - rescale the denominator upwards from its ordinary value by - multiplying numerator and denominator so that the denominator - becomes at least hzmin. This rescaling avoids returning a - timestamp that is less precise than both a and b, or a - timestamp that looks obsolete when that might be a problem. */ + denominator by ig = gcd (iticks, ihz). For speed, though, + skip this division if ihz = 1. */ mpz_t *ig = &mpz[3]; mpz_gcd (*ig, *iticks, *ihz); - if (!FASTER_TIMEFNS || mpz_cmp_ui (*ig, 1) > 0) { mpz_divexact (*iticks, *iticks, *ig); mpz_divexact (*ihz, *ihz, *ig); + /* However, if dividing the denominator by ig would cause the + denominator to become less than hzmin, rescale the denominator + upwards by multiplying the normalized numerator and denominator + so that the resulting denominator becomes at least hzmin. + This rescaling avoids returning a timestamp that is less precise + than both a and b, or a timestamp that looks obsolete when that + might be a problem. */ if (!FASTER_TIMEFNS || mpz_cmp (*ihz, *hzmin) < 0) { /* Rescale straightforwardly. Although this might not @@ -1144,6 +1158,8 @@ time_arith (Lisp_Object a, Lisp_Object b, bool subtract) mpz_mul (*ihz, *ihz, *rescale); } } + + /* mpz[0] and iticks now correspond to the (HZ . TICKS) pair. */ hz = make_integer_mpz (); mpz_swap (mpz[0], *iticks); ticks = make_integer_mpz ();