]> git.eshelyaron.com Git - emacs.git/commitdiff
Let integers use up 2 tags to give them one extra bit and double their range.
authorStefan Monnier <monnier@iro.umontreal.ca>
Fri, 6 Nov 2009 18:47:48 +0000 (18:47 +0000)
committerStefan Monnier <monnier@iro.umontreal.ca>
Fri, 6 Nov 2009 18:47:48 +0000 (18:47 +0000)
* lisp.h (USE_2_TAGS_FOR_INTS): New macro.
(LISP_INT_TAG, case_Lisp_Int, LISP_STRING_TAG, LISP_INT_TAG_P): New macros.
(enum Lisp_Type): Use them.  Give explicit values.
(Lisp_Type_Limit): Remove.
(XINT, XUINT, make_number) [!USE_LISP_UNION_TYPE]:
(MOST_NEGATIVE_FIXNUM, MOST_POSITIVE_FIXNUM, INTMASK):
Pay attention to USE_2_TAGS_FOR_INTS.
(INTEGERP): Use LISP_INT_TAG_P.
* fns.c (internal_equal): Simplify the default case.
(sxhash): Use case_Lisp_Int.
* data.c (wrong_type_argument): Don't check against Lisp_Type_Limit any more.
(Ftype_of): Use case_Lisp_Int.
(store_symval_forwarding): Take into account the fact that Ints can
now have more than one tag.
* buffer.c (syms_of_buffer): Use LISP_INT_TAG.
buffer_slot_type_mismatch):
* xfaces.c (face_attr_equal_p):
* print.c (print_object):
* alloc.c (mark_maybe_object, mark_object, survives_gc_p): Use case_Lisp_Int.

etc/NEWS
src/ChangeLog
src/alloc.c
src/buffer.c
src/data.c
src/fns.c
src/lisp.h
src/print.c
src/xfaces.c

index ad12cae496e33cefcbdab266137a5892671bb25b..63096f438594d22cdd5933fb3741ea8350977f26 100644 (file)
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -49,6 +49,9 @@ were loaded.
 
 * Changes in Emacs 23.2
 
+** The maximum size of buffers (as well as the largest fixnum) is doubled.
+On typical 32bit systems, buffers can now be up to 512MB.
+
 ** Function arguments in *Help* buffers are now in uppercase by default.
 You can customize the new variable `help-downcase-arguments' to change it.
 
index 80e772d9424742ee404ba3a9450f5964fb8bcc26..0bd5d838c587ade6933fdebfb24c2c08586d6d93 100644 (file)
@@ -1,3 +1,31 @@
+2009-11-06  Stefan Monnier  <monnier@iro.umontreal.ca>
+
+       Let integers use up 2 tags to give them one extra bit and thus double
+       their range.
+       * lisp.h (USE_2_TAGS_FOR_INTS): New macro.
+       (LISP_INT_TAG, case_Lisp_Int, LISP_STRING_TAG, LISP_INT_TAG_P):
+       New macros.
+       (enum Lisp_Type): Use them.  Give explicit values.
+       (Lisp_Type_Limit): Remove.
+       (XINT, XUINT, make_number) [!USE_LISP_UNION_TYPE]:
+       (MOST_NEGATIVE_FIXNUM, MOST_POSITIVE_FIXNUM, INTMASK):
+       Pay attention to USE_2_TAGS_FOR_INTS.
+       (INTEGERP): Use LISP_INT_TAG_P.
+       * fns.c (internal_equal): Simplify the default case.
+       (sxhash): Use case_Lisp_Int.
+       * data.c (wrong_type_argument): Don't check against Lisp_Type_Limit
+       any more.
+       (Ftype_of): Use case_Lisp_Int.
+       (store_symval_forwarding): Take into account the fact that Ints can
+       now have more than one tag.
+       * buffer.c (syms_of_buffer): Use LISP_INT_TAG.
+       buffer_slot_type_mismatch):
+       * xfaces.c (face_attr_equal_p):
+       * print.c (print_object):
+       * alloc.c (mark_maybe_object, mark_object, survives_gc_p):
+       Use case_Lisp_Int.
+
+
 2009-11-06  Eli Zaretskii  <eliz@gnu.org>
 
        * s/msdos.h (SYSTEM_PURESIZE_EXTRA): Reduce by further 30K.
index bb148b37ba3709bd9a54a521aa51f7ee76da1793..6241cde424b59eb24004ccf5e575f2ea08842a2c 100644 (file)
@@ -4149,8 +4149,7 @@ mark_maybe_object (obj)
          mark_p = (live_misc_p (m, po) && !XMISCANY (obj)->gcmarkbit);
          break;
 
-       case Lisp_Int:
-       case Lisp_Type_Limit:
+       default:
          break;
        }
 
@@ -5713,7 +5712,7 @@ mark_object (arg)
       FLOAT_MARK (XFLOAT (obj));
       break;
 
-    case Lisp_Int:
+    case_Lisp_Int:
       break;
 
     default:
@@ -5799,7 +5798,7 @@ survives_gc_p (obj)
 
   switch (XTYPE (obj))
     {
-    case Lisp_Int:
+    case_Lisp_Int:
       survives_p = 1;
       break;
 
index 5359c7cf69c5b65da37b01009478db51d273548c..c4e90363c6a4c8d00e2453a435307843af8ceaa2 100644 (file)
@@ -4573,7 +4573,7 @@ buffer_slot_type_mismatch (newval, type)
 
   switch (type)
     {
-    case Lisp_Int:    predicate = Qintegerp; break;
+    case_Lisp_Int:    predicate = Qintegerp; break;
     case Lisp_String: predicate = Qstringp;  break;
     case Lisp_Symbol: predicate = Qsymbolp;  break;
     default: abort ();
@@ -5738,17 +5738,17 @@ Format with `format-mode-line' to produce a string value.  */);
                     doc: /* *Non-nil if searches and matches should ignore case.  */);
 
   DEFVAR_PER_BUFFER ("fill-column", &current_buffer->fill_column,
-                    make_number (Lisp_Int),
+                    make_number (LISP_INT_TAG),
                     doc: /* *Column beyond which automatic line-wrapping should happen.
 Interactively, you can set the buffer local value using \\[set-fill-column].  */);
 
   DEFVAR_PER_BUFFER ("left-margin", &current_buffer->left_margin,
-                    make_number (Lisp_Int),
+                    make_number (LISP_INT_TAG),
                     doc: /* *Column for the default `indent-line-function' to indent to.
 Linefeed indents to this column in Fundamental mode.  */);
 
   DEFVAR_PER_BUFFER ("tab-width", &current_buffer->tab_width,
-                    make_number (Lisp_Int),
+                    make_number (LISP_INT_TAG),
                     doc: /* *Distance between tab stops (for display of tab characters), in columns.  */);
 
   DEFVAR_PER_BUFFER ("ctl-arrow", &current_buffer->ctl_arrow, Qnil,
@@ -5859,7 +5859,7 @@ If it is nil, that means don't auto-save this buffer.  */);
 Backing up is done before the first time the file is saved.  */);
 
   DEFVAR_PER_BUFFER ("buffer-saved-size", &current_buffer->save_length,
-                    make_number (Lisp_Int),
+                    make_number (LISP_INT_TAG),
                     doc: /* Length of current buffer when last read in, saved or auto-saved.
 0 initially.
 -1 means auto-saving turned off until next real save.
index fc50658dd7cec59c470ca6cd596a90dcd79019ef..7110fb7eae7e9921dff4fb81290f21e572b3e437 100644 (file)
@@ -108,10 +108,12 @@ Lisp_Object
 wrong_type_argument (predicate, value)
      register Lisp_Object predicate, value;
 {
-  /* If VALUE is not even a valid Lisp object, abort here
-     where we can get a backtrace showing where it came from.  */
-  if ((unsigned int) XTYPE (value) >= Lisp_Type_Limit)
-    abort ();
+  /* If VALUE is not even a valid Lisp object, we'd want to abort here
+     where we can get a backtrace showing where it came from.  We used
+     to try and do that by checking the tagbits, but nowadays all
+     tagbits are potentially valid.  */
+  /* if ((unsigned int) XTYPE (value) >= Lisp_Type_Limit)
+   *   abort (); */
 
   xsignal2 (Qwrong_type_argument, predicate, value);
 }
@@ -184,7 +186,7 @@ for example, (type-of 1) returns `integer'.  */)
 {
   switch (XTYPE (object))
     {
-    case Lisp_Int:
+    case_Lisp_Int:
       return Qinteger;
 
     case Lisp_Symbol:
@@ -975,8 +977,10 @@ store_symval_forwarding (symbol, valcontents, newval, buf)
            int offset = XBUFFER_OBJFWD (valcontents)->offset;
            Lisp_Object type = XBUFFER_OBJFWD (valcontents)->slottype;
 
-           if (! NILP (type) && ! NILP (newval)
-               && XTYPE (newval) != XINT (type))
+           if (!(NILP (type) || NILP (newval)
+                 || (XINT (type) == LISP_INT_TAG
+                     ? INTEGERP (newval)
+                     : XTYPE (newval) == XINT (type))))
              buffer_slot_type_mismatch (newval, XINT (type));
 
            if (buf == NULL)
index 09bad09551d593cfe6460e282d2b0862bbb91283..e160e288467bd63ab7c7edc162d2c3e3d993b77a 100644 (file)
--- a/src/fns.c
+++ b/src/fns.c
@@ -2267,9 +2267,7 @@ internal_equal (o1, o2, depth, props)
        return 0;
       return 1;
 
-    case Lisp_Int:
-    case Lisp_Symbol:
-    case Lisp_Type_Limit:
+    default:
       break;
     }
 
@@ -4565,7 +4563,7 @@ sxhash (obj, depth)
 
   switch (XTYPE (obj))
     {
-    case Lisp_Int:
+    case_Lisp_Int:
       hash = XUINT (obj);
       break;
 
index 95759c18f51589176cd1bd259b34e063550d52ee..65c88dcfab7a1e305fec34c0c81a755b8f8c942a 100644 (file)
@@ -150,37 +150,68 @@ extern void die P_((const char *, const char *, int)) NO_RETURN;
 
 /* Define the fundamental Lisp data structures.  */
 
+/* If USE_2_TAGBITS_FOR_INTS is defined, then Lisp integers use
+   2 tags, to give them one extra bit, thus extending their range from
+   e.g -2^28..2^28-1 to -2^29..2^29-1.  */
+#define USE_2_TAGS_FOR_INTS
+
+/* Making it work for the union case is too much trouble.  */
+#ifdef USE_LISP_UNION_TYPE
+# undef USE_2_TAGS_FOR_INTS
+#endif
+
 /* This is the set of Lisp data types.  */
 
+#if !defined USE_2_TAGS_FOR_INTS
+# define LISP_INT_TAG Lisp_Int
+# define case_Lisp_Int case Lisp_Int
+# define LISP_STRING_TAG 4
+# define LISP_INT_TAG_P(x) ((x) == Lisp_Int)
+#else
+# define LISP_INT_TAG Lisp_Int0
+# define case_Lisp_Int case Lisp_Int0: case Lisp_Int1
+# ifdef USE_LSB_TAG
+#  define LISP_INT1_TAG 4
+#  define LISP_STRING_TAG 1
+#  define LISP_INT_TAG_P(x) (((x) & 3) == 0)
+# else
+#  define LISP_INT1_TAG 1
+#  define LISP_STRING_TAG 4
+#  define LISP_INT_TAG_P(x) (((x) & 6) == 0)
+# endif
+#endif
+
 enum Lisp_Type
   {
     /* Integer.  XINT (obj) is the integer value.  */
-    Lisp_Int,
+#ifdef USE_2_TAGS_FOR_INTS
+    Lisp_Int0 = 0,
+    Lisp_Int1 = LISP_INT1_TAG,
+#else
+    Lisp_Int = 0,
+#endif
 
     /* Symbol.  XSYMBOL (object) points to a struct Lisp_Symbol.  */
-    Lisp_Symbol,
+    Lisp_Symbol = 2,
 
     /* Miscellaneous.  XMISC (object) points to a union Lisp_Misc,
        whose first member indicates the subtype.  */
-    Lisp_Misc,
+    Lisp_Misc = 3,
 
     /* String.  XSTRING (object) points to a struct Lisp_String.
        The length of the string, and its contents, are stored therein.  */
-    Lisp_String,
+    Lisp_String = LISP_STRING_TAG,
 
     /* Vector of Lisp objects, or something resembling it.
        XVECTOR (object) points to a struct Lisp_Vector, which contains
        the size and contents.  The size field also contains the type
        information, if it's not a real vector object.  */
-    Lisp_Vectorlike,
+    Lisp_Vectorlike = 5,
 
     /* Cons.  XCONS (object) points to a struct Lisp_Cons.  */
-    Lisp_Cons,
-
-    Lisp_Float,
+    Lisp_Cons = 6,
 
-    /* This is not a type code.  It is for range checking.  */
-    Lisp_Type_Limit
+    Lisp_Float = 7,
   };
 
 /* This is the set of data types that share a common structure.
@@ -353,12 +384,18 @@ enum pvec_type
 
 #define TYPEMASK ((((EMACS_INT) 1) << GCTYPEBITS) - 1)
 #define XTYPE(a) ((enum Lisp_Type) (((EMACS_UINT) (a)) & TYPEMASK))
-#define XINT(a) (((EMACS_INT) (a)) >> GCTYPEBITS)
-#define XUINT(a) (((EMACS_UINT) (a)) >> GCTYPEBITS)
+#ifdef USE_2_TAGS_FOR_INTS
+# define XINT(a) (((EMACS_INT) (a)) >> (GCTYPEBITS - 1))
+# define XUINT(a) (((EMACS_UINT) (a)) >> (GCTYPEBITS - 1))
+# define make_number(N) (((EMACS_INT) (N)) << (GCTYPEBITS - 1))
+#else
+# define XINT(a) (((EMACS_INT) (a)) >> GCTYPEBITS)
+# define XUINT(a) (((EMACS_UINT) (a)) >> GCTYPEBITS)
+# define make_number(N) (((EMACS_INT) (N)) << GCTYPEBITS)
+#endif
 #define XSET(var, type, ptr)                                   \
     (eassert (XTYPE (ptr) == 0), /* Check alignment.  */       \
      (var) = ((EMACS_INT) (type)) | ((EMACS_INT) (ptr)))
-#define make_number(N) (((EMACS_INT) (N)) << GCTYPEBITS)
 
 #define XPNTR(a) ((EMACS_INT) ((a) & ~TYPEMASK))
 
@@ -378,41 +415,43 @@ enum pvec_type
 #define XFASTINT(a) ((a) + 0)
 #define XSETFASTINT(a, b) ((a) = (b))
 
-/* Extract the value of a Lisp_Object as a signed integer.  */
+/* Extract the value of a Lisp_Object as a (un)signed integer.  */
 
-#ifndef XINT   /* Some machines need to do this differently.  */
-#define XINT(a) ((((EMACS_INT) (a)) << (BITS_PER_EMACS_INT - VALBITS)) \
+#ifdef USE_2_TAGS_FOR_INTS
+# define XINT(a) ((((EMACS_INT) (a)) << (GCTYPEBITS - 1)) >> (GCTYPEBITS - 1))
+# define XUINT(a) ((EMACS_UINT) ((a) & (1 + (VALMASK << 1))))
+# define make_number(N) ((((EMACS_INT) (N)) & (1 + (VALMASK << 1))))
+#else
+# define XINT(a) ((((EMACS_INT) (a)) << (BITS_PER_EMACS_INT - VALBITS))        \
                 >> (BITS_PER_EMACS_INT - VALBITS))
+# define XUINT(a) ((EMACS_UINT) ((a) & VALMASK))
+# define make_number(N)                \
+  ((((EMACS_INT) (N)) & VALMASK) | ((EMACS_INT) Lisp_Int) << VALBITS)
 #endif
 
-/* Extract the value as an unsigned integer.  This is a basis
-   for extracting it as a pointer to a structure in storage.  */
-
-#ifndef XUINT
-#define XUINT(a) ((EMACS_UINT) ((a) & VALMASK))
-#endif
-
-#ifndef XSET
 #define XSET(var, type, ptr) \
    ((var) = ((EMACS_INT)(type) << VALBITS) + ((EMACS_INT) (ptr) & VALMASK))
-#endif
-
-/* Convert a C integer into a Lisp_Object integer.  */
 
-#define make_number(N)         \
-  ((((EMACS_INT) (N)) & VALMASK) | ((EMACS_INT) Lisp_Int) << VALBITS)
+#define XPNTR(a) ((EMACS_UINT) ((a) & VALMASK))
 
 #endif /* not USE_LSB_TAG */
 
 #else /* USE_LISP_UNION_TYPE */
 
+#ifdef USE_2_TAGS_FOR_INTS
+# error "USE_2_TAGS_FOR_INTS is not supported with USE_LISP_UNION_TYPE"
+#endif
+
 #define XHASH(a) ((a).i)
 
 #define XTYPE(a) ((enum Lisp_Type) (a).u.type)
 
 #ifdef EXPLICIT_SIGN_EXTEND
-/* Make sure we sign-extend; compilers have been known to fail to do so.  */
-#define XINT(a) (((a).s.val << (BITS_PER_EMACS_INT - VALBITS)) \
+/* Make sure we sign-extend; compilers have been known to fail to do so.
+   We additionally cast to EMACS_INT since it seems that some compilers
+   have been known to fail to do so, even though the bitfield is declared
+   as EMACS_INT already.  */
+#define XINT(a) ((((EMACS_INT) (a).s.val) << (BITS_PER_EMACS_INT - VALBITS)) \
                 >> (BITS_PER_EMACS_INT - VALBITS))
 #else
 #define XINT(a) ((a).s.val)
@@ -491,11 +530,19 @@ extern size_t pure_size;
 /* Largest and smallest representable fixnum values.  These are the C
    values.  */
 
-#define MOST_NEGATIVE_FIXNUM   - ((EMACS_INT) 1 << (VALBITS - 1))
-#define MOST_POSITIVE_FIXNUM   (((EMACS_INT) 1 << (VALBITS - 1)) - 1)
+#ifdef USE_2_TAGS_FOR_INTS
+# define MOST_NEGATIVE_FIXNUM  - ((EMACS_INT) 1 << VALBITS)
+# define MOST_POSITIVE_FIXNUM  (((EMACS_INT) 1 << VALBITS) - 1)
 /* Mask indicating the significant bits of a Lisp_Int.
    I.e. (x & INTMASK) == XUINT (make_number (x)).  */
-#define INTMASK ((((EMACS_INT) 1) << VALBITS) - 1)
+# define INTMASK ((((EMACS_INT) 1) << (VALBITS + 1)) - 1)
+#else
+# define MOST_NEGATIVE_FIXNUM  - ((EMACS_INT) 1 << (VALBITS - 1))
+# define MOST_POSITIVE_FIXNUM  (((EMACS_INT) 1 << (VALBITS - 1)) - 1)
+/* Mask indicating the significant bits of a Lisp_Int.
+   I.e. (x & INTMASK) == XUINT (make_number (x)).  */
+# define INTMASK ((((EMACS_INT) 1) << VALBITS) - 1)
+#endif
 
 /* Value is non-zero if I doesn't fit into a Lisp fixnum.  It is
    written this way so that it also works if I is of unsigned
@@ -1506,7 +1553,7 @@ typedef struct {
 #define NUMBERP(x) (INTEGERP (x) || FLOATP (x))
 #define NATNUMP(x) (INTEGERP (x) && XINT (x) >= 0)
 
-#define INTEGERP(x) (XTYPE ((x)) == Lisp_Int)
+#define INTEGERP(x) (LISP_INT_TAG_P (XTYPE ((x))))
 #define SYMBOLP(x) (XTYPE ((x)) == Lisp_Symbol)
 #define MISCP(x) (XTYPE ((x)) == Lisp_Misc)
 #define VECTORLIKEP(x) (XTYPE ((x)) == Lisp_Vectorlike)
index 14fed114325de691137c2e36fc5cd4dad97a1b68..24d497ed36592dfbec86982090bdf9ddea8d2bd1 100644 (file)
@@ -1588,7 +1588,7 @@ print_object (obj, printcharfun, escapeflag)
 
   switch (XTYPE (obj))
     {
-    case Lisp_Int:
+    case_Lisp_Int:
       if (sizeof (int) == sizeof (EMACS_INT))
        sprintf (buf, "%d", (int) XINT (obj));
       else if (sizeof (long) == sizeof (EMACS_INT))
index 2b6df6406f59f157284ec87bef957c7738a13382..9da3cc7f3253fc0977cdfb35711a98045a4e762d 100644 (file)
@@ -4085,7 +4085,7 @@ face_attr_equal_p (v1, v2)
 
       return bcmp (SDATA (v1), SDATA (v2), SBYTES (v1)) == 0;
 
-    case Lisp_Int:
+    case_Lisp_Int:
     case Lisp_Symbol:
       return 0;