]> git.eshelyaron.com Git - emacs.git/commitdiff
Fix bignum bugs with nth, elt, =
authorPaul Eggert <eggert@cs.ucla.edu>
Tue, 21 Aug 2018 18:40:23 +0000 (11:40 -0700)
committerPaul Eggert <eggert@cs.ucla.edu>
Tue, 21 Aug 2018 18:41:54 +0000 (11:41 -0700)
* src/bytecode.c (exec_byte_code): Support bignums
when implementing nth, elt, and =.
* src/lisp.h (SMALL_LIST_LEN_MAX): New constant.
* src/fns.c (Fnthcdr): Use it.
(Felt): Do not reject bignum indexes.

src/bytecode.c
src/fns.c
src/lisp.h

index b27fa7c5c68ce9a3060ec6cc2145b4c3a5550d2b..17457fc57424835b3a92b2d1ad67afc9b65530c6 100644 (file)
@@ -832,13 +832,14 @@ exec_byte_code (Lisp_Object bytestr, Lisp_Object vector, Lisp_Object maxdepth,
        CASE (Bnth):
          {
            Lisp_Object v2 = POP, v1 = TOP;
-           CHECK_FIXNUM (v1);
-           for (EMACS_INT n = XFIXNUM (v1); 0 < n && CONSP (v2); n--)
+           if (RANGED_FIXNUMP (0, v1, SMALL_LIST_LEN_MAX))
              {
-               v2 = XCDR (v2);
-               rarely_quit (n);
+               for (EMACS_INT n = XFIXNUM (v1); 0 < n && CONSP (v2); n--)
+                 v2 = XCDR (v2);
+               TOP = CAR (v2);
              }
-           TOP = CAR (v2);
+           else
+             TOP = Fnth (v1, v2);
            NEXT;
          }
 
@@ -985,15 +986,8 @@ exec_byte_code (Lisp_Object bytestr, Lisp_Object vector, Lisp_Object maxdepth,
 
        CASE (Beqlsign):
          {
-           Lisp_Object v2 = POP, v1 = TOP;
-           if (FLOATP (v1) || FLOATP (v2))
-             TOP = arithcompare (v1, v2, ARITH_EQUAL);
-           else
-             {
-               CHECK_FIXNUM_OR_FLOAT_COERCE_MARKER (v1);
-               CHECK_FIXNUM_OR_FLOAT_COERCE_MARKER (v2);
-               TOP = EQ (v1, v2) ? Qt : Qnil;
-             }
+           Lisp_Object v1 = POP;
+           TOP = arithcompare (TOP, v1, ARITH_EQUAL);
            NEXT;
          }
 
@@ -1264,23 +1258,16 @@ exec_byte_code (Lisp_Object bytestr, Lisp_Object vector, Lisp_Object maxdepth,
 
        CASE (Belt):
          {
-           if (CONSP (TOP))
+           Lisp_Object v2 = POP, v1 = TOP;
+           if (CONSP (v1) && RANGED_FIXNUMP (0, v2, SMALL_LIST_LEN_MAX))
              {
-               /* Exchange args and then do nth.  */
-               Lisp_Object v2 = POP, v1 = TOP;
-               CHECK_FIXNUM (v2);
+               /* Like the fast case for Bnth, but with args reversed.  */
                for (EMACS_INT n = XFIXNUM (v2); 0 < n && CONSP (v1); n--)
-                 {
-                   v1 = XCDR (v1);
-                   rarely_quit (n);
-                 }
+                 v1 = XCDR (v1);
                TOP = CAR (v1);
              }
            else
-             {
-               Lisp_Object v1 = POP;
-               TOP = Felt (TOP, v1);
-             }
+             TOP = Felt (v1, v2);
            NEXT;
          }
 
index 9d681017c14af57bee68ded448474f59c5fc417c..b368ffd58f234bbc5cc88474caca410ab4569060 100644 (file)
--- a/src/fns.c
+++ b/src/fns.c
@@ -1418,7 +1418,7 @@ DEFUN ("nthcdr", Fnthcdr, Snthcdr, 2, 2, 0,
       num = XFIXNUM (n);
 
       /* Speed up small lists by omitting circularity and quit checking.  */
-      if (num < 128)
+      if (num <= SMALL_LIST_LEN_MAX)
        {
          for (; 0 < num; num--, tail = XCDR (tail))
            if (! CONSP (tail))
@@ -1503,9 +1503,8 @@ N counts from zero.  If LIST is not that long, nil is returned.  */)
 
 DEFUN ("elt", Felt, Selt, 2, 2, 0,
        doc: /* Return element of SEQUENCE at index N.  */)
-  (register Lisp_Object sequence, Lisp_Object n)
+  (Lisp_Object sequence, Lisp_Object n)
 {
-  CHECK_FIXNUM (n);
   if (CONSP (sequence) || NILP (sequence))
     return Fcar (Fnthcdr (n, sequence));
 
index 8f48a334844d6adb12c44b6e47ee00da17f8496a..c5593b210088be1fc1b3afc737f8fa1423517387 100644 (file)
@@ -4694,6 +4694,11 @@ enum
         Lisp_String))                                                  \
      : make_unibyte_string (str, len))
 
+/* The maximum length of "small" lists, as a heuristic.  These lists
+   are so short that code need not check for cycles or quits while
+   traversing.  */
+enum { SMALL_LIST_LEN_MAX = 127 };
+
 /* Loop over conses of the list TAIL, signaling if a cycle is found,
    and possibly quitting after each loop iteration.  In the loop body,
    set TAIL to the current cons.  If the loop exits normally,