changeset 105885:8103235103a7

Let integers use up 2 tags to give them one extra bit and 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.
author Stefan Monnier <monnier@iro.umontreal.ca>
date Fri, 06 Nov 2009 18:47:48 +0000
parents 3c37f8b33131
children 544761863e24
files 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
diffstat 9 files changed, 139 insertions(+), 60 deletions(-) [+]
line wrap: on
line diff
--- a/etc/NEWS	Fri Nov 06 11:40:24 2009 +0000
+++ b/etc/NEWS	Fri Nov 06 18:47:48 2009 +0000
@@ -49,6 +49,9 @@
 
 * 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.
 
--- a/src/ChangeLog	Fri Nov 06 11:40:24 2009 +0000
+++ b/src/ChangeLog	Fri Nov 06 18:47:48 2009 +0000
@@ -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.
--- a/src/alloc.c	Fri Nov 06 11:40:24 2009 +0000
+++ b/src/alloc.c	Fri Nov 06 18:47:48 2009 +0000
@@ -4149,8 +4149,7 @@
 	  mark_p = (live_misc_p (m, po) && !XMISCANY (obj)->gcmarkbit);
 	  break;
 
-	case Lisp_Int:
-	case Lisp_Type_Limit:
+	default:
 	  break;
 	}
 
@@ -5713,7 +5712,7 @@
       FLOAT_MARK (XFLOAT (obj));
       break;
 
-    case Lisp_Int:
+    case_Lisp_Int:
       break;
 
     default:
@@ -5799,7 +5798,7 @@
 
   switch (XTYPE (obj))
     {
-    case Lisp_Int:
+    case_Lisp_Int:
       survives_p = 1;
       break;
 
--- a/src/buffer.c	Fri Nov 06 11:40:24 2009 +0000
+++ b/src/buffer.c	Fri Nov 06 18:47:48 2009 +0000
@@ -4573,7 +4573,7 @@
 
   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 @@
 		     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 @@
 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.
--- a/src/data.c	Fri Nov 06 11:40:24 2009 +0000
+++ b/src/data.c	Fri Nov 06 18:47:48 2009 +0000
@@ -108,10 +108,12 @@
 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 @@
 {
   switch (XTYPE (object))
     {
-    case Lisp_Int:
+    case_Lisp_Int:
       return Qinteger;
 
     case Lisp_Symbol:
@@ -975,8 +977,10 @@
 	    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)
--- a/src/fns.c	Fri Nov 06 11:40:24 2009 +0000
+++ b/src/fns.c	Fri Nov 06 18:47:48 2009 +0000
@@ -2267,9 +2267,7 @@
 	return 0;
       return 1;
 
-    case Lisp_Int:
-    case Lisp_Symbol:
-    case Lisp_Type_Limit:
+    default:
       break;
     }
 
@@ -4565,7 +4563,7 @@
 
   switch (XTYPE (obj))
     {
-    case Lisp_Int:
+    case_Lisp_Int:
       hash = XUINT (obj);
       break;
 
--- a/src/lisp.h	Fri Nov 06 11:40:24 2009 +0000
+++ b/src/lisp.h	Fri Nov 06 18:47:48 2009 +0000
@@ -150,37 +150,68 @@
 
 /* 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,
-
-    /* This is not a type code.  It is for range checking.  */
-    Lisp_Type_Limit
+    Lisp_Cons = 6,
+
+    Lisp_Float = 7,
   };
 
 /* This is the set of data types that share a common structure.
@@ -353,12 +384,18 @@
 
 #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 @@
 #define XFASTINT(a) ((a) + 0)
 #define XSETFASTINT(a, b) ((a) = (b))
 
-/* Extract the value of a Lisp_Object as a signed integer.  */
-
-#ifndef XINT   /* Some machines need to do this differently.  */
-#define XINT(a) ((((EMACS_INT) (a)) << (BITS_PER_EMACS_INT - VALBITS))	\
+/* Extract the value of a Lisp_Object as a (un)signed integer.  */
+
+#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 @@
 /* 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 @@
 #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)
--- a/src/print.c	Fri Nov 06 11:40:24 2009 +0000
+++ b/src/print.c	Fri Nov 06 18:47:48 2009 +0000
@@ -1588,7 +1588,7 @@
 
   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))
--- a/src/xfaces.c	Fri Nov 06 11:40:24 2009 +0000
+++ b/src/xfaces.c	Fri Nov 06 18:47:48 2009 +0000
@@ -4085,7 +4085,7 @@
 
       return bcmp (SDATA (v1), SDATA (v2), SBYTES (v1)) == 0;
 
-    case Lisp_Int:
+    case_Lisp_Int:
     case Lisp_Symbol:
       return 0;