VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVT
For integral Lisp types, i.e. integers and characters, the value
- bits are the Lisp object.
+ bits are the Lisp object. Some people call such Lisp_Objects "immediate".
- The object is obtained by masking off the type and mark bits.
+ The object is obtained by masking off the type bits.
Bit 1 is used as a value bit by splitting the Lisp integer type
- into two subtypes, Lisp_Type_Int_Even and Lisp_Type_Int_Odd. By
- this trickery we get 31 bits for integers instead of 30.
+ into two subtypes, Lisp_Type_Int_Even and Lisp_Type_Int_Odd.
+ By this trickery we get 31 bits for integers instead of 30.
For non-integral types, the value bits of a Lisp_Object contain
a pointer to a structure containing the object. The pointer is
obtained by masking off the type and mark bits.
All pointer-based types are coalesced under a single type called
- Lisp_Type_Record. The type bits for this type are required
- by the implementation to be 00, just like the least
- significant bits of word-aligned struct pointers on 32-bit
- hardware. Because of this, Lisp_Object pointers don't have
- to be masked and are full-sized.
+ Lisp_Type_Record. The type bits for this type are required by the
+ implementation to be 00, just like the least significant bits of
+ word-aligned struct pointers on 32-bit hardware. This requires that
+ all structs implementing Lisp_Objects have an alignment of at least 4
+ bytes. Because of this, Lisp_Object pointers don't have to be masked
+ and are full-sized.
- There are no mark bits.
- Integers and characters don't need to be marked. All other types
- are lrecord-based, which means they get marked by incrementing
- their ->implementation pointer.
+ There are no mark bits in the Lisp_Object itself (there used to be).
+
+ Integers and characters don't need to be marked. All other types are
+ lrecord-based, which means they get marked by setting the mark bit in
+ the struct lrecord_header.
Here is a brief description of the following macros:
XCHARVAL The value bits of a Lisp_Object storing a Emchar
XREALINT The value bits of a Lisp_Object storing an integer, signed
XUINT The value bits of a Lisp_Object storing an integer, unsigned
- INTP Non-zero if this Lisp_Object an integer?
+ INTP Non-zero if this Lisp_Object is an integer
Qzero Lisp Integer 0
- EQ Non-zero if two Lisp_Objects are identical */
+ EQ Non-zero if two Lisp_Objects are identical, not merely equal. */
typedef EMACS_INT Lisp_Object;
#define Lisp_Type_Int_Bit (Lisp_Type_Int_Even & Lisp_Type_Int_Odd)
#define wrap_object(ptr) ((Lisp_Object) (ptr))
-#define make_int(x) ((Lisp_Object) (((x) << INT_GCBITS) | Lisp_Type_Int_Bit))
-#define make_char(x) ((Lisp_Object) (((x) << GCBITS) | Lisp_Type_Char))
+#define make_int(x) ((Lisp_Object) (((EMACS_INT)(x) << INT_GCBITS) | Lisp_Type_Int_Bit))
+#define make_char(x) ((Lisp_Object) (((EMACS_INT)(x) << GCBITS) | Lisp_Type_Char))
#define VALMASK (((1UL << VALBITS) - 1UL) << GCTYPEBITS)
#define XTYPE(x) ((enum Lisp_Type) (((EMACS_UINT)(x)) & ~VALMASK))
#define XPNTRVAL(x) (x) /* This depends on Lisp_Type_Record == 0 */
-#define XCHARVAL(x) ((x) >> GCBITS)
+#if defined(UTF2000) && (SIZEOF_EMACS_INT == 4)
+INLINE_HEADER Emchar XCHARVAL (Lisp_Object chr);
+INLINE_HEADER Emchar
+XCHARVAL (Lisp_Object chr)
+{
+ int code = (EMACS_UINT)(chr) >> GCBITS;
+
+ if (code & 0x20000000)
+ return code | 0x40000000;
+ else
+ return code;
+}
+#else
+#define XCHARVAL(x) ((Emchar)((EMACS_UINT)(x) >> GCBITS))
+#endif
#define XREALINT(x) ((x) >> INT_GCBITS)
#define XUINT(x) ((EMACS_UINT)(x) >> INT_GCBITS)
#define INTP(x) ((EMACS_UINT)(x) & Lisp_Type_Int_Bit)