0.8.14.2:
authorNathan Froyd <froydnj@cs.rice.edu>
Wed, 8 Sep 2004 16:05:14 +0000 (16:05 +0000)
committerNathan Froyd <froydnj@cs.rice.edu>
Wed, 8 Sep 2004 16:05:14 +0000 (16:05 +0000)
Lots of GC cleanups:

* use N_WORD_BYTES where appropriate, even in gencgc.c
* use inline functions instead of macros (there are a few cases
  yet to replace, though)
* use `fixnump' where possible instead of `& 0x3' (which will
  break with 64-bit ports)
* tweak NWORDS to function correctly for n_bits greater than
  the word size (important for 64-bit ports)
* changes to use to new, improved NWORDS function when
  appropriate (e.g. for determining the length of float arrays)

purify.c needs some of the same tweaks; I have a version which
  seems to work on alpha64 but fails at the end of warm-init.

Passes all tests.

src/runtime/cheneygc.c
src/runtime/gc-common.c
src/runtime/gc-internal.h
src/runtime/gencgc.c
src/runtime/runtime.h
version.lisp-expr

index 07e9d15..63383f5 100644 (file)
@@ -72,7 +72,7 @@ tv_diff(struct timeval *x, struct timeval *y)
 static void
 zero_stack(void)
 {
-    u32 *ptr = (u32 *)current_control_stack_pointer;
+    lispobj *ptr = current_control_stack_pointer;
  search:
     do {
        if (*ptr)
@@ -92,7 +92,7 @@ zero_stack(void)
 void *
 gc_general_alloc(int bytes, int unboxed_p, int quick_p) {
     lispobj *new=new_space_free_pointer;
-    new_space_free_pointer+=(bytes/4);
+    new_space_free_pointer+=(bytes/N_WORD_BYTES);
     return new;
 }
 
@@ -273,15 +273,8 @@ collect_garbage(unsigned ignore)
     user_time = tv_diff(&stop_rusage.ru_utime, &start_rusage.ru_utime);
     system_time = tv_diff(&stop_rusage.ru_stime, &start_rusage.ru_stime);
 
-#if 0
-    printf("Statistics:\n");
-    printf("%10.2f sec of real time\n", real_time);
-    printf("%10.2f sec of user time,\n", user_time);
-    printf("%10.2f sec of system time.\n", system_time);
-#else
     printf("Statistics: %10.2fs real, %10.2fs user, %10.2fs system.\n",
           real_time, user_time, system_time);
-#endif        
 
     gc_rate = ((float) size_retained / (float) (1<<20)) / real_time;
        
@@ -339,8 +332,9 @@ scavenge_interrupt_context(os_context_t *context)
     /* before we scavenge the context. */
 #ifdef reg_LIP
     lip = *os_context_register_addr(context, reg_LIP);
-    /*  0x7FFFFFFF or 0x7FFFFFFFFFFFFFFF ? */
-    lip_offset = 0x7FFFFFFF;
+    /* 0x7FFFFFFF on 32-bit platforms;
+       0x7FFFFFFFFFFFFFFF on 64-bit platforms */
+    lip_offset = (((unsigned long)1) << (N_WORD_BITS - 1)) - 1;
     lip_register_pair = -1;
     for (i = 0; i < (sizeof(boxed_registers) / sizeof(int)); i++) {
        unsigned long reg;
@@ -529,7 +523,7 @@ scav_fdefn(lispobj *where, lispobj object)
        == (char *)((unsigned long)(fdefn->raw_addr))) {
         scavenge(where + 1, sizeof(struct fdefn)/sizeof(lispobj) - 1);
         fdefn->raw_addr =
-           (u32)  ((char *) LOW_WORD(fdefn->fun)) + FUN_RAW_ADDR_OFFSET;
+            (u32) ((char *) LOW_WORD(fdefn->fun)) + FUN_RAW_ADDR_OFFSET;
         return sizeof(struct fdefn) / sizeof(lispobj);
     }
     else
index 0e94dd4..2dfe4c9 100644 (file)
@@ -107,10 +107,10 @@ copy_object(lispobj object, int nwords)
     tag = lowtag_of(object);
 
     /* Allocate space. */
-    new = gc_general_alloc(nwords*4,ALLOC_BOXED,ALLOC_QUICK);
+    new = gc_general_alloc(nwords*N_WORD_BYTES,ALLOC_BOXED,ALLOC_QUICK);
 
     /* Copy the object. */
-    memcpy(new,native_pointer(object),nwords*4);
+    memcpy(new,native_pointer(object),nwords*N_WORD_BYTES);
     return make_lispobj(new,tag);
 }
 
@@ -175,7 +175,7 @@ scavenge(lispobj *start, long n_words)
            }
        }
 #endif
-       else if ((object & 3) == 0) {
+       else if (fixnump(object)) {
            /* It's a fixnum: really easy.. */
            n_words_scavenged = 1;
        } else {
@@ -399,7 +399,8 @@ trans_return_pc_header(lispobj object)
     struct code *code, *ncode;
 
     return_pc = (struct simple_fun *) native_pointer(object);
-    offset = HeaderValue(return_pc->header)  * 4 ;
+    /* FIXME: was times 4, should it really be N_WORD_BYTES? */
+    offset = HeaderValue(return_pc->header) * N_WORD_BYTES;
 
     /* Transport the whole code object */
     code = (struct code *) ((unsigned long) return_pc - offset);
@@ -453,7 +454,8 @@ trans_fun_header(lispobj object)
     struct code *code, *ncode;
        
     fheader = (struct simple_fun *) native_pointer(object);
-    offset = HeaderValue(fheader->header) * 4;
+    /* FIXME: was times 4, should it really be N_WORD_BYTES? */
+    offset = HeaderValue(fheader->header) * N_WORD_BYTES;
 
     /* Transport the whole code object */
     code = (struct code *) ((unsigned long) fheader - offset);
@@ -690,8 +692,7 @@ scav_fdefn(lispobj *where, lispobj object)
            fdefn->raw_addr = (char *)(fdefn->fun + FUN_RAW_ADDR_OFFSET);
        /* gc.c has more casts here, which may be relevant or alternatively
           may be compiler warning defeaters.  try 
-        fdefn->raw_addr =
-           (u32)  ((char *) LOW_WORD(fdefn->fun)) + FUN_RAW_ADDR_OFFSET;
+        fdefn->raw_addr = ((char *) LOW_WORD(fdefn->fun)) + FUN_RAW_ADDR_OFFSET;
        */
        return sizeof(struct fdefn) / sizeof(lispobj);
     } else {
@@ -1144,7 +1145,7 @@ scav_vector_single_float(lispobj *where, lispobj object)
 
     vector = (struct vector *) where;
     length = fixnum_value(vector->length);
-    nwords = CEILING(length + 2, 2);
+    nwords = CEILING(NWORDS(length, 32) + 2, 2);
 
     return nwords;
 }
@@ -1159,7 +1160,7 @@ trans_vector_single_float(lispobj object)
 
     vector = (struct vector *) native_pointer(object);
     length = fixnum_value(vector->length);
-    nwords = CEILING(length + 2, 2);
+    nwords = CEILING(NWORDS(length, 32) + 2, 2);
 
     return copy_large_unboxed_object(object, nwords);
 }
@@ -1172,7 +1173,7 @@ size_vector_single_float(lispobj *where)
 
     vector = (struct vector *) where;
     length = fixnum_value(vector->length);
-    nwords = CEILING(length + 2, 2);
+    nwords = CEILING(NWORDS(length, 32) + 2, 2);
 
     return nwords;
 }
@@ -1185,7 +1186,7 @@ scav_vector_double_float(lispobj *where, lispobj object)
 
     vector = (struct vector *) where;
     length = fixnum_value(vector->length);
-    nwords = CEILING(length * 2 + 2, 2);
+    nwords = CEILING(NWORDS(length, 64) + 2, 2);
 
     return nwords;
 }
@@ -1200,7 +1201,7 @@ trans_vector_double_float(lispobj object)
 
     vector = (struct vector *) native_pointer(object);
     length = fixnum_value(vector->length);
-    nwords = CEILING(length * 2 + 2, 2);
+    nwords = CEILING(NWORDS(length, 64) + 2, 2);
 
     return copy_large_unboxed_object(object, nwords);
 }
@@ -1213,7 +1214,7 @@ size_vector_double_float(lispobj *where)
 
     vector = (struct vector *) where;
     length = fixnum_value(vector->length);
-    nwords = CEILING(length * 2 + 2, 2);
+    nwords = CEILING(NWORDS(length, 64) + 2, 2);
 
     return nwords;
 }
@@ -1272,7 +1273,7 @@ scav_vector_complex_single_float(lispobj *where, lispobj object)
 
     vector = (struct vector *) where;
     length = fixnum_value(vector->length);
-    nwords = CEILING(length * 2 + 2, 2);
+    nwords = CEILING(NWORDS(length, 64) + 2, 2);
 
     return nwords;
 }
@@ -1287,7 +1288,7 @@ trans_vector_complex_single_float(lispobj object)
 
     vector = (struct vector *) native_pointer(object);
     length = fixnum_value(vector->length);
-    nwords = CEILING(length * 2 + 2, 2);
+    nwords = CEILING(NWORDS(length, 64) + 2, 2);
 
     return copy_large_unboxed_object(object, nwords);
 }
@@ -1300,7 +1301,7 @@ size_vector_complex_single_float(lispobj *where)
 
     vector = (struct vector *) where;
     length = fixnum_value(vector->length);
-    nwords = CEILING(length * 2 + 2, 2);
+    nwords = CEILING(NWORDS(length, 64) + 2, 2);
 
     return nwords;
 }
@@ -1315,7 +1316,7 @@ scav_vector_complex_double_float(lispobj *where, lispobj object)
 
     vector = (struct vector *) where;
     length = fixnum_value(vector->length);
-    nwords = CEILING(length * 4 + 2, 2);
+    nwords = CEILING(NWORDS(length, 128) + 2, 2);
 
     return nwords;
 }
@@ -1330,7 +1331,7 @@ trans_vector_complex_double_float(lispobj object)
 
     vector = (struct vector *) native_pointer(object);
     length = fixnum_value(vector->length);
-    nwords = CEILING(length * 4 + 2, 2);
+    nwords = CEILING(NWORDS(length, 128) + 2, 2);
 
     return copy_large_unboxed_object(object, nwords);
 }
@@ -1343,7 +1344,7 @@ size_vector_complex_double_float(lispobj *where)
 
     vector = (struct vector *) where;
     length = fixnum_value(vector->length);
-    nwords = CEILING(length * 4 + 2, 2);
+    nwords = CEILING(NWORDS(length, 128) + 2, 2);
 
     return nwords;
 }
@@ -1470,8 +1471,9 @@ static int
 scav_lose(lispobj *where, lispobj object)
 {
     lose("no scavenge function for object 0x%08x (widetag 0x%x)",
-        (unsigned long)object,
-        widetag_of(*(lispobj*)native_pointer(object)));
+         (unsigned long)object,
+         widetag_of(*(lispobj*)native_pointer(object)));
+
     return 0; /* bogus return value to satisfy static type checking */
 }
 
@@ -1697,7 +1699,7 @@ gc_init_tables(void)
        trans_vector_unsigned_byte_32;
 #ifdef SIMPLE_ARRAY_UNSIGNED_BYTE_60_WIDETAG
     transother[SIMPLE_ARRAY_UNSIGNED_BYTE_60_WIDETAG] =
-       trans_vector_unsigned_byte_32;
+       trans_vector_unsigned_byte_64;
 #endif
 #ifdef SIMPLE_ARRAY_UNSIGNED_BYTE_63_WIDETAG
     transother[SIMPLE_ARRAY_UNSIGNED_BYTE_63_WIDETAG] =
index 8928f2b..0b4bd4d 100644 (file)
 static inline unsigned int
 NWORDS(unsigned int x, unsigned int n_bits)
 {
-    unsigned int elements_per_word = N_WORD_BITS/n_bits;
+    /* A good compiler should be able to constant-fold this whole thing,
+       even with the conditional. */
+    if(n_bits <= N_WORD_BITS) {
+        unsigned int elements_per_word = N_WORD_BITS/n_bits;
 
-    return CEILING(x, elements_per_word)/elements_per_word;
+        return CEILING(x, elements_per_word)/elements_per_word;
+    }
+    else {
+        /* FIXME: should have some sort of assertion that N_WORD_BITS
+           evenly divides n_bits */
+        return x * (n_bits/N_WORD_BITS);
+    }
 }
 
 /* FIXME: Shouldn't this be defined in sbcl.h? */
@@ -82,7 +91,7 @@ search_space(lispobj *start, size_t words, lispobj *pointer)
 
        /* If thing is an immediate then this is a cons. */
        if (is_lisp_pointer(thing)
-           || ((thing & 3) == 0) /* fixnum */
+           || (fixnump(thing))
            || (widetag_of(thing) == BASE_CHAR_WIDETAG)
            || (widetag_of(thing) == UNBOUND_MARKER_WIDETAG))
            count = 2;
index e3acbe3..b50b8d8 100644 (file)
@@ -1150,7 +1150,7 @@ copy_large_object(lispobj object, int nwords)
        gc_assert(page_table[first_page].first_object_offset == 0);
 
        next_page = first_page;
-       remaining_bytes = nwords*4;
+       remaining_bytes = nwords*N_WORD_BYTES;
        while (remaining_bytes > PAGE_BYTES) {
            gc_assert(page_table[next_page].gen == from_space);
            gc_assert(page_table[next_page].allocated == BOXED_PAGE_FLAG);
@@ -1212,7 +1212,7 @@ copy_large_object(lispobj object, int nwords)
        bytes_allocated -= bytes_freed;
 
        /* Add the region to the new_areas if requested. */
-       add_new_area(first_page,0,nwords*4);
+       add_new_area(first_page,0,nwords*N_WORD_BYTES);
 
        return(object);
     } else {
@@ -1220,9 +1220,9 @@ copy_large_object(lispobj object, int nwords)
        tag = lowtag_of(object);
 
        /* Allocate space. */
-       new = gc_quick_alloc_large(nwords*4);
+       new = gc_quick_alloc_large(nwords*N_WORD_BYTES);
 
-       memcpy(new,native_pointer(object),nwords*4);
+       memcpy(new,native_pointer(object),nwords*N_WORD_BYTES);
 
        /* Return Lisp pointer of new object. */
        return ((lispobj) new) | tag;
@@ -1244,9 +1244,9 @@ copy_unboxed_object(lispobj object, int nwords)
     tag = lowtag_of(object);
 
     /* Allocate space. */
-    new = gc_quick_alloc_unboxed(nwords*4);
+    new = gc_quick_alloc_unboxed(nwords*N_WORD_BYTES);
 
-    memcpy(new,native_pointer(object),nwords*4);
+    memcpy(new,native_pointer(object),nwords*N_WORD_BYTES);
 
     /* Return Lisp pointer of new object. */
     return ((lispobj) new) | tag;
@@ -1268,7 +1268,6 @@ copy_large_unboxed_object(lispobj object, int nwords)
 {
     int tag;
     lispobj *new;
-    lispobj *source, *dest;
     int first_page;
 
     gc_assert(is_lisp_pointer(object));
@@ -1276,7 +1275,7 @@ copy_large_unboxed_object(lispobj object, int nwords)
     gc_assert((nwords & 0x01) == 0);
 
     if ((nwords > 1024*1024) && gencgc_verbose)
-       FSHOW((stderr, "/copy_large_unboxed_object: %d bytes\n", nwords*4));
+       FSHOW((stderr, "/copy_large_unboxed_object: %d bytes\n", nwords*N_WORD_BYTES));
 
     /* Check whether it's a large object. */
     first_page = find_page_index((void *)object);
@@ -1294,7 +1293,7 @@ copy_large_unboxed_object(lispobj object, int nwords)
        gc_assert(page_table[first_page].first_object_offset == 0);
 
        next_page = first_page;
-       remaining_bytes = nwords*4;
+       remaining_bytes = nwords*N_WORD_BYTES;
        while (remaining_bytes > PAGE_BYTES) {
            gc_assert(page_table[next_page].gen == from_space);
            gc_assert((page_table[next_page].allocated == UNBOXED_PAGE_FLAG)
@@ -1352,8 +1351,8 @@ copy_large_unboxed_object(lispobj object, int nwords)
                   "/copy_large_unboxed bytes_freed=%d\n",
                   bytes_freed));
 
-       generations[from_space].bytes_allocated -= 4*nwords + bytes_freed;
-       generations[new_space].bytes_allocated += 4*nwords;
+       generations[from_space].bytes_allocated -= nwords*N_WORD_BYTES + bytes_freed;
+       generations[new_space].bytes_allocated += nwords*N_WORD_BYTES;
        bytes_allocated -= bytes_freed;
 
        return(object);
@@ -1363,19 +1362,10 @@ copy_large_unboxed_object(lispobj object, int nwords)
        tag = lowtag_of(object);
 
        /* Allocate space. */
-       new = gc_quick_alloc_large_unboxed(nwords*4);
-
-       dest = new;
-       source = (lispobj *) native_pointer(object);
-
-       /* Copy the object. */
-       while (nwords > 0) {
-           dest[0] = source[0];
-           dest[1] = source[1];
-           dest += 2;
-           source += 2;
-           nwords -= 2;
-       }
+       new = gc_quick_alloc_large_unboxed(nwords*N_WORD_BYTES);
+
+        /* Copy the object. */
+        memcpy(new,native_pointer(object),nwords*N_WORD_BYTES);
 
        /* Return Lisp pointer of new object. */
        return ((lispobj) new) | tag;
@@ -1419,10 +1409,10 @@ sniff_code_object(struct code *code, unsigned displacement)
     nheader_words = HeaderValue(*(lispobj *)code);
     nwords = ncode_words + nheader_words;
 
-    constants_start_addr = (void *)code + 5*4;
-    constants_end_addr = (void *)code + nheader_words*4;
-    code_start_addr = (void *)code + nheader_words*4;
-    code_end_addr = (void *)code + nwords*4;
+    constants_start_addr = (void *)code + 5*N_WORD_BYTES;
+    constants_end_addr = (void *)code + nheader_words*N_WORD_BYTES;
+    code_start_addr = (void *)code + nheader_words*N_WORD_BYTES;
+    code_end_addr = (void *)code + nwords*N_WORD_BYTES;
 
     /* Work through the unboxed code. */
     for (p = code_start_addr; p < code_end_addr; p++) {
@@ -1589,10 +1579,10 @@ gencgc_apply_code_fixups(struct code *old_code, struct code *new_code)
     /* FSHOW((stderr,
             "/compiled code object at %x: header words = %d, code words = %d\n",
             new_code, nheader_words, ncode_words)); */
-    constants_start_addr = (void *)new_code + 5*4;
-    constants_end_addr = (void *)new_code + nheader_words*4;
-    code_start_addr = (void *)new_code + nheader_words*4;
-    code_end_addr = (void *)new_code + nwords*4;
+    constants_start_addr = (void *)new_code + 5*N_WORD_BYTES;
+    constants_end_addr = (void *)new_code + nheader_words*N_WORD_BYTES;
+    code_start_addr = (void *)new_code + nheader_words*N_WORD_BYTES;
+    code_end_addr = (void *)new_code + nwords*N_WORD_BYTES;
     /*
     FSHOW((stderr,
           "/const start = %x, end = %x\n",
@@ -1648,7 +1638,7 @@ gencgc_apply_code_fixups(struct code *old_code, struct code *new_code)
            /* If it's within the old_code object then it must be an
             * absolute fixup (relative ones are not saved) */
            if ((old_value >= (unsigned)old_code)
-               && (old_value < ((unsigned)old_code + nwords*4)))
+               && (old_value < ((unsigned)old_code + nwords*N_WORD_BYTES)))
                /* So add the dispacement. */
                *(unsigned *)((unsigned)code_start_addr + offset) =
                    old_value + displacement;
@@ -2065,11 +2055,11 @@ possibly_valid_dynamic_space_pointer(lispobj *pointer)
        }
        /* Is it plausible cons? */
        if ((is_lisp_pointer(start_addr[0])
-           || ((start_addr[0] & 3) == 0) /* fixnum */
+           || (fixnump(start_addr[0]))
            || (widetag_of(start_addr[0]) == BASE_CHAR_WIDETAG)
            || (widetag_of(start_addr[0]) == UNBOUND_MARKER_WIDETAG))
           && (is_lisp_pointer(start_addr[1])
-              || ((start_addr[1] & 3) == 0) /* fixnum */
+              || (fixnump(start_addr[1]))
               || (widetag_of(start_addr[1]) == BASE_CHAR_WIDETAG)
               || (widetag_of(start_addr[1]) == UNBOUND_MARKER_WIDETAG)))
            break;
@@ -2315,7 +2305,7 @@ maybe_adjust_large_object(lispobj *where)
     gc_assert(page_table[first_page].first_object_offset == 0);
 
     next_page = first_page;
-    remaining_bytes = nwords*4;
+    remaining_bytes = nwords*N_WORD_BYTES;
     while (remaining_bytes > PAGE_BYTES) {
        gc_assert(page_table[next_page].gen == from_space);
        gc_assert((page_table[next_page].allocated == BOXED_PAGE_FLAG)
@@ -2532,7 +2522,7 @@ update_page_write_prot(int page)
     int j;
     int wp_it = 1;
     void **page_addr = (void **)page_address(page);
-    int num_words = page_table[page].bytes_used / 4;
+    int num_words = page_table[page].bytes_used / N_WORD_BYTES;
 
     /* Shouldn't be a free page. */
     gc_assert(page_table[page].allocated != FREE_PAGE_FLAG);
@@ -2871,12 +2861,10 @@ scavenge_newspace_generation(int generation)
 
            /* Work through previous_new_areas. */
            for (i = 0; i < previous_new_areas_index; i++) {
-               /* FIXME: All these bare *4 and /4 should be something
-                * like BYTES_PER_WORD or WBYTES. */
                int page = (*previous_new_areas)[i].page;
                int offset = (*previous_new_areas)[i].offset;
-               int size = (*previous_new_areas)[i].size / 4;
-               gc_assert((*previous_new_areas)[i].size % 4 == 0);
+               int size = (*previous_new_areas)[i].size / N_WORD_BYTES;
+               gc_assert((*previous_new_areas)[i].size % N_WORD_BYTES == 0);
                scavenge(page_address(page)+offset, size);
            }
 
@@ -3346,7 +3334,7 @@ verify_zero_fill(void)
            if (free_bytes > 0) {
                int *start_addr = (int *)((unsigned)page_address(page)
                                          + page_table[page].bytes_used);
-               int size = free_bytes / 4;
+               int size = free_bytes / N_WORD_BYTES;
                int i;
                for (i = 0; i < size; i++) {
                    if (start_addr[i] != 0) {
index 88d6ca9..c6e8a6e 100644 (file)
  * problem.. */
 #define QSHOW_SIGNALS 0
 
-/* FIXME: Make HeaderValue, CONS, SYMBOL, and FDEFN into inline
- * functions instead of macros. */
-
-#define HeaderValue(obj) ((unsigned long) ((obj) >> N_WIDETAG_BITS))
-
-#define CONS(obj) ((struct cons *)((obj)-LIST_POINTER_LOWTAG))
-#define SYMBOL(obj) ((struct symbol *)((obj)-OTHER_POINTER_LOWTAG))
-#define FDEFN(obj) ((struct fdefn *)((obj)-OTHER_POINTER_LOWTAG))
-
 /* KLUDGE: These are in theory machine-dependent and OS-dependent, but
  * in practice the "foo int" definitions work for all the machines
  * that SBCL runs on as of 0.6.7. If we port to the Alpha or some
  * other non-32-bit machine we'll probably need real machine-dependent
  * and OS-dependent definitions again. */
 /* even on alpha, int happens to be 4 bytes.  long is longer. */
+/* FIXME: these names really shouldn't reflect their length and this
+   is not quite right for some of the FFI stuff */
+#if 64 == N_WORD_BITS
+typedef unsigned long u32;
+typedef signed long s32;
+#else
 typedef unsigned int u32;
 typedef signed int s32;
-#define LOW_WORD(c) ((long)(c) & 0xFFFFFFFFL)
+#endif
+
 /* this is an integral type the same length as a machine pointer */
 typedef unsigned long pointer_sized_uint_t ;
 
-typedef u32 lispobj;
+/* FIXME: we do things this way because of the alpha32 port.  once
+   alpha64 has arrived, all this nastiness can go away */
+#if 64 == N_WORD_BITS
+#define LOW_WORD(c) ((pointer_sized_uint_t)c)
+typedef unsigned long lispobj;
+#else
+#define LOW_WORD(c) ((long)(c) & 0xFFFFFFFFL)
+/* fake it on alpha32 */
+typedef unsigned int lispobj;
+#endif
 
 static inline int
 lowtag_of(lispobj obj) {
@@ -70,6 +77,30 @@ widetag_of(lispobj obj) {
     return obj & WIDETAG_MASK;
 }
 
+static inline unsigned long
+HeaderValue(lispobj obj)
+{
+  return obj >> N_WIDETAG_BITS;
+}
+
+static inline struct cons *
+CONS(lispobj obj)
+{
+  return (struct cons *)(obj - LIST_POINTER_LOWTAG);
+}
+
+static inline struct symbol *
+SYMBOL(lispobj obj)
+{
+  return (struct symbol *)(obj - OTHER_POINTER_LOWTAG);
+}
+
+static inline struct fdefn *
+FDEFN(lispobj obj)
+{
+  return (struct fdefn *)(obj - OTHER_POINTER_LOWTAG);
+}
+
 /* Is the Lisp object obj something with pointer nature (as opposed to
  * e.g. a fixnum or character or unbound marker)? */
 static inline int
index c0b95e7..2137863 100644 (file)
@@ -17,4 +17,4 @@
 ;;; checkins which aren't released. (And occasionally for internal
 ;;; versions, especially for internal versions off the main CVS
 ;;; branch, it gets hairier, e.g. "0.pre7.14.flaky4.13".)
-"0.8.14.1"
+"0.8.14.2"