- Various macros are used to convert between Lisp_Objects and the
-corresponding C type. Macros of the form `XINT()', `XCHAR()',
-`XSTRING()', `XSYMBOL()', do any required bit shifting and/or masking
-and cast it to the appropriate type. `XINT()' needs to be a bit tricky
-so that negative numbers are properly sign-extended. Since integers
-are stored left-shifted, if the right-shift operator does an arithmetic
-shift (i.e. it leaves the most-significant bit as-is rather than
-shifting in a zero, so that it mimics a divide-by-two even for negative
-numbers) the shift to remove the tag bit is enough. This is the case
-on all the systems we support.
-
- Note that when `ERROR_CHECK_TYPECHECK' is defined, the converter
-macros become more complicated--they check the tag bits and/or the type
-field in the first four bytes of a record type to ensure that the
+ Note that there are only eight types that the tag can represent, but
+many more actual types than this. This is handled by having one of the
+tag types specify a meta-type called a "record"; for all such objects,
+the first four bytes of the pointed-to structure indicate what the
+actual type is.
+
+ Note also that having 28 bits for pointers and integers restricts a
+lot of things to 256 megabytes of memory. (Basically, enough pointers
+and indices and whatnot get stuffed into Lisp objects that the total
+amount of memory used by XEmacs can't grow above 256 megabytes. In
+older versions of XEmacs and GNU Emacs, the tag was 5 bits wide,
+allowing for 32 types, which was more than the actual number of types
+that existed at the time, and no "record" type was necessary. However,
+this limited the editor to 64 megabytes total, which some users who
+edited large files might conceivably exceed.)
+
+ Also, note that there is an implicit assumption here that all
+pointers are low enough that the top bits are all zero and can just be
+chopped off. On standard machines that allocate memory from the bottom
+up (and give each process its own address space), this works fine. Some
+machines, however, put the data space somewhere else in memory (e.g.
+beginning at 0x80000000). Those machines cope by defining
+`DATA_SEG_BITS' in the corresponding `m/' or `s/' file to the proper
+mask. Then, pointers retrieved from Lisp objects are automatically
+OR'ed with this value prior to being used.
+
+ A corollary of the previous paragraph is that *(pointers to)
+stack-allocated structures cannot be put into Lisp objects*. The stack
+is generally located near the top of memory; if you put such a pointer
+into a Lisp object, it will get its top bits chopped off, and you will
+lose.
+
+ Actually, there's an alternative representation of a `Lisp_Object',
+invented by Kyle Jones, that is used when the `--use-minimal-tagbits'
+option to `configure' is used. In this case the 2 lower bits are used
+for the tag bits. This representation assumes that pointers to structs
+are always aligned to multiples of 4, so the lower 2 bits are always
+zero.
+
+ [ 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 ]
+ [ 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 ]
+
+ <---------------------------------------------------------> <->
+ a pointer to a structure, or an integer tag
+
+ A tag of 00 is used for all pointer object types, a tag of 10 is used
+for characters, and the other two tags 01 and 11 are joined together to
+form the integer object type. The markbit is moved to part of the
+structure being pointed at (integers and chars do not need to be marked,
+since no memory is allocated). This representation has these
+advantages:
+
+ 1. 31 bits can be used for Lisp Integers.
+
+ 2. *Any* pointer can be represented directly, and no bit masking
+ operations are necessary.
+
+ The disadvantages are:
+
+ 1. An extra level of indirection is needed when accessing the object
+ types that were not record types. So checking whether a Lisp
+ object is a cons cell becomes a slower operation.
+
+ 2. Mark bits can no longer be stored directly in Lisp objects, so
+ another place for them must be found. This means that a cons cell
+ requires more memory than merely room for 2 lisp objects, leading
+ to extra memory use.
+
+ Various macros are used to construct Lisp objects and extract the
+components. Macros of the form `XINT()', `XCHAR()', `XSTRING()',
+`XSYMBOL()', etc. mask out the pointer/integer field and cast it to the
+appropriate type. All of the macros that construct pointers will `OR'
+with `DATA_SEG_BITS' if necessary. `XINT()' needs to be a bit tricky
+so that negative numbers are properly sign-extended: Usually it does
+this by shifting the number four bits to the left and then four bits to
+the right. This assumes that the right-shift operator does an
+arithmetic shift (i.e. it leaves the most-significant bit as-is rather
+than shifting in a zero, so that it mimics a divide-by-two even for
+negative numbers). Not all machines/compilers do this, and on the ones
+that don't, a more complicated definition is selected by defining
+`EXPLICIT_SIGN_EXTEND'.
+
+ Note that when `ERROR_CHECK_TYPECHECK' is defined, the extractor
+macros become more complicated - they check the tag bits and/or the
+type field in the first four bytes of a record type to ensure that the