mirror of
git://git.code.sf.net/p/sbcl/sbcl
synced 2026-09-10 07:26:40 -04:00
Improve header layering
Rearranging lispobj.h and runtime.h to put object-representation-related macros in the former makes genesis/gc-tables.h self-contained, i.e. having no need for pthreads.h and signal.h and and everything that runtime.h pulls in. I thought fixnump.h stemmed from one of my early failed attempts to do this but, no, it was here since 2004. Just fold it into lispobj.h now.
This commit is contained in:
parent
303e68681e
commit
a822ffb50d
|
|
@ -1,20 +0,0 @@
|
|||
/*
|
||||
* This software is part of the SBCL system. See the README file for
|
||||
* more information.
|
||||
*
|
||||
* This software is derived from the CMU CL system, which was
|
||||
* written at Carnegie Mellon University and released into the
|
||||
* public domain. The software is in the public domain and is
|
||||
* provided with absolutely no warranty. See the COPYING and CREDITS
|
||||
* files for more information.
|
||||
*/
|
||||
|
||||
#ifndef _FIXNUMP_H
|
||||
#define _FIXNUMP_H
|
||||
|
||||
static inline int fixnump(lispobj obj)
|
||||
{
|
||||
return((obj & FIXNUM_TAG_MASK) == 0);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
@ -149,8 +149,6 @@ void gencgc_apply_code_fixups(struct code *old_code, struct code *new_code);
|
|||
#define gencgc_apply_code_fixups(ignore1,ignore2)
|
||||
#endif
|
||||
|
||||
#include "fixnump.h"
|
||||
|
||||
#if N_WORD_BITS == 32
|
||||
# define SIMPLE_ARRAY_WORD_WIDETAG SIMPLE_ARRAY_UNSIGNED_BYTE_32_WIDETAG
|
||||
#elif N_WORD_BITS == 64
|
||||
|
|
|
|||
|
|
@ -6,4 +6,181 @@ typedef intptr_t sword_t;
|
|||
typedef uintptr_t uword_t;
|
||||
typedef uword_t lispobj;
|
||||
|
||||
#include "sbcl.h"
|
||||
|
||||
static inline int fixnump(lispobj obj)
|
||||
{
|
||||
return((obj & FIXNUM_TAG_MASK) == 0);
|
||||
}
|
||||
|
||||
static inline int header_widetag(lispobj obj)
|
||||
{
|
||||
return obj & WIDETAG_MASK;
|
||||
}
|
||||
|
||||
static inline uword_t HeaderValue(lispobj obj)
|
||||
{
|
||||
return obj >> N_WIDETAG_BITS;
|
||||
}
|
||||
|
||||
/* Is the Lisp object obj something with immediate nature (e.g. a
|
||||
* fixnum or character or unbound marker)? */
|
||||
static inline int
|
||||
is_lisp_immediate(lispobj obj)
|
||||
{
|
||||
int widetag;
|
||||
return (fixnump(obj)
|
||||
|| ((widetag = header_widetag(obj)) == CHARACTER_WIDETAG)
|
||||
#if N_WORD_BITS == 64
|
||||
|| (widetag == SINGLE_FLOAT_WIDETAG)
|
||||
#endif
|
||||
|| (widetag == UNBOUND_MARKER_WIDETAG));
|
||||
}
|
||||
|
||||
static inline int lowtag_of(lispobj obj)
|
||||
{
|
||||
return obj & LOWTAG_MASK;
|
||||
}
|
||||
|
||||
static inline int widetag_of(lispobj* obj)
|
||||
{
|
||||
#ifdef LISP_FEATURE_BIG_ENDIAN
|
||||
return ((unsigned char*)obj)[N_WORD_BYTES-1];
|
||||
#else
|
||||
return *(unsigned char*)obj;
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline int listp(lispobj obj) {
|
||||
return lowtag_of(obj) == LIST_POINTER_LOWTAG;
|
||||
}
|
||||
static inline int instancep(lispobj obj) {
|
||||
return lowtag_of(obj) == INSTANCE_POINTER_LOWTAG;
|
||||
}
|
||||
static inline int functionp(lispobj obj) {
|
||||
return lowtag_of(obj) == FUN_POINTER_LOWTAG;
|
||||
}
|
||||
static inline int other_pointer_p(lispobj obj) {
|
||||
return lowtag_of(obj) == OTHER_POINTER_LOWTAG;
|
||||
}
|
||||
static inline int simple_vector_p(lispobj obj) {
|
||||
return other_pointer_p(obj) &&
|
||||
widetag_of((lispobj*)(obj-OTHER_POINTER_LOWTAG)) == SIMPLE_VECTOR_WIDETAG;
|
||||
}
|
||||
|
||||
/* Convert from a lispobj with type bits to a native (ordinary
|
||||
* C/assembly) pointer to the beginning of the object. */
|
||||
static inline lispobj *
|
||||
native_pointer(lispobj obj)
|
||||
{
|
||||
return (lispobj *) ((uintptr_t) (obj & ~LOWTAG_MASK));
|
||||
}
|
||||
|
||||
/* inverse operation: create a suitably tagged lispobj from a native pointer. */
|
||||
static inline lispobj
|
||||
make_lispobj(void *o, int low_tag)
|
||||
{
|
||||
return (lispobj)o | low_tag;
|
||||
}
|
||||
|
||||
#define make_fixnum(n) ((uword_t)(n) << N_FIXNUM_TAG_BITS)
|
||||
|
||||
static inline sword_t
|
||||
fixnum_value(lispobj n)
|
||||
{
|
||||
return (sword_t)n >> N_FIXNUM_TAG_BITS;
|
||||
}
|
||||
|
||||
/* Is the Lisp object obj something with pointer nature (as opposed to
|
||||
* e.g. a fixnum or character or unbound marker)? */
|
||||
static inline int is_lisp_pointer(lispobj obj)
|
||||
{
|
||||
#ifdef LISP_FEATURE_PPC64
|
||||
return (obj & 5) == 4;
|
||||
#elif N_WORD_BITS == 64
|
||||
return (obj & 3) == 3;
|
||||
#else
|
||||
return obj & 1;
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline int is_cons_half(lispobj obj)
|
||||
{
|
||||
if (fixnump(obj) || is_lisp_pointer(obj)) return 1;
|
||||
int widetag = header_widetag(obj);
|
||||
return widetag == CHARACTER_WIDETAG ||
|
||||
#if N_WORD_BITS == 64
|
||||
widetag == SINGLE_FLOAT_WIDETAG ||
|
||||
#endif
|
||||
widetag == UNBOUND_MARKER_WIDETAG;
|
||||
}
|
||||
|
||||
/* Each size category is designed to allow for some flag bits, and the payload
|
||||
* length in words, which is always an odd number so that total word count is even.
|
||||
* There are three size categories for most non-vector objects,
|
||||
* differing in how many flag bits versus size bits there are.
|
||||
*/
|
||||
|
||||
/* The largest payload count is expressed in 23 bits. These objects
|
||||
* can't reside in immobile space as there is no room for generation bits.
|
||||
* All sorts of objects fall into this category, but mostly due to inertia.
|
||||
* There are no non-vector boxed objects whose size should be so large.
|
||||
* Header: size | tag
|
||||
* ----- ------
|
||||
* 23 bits | 8 bits
|
||||
*/
|
||||
#define BOXED_NWORDS(obj) ((HeaderValue(obj) & 0x7FFFFF) | 1)
|
||||
|
||||
/* Medium-sized payload count is expressed in 15 bits. Objects in this category
|
||||
* may reside in immobile space: CLOSURE, FUNCALLABLE-INSTANCE.
|
||||
* The single data bit is used as a closure's NAMED flag.
|
||||
*
|
||||
* Header: gen# | data | size | tag
|
||||
* ----- ----- ------- ------
|
||||
* 8 bits | 1 bit | 15 bits | 8 bits
|
||||
*/
|
||||
#define SHORT_BOXED_NWORDS(obj) ((HeaderValue(obj) & SHORT_HEADER_MAX_WORDS) | 1)
|
||||
|
||||
/* Tiny payload count is expressed in 8 bits. Objects in this size category
|
||||
* can reside in immobile space: SYMBOL, FDEFN.
|
||||
* Header: gen# | flags | size | tag
|
||||
* ----- ------ ------ ------
|
||||
* 8 bits 8 bits 8 bits | 8 bits
|
||||
* FDEFN flag bits: 1 bit for statically-linked
|
||||
* SYMBOL flag bits: 1 bit for present in initial core image
|
||||
*/
|
||||
#define TINY_BOXED_NWORDS(obj) ((HeaderValue(obj) & 0xFF) | 1)
|
||||
|
||||
// other_immediate_lowtag_p is the least strict of the tests for whether a word
|
||||
// is potentially an object header, merely checking whether the bits fit the general
|
||||
// pattern of header widetags without regard for whether some headered object type
|
||||
// could in fact have those exact low bits. Specifically, this falsely returns 1
|
||||
// for UNBOUND_MARKER_WIDETAG, CHARACTER_WIDETAG, and on 64-bit machines,
|
||||
// SINGLE_FLOAT_WIDETAG; as well as unallocated and unused widetags (e.g. LRA on x86)
|
||||
// none of which denote the start of a headered object.
|
||||
// The ambiguous cases are for words would start a cons - the three mentioned above.
|
||||
// Other cases (NO_TLS_VALUE_MARKER_WIDETAG and other things) do not cause a problem
|
||||
// in practice because they can't be the first word of a lisp object.
|
||||
static inline int other_immediate_lowtag_p(lispobj header)
|
||||
{
|
||||
/* These lowtags are spaced 4 apart throughout the lowtag space. */
|
||||
return (lowtag_of(header) & 3) == OTHER_IMMEDIATE_0_LOWTAG;
|
||||
}
|
||||
|
||||
// widetag_lowtag encodes in the sign bit whether the byte corresponds
|
||||
// to a headered object, and in the low bits the lowtag of a tagged pointer
|
||||
// pointing to this object, be it headered or a cons.
|
||||
extern unsigned char widetag_lowtag[256];
|
||||
#define LOWTAG_FOR_WIDETAG(x) (widetag_lowtag[x] & LOWTAG_MASK)
|
||||
|
||||
// is_header() and is_cons_half() are logical complements when invoked
|
||||
// on the first word of any lisp object. However, given a word which is
|
||||
// only *potentially* the first word of a lisp object, they can both be false.
|
||||
// In ambiguous root detection, is_cons_half() is to be used, as it is the more
|
||||
// stringent check. The set of valid bit patterns in the low byte of the car
|
||||
// of a cons is smaller than the set of patterns accepted by !is_header().
|
||||
static inline int is_header(lispobj potential_header_word) {
|
||||
return widetag_lowtag[potential_header_word & WIDETAG_MASK] & 0x80;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -143,104 +143,6 @@ void dyndebug_init(void);
|
|||
|
||||
#define OBJ_FMTX PRIxPTR
|
||||
|
||||
static inline int
|
||||
lowtag_of(lispobj obj)
|
||||
{
|
||||
return obj & LOWTAG_MASK;
|
||||
}
|
||||
|
||||
static inline int
|
||||
widetag_of(lispobj* obj)
|
||||
{
|
||||
#ifdef LISP_FEATURE_BIG_ENDIAN
|
||||
return ((unsigned char*)obj)[N_WORD_BYTES-1];
|
||||
#else
|
||||
return *(unsigned char*)obj;
|
||||
#endif
|
||||
}
|
||||
static inline int
|
||||
header_widetag(lispobj obj)
|
||||
{
|
||||
return obj & WIDETAG_MASK;
|
||||
}
|
||||
|
||||
static inline uword_t
|
||||
HeaderValue(lispobj obj)
|
||||
{
|
||||
return obj >> N_WIDETAG_BITS;
|
||||
}
|
||||
|
||||
static inline int listp(lispobj obj) {
|
||||
return lowtag_of(obj) == LIST_POINTER_LOWTAG;
|
||||
}
|
||||
static inline int instancep(lispobj obj) {
|
||||
return lowtag_of(obj) == INSTANCE_POINTER_LOWTAG;
|
||||
}
|
||||
static inline int functionp(lispobj obj) {
|
||||
return lowtag_of(obj) == FUN_POINTER_LOWTAG;
|
||||
}
|
||||
static inline int other_pointer_p(lispobj obj) {
|
||||
return lowtag_of(obj) == OTHER_POINTER_LOWTAG;
|
||||
}
|
||||
static inline int simple_vector_p(lispobj obj) {
|
||||
return other_pointer_p(obj) &&
|
||||
widetag_of((lispobj*)(obj-OTHER_POINTER_LOWTAG)) == SIMPLE_VECTOR_WIDETAG;
|
||||
}
|
||||
|
||||
/* Is the Lisp object obj something with pointer nature (as opposed to
|
||||
* e.g. a fixnum or character or unbound marker)? */
|
||||
static inline int
|
||||
is_lisp_pointer(lispobj obj)
|
||||
{
|
||||
#ifdef LISP_FEATURE_PPC64
|
||||
return (obj & 5) == 4;
|
||||
#elif N_WORD_BITS == 64
|
||||
return (obj & 3) == 3;
|
||||
#else
|
||||
return obj & 1;
|
||||
#endif
|
||||
}
|
||||
|
||||
#include "fixnump.h"
|
||||
|
||||
/* Is the Lisp object obj something with immediate nature (e.g. a
|
||||
* fixnum or character or unbound marker)? */
|
||||
static inline int
|
||||
is_lisp_immediate(lispobj obj)
|
||||
{
|
||||
int widetag;
|
||||
return (fixnump(obj)
|
||||
|| ((widetag = header_widetag(obj)) == CHARACTER_WIDETAG)
|
||||
#if N_WORD_BITS == 64
|
||||
|| (widetag == SINGLE_FLOAT_WIDETAG)
|
||||
#endif
|
||||
|| (widetag == UNBOUND_MARKER_WIDETAG));
|
||||
}
|
||||
|
||||
/* Convert from a lispobj with type bits to a native (ordinary
|
||||
* C/assembly) pointer to the beginning of the object. */
|
||||
static inline lispobj *
|
||||
native_pointer(lispobj obj)
|
||||
{
|
||||
return (lispobj *) ((uintptr_t) (obj & ~LOWTAG_MASK));
|
||||
}
|
||||
|
||||
/* inverse operation: create a suitably tagged lispobj from a native
|
||||
* pointer or integer.*/
|
||||
static inline lispobj
|
||||
make_lispobj(void *o, int low_tag)
|
||||
{
|
||||
return (lispobj)o | low_tag;
|
||||
}
|
||||
|
||||
#define make_fixnum(n) ((uword_t)(n) << N_FIXNUM_TAG_BITS)
|
||||
|
||||
static inline sword_t
|
||||
fixnum_value(lispobj n)
|
||||
{
|
||||
return (sword_t)n >> N_FIXNUM_TAG_BITS;
|
||||
}
|
||||
|
||||
#include "align.h"
|
||||
|
||||
#if defined(LISP_FEATURE_WIN32)
|
||||
|
|
@ -258,51 +160,6 @@ fixnum_value(lispobj n)
|
|||
#endif
|
||||
typedef int boolean;
|
||||
|
||||
// other_immediate_lowtag_p is the least strict of the tests for whether a word
|
||||
// is potentially an object header, merely checking whether the bits fit the general
|
||||
// pattern of header widetags without regard for whether some headered object type
|
||||
// could in fact have those exact low bits. Specifically, this falsely returns 1
|
||||
// for UNBOUND_MARKER_WIDETAG, CHARACTER_WIDETAG, and on 64-bit machines,
|
||||
// SINGLE_FLOAT_WIDETAG; as well as unallocated and unused widetags (e.g. LRA on x86)
|
||||
// none of which denote the start of a headered object.
|
||||
// The ambiguous cases are for words would start a cons - the three mentioned above.
|
||||
// Other cases (NO_TLS_VALUE_MARKER_WIDETAG and other things) do not cause a problem
|
||||
// in practice because they can't be the first word of a lisp object.
|
||||
static inline boolean
|
||||
other_immediate_lowtag_p(lispobj header)
|
||||
{
|
||||
/* These lowtags are spaced 4 apart throughout the lowtag space. */
|
||||
return (lowtag_of(header) & 3) == OTHER_IMMEDIATE_0_LOWTAG;
|
||||
}
|
||||
|
||||
// widetag_lowtag encodes in the sign bit whether the byte corresponds
|
||||
// to a headered object, and in the low bits the lowtag of a tagged pointer
|
||||
// pointing to this object, be it headered or a cons.
|
||||
extern unsigned char widetag_lowtag[256];
|
||||
#define LOWTAG_FOR_WIDETAG(x) (widetag_lowtag[x] & LOWTAG_MASK)
|
||||
|
||||
// is_header() and is_cons_half() are logical complements when invoked
|
||||
// on the first word of any lisp object. However, given a word which is
|
||||
// only *potentially* the first word of a lisp object, they can both be false.
|
||||
// In ambiguous root detection, is_cons_half() is to be used, as it is the more
|
||||
// stringent check. The set of valid bit patterns in the low byte of the car
|
||||
// of a cons is smaller than the set of patterns accepted by !is_header().
|
||||
static inline int is_header(lispobj potential_header_word) {
|
||||
return widetag_lowtag[potential_header_word & WIDETAG_MASK] & 0x80;
|
||||
}
|
||||
|
||||
static inline int
|
||||
is_cons_half(lispobj obj)
|
||||
{
|
||||
if (fixnump(obj) || is_lisp_pointer(obj)) return 1;
|
||||
int widetag = header_widetag(obj);
|
||||
return widetag == CHARACTER_WIDETAG ||
|
||||
#if N_WORD_BITS == 64
|
||||
widetag == SINGLE_FLOAT_WIDETAG ||
|
||||
#endif
|
||||
widetag == UNBOUND_MARKER_WIDETAG;
|
||||
}
|
||||
|
||||
/* KLUDGE: As far as I can tell there's no ANSI C way of saying
|
||||
* "this function never returns". This is the way that you do it
|
||||
* in GCC later than version 2.5 or so. */
|
||||
|
|
@ -365,55 +222,4 @@ extern struct lisp_startup_options lisp_startup_options;
|
|||
#define NO_SANITIZE_MEMORY
|
||||
#endif
|
||||
|
||||
/// Object sizing macros. One of these days I'd like to rationalize
|
||||
/// all our headers making them more intuitive as to which need be
|
||||
/// included to get access to various things.
|
||||
/// For the time being, this file makes as much sense as anything else.
|
||||
|
||||
/// These sizing macros return the number of *payload* words,
|
||||
/// exclusive of the object header word. Payload length is always
|
||||
/// an odd number so that total word count is an even number.
|
||||
|
||||
/* Each size category is designed to allow 1 bit for a GC mark bit,
|
||||
* possibly some flag bits, and the payload length in words.
|
||||
* There are three size categories for most non-vector objects,
|
||||
* differing in how many flag bits versus size bits there are.
|
||||
* The GC mark bit is always in bit index 31 of the header regardless of
|
||||
* machine word size. Bit index 31 is chosen for consistency between 32-bit
|
||||
* and 64-bit machines. It is a natural choice for 32-bit headers by avoiding
|
||||
* intererence with other header fields. It is also chosen for 64-bit headers
|
||||
* because the upper 32 bits of headers for some objects are already occupied
|
||||
* by other data: symbol TLS index, instance layout, etc.
|
||||
*/
|
||||
|
||||
/* The largest payload count is expressed in 23 bits. These objects
|
||||
* can't reside in immobile space as there is no room for generation bits.
|
||||
* All sorts of objects fall into this category, but mostly due to inertia.
|
||||
* There are no non-vector boxed objects whose size should be so large.
|
||||
* Header: size | tag
|
||||
* ----- ------
|
||||
* 23 bits | 8 bits
|
||||
*/
|
||||
#define BOXED_NWORDS(obj) ((HeaderValue(obj) & 0x7FFFFF) | 1)
|
||||
|
||||
/* Medium-sized payload count is expressed in 15 bits. Objects in this category
|
||||
* may reside in immobile space: CLOSURE, FUNCALLABLE-INSTANCE.
|
||||
* The single data bit is used as a closure's NAMED flag.
|
||||
*
|
||||
* Header: gen# | data | size | tag
|
||||
* ----- ----- ------- ------
|
||||
* 8 bits | 1 bit | 15 bits | 8 bits
|
||||
*/
|
||||
#define SHORT_BOXED_NWORDS(obj) ((HeaderValue(obj) & SHORT_HEADER_MAX_WORDS) | 1)
|
||||
|
||||
/* Tiny payload count is expressed in 8 bits. Objects in this size category
|
||||
* can reside in immobile space: SYMBOL, FDEFN.
|
||||
* Header: gen# | flags | size | tag
|
||||
* ----- ------ ------ ------
|
||||
* 8 bits 8 bits 8 bits | 8 bits
|
||||
* FDEFN flag bits: 1 bit for statically-linked
|
||||
* SYMBOL flag bits: 1 bit for present in initial core image
|
||||
*/
|
||||
#define TINY_BOXED_NWORDS(obj) ((HeaderValue(obj) & 0xFF) | 1)
|
||||
|
||||
#endif /* _SBCL_RUNTIME_H_ */
|
||||
|
|
|
|||
|
|
@ -39,13 +39,8 @@ if [ -r $TEST_DIRECTORY/array.h ]
|
|||
then
|
||||
for i in $TEST_DIRECTORY/*.h
|
||||
do
|
||||
case $i in
|
||||
*/gc-tables.h) ;; # fails to compile by itself (FIXME)
|
||||
*)
|
||||
echo "#include \"$i\"" > ${src}
|
||||
./run-compiler.sh -I../src/runtime -c -o ${obj} ${src}
|
||||
;;
|
||||
esac
|
||||
done
|
||||
fi
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue