summaryrefslogtreecommitdiff
path: root/src/lisp.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/lisp.h')
-rw-r--r--src/lisp.h98
1 files changed, 63 insertions, 35 deletions
diff --git a/src/lisp.h b/src/lisp.h
index a0d6c6b3c0b..9b2dda244e9 100644
--- a/src/lisp.h
+++ b/src/lisp.h
@@ -341,28 +341,26 @@ typedef EMACS_INT Lisp_Object;
It is not crucial, but there are plenty of bits here, so why not do it? */
enum pvec_type
{
- PVEC_NORMAL_VECTOR = 0,
- PVEC_PROCESS = 0x200,
- PVEC_FRAME = 0x400,
- PVEC_COMPILED = 0x800,
- PVEC_WINDOW = 0x1000,
- PVEC_WINDOW_CONFIGURATION = 0x2000,
- PVEC_SUBR = 0x4000,
- PVEC_CHAR_TABLE = 0x8000,
- PVEC_BOOL_VECTOR = 0x10000,
- PVEC_BUFFER = 0x20000,
- PVEC_HASH_TABLE = 0x40000,
- PVEC_TERMINAL = 0x80000,
- PVEC_SUB_CHAR_TABLE = 0x100000,
- PVEC_FONT = 0x200000,
- PVEC_OTHER = 0x400000,
- PVEC_TYPE_MASK = 0x7ffe00
-
-#if 0 /* This is used to make the value of PSEUDOVECTOR_FLAG available to
- GDB. It doesn't work on OS Alpha. Moved to a variable in
- emacs.c. */
- PVEC_FLAG = PSEUDOVECTOR_FLAG
-#endif
+ PVEC_NORMAL_VECTOR = 0, /* Unused! */
+ PVEC_FREE,
+ PVEC_PROCESS,
+ PVEC_FRAME,
+ PVEC_WINDOW,
+ PVEC_BOOL_VECTOR,
+ PVEC_BUFFER,
+ PVEC_HASH_TABLE,
+ PVEC_TERMINAL,
+ PVEC_WINDOW_CONFIGURATION,
+ PVEC_SUBR,
+ PVEC_OTHER,
+ /* These last 4 are special because we OR them in fns.c:internal_equal,
+ so they have to use a disjoint bit pattern:
+ if (!(size & (PVEC_COMPILED | PVEC_CHAR_TABLE
+ | PVEC_SUB_CHAR_TABLE | PVEC_FONT))) */
+ PVEC_COMPILED = 0x10,
+ PVEC_CHAR_TABLE = 0x20,
+ PVEC_SUB_CHAR_TABLE = 0x30,
+ PVEC_FONT = 0x40
};
/* For convenience, we also store the number of elements in these bits.
@@ -370,7 +368,9 @@ enum pvec_type
only the number of Lisp_Object fields (that need to be traced by the GC).
The distinction is used e.g. by Lisp_Process which places extra
non-Lisp_Object fields at the end of the structure. */
-#define PSEUDOVECTOR_SIZE_MASK 0x1ff
+#define PSEUDOVECTOR_SIZE_BITS 16
+#define PSEUDOVECTOR_SIZE_MASK ((1 << PSEUDOVECTOR_SIZE_BITS) - 1)
+#define PVEC_TYPE_MASK (0x0fff << PSEUDOVECTOR_SIZE_BITS)
/* Number of bits to put in each character in the internal representation
of bool vectors. This should not vary across implementations. */
@@ -536,9 +536,11 @@ clip_to_bounds (ptrdiff_t lower, EMACS_INT num, ptrdiff_t upper)
#define XSETPVECTYPE(v, code) XSETTYPED_PVECTYPE (v, header.size, code)
#define XSETTYPED_PVECTYPE(v, size_member, code) \
- ((v)->size_member |= PSEUDOVECTOR_FLAG | (code))
+ ((v)->size_member |= PSEUDOVECTOR_FLAG | ((code) << PSEUDOVECTOR_SIZE_BITS))
#define XSETPVECTYPESIZE(v, code, sizeval) \
- ((v)->header.size = PSEUDOVECTOR_FLAG | (code) | (sizeval))
+ ((v)->header.size = (PSEUDOVECTOR_FLAG \
+ | ((code) << PSEUDOVECTOR_SIZE_BITS) \
+ | (sizeval)))
/* The cast to struct vectorlike_header * avoids aliasing issues. */
#define XSETPSEUDOVECTOR(a, b, code) \
@@ -550,7 +552,7 @@ clip_to_bounds (ptrdiff_t lower, EMACS_INT num, ptrdiff_t upper)
#define XSETTYPED_PSEUDOVECTOR(a, b, size, code) \
(XSETVECTOR (a, b), \
eassert ((size & (PSEUDOVECTOR_FLAG | PVEC_TYPE_MASK)) \
- == (PSEUDOVECTOR_FLAG | (code))))
+ == (PSEUDOVECTOR_FLAG | (code << PSEUDOVECTOR_SIZE_BITS))))
#define XSETWINDOW_CONFIGURATION(a, b) \
(XSETPSEUDOVECTOR (a, b, PVEC_WINDOW_CONFIGURATION))
@@ -730,13 +732,13 @@ extern ptrdiff_t string_bytes (struct Lisp_String *);
/* Set text properties. */
#define STRING_SET_INTERVALS(STR, INT) (XSTRING (STR)->intervals = (INT))
-/* In a string or vector, the sign bit of the `size' is the gc mark bit */
+/* In a string or vector, the sign bit of the `size' is the gc mark bit. */
struct Lisp_String
{
ptrdiff_t size;
ptrdiff_t size_byte;
- INTERVAL intervals; /* text properties in this string */
+ INTERVAL intervals; /* Text properties in this string. */
unsigned char *data;
};
@@ -749,6 +751,20 @@ struct Lisp_String
<http://debbugs.gnu.org/cgi/bugreport.cgi?bug=8546>. */
struct vectorlike_header
{
+ /* This field contains various pieces of information:
+ - The MSB (ARRAY_MARK_FLAG) holds the gcmarkbit.
+ - The next bit (PSEUDOVECTOR_FLAG) indicates whether this is a plain
+ vector (0) or a pseudovector (1).
+ - If PSEUDOVECTOR_FLAG is 0, the rest holds the size (number
+ of slots) of the vector.
+ - If PSEUDOVECTOR_FLAG is 1, the rest is subdivided into
+ a "pvec type" tag held in PVEC_TYPE_MASK and a size held in the lowest
+ PSEUDOVECTOR_SIZE_BITS. That size normally indicates the number of
+ Lisp_Object slots at the beginning of the object that need to be
+ traced by the GC, tho some types use it slightly differently.
+ - E.g. if the pvec type is PVEC_FREE it means this is an unallocated
+ vector on a free-list and PSEUDOVECTOR_SIZE_BITS indicates its size
+ in bytes. */
ptrdiff_t size;
/* When the vector is allocated from a vector block, NBYTES is used
@@ -759,8 +775,17 @@ struct vectorlike_header
pointer: this way, one can write P->next.vector instead of ((struct
Lisp_Vector *) P->next). */
union {
+ /* This is only needed for small vectors that are not free because the
+ `size' field only gives us the number of Lisp_Object slots, whereas we
+ need to know the total size, including non-Lisp_Object data.
+ FIXME: figure out a way to store this info elsewhere so we can
+ finally get rid of this extra word of overhead. */
ptrdiff_t nbytes;
struct buffer *buffer;
+ /* FIXME: This can be removed: For large vectors, this field could be
+ placed *before* the vector itself. And for small vectors on a free
+ list, this field could be stored in the vector's bytes, since the
+ empty vector is handled specially anyway. */
struct Lisp_Vector *vector;
} next;
};
@@ -775,7 +800,7 @@ struct Lisp_Vector
of the shortest vector that would hold that struct. */
#define VECSIZE(type) ((sizeof (type) \
- offsetof (struct Lisp_Vector, contents[0]) \
- + sizeof (Lisp_Object) - 1) /* round up */ \
+ + sizeof (Lisp_Object) - 1) /* Round up. */ \
/ sizeof (Lisp_Object))
/* Like VECSIZE, but used when the pseudo-vector has non-Lisp_Object fields
@@ -1617,15 +1642,17 @@ typedef struct {
/* True if object X is a pseudovector whose code is CODE. The cast to struct
vectorlike_header * avoids aliasing issues. */
#define PSEUDOVECTORP(x, code) \
- TYPED_PSEUDOVECTORP(x, vectorlike_header, code)
+ TYPED_PSEUDOVECTORP (x, vectorlike_header, code)
+
+#define PSEUDOVECTOR_TYPEP(v, code) \
+ (((v)->size & (PSEUDOVECTOR_FLAG | PVEC_TYPE_MASK)) \
+ == (PSEUDOVECTOR_FLAG | ((code) << PSEUDOVECTOR_SIZE_BITS)))
/* True if object X, with internal type struct T *, is a pseudovector whose
code is CODE. */
#define TYPED_PSEUDOVECTORP(x, t, code) \
(VECTORLIKEP (x) \
- && (((((struct t *) XUNTAG (x, Lisp_Vectorlike))->size \
- & (PSEUDOVECTOR_FLAG | (code)))) \
- == (PSEUDOVECTOR_FLAG | (code))))
+ && PSEUDOVECTOR_TYPEP ((struct t *) XUNTAG (x, Lisp_Vectorlike), code))
/* Test for specific pseudovector types. */
#define WINDOW_CONFIGURATIONP(x) PSEUDOVECTORP (x, PVEC_WINDOW_CONFIGURATION)
@@ -1818,7 +1845,8 @@ typedef struct {
#define DEFUN(lname, fnname, sname, minargs, maxargs, intspec, doc) \
Lisp_Object fnname DEFUN_ARGS_ ## maxargs ; \
static DECL_ALIGN (struct Lisp_Subr, sname) = \
- { PVEC_SUBR | (sizeof (struct Lisp_Subr) / sizeof (EMACS_INT)), \
+ { (PVEC_SUBR << PSEUDOVECTOR_SIZE_BITS) \
+ | (sizeof (struct Lisp_Subr) / sizeof (EMACS_INT)), \
{ (Lisp_Object (__cdecl *)(void))fnname }, \
minargs, maxargs, lname, intspec, 0}; \
Lisp_Object fnname
@@ -1826,7 +1854,7 @@ typedef struct {
#define DEFUN(lname, fnname, sname, minargs, maxargs, intspec, doc) \
Lisp_Object fnname DEFUN_ARGS_ ## maxargs ; \
static DECL_ALIGN (struct Lisp_Subr, sname) = \
- { PVEC_SUBR, \
+ { PVEC_SUBR << PSEUDOVECTOR_SIZE_BITS, \
{ .a ## maxargs = fnname }, \
minargs, maxargs, lname, intspec, 0}; \
Lisp_Object fnname