]> git.eshelyaron.com Git - emacs.git/commitdiff
Always allow at least double-precision bignums
authorPaul Eggert <eggert@cs.ucla.edu>
Tue, 4 Jun 2019 15:13:20 +0000 (08:13 -0700)
committerPaul Eggert <eggert@cs.ucla.edu>
Tue, 4 Jun 2019 15:34:15 +0000 (08:34 -0700)
Without this fix, Emacs can get into a tight loop reporting
a range error when calculating timestamps.
* doc/lispref/numbers.texi (Integer Basics):
* src/alloc.c (syms_of_alloc): Document this.
* src/bignum.c (make_bignum_bits): Always allow bignums
of at least twice the width of (u)intmax_t.

doc/lispref/numbers.texi
src/alloc.c
src/bignum.c

index fbdd83fa86ed033d4fcbd632cb3edc977d90b8a5..cae8babcb40bf0e3b8ac9521f26d26b32dfb2216 100644 (file)
@@ -191,19 +191,19 @@ on 64-bit platforms.
 @cindex integer range
 @cindex number of bignum bits, limit on
 @defvar integer-width
-The value of this variable is a nonnegative integer that is an upper
-bound on the number of bits in a bignum.  Integers outside the fixnum
-range are limited to absolute values less than
+The value of this variable is a nonnegative integer that controls
+whether Emacs signals a range error when a large integer would be
+calculated.  Integers with absolute values less than
 @ifnottex
 2**@var{n},
 @end ifnottex
 @tex
 @math{2^{n}},
 @end tex
-where @var{n} is this variable's value.  Attempts to create bignums outside
-this range signal a range error.  Setting this variable
-to zero disables creation of bignums; setting it to a large number can
-cause Emacs to consume large quantities of memory if a computation
+where @var{n} is this variable's value, do not signal a range error.
+Attempts to create larger integers typically signal a range error,
+although there might be no signal if a larger integer can be created cheaply.
+Setting this variable to a large number can be costly if a computation
 creates huge integers.
 @end defvar
 
index 5c5b56d02e9a2d41139aa69325cf51bac687173a..64aaa8acdfa75d6110bcca707964221fdc9e39c6 100644 (file)
@@ -7369,9 +7369,9 @@ The time is in seconds as a floating point value.  */);
               doc: /* Accumulated number of garbage collections done.  */);
 
   DEFVAR_INT ("integer-width", integer_width,
-             doc: /* Maximum number of bits in bignums.
-Integers outside the fixnum range are limited to absolute values less
-than 2**N, where N is this variable's value.  N should be nonnegative.  */);
+             doc: /* Maximum number N of bits in safely-calculated integers.
+Integers with absolute values less than 2**N do not signal a range error.
+N should be nonnegative.  */);
 
   defsubr (&Scons);
   defsubr (&Slist);
index 009d73118c29369d2737399a1f9c89a2135ea2c2..3883d3a39446cbc1db587f764858107a08e83418 100644 (file)
@@ -82,8 +82,11 @@ static Lisp_Object
 make_bignum_bits (size_t bits)
 {
   /* The documentation says integer-width should be nonnegative, so
-     a single comparison suffices even though 'bits' is unsigned.  */
-  if (integer_width < bits)
+     comparing it to BITS works even though BITS is unsigned.  Treat
+     integer-width as if it were at least twice the machine integer width,
+     so that timefns.c can safely use bignums for double-precision
+     timestamps.  */
+  if (integer_width < bits && 2 * max (INTMAX_WIDTH, UINTMAX_WIDTH) < bits)
     overflow_error ();
 
   struct Lisp_Bignum *b = ALLOCATE_PLAIN_PSEUDOVECTOR (struct Lisp_Bignum,