Mercurial > emacs
diff src/lisp.h @ 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 | 89183b6f6e9d |
children | cd4cbab8bb21 |
line wrap: on
line diff
--- 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)