0.9.1.45:
[sbcl.git] / src / runtime / gc-common.c
index ed70962..8e8b3fa 100644 (file)
@@ -41,6 +41,7 @@
 #include "gc.h"
 #include "genesis/primitive-objects.h"
 #include "genesis/static-symbols.h"
+#include "genesis/layout.h"
 #include "gc-internal.h"
 
 #ifdef LISP_FEATURE_SPARC
@@ -382,7 +383,7 @@ size_code_header(lispobj *where)
     return nwords;
 }
 
-#ifndef LISP_FEATURE_X86 || LISP_FEATURE_X86_64
+#if !defined(LISP_FEATURE_X86) && ! defined(LISP_FEATURE_X86_64)
 static long
 scav_return_pc_header(lispobj *where, lispobj object)
 {
@@ -643,6 +644,24 @@ scav_boxed(lispobj *where, lispobj object)
     return 1;
 }
 
+static long
+scav_instance(lispobj *where, lispobj object)
+{
+    lispobj nuntagged;
+    long ntotal = HeaderValue(object);
+    lispobj layout = ((struct instance *)native_pointer(where))->slots[0];
+
+    if (!layout)
+       return 1;
+    if (forwarding_pointer_p(native_pointer(layout)))
+        layout = (lispobj) forwarding_pointer_value(native_pointer(layout));
+
+    nuntagged = ((struct layout *)native_pointer(layout))->n_untagged_slots;
+    scavenge(where + 1, ntotal - fixnum_value(nuntagged));
+
+    return ntotal + 1;
+}
+
 static lispobj
 trans_boxed(lispobj object)
 {
@@ -1585,7 +1604,11 @@ gc_init_tables(void)
      * tag) get one entry each in the scavenge table. */
     scavtab[BIGNUM_WIDETAG] = scav_unboxed;
     scavtab[RATIO_WIDETAG] = scav_boxed;
+#if N_WORD_BITS == 64
+    scavtab[SINGLE_FLOAT_WIDETAG] = scav_immediate;
+#else
     scavtab[SINGLE_FLOAT_WIDETAG] = scav_unboxed;
+#endif
     scavtab[DOUBLE_FLOAT_WIDETAG] = scav_unboxed;
 #ifdef LONG_FLOAT_WIDETAG
     scavtab[LONG_FLOAT_WIDETAG] = scav_unboxed;
@@ -1704,7 +1727,7 @@ gc_init_tables(void)
     scavtab[CHARACTER_WIDETAG] = scav_immediate;
     scavtab[SAP_WIDETAG] = scav_unboxed;
     scavtab[UNBOUND_MARKER_WIDETAG] = scav_immediate;
-    scavtab[INSTANCE_HEADER_WIDETAG] = scav_boxed;
+    scavtab[INSTANCE_HEADER_WIDETAG] = scav_instance;
 #ifdef LISP_FEATURE_SPARC
     scavtab[FDEFN_WIDETAG] = scav_boxed;
 #else
@@ -1716,7 +1739,12 @@ gc_init_tables(void)
        transother[i] = trans_lose;
     transother[BIGNUM_WIDETAG] = trans_unboxed;
     transother[RATIO_WIDETAG] = trans_boxed;
+
+#if N_WORD_BITS == 64
+    transother[SINGLE_FLOAT_WIDETAG] = trans_immediate;
+#else
     transother[SINGLE_FLOAT_WIDETAG] = trans_unboxed;
+#endif
     transother[DOUBLE_FLOAT_WIDETAG] = trans_unboxed;
 #ifdef LONG_FLOAT_WIDETAG
     transother[LONG_FLOAT_WIDETAG] = trans_unboxed;
@@ -1852,7 +1880,11 @@ gc_init_tables(void)
     }
     sizetab[BIGNUM_WIDETAG] = size_unboxed;
     sizetab[RATIO_WIDETAG] = size_boxed;
+#if N_WORD_BITS == 64
+    sizetab[SINGLE_FLOAT_WIDETAG] = size_immediate;
+#else
     sizetab[SINGLE_FLOAT_WIDETAG] = size_unboxed;
+#endif
     sizetab[DOUBLE_FLOAT_WIDETAG] = size_unboxed;
 #ifdef LONG_FLOAT_WIDETAG
     sizetab[LONG_FLOAT_WIDETAG] = size_unboxed;
@@ -1994,3 +2026,40 @@ component_ptr_from_pc(lispobj *pc)
 
     return (NULL);
 }
+
+/* Scan an area looking for an object which encloses the given pointer.
+ * Return the object start on success or NULL on failure. */
+lispobj *
+gc_search_space(lispobj *start, size_t words, lispobj *pointer)
+{
+    while (words > 0) {
+       size_t count = 1;
+       lispobj thing = *start;
+
+       /* If thing is an immediate then this is a cons. */
+       if (is_lisp_pointer(thing)
+           || (fixnump(thing))
+           || (widetag_of(thing) == CHARACTER_WIDETAG)
+#if N_WORD_BITS == 64
+           || (widetag_of(thing) == SINGLE_FLOAT_WIDETAG)
+#endif
+           || (widetag_of(thing) == UNBOUND_MARKER_WIDETAG))
+           count = 2;
+       else
+           count = (sizetab[widetag_of(thing)])(start);
+
+       /* Check whether the pointer is within this object. */
+       if ((pointer >= start) && (pointer < (start+count))) {
+           /* found it! */
+           /*FSHOW((stderr,"/found %x in %x %x\n", pointer, start, thing));*/
+           return(start);
+       }
+
+       /* Round up the count. */
+       count = CEILING(count,2);
+
+       start += count;
+       words -= count;
+    }
+    return (NULL);
+}