Turn VECTOR_FREE_LIST_FLAG into PVEC_FREE.
* src/lisp.h (enum pvec_type): Use fewer bits. (PSEUDOVECTOR_SIZE_BITS): New constant. (PSEUDOVECTOR_SIZE_MASK, PVEC_TYPE_MASK): Use it. (XSETPVECTYPESIZE, XSETTYPED_PSEUDOVECTOR, DEFUN): Adapt code to change in pvec_type. (PSEUDOVECTOR_TYPEP): New macro. (TYPED_PSEUDOVECTORP): Use it. * src/fns.c (internal_equal): Adapt code to extract pvectype. * src/emacs.c (gdb_pvec_type): Update type. * src/alloc.c (PSEUDOVECTOR_NBYTES): New macro. (VECTOR_FREE_LIST_SIZE_MASK): Remove (=> PSEUDOVECTOR_SIZE_MASK). (VECTOR_FREE_LIST_FLAG): Remove (=> PVEC_FREE). (SETUP_ON_FREE_LIST): Use XSETPVECTYPESIZE. (sweep_vectors): Use it. Use local var `total_bytes' instead of abusing vector->header.next.nbytes. (live_vector_p): Use PVEC_TYPE. (mark_object): Adapt code to extract pvectype. Use switch.
This commit is contained in:
parent
1a9746debd
commit
ee28be33a5
5 changed files with 188 additions and 130 deletions
|
@ -1,3 +1,24 @@
|
|||
2012-07-04 Stefan Monnier <monnier@iro.umontreal.ca>
|
||||
|
||||
Turn VECTOR_FREE_LIST_FLAG into PVEC_FREE.
|
||||
* lisp.h (enum pvec_type): Use fewer bits.
|
||||
(PSEUDOVECTOR_SIZE_BITS): New constant.
|
||||
(PSEUDOVECTOR_SIZE_MASK, PVEC_TYPE_MASK): Use it.
|
||||
(XSETPVECTYPESIZE, XSETTYPED_PSEUDOVECTOR, DEFUN): Adapt code to
|
||||
change in pvec_type.
|
||||
(PSEUDOVECTOR_TYPEP): New macro.
|
||||
(TYPED_PSEUDOVECTORP): Use it.
|
||||
* fns.c (internal_equal): Adapt code to extract pvectype.
|
||||
* emacs.c (gdb_pvec_type): Update type.
|
||||
* alloc.c (PSEUDOVECTOR_NBYTES): New macro.
|
||||
(VECTOR_FREE_LIST_SIZE_MASK): Remove (=> PSEUDOVECTOR_SIZE_MASK).
|
||||
(VECTOR_FREE_LIST_FLAG): Remove (=> PVEC_FREE).
|
||||
(SETUP_ON_FREE_LIST): Use XSETPVECTYPESIZE.
|
||||
(sweep_vectors): Use it. Use local var `total_bytes' instead of
|
||||
abusing vector->header.next.nbytes.
|
||||
(live_vector_p): Use PVEC_TYPE.
|
||||
(mark_object): Adapt code to extract pvectype. Use switch.
|
||||
|
||||
2012-07-04 Paul Eggert <eggert@cs.ucla.edu>
|
||||
|
||||
* doprnt.c (doprnt): Don't assume string length fits in 'int'.
|
||||
|
|
192
src/alloc.c
192
src/alloc.c
|
@ -1529,7 +1529,7 @@ make_interval (void)
|
|||
}
|
||||
|
||||
|
||||
/* Mark Lisp objects in interval I. */
|
||||
/* Mark Lisp objects in interval I. */
|
||||
|
||||
static void
|
||||
mark_interval (register INTERVAL i, Lisp_Object dummy)
|
||||
|
@ -1836,7 +1836,7 @@ check_sblock (struct sblock *b)
|
|||
ptrdiff_t nbytes;
|
||||
|
||||
/* Check that the string size recorded in the string is the
|
||||
same as the one recorded in the sdata structure. */
|
||||
same as the one recorded in the sdata structure. */
|
||||
if (from->string)
|
||||
CHECK_STRING_BYTES (from->string);
|
||||
|
||||
|
@ -2869,12 +2869,6 @@ DEFUN ("make-list", Fmake_list, Smake_list, 2, 2, 0,
|
|||
|
||||
#define VECTOR_BLOCK_SIZE 4096
|
||||
|
||||
/* This special value is used to calculate vector size when the vector is
|
||||
on a free list. It should be VECTOR_BLOCK_SIZE rounded up to nearest
|
||||
power of two, minus one. */
|
||||
|
||||
#define VECTOR_FREE_LIST_SIZE_MASK 4095
|
||||
|
||||
/* Handy constants for vectorlike objects. */
|
||||
enum
|
||||
{
|
||||
|
@ -2889,8 +2883,7 @@ verify ((roundup_size & (roundup_size - 1)) == 0);
|
|||
|
||||
/* Verify assumptions described above. */
|
||||
verify ((VECTOR_BLOCK_SIZE % roundup_size) == 0);
|
||||
verify ((VECTOR_FREE_LIST_SIZE_MASK + 1) >= VECTOR_BLOCK_SIZE);
|
||||
verify ((VECTOR_FREE_LIST_SIZE_MASK & (VECTOR_FREE_LIST_SIZE_MASK + 1)) == 0);
|
||||
verify (VECTOR_BLOCK_SIZE <= (1 << PSEUDOVECTOR_SIZE_BITS));
|
||||
|
||||
/* Round up X to nearest mult-of-ROUNDUP_SIZE. */
|
||||
|
||||
|
@ -2915,12 +2908,6 @@ verify ((VECTOR_FREE_LIST_SIZE_MASK & (VECTOR_FREE_LIST_SIZE_MASK + 1)) == 0);
|
|||
#define VECTOR_MAX_FREE_LIST_INDEX \
|
||||
((VECTOR_BLOCK_BYTES - VBLOCK_BYTES_MIN) / roundup_size + 1)
|
||||
|
||||
/* When the vector is on a free list, vectorlike_header.SIZE is set to
|
||||
this special value ORed with vector's memory footprint size. */
|
||||
|
||||
#define VECTOR_FREE_LIST_FLAG (~(ARRAY_MARK_FLAG | PSEUDOVECTOR_FLAG \
|
||||
| VECTOR_FREE_LIST_SIZE_MASK))
|
||||
|
||||
/* Common shortcut to advance vector pointer over a block data. */
|
||||
|
||||
#define ADVANCE(v, nbytes) ((struct Lisp_Vector *) ((char *) (v) + (nbytes)))
|
||||
|
@ -2933,7 +2920,7 @@ verify ((VECTOR_FREE_LIST_SIZE_MASK & (VECTOR_FREE_LIST_SIZE_MASK + 1)) == 0);
|
|||
|
||||
#define SETUP_ON_FREE_LIST(v, nbytes, index) \
|
||||
do { \
|
||||
(v)->header.size = VECTOR_FREE_LIST_FLAG | (nbytes); \
|
||||
XSETPVECTYPESIZE (v, PVEC_FREE, nbytes); \
|
||||
eassert ((nbytes) % roundup_size == 0); \
|
||||
(index) = VINDEX (nbytes); \
|
||||
eassert ((index) < VECTOR_MAX_FREE_LIST_INDEX); \
|
||||
|
@ -3065,6 +3052,16 @@ allocate_vector_from_block (size_t nbytes)
|
|||
((char *) (vector) <= (block)->data \
|
||||
+ VECTOR_BLOCK_BYTES - VBLOCK_BYTES_MIN)
|
||||
|
||||
/* Number of bytes used by vector-block-allocated object. This is the only
|
||||
place where we actually use the `nbytes' field of the vector-header.
|
||||
I.e. we could get rid of the `nbytes' field by computing it based on the
|
||||
vector-type. */
|
||||
|
||||
#define PSEUDOVECTOR_NBYTES(vector) \
|
||||
(PSEUDOVECTOR_TYPEP (&vector->header, PVEC_FREE) \
|
||||
? vector->header.size & PSEUDOVECTOR_SIZE_MASK \
|
||||
: vector->header.next.nbytes);
|
||||
|
||||
/* Reclaim space used by unmarked vectors. */
|
||||
|
||||
static void
|
||||
|
@ -3093,14 +3090,10 @@ sweep_vectors (void)
|
|||
}
|
||||
else
|
||||
{
|
||||
ptrdiff_t nbytes;
|
||||
ptrdiff_t nbytes = PSEUDOVECTOR_NBYTES (vector);
|
||||
ptrdiff_t total_bytes = nbytes;
|
||||
|
||||
if ((vector->header.size & VECTOR_FREE_LIST_FLAG)
|
||||
== VECTOR_FREE_LIST_FLAG)
|
||||
vector->header.next.nbytes =
|
||||
vector->header.size & VECTOR_FREE_LIST_SIZE_MASK;
|
||||
|
||||
next = ADVANCE (vector, vector->header.next.nbytes);
|
||||
next = ADVANCE (vector, nbytes);
|
||||
|
||||
/* While NEXT is not marked, try to coalesce with VECTOR,
|
||||
thus making VECTOR of the largest possible size. */
|
||||
|
@ -3109,16 +3102,12 @@ sweep_vectors (void)
|
|||
{
|
||||
if (VECTOR_MARKED_P (next))
|
||||
break;
|
||||
if ((next->header.size & VECTOR_FREE_LIST_FLAG)
|
||||
== VECTOR_FREE_LIST_FLAG)
|
||||
nbytes = next->header.size & VECTOR_FREE_LIST_SIZE_MASK;
|
||||
else
|
||||
nbytes = next->header.next.nbytes;
|
||||
vector->header.next.nbytes += nbytes;
|
||||
nbytes = PSEUDOVECTOR_NBYTES (next);
|
||||
total_bytes += nbytes;
|
||||
next = ADVANCE (next, nbytes);
|
||||
}
|
||||
|
||||
eassert (vector->header.next.nbytes % roundup_size == 0);
|
||||
eassert (total_bytes % roundup_size == 0);
|
||||
|
||||
if (vector == (struct Lisp_Vector *) block->data
|
||||
&& !VECTOR_IN_BLOCK (next, block))
|
||||
|
@ -3126,7 +3115,10 @@ sweep_vectors (void)
|
|||
space was coalesced into the only free vector. */
|
||||
free_this_block = 1;
|
||||
else
|
||||
SETUP_ON_FREE_LIST (vector, vector->header.next.nbytes, nbytes);
|
||||
{
|
||||
int tmp;
|
||||
SETUP_ON_FREE_LIST (vector, total_bytes, tmp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -4342,10 +4334,9 @@ live_vector_p (struct mem_node *m, void *p)
|
|||
while (VECTOR_IN_BLOCK (vector, block)
|
||||
&& vector <= (struct Lisp_Vector *) p)
|
||||
{
|
||||
if ((vector->header.size & VECTOR_FREE_LIST_FLAG)
|
||||
== VECTOR_FREE_LIST_FLAG)
|
||||
if (PSEUDOVECTOR_TYPEP (&vector->header, PVEC_FREE))
|
||||
vector = ADVANCE (vector, (vector->header.size
|
||||
& VECTOR_FREE_LIST_SIZE_MASK));
|
||||
& PSEUDOVECTOR_SIZE_MASK));
|
||||
else if (vector == p)
|
||||
return 1;
|
||||
else
|
||||
|
@ -5913,15 +5904,17 @@ mark_object (Lisp_Object arg)
|
|||
#endif /* GC_CHECK_MARKED_OBJECTS */
|
||||
|
||||
if (ptr->header.size & PSEUDOVECTOR_FLAG)
|
||||
pvectype = ptr->header.size & PVEC_TYPE_MASK;
|
||||
pvectype = ((ptr->header.size & PVEC_TYPE_MASK)
|
||||
>> PSEUDOVECTOR_SIZE_BITS);
|
||||
else
|
||||
pvectype = 0;
|
||||
|
||||
if (pvectype != PVEC_SUBR && pvectype != PVEC_BUFFER)
|
||||
CHECK_LIVE (live_vector_p);
|
||||
|
||||
if (pvectype == PVEC_BUFFER)
|
||||
switch (pvectype)
|
||||
{
|
||||
case PVEC_BUFFER:
|
||||
#ifdef GC_CHECK_MARKED_OBJECTS
|
||||
if (po != &buffer_defaults && po != &buffer_local_symbols)
|
||||
{
|
||||
|
@ -5933,67 +5926,82 @@ mark_object (Lisp_Object arg)
|
|||
}
|
||||
#endif /* GC_CHECK_MARKED_OBJECTS */
|
||||
mark_buffer ((struct buffer *) ptr);
|
||||
}
|
||||
break;
|
||||
|
||||
else if (pvectype == PVEC_COMPILED)
|
||||
/* We could treat this just like a vector, but it is better
|
||||
to save the COMPILED_CONSTANTS element for last and avoid
|
||||
recursion there. */
|
||||
{
|
||||
int size = ptr->header.size & PSEUDOVECTOR_SIZE_MASK;
|
||||
int i;
|
||||
case PVEC_COMPILED:
|
||||
{ /* We could treat this just like a vector, but it is better
|
||||
to save the COMPILED_CONSTANTS element for last and avoid
|
||||
recursion there. */
|
||||
int size = ptr->header.size & PSEUDOVECTOR_SIZE_MASK;
|
||||
int i;
|
||||
|
||||
VECTOR_MARK (ptr);
|
||||
for (i = 0; i < size; i++)
|
||||
if (i != COMPILED_CONSTANTS)
|
||||
mark_object (ptr->contents[i]);
|
||||
if (size > COMPILED_CONSTANTS)
|
||||
{
|
||||
obj = ptr->contents[COMPILED_CONSTANTS];
|
||||
goto loop;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case PVEC_FRAME:
|
||||
{
|
||||
mark_vectorlike (ptr);
|
||||
mark_face_cache (((struct frame *) ptr)->face_cache);
|
||||
}
|
||||
break;
|
||||
|
||||
case PVEC_WINDOW:
|
||||
{
|
||||
struct window *w = (struct window *) ptr;
|
||||
|
||||
mark_vectorlike (ptr);
|
||||
/* Mark glyphs for leaf windows. Marking window
|
||||
matrices is sufficient because frame matrices
|
||||
use the same glyph memory. */
|
||||
if (NILP (w->hchild) && NILP (w->vchild) && w->current_matrix)
|
||||
{
|
||||
mark_glyph_matrix (w->current_matrix);
|
||||
mark_glyph_matrix (w->desired_matrix);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case PVEC_HASH_TABLE:
|
||||
{
|
||||
struct Lisp_Hash_Table *h = (struct Lisp_Hash_Table *) ptr;
|
||||
|
||||
mark_vectorlike (ptr);
|
||||
/* If hash table is not weak, mark all keys and values.
|
||||
For weak tables, mark only the vector. */
|
||||
if (NILP (h->weak))
|
||||
mark_object (h->key_and_value);
|
||||
else
|
||||
VECTOR_MARK (XVECTOR (h->key_and_value));
|
||||
}
|
||||
break;
|
||||
|
||||
case PVEC_CHAR_TABLE:
|
||||
mark_char_table (ptr);
|
||||
break;
|
||||
|
||||
case PVEC_BOOL_VECTOR:
|
||||
/* No Lisp_Objects to mark in a bool vector. */
|
||||
VECTOR_MARK (ptr);
|
||||
for (i = 0; i < size; i++)
|
||||
if (i != COMPILED_CONSTANTS)
|
||||
mark_object (ptr->contents[i]);
|
||||
obj = ptr->contents[COMPILED_CONSTANTS];
|
||||
goto loop;
|
||||
}
|
||||
break;
|
||||
|
||||
else if (pvectype == PVEC_FRAME)
|
||||
{
|
||||
case PVEC_SUBR:
|
||||
break;
|
||||
|
||||
case PVEC_FREE:
|
||||
abort ();
|
||||
|
||||
default:
|
||||
mark_vectorlike (ptr);
|
||||
mark_face_cache (((struct frame *) ptr)->face_cache);
|
||||
}
|
||||
|
||||
else if (pvectype == PVEC_WINDOW)
|
||||
{
|
||||
struct window *w = (struct window *) ptr;
|
||||
|
||||
mark_vectorlike (ptr);
|
||||
/* Mark glyphs for leaf windows. Marking window
|
||||
matrices is sufficient because frame matrices
|
||||
use the same glyph memory. */
|
||||
if (NILP (w->hchild) && NILP (w->vchild) && w->current_matrix)
|
||||
{
|
||||
mark_glyph_matrix (w->current_matrix);
|
||||
mark_glyph_matrix (w->desired_matrix);
|
||||
}
|
||||
}
|
||||
|
||||
else if (pvectype == PVEC_HASH_TABLE)
|
||||
{
|
||||
struct Lisp_Hash_Table *h = (struct Lisp_Hash_Table *) ptr;
|
||||
|
||||
mark_vectorlike (ptr);
|
||||
/* If hash table is not weak, mark all keys and values.
|
||||
For weak tables, mark only the vector. */
|
||||
if (NILP (h->weak))
|
||||
mark_object (h->key_and_value);
|
||||
else
|
||||
VECTOR_MARK (XVECTOR (h->key_and_value));
|
||||
}
|
||||
|
||||
else if (pvectype == PVEC_CHAR_TABLE)
|
||||
mark_char_table (ptr);
|
||||
|
||||
else if (pvectype == PVEC_BOOL_VECTOR)
|
||||
/* No Lisp_Objects to mark in a bool vector. */
|
||||
VECTOR_MARK (ptr);
|
||||
|
||||
else if (pvectype != PVEC_SUBR)
|
||||
mark_vectorlike (ptr);
|
||||
}
|
||||
break;
|
||||
|
||||
|
|
|
@ -119,7 +119,7 @@ ptrdiff_t PVEC_FLAG EXTERNALLY_VISIBLE = PSEUDOVECTOR_FLAG;
|
|||
ptrdiff_t gdb_array_mark_flag EXTERNALLY_VISIBLE = ARRAY_MARK_FLAG;
|
||||
/* GDB might say "No enum type named pvec_type" if we don't have at
|
||||
least one symbol with that type, and then xbacktrace could fail. */
|
||||
enum pvec_type gdb_pvec_type EXTERNALLY_VISIBLE = PVEC_TYPE_MASK;
|
||||
ptrdiff_t gdb_pvec_type EXTERNALLY_VISIBLE = PVEC_TYPE_MASK;
|
||||
|
||||
/* Empty lisp strings. To avoid having to build any others. */
|
||||
Lisp_Object empty_unibyte_string, empty_multibyte_string;
|
||||
|
|
|
@ -2095,8 +2095,9 @@ internal_equal (register Lisp_Object o1, register Lisp_Object o2, int depth, int
|
|||
are sensible to compare, so eliminate the others now. */
|
||||
if (size & PSEUDOVECTOR_FLAG)
|
||||
{
|
||||
if (!(size & (PVEC_COMPILED
|
||||
| PVEC_CHAR_TABLE | PVEC_SUB_CHAR_TABLE | PVEC_FONT)))
|
||||
if (!(size & ((PVEC_COMPILED | PVEC_CHAR_TABLE
|
||||
| PVEC_SUB_CHAR_TABLE | PVEC_FONT)
|
||||
<< PSEUDOVECTOR_SIZE_BITS)))
|
||||
return 0;
|
||||
size &= PSEUDOVECTOR_SIZE_MASK;
|
||||
}
|
||||
|
|
98
src/lisp.h
98
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
|
||||
|
|
Loading…
Add table
Reference in a new issue