Mercurial > hg > xemacs-beta
diff src/lrecord.h @ 211:78478c60bfcd r20-4b4
Import from CVS: tag r20-4b4
author | cvs |
---|---|
date | Mon, 13 Aug 2007 10:05:51 +0200 |
parents | e45d5e7c476e |
children | 78f53ef88e17 |
line wrap: on
line diff
--- a/src/lrecord.h Mon Aug 13 10:05:01 2007 +0200 +++ b/src/lrecord.h Mon Aug 13 10:05:51 2007 +0200 @@ -29,23 +29,25 @@ implemented but only a few bits required in a Lisp object for type information. (The tradeoff is that each object has its type marked in it, thereby increasing its size.) The first - four bytes of all lrecords is a pointer to a struct - lrecord_implementation, which contains methods describing - how to process this object. + four bytes of all lrecords is either a pointer to a struct + lrecord_implementation, which contains methods describing how + to process this object, or an index into an array of pointers + to struct lrecord_implementations plus some other data bits. lrecords are of two types: straight lrecords, and lcrecords. Straight lrecords are used for those types of objects that - have their own allocation routines (typically allocated out - of 2K chunks of memory). These objects have a - `struct lrecord_header' at the top, containing only the - implementation pointer. There are special routines in alloc.c - to deal with each such object type. + have their own allocation routines (typically allocated out of + 2K chunks of memory). These objects have a `struct + lrecord_header' at the top, containing only the bits needed to + find the lrecord_implementation for the object. There are + special routines in alloc.c to deal with each such object + type. Lcrecords are used for less common sorts of objects that don't do their own allocation. Each such object is malloc()ed individually, and the objects are chained together through a `next' pointer. Lcrecords have a `struct lcrecord_header' - at the top, which contains an implementation pointer and + at the top, which contains a `struct lrecord_header' and a `next' pointer, and are allocated using alloc_lcrecord(). Creating a new lcrecord type is fairly easy; just follow the @@ -80,9 +82,33 @@ type-code table dynamically rather that pre-defining them.) I think I remember that Elk Lisp does something like this. Gee, I wonder if some cretin has patented it? */ + + /* + * If USE_INDEXED_LRECORD_IMPLEMENTATION is defined, we are + * implementing the scheme described in the 'It would be better + * ...' paragraph above. + */ +#ifdef USE_INDEXED_LRECORD_IMPLEMENTATION + /* index into lrecord_implementations_table[] */ + unsigned type:8; + /* 1 if the object is marked during GC, 0 otherwise. */ + unsigned mark:1; + /* 1 if the object was resides in pure (read-only) space */ + unsigned pure:1; +#else CONST struct lrecord_implementation *implementation; +#endif }; -#define set_lheader_implementation(header,imp) (header)->implementation=(imp) + +#ifdef USE_INDEXED_LRECORD_IMPLEMENTATION +# define set_lheader_implementation(header,imp) \ + do { (header)->type = lrecord_type_index((imp)) \ + (header)->mark = 0; \ + (header)->pure = 0; \ + } while (0) +#else +# define set_lheader_implementation(header,imp) (header)->implementation=(imp) +#endif struct lcrecord_header { @@ -178,23 +204,48 @@ int basic_p; }; +extern CONST struct lrecord_implementation *lrecord_implementations_table[]; + +#ifdef USE_INDEXED_LRECORD_IMPLEMENTATION +# define XRECORD_LHEADER_IMPLEMENTATION(obj) \ + (lrecord_implementations_table[XRECORD_LHEADER (obj)->type]) +# define LHEADER_IMPLEMENTATION(lh) (lrecord_implementations_table[(lh)->type]) +#else +# define XRECORD_LHEADER_IMPLEMENTATION(obj) \ + (XRECORD_LHEADER (obj)->implementation) +# define LHEADER_IMPLEMENTATION(lh) ((lh)->implementation) +#endif + extern int gc_in_progress; -#define MARKED_RECORD_P(obj) (gc_in_progress && \ +#ifdef USE_INDEXED_LRECORD_IMPLEMENTATION +# define MARKED_RECORD_P(obj) (gc_in_progress && XRECORD_LHEADER (obj)->mark) +#else +# define MARKED_RECORD_P(obj) (gc_in_progress && \ XRECORD_LHEADER (obj)->implementation->finalizer == \ this_marks_a_marked_record) +#endif +#ifdef USE_INDEXED_LRECORD_IMPLEMENTATION -/* moved here from alloc.c so that lisp.h macros can use them. */ -#define MARKED_RECORD_HEADER_P(lheader) \ +# define MARKED_RECORD_HEADER_P(lheader) (lheader)->mark +# define MARK_RECORD_HEADER(lheader) (lheader)->mark = 1 +# define UNMARK_RECORD_HEADER(lheader) (lheader)->mark = 0 + +#else /* ! USE_INDEXED_LRECORD_IMPLEMENTATION */ + +# define MARKED_RECORD_HEADER_P(lheader) \ (((lheader)->implementation->finalizer) == this_marks_a_marked_record) -#define UNMARKABLE_RECORD_HEADER_P(lheader) \ - (((lheader)->implementation->marker) == this_one_is_unmarkable) -#define MARK_RECORD_HEADER(lheader) \ +# define MARK_RECORD_HEADER(lheader) \ do { (((lheader)->implementation)++); } while (0) -#define UNMARK_RECORD_HEADER(lheader) \ +# define UNMARK_RECORD_HEADER(lheader) \ do { (((lheader)->implementation)--); } while (0) +#endif /* ! USE_INDEXED_LRECORD_IMPLEMENTATION */ + +#define UNMARKABLE_RECORD_HEADER_P(lheader) \ + ((LHEADER_IMPLEMENTATION (lheader)->marker) \ + == this_one_is_unmarkable) /* Declaring the following structures as const puts them in the text (read-only) segment, which makes debugging inconvenient @@ -273,8 +324,15 @@ #define LRECORDP(a) (XTYPE ((a)) == Lisp_Type_Record) #define XRECORD_LHEADER(a) ((struct lrecord_header *) XPNTR (a)) -#define RECORD_TYPEP(x, ty) \ + +#ifdef USE_INDEXED_LRECORD_IMPLEMENTATION +# define RECORD_TYPEP(x, ty) \ + (LRECORDP (x) && \ + lrecord_implementations_table[XRECORD_LHEADER (x)->type] == (ty)) +#else +# define RECORD_TYPEP(x, ty) \ (LRECORDP (x) && XRECORD_LHEADER (x)->implementation == (ty)) +#endif /* NOTE: the DECLARE_LRECORD() must come before the associated DEFINE_LRECORD_*() or you will get compile errors.