Re: [Sbcl-devel] [Sbcl-commits] master: Move a couple GC diagnostic controls to gc-common

6 views
Skip to first unread message

Stas Boukarev

unread,
Sep 28, 2023, 2:35:50 PM9/28/23
to Douglas Katzman, sbcl-...@lists.sourceforge.net, sbcl-c...@lists.sourceforge.net
darwin-x86-64:
gc-common.c:2861:5: error: implicit declaration of function 'dump_immobile_fixedobjs' is invalid in C99 [-Werror,-Wimplicit-function-declaration]
    dump_immobile_fixedobjs((lispobj*)FIXEDOBJ_SPACE_START, fixedobj_free_pointer, f);
    ^
gc-common.c:2863:5: error: implicit declaration of function 'dump_immobile_text' is invalid in C99 [-Werror,-Wimplicit-function-declaration]
    dump_immobile_text((lispobj*)TEXT_SPACE_START, text_space_highwatermark, f);

On Thu, Sep 28, 2023 at 8:30 PM snuglas via Sbcl-commits <sbcl-c...@lists.sourceforge.net> wrote:
The branch "master" has been updated in SBCL:
       via  8e2fa4ab09c04991af782ef056acbdae93b3eb9c (commit)
      from  9b8f9c878cfb5d43046261b20b8b550b31d951e6 (commit)

- Log -----------------------------------------------------------------
commit 8e2fa4ab09c04991af782ef056acbdae93b3eb9c
Author: Douglas Katzman <do...@google.com>
Date:   Thu Sep 28 13:21:59 2023 -0400

    Move a couple GC diagnostic controls to gc-common
---
 src/runtime/gc-common.c | 197 ++++++++++++++++++++++++++++++++++++++++++++
 src/runtime/gc.h        |  27 +++---
 src/runtime/gencgc.c    | 215 ++----------------------------------------------
 src/runtime/pmrgc.c     |  58 ++-----------
 4 files changed, 229 insertions(+), 268 deletions(-)

diff --git a/src/runtime/gc-common.c b/src/runtime/gc-common.c
index 493933828..fb4280305 100644
--- a/src/runtime/gc-common.c
+++ b/src/runtime/gc-common.c
@@ -2772,3 +2772,200 @@ uword_t primitive_object_size(lispobj ptr) {
     lispobj* addr = native_pointer(ptr);
     return object_size(addr) * N_WORD_BYTES;
 }
+
+#ifdef LISP_FEATURE_GENERATIONAL
+/* We hunt for pointers to old-space, when GCing generations >= verify_gen.
+ * Set verify_gens to HIGHEST_NORMAL_GENERATION + 2 to disable this kind of
+ * check. */
+generation_index_t verify_gens = HIGHEST_NORMAL_GENERATION + 2;
+
+/* Should we do a pre-scan of the heap before it's GCed? */
+int pre_verify_gen_0 = 0;
+
+int hexdump_enabled = 0;
+static int hexdump_counter;
+#define HEXDUMP_PATH_TEMPLATE "/var/tmp/heap-%d-%d.txt"
+
+char *page_card_mark_string(page_index_t page, char *result)
+{
+    long card = addr_to_card_index(page_address(page));
+    if (cardseq_all_marked_nonsticky(card))
+        result[0] = '*', result[1] = 0;
+    else if (!cardseq_any_marked(card))
+        result[0] = '-', result[1] = 0;
+    else {
+        int i;
+        for(i=0; i<CARDS_PER_PAGE; ++i)
+        switch (gc_card_mark[card+i] & MARK_BYTE_MASK) {
+        case CARD_MARKED: result[i] = '*'; break;
+        case CARD_UNMARKED: result[i] = '-'; break;
+#ifdef LISP_FEATURE_SOFT_CARD_MARKS
+        case STICKY_MARK: result[i] = 'S'; break;
+#else
+        case WP_CLEARED_AND_MARKED: result[i] = 'd'; break; // "d" is for dirty
+#endif
+        default: result[i] = '?'; break; // illegal value
+        }
+        result[CARDS_PER_PAGE] = 0;
+    }
+    return result;
+}
+
+static int dump_completely_p(lispobj* obj, struct verify_state* state)
+{
+    int i;
+    if (!state) {
+        page_index_t pg = find_page_index(obj);
+        if (pg >= 10470 && pg <= 10485) return 1; // (as an example)
+        return 0;
+    }
+    for (i=0; i<MAX_ERR_OBJS; ++i)
+        if (state->err_objs[i] == (uword_t)obj) return 1;
+    return 0;
+}
+
+static void hexdump_control_stacks(__attribute__((unused)) void* approximate_stackptr,
+                                   __attribute__((unused)) FILE *stream)
+{
+#ifdef LISP_FEATURE_C_STACK_IS_CONTROL_STACK
+    struct thread* th;
+    for_each_thread(th) {
+        if (th->state_word.state == STATE_DEAD) continue;
+        lispobj* stackptr;
+        if (th == get_sb_vm_thread()) {
+            stackptr = approximate_stackptr;
+        } else {
+            int ici = fixnum_value(read_TLS(FREE_INTERRUPT_CONTEXT_INDEX,th))-1;
+            os_context_t *c = nth_interrupt_context(ici, th);
+            stackptr = (lispobj*) *os_context_register_addr(c,reg_SP);
+        }
+        gc_assert(((uword_t)stackptr & (LOWTAG_MASK>>1)) == 0); // lispword-aligned
+        lispobj* where = th->control_stack_end;
+        fprintf(stream, "\nThread @ %p\n", th);
+        for (--where; where >= stackptr; --where) {
+            lispobj word = *where;
+            if (!fixnump(word) && gc_managed_addr_p(word))
+                fprintf(stream, "  %p: %"OBJ_FMTX"\n", where, word);
+        }
+    }
+#endif
+}
+
+/* Dump spaces as human-readable text (hexadecimal) */
+void hexdump_spaces(struct verify_state* state, char *reason, char* pathname)
+{
+    FILE *f = fopen(pathname, "w");
+
+#ifdef LISP_FEATURE_IMMOBILE_SPACE
+    fprintf(f, "Fixedobj space:\n");
+    dump_immobile_fixedobjs((lispobj*)FIXEDOBJ_SPACE_START, fixedobj_free_pointer, f);
+    fprintf(f, "Text space (tlsf mem @ %p):\n", tlsf_mem_start);
+    dump_immobile_text((lispobj*)TEXT_SPACE_START, text_space_highwatermark, f);
+#endif
+
+    fprintf(f, "Dynamic space:\n");
+    page_index_t firstpage = 0, lastpage;
+    while (firstpage < next_free_page) {
+        lastpage = firstpage;
+        while (!page_ends_contiguous_block_p(lastpage, page_table[firstpage].gen))
+            lastpage++;
+        if (!page_bytes_used(firstpage)) {
+            firstpage = 1+lastpage;
+            continue;
+        }
+        lispobj* base = (lispobj*)page_address(firstpage);
+        lispobj* limit = (lispobj*)page_address(lastpage) + page_words_used(lastpage);
+        fprintf(f, "range %d:%d (%p:%p) t%d g%d ",
+                (int)firstpage, (int)lastpage, base, limit,
+                page_table[firstpage].type, page_table[firstpage].gen);
+        page_index_t p;
+        for (p = firstpage; p <= lastpage; ++p) {
+            char marks[1+CARDS_PER_PAGE];
+            putc((p == firstpage) ? '(' : ' ', f);
+            fprintf(f, "%s", page_card_mark_string(p, marks));
+        }
+        fprintf(f, ")\n");
+        lispobj *where = base;
+        while (where<limit){
+            sword_t nwords = object_size(where);
+            /* If your'e having trouble with a subset of objects, and you can get
+             * a reliable reproducer, this predicate can decide which objects to
+             * output in full. Generally you don't need that much output */
+            if (widetag_of(where) == FILLER_WIDETAG) {
+                lispobj* end = where + filler_total_nwords(*where);
+                fprintf(f, " %06x: fill to %p\n", (int)(uword_t)where & 0xffffff, end);
+            } else if (dump_completely_p(where, state)) {
+                sword_t i;
+                for(i=0;i<nwords;++i) {
+                    uword_t word = where[i];
+                    if (i==0)
+                        fprintf(f, " %06x: ", (int)(uword_t)(where+i) & 0xffffff);
+                    else
+                        fprintf(f, "   %04x: ", (int)(uword_t)(where+i) & 0xffff);
+                    if (word == NIL) fprintf(f, "nil"); else fprintf(f, "%" OBJ_FMTX, word);
+#ifdef LISP_FEATURE_IMMOBILE_SPACE
+                    if (i == 0 && header_widetag(word) == INSTANCE_WIDETAG) word >>= 32;
+#endif
+                    if (is_lisp_pointer(word)
+                        && (find_page_index((void*)word)>=0 || immobile_space_p(word)))
+                        fprintf(f, " (g%d)", gc_gen_of(word, 0xff));
+                    fprintf(f,"\n");
+                }
+            } else {
+                int min_gen = 8;
+                int prefix = ' ';
+                if (widetag_of(where)==CODE_HEADER_WIDETAG && header_rememberedp(*where))
+                    prefix = '#';
+                else if (card_dirtyp(addr_to_card_index(where)))
+                    prefix = '|';
+                fprintf(f, "%c%06x: %"OBJ_FMTX, prefix, (int)(uword_t)where & 0xffffff, *where);
+                int i;
+                int boxed_nwords = nwords;
+                // This is just a heuristic guess of pointee generation.
+                // For code it's (mostly) right, for other things it's slightly less right
+                // because we're really not respecting the tagged or raw nature of each word.
+                if (widetag_of(where)==CODE_HEADER_WIDETAG)
+                    boxed_nwords = code_header_words((struct code*)where);
+                for (i=0; i<boxed_nwords; ++i) {
+                    uword_t word = where[i];
+                    page_index_t pointee_page;
+                    if (is_lisp_pointer(word) && (pointee_page=find_page_index((void*)word))>=0
+                        && page_table[pointee_page].gen < min_gen)
+                        min_gen = page_table[pointee_page].gen;
+                }
+                if (min_gen != 8)
+                    fprintf(f, " (>g%d)\n", min_gen);
+                else
+                  fprintf(f, "\n");
+            }
+            where += nwords;
+        }
+        fprintf(f,"--\n");
+        firstpage = 1+lastpage;
+    }
+    hexdump_control_stacks(&reason, f);
+    fclose(f);
+    fprintf(stderr, "%s: wrote [%s]\n", reason, pathname);
+}
+
+int hexdump_and_verify_heap(lispobj* cur_thread_approx_stackptr, int flags)
+{
+    if (hexdump_enabled) {
+        char path[100];
+        ++hexdump_counter;
+        sprintf(path, HEXDUMP_PATH_TEMPLATE, getpid(), hexdump_counter);
+        hexdump_spaces(0, flags & VERIFY_POST_GC ? "post-GC" : "pre-GC", path);
+    }
+#if 0
+    if (hexdump_counter >= 9) {
+        char pathname[128];
+        sprintf(pathname, "gc-%d-%d-%d-%s.bin",
+                getpid(), n_gcs, from_space,
+                flags & VERIFY_POST_GC ? "post" : "pre");
+        save_gc_crashdump(pathname, cur_thread_approx_stackptr);
+        fprintf(stderr, "Wrote [%s]\n", pathname);
+    }
+#endif
+    return verify_heap(cur_thread_approx_stackptr, flags);
+}
+#endif
diff --git a/src/runtime/gc.h b/src/runtime/gc.h
index 125ad7498..6eadb69b5 100644
--- a/src/runtime/gc.h
+++ b/src/runtime/gc.h
@@ -47,33 +47,37 @@ extern int sb_sprof_enabled;

 extern os_vm_size_t bytes_consed_between_gcs;

-#define VERIFY_VERBOSE    1
-#define VERIFY_PRE_GC     2
-#define VERIFY_POST_GC    4
+// flags passed to verify_heap().
+// The low 4 bits supply the generation number and 'raise' flag
+#define VERIFY_VERBOSE    (1<<4)
+#define VERIFY_PRE_GC     (1<<5)
+#define VERIFY_POST_GC    (1<<6)
 /* AGGRESSIVE = always call valid_lisp_pointer_p() on pointers. */
-#define VERIFY_AGGRESSIVE 8
-#define VERIFY_TAGS       16
+#define VERIFY_AGGRESSIVE (1<<7)
+#define VERIFY_TAGS       (1<<8)
 /* QUICK = skip most tests. This is intended for use when GC is believed
  * to be correct per se (i.e. not for debugging GC), and so the verify
  * pass executes more quickly */
-#define VERIFY_QUICK      32
+#define VERIFY_QUICK      (1<<9)
 /* FINAL = warn about pointers from heap space to non-heap space.
  * Such pointers would normally be ignored and do not get flagged as failure.
  * This can be used in conjunction with QUICK, AGGRESSIVE, or neither. */
-#define VERIFY_FINAL      64
-#define VERIFY_DONT_LOSE  128
+#define VERIFY_FINAL      (1<<10)
+#define VERIFY_DONT_LOSE  (1<<11)

 /* VERIFYING_foo indicates internal state, not a caller's option */
 /* GENERATIONAL implies formatted objects, but there are ranges of objects
  * that are not generational (static space)
  * so there are no page protection checks performed for pointers from objects
  * in such ranges */
-#define VERIFYING_GENERATIONAL 256
+#define VERIFYING_GENERATIONAL (1<<12)
 /* UNFORMATTED implies that this is not a range of objects
  * but rather a range of pointers such as a binding stack, TLS,
  * lisp signal handler array, or other similar array */
-#define VERIFYING_UNFORMATTED 512
+#define VERIFYING_UNFORMATTED (1<<13)
+#define VERIFY_PRINT_HEADER_ON_FAILURE (1<<14)

+extern generation_index_t verify_gens;
 #define MAX_ERR_OBJS 5
 struct verify_state {
     lispobj* object_addr;
@@ -88,7 +92,7 @@ struct verify_state {
 #endif
     lispobj err_objs[5];
 };
-void hexdump_spaces(struct verify_state*, char *reason);
+void hexdump_spaces(struct verify_state*, char *reason, char *pathname);
 int verify_heap(lispobj*, int flags);
 int hexdump_and_verify_heap(lispobj*, int flags);

@@ -101,6 +105,7 @@ extern generation_index_t gencgc_oldest_gen_to_gc;
 extern page_index_t gencgc_alloc_start_page;
 extern bool conservative_stack;
 extern lispobj lisp_init_function;
+char *page_card_mark_string(page_index_t page, char *result);

 #include "immobile-space.h" // provides dummy stubs if #-immobile-space
 #ifdef LISP_FEATURE_MARK_REGION_GC
diff --git a/src/runtime/gencgc.c b/src/runtime/gencgc.c
index 26ecfce3d..e92ecb1ae 100644
--- a/src/runtime/gencgc.c
+++ b/src/runtime/gencgc.c
@@ -70,18 +70,6 @@ int n_gcs;
  * and only a few rare messages are printed at level 1. */
 int gencgc_verbose = 0;

-/* FIXME: At some point enable the various error-checking things below
- * and see what they say. */
-
-/* We hunt for pointers to old-space, when GCing generations >= verify_gen.
- * Set verify_gens to HIGHEST_NORMAL_GENERATION + 2 to disable this kind of
- * check. */
-generation_index_t verify_gens = HIGHEST_NORMAL_GENERATION + 2;
-
-/* Should we do a pre-scan of the heap before it's GCed? */
-int pre_verify_gen_0 = 0; // FIXME: should be named 'pre_verify_gc'
-
-
 /*
  * GC structures and variables
  */
@@ -3924,7 +3912,8 @@ maybe_verify:
     // been on pages that got freed by free_oldspace.
     dynspace_codeblob_tree_snapshot = 0;
     if (generation >= verify_gens)
-        hexdump_and_verify_heap(cur_thread_approx_stackptr, VERIFY_POST_GC | (generation<<16));
+        hexdump_and_verify_heap(cur_thread_approx_stackptr,
+                                VERIFY_POST_GC | (generation<<1) | raise);

     extern int n_unboxed_instances;
     n_unboxed_instances = 0;
@@ -4777,33 +4766,6 @@ static bool card_markedp(void* addr)
     return gc_card_mark[addr_to_card_index(addr)] != CARD_UNMARKED;
 }

-char *page_card_mark_string(page_index_t page, char *result)
-{
-    long card = addr_to_card_index(page_address(page));
-    if (cardseq_all_marked_nonsticky(card))
-        result[0] = '*', result[1] = 0;
-    else if (!cardseq_any_marked(card))
-        result[0] = '-', result[1] = 0;
-    else {
-        int i;
-        for(i=0; i<CARDS_PER_PAGE; ++i)
-        switch (gc_card_mark[card+i] & MARK_BYTE_MASK) {
-        case CARD_MARKED: result[i] = '*'; break;
-        case CARD_UNMARKED: result[i] = '-'; break;
-#ifdef LISP_FEATURE_SOFT_CARD_MARKS
-        case STICKY_MARK: result[i] = 'S'; break;
-#else
-        case WP_CLEARED_AND_MARKED: result[i] = 'd'; break; // "d" is for dirty
-#endif
-        default: result[i] = '?'; break; // illegal value
-        }
-        result[CARDS_PER_PAGE] = 0;
-    }
-    return result;
-}
-
-#define PRINT_HEADER_ON_FAILURE 2048
-
 // Check a single pointer. Return 1 if we should stop verifying due to too many errors.
 // (Otherwise continue showing errors until then)
 // NOTE: This function can produces false failure indications,
@@ -4812,10 +4774,10 @@ char *page_card_mark_string(page_index_t page, char *result)
 static void note_failure(lispobj thing, lispobj *where, struct verify_state *state,
                          char *str)
 {
-    if (state->flags & PRINT_HEADER_ON_FAILURE) {
+    if (state->flags & VERIFY_PRINT_HEADER_ON_FAILURE) {
         if (state->flags & VERIFY_PRE_GC) fprintf(stderr, "pre-GC failure\n");
         if (state->flags & VERIFY_POST_GC) fprintf(stderr, "post-GC failure\n");
-        state->flags &= ~PRINT_HEADER_ON_FAILURE;
+        state->flags &= ~VERIFY_PRINT_HEADER_ON_FAILURE;
     }
     if (state->object_addr) {
         lispobj obj = compute_lispobj(state->object_addr);
@@ -5169,11 +5131,12 @@ int verify_heap(__attribute__((unused)) lispobj* cur_thread_approx_stackptr,
     if (verbose)
         fprintf(stderr,
                 flags & VERIFY_PRE_GC ? "Verify before GC" :
-                flags & VERIFY_POST_GC ? "Verify after GC(%d)" :
+                flags & VERIFY_POST_GC ? "Verify after GC(%d,%d)" :
                 "Heap check", // if called at a random time
-                (int)(flags>>16)); // generation number
+                flags >> 1, // generation number
+                flags & 1); // 'raise'
     else
-        state.flags |= PRINT_HEADER_ON_FAILURE;
+        state.flags |= VERIFY_PRINT_HEADER_ON_FAILURE;

 #ifdef LISP_FEATURE_IMMOBILE_SPACE
 #  ifdef __linux__
@@ -5267,170 +5230,8 @@ void gc_show_pte(lispobj obj)
     printf("not in GC'ed space\n");
 }

-static int hexdump_counter;
-
 extern void dump_immobile_fixedobjs(lispobj* where, lispobj* end, FILE*f);
 extern void dump_immobile_text(lispobj* where, lispobj* end, FILE*f);
-static int dump_completely_p(lispobj* obj, struct verify_state* state)
-{
-    int i;
-    if (!state) {
-        page_index_t pg = find_page_index(obj);
-        if (pg >= 10470 && pg <= 10485) return 1; // (as an example)
-        return 0;
-    }
-    for (i=0; i<MAX_ERR_OBJS; ++i)
-        if (state->err_objs[i] == (uword_t)obj) return 1;
-    return 0;
-}
-static void hexdump_control_stacks(__attribute__((unused)) void* approximate_stackptr,
-                                   __attribute__((unused)) FILE *stream)
-{
-#ifdef LISP_FEATURE_C_STACK_IS_CONTROL_STACK
-    struct thread* th;
-    for_each_thread(th) {
-        if (th->state_word.state == STATE_DEAD) continue;
-        lispobj* stackptr;
-        if (th == get_sb_vm_thread()) {
-            stackptr = approximate_stackptr;
-        } else {
-            int ici = fixnum_value(read_TLS(FREE_INTERRUPT_CONTEXT_INDEX,th))-1;
-            os_context_t *c = nth_interrupt_context(ici, th);
-            stackptr = (lispobj*) *os_context_register_addr(c,reg_SP);
-        }
-        gc_assert(((uword_t)stackptr & (LOWTAG_MASK>>1)) == 0); // lispword-aligned
-        lispobj* where = th->control_stack_end;
-        fprintf(stream, "\nThread @ %p\n", th);
-        for (--where; where >= stackptr; --where) {
-            lispobj word = *where;
-            if (!fixnump(word) && gc_managed_addr_p(word))
-                fprintf(stream, "  %p: %"OBJ_FMTX"\n", where, word);
-        }
-    }
-#endif
-}
-
-#define HEXDUMP_PATH_TEMPLATE "/var/tmp/heap-%d-%d.txt"
-
-/* Dump spaces as human-readable text (hexadecimal) */
-void hexdump_spaces(struct verify_state* state, char *reason)
-{
-    char path[100];
-
-    ++hexdump_counter;
-    sprintf(path, HEXDUMP_PATH_TEMPLATE, getpid(), hexdump_counter);
-    FILE *f = fopen(path, "w");
-
-#ifdef LISP_FEATURE_IMMOBILE_SPACE
-    fprintf(f, "Fixedobj space:\n");
-    dump_immobile_fixedobjs((lispobj*)FIXEDOBJ_SPACE_START, fixedobj_free_pointer, f);
-    fprintf(f, "Text space (tlsf mem @ %p):\n", tlsf_mem_start);
-    dump_immobile_text((lispobj*)TEXT_SPACE_START, text_space_highwatermark, f);
-#endif
-
-    fprintf(f, "Dynamic space:\n");
-    page_index_t firstpage = 0, lastpage;
-    while (firstpage < next_free_page) {
-        lastpage = firstpage;
-        while (!page_ends_contiguous_block_p(lastpage, page_table[firstpage].gen))
-            lastpage++;
-        if (!page_bytes_used(firstpage)) {
-            firstpage = 1+lastpage;
-            continue;
-        }
-        lispobj* base = (lispobj*)page_address(firstpage);
-        lispobj* limit = (lispobj*)page_address(lastpage) + page_words_used(lastpage);
-        fprintf(f, "range %d:%d (%p:%p) t%d g%d ",
-                (int)firstpage, (int)lastpage, base, limit,
-                page_table[firstpage].type, page_table[firstpage].gen);
-        page_index_t p;
-        for (p = firstpage; p <= lastpage; ++p) {
-            char marks[1+CARDS_PER_PAGE];
-            putc((p == firstpage) ? '(' : ' ', f);
-            fprintf(f, "%s", page_card_mark_string(p, marks));
-        }
-        fprintf(f, ")\n");
-        lispobj *where = base;
-        while (where<limit){
-            sword_t nwords = object_size(where);
-            /* If your'e having trouble with a subset of objects, and you can get
-             * a reliable reproducer, this predicate can decide which objects to
-             * output in full. Generally you don't need that much output */
-            if (widetag_of(where) == FILLER_WIDETAG) {
-                lispobj* end = where + filler_total_nwords(*where);
-                fprintf(f, " %06x: fill to %p\n", (int)(uword_t)where & 0xffffff, end);
-            } else if (dump_completely_p(where, state)) {
-                sword_t i;
-                for(i=0;i<nwords;++i) {
-                    uword_t word = where[i];
-                    if (i==0)
-                        fprintf(f, " %06x: ", (int)(uword_t)(where+i) & 0xffffff);
-                    else
-                        fprintf(f, "   %04x: ", (int)(uword_t)(where+i) & 0xffff);
-                    if (word == NIL) fprintf(f, "nil"); else fprintf(f, "%" OBJ_FMTX, word);
-#ifdef LISP_FEATURE_IMMOBILE_SPACE
-                    if (i == 0 && header_widetag(word) == INSTANCE_WIDETAG) word >>= 32;
-#endif
-                    if (is_lisp_pointer(word)
-                        && (find_page_index((void*)word)>=0 || immobile_space_p(word)))
-                        fprintf(f, " (g%d)", gc_gen_of(word, 0xff));
-                    fprintf(f,"\n");
-                }
-            } else {
-                int min_gen = 8;
-                int prefix = ' ';
-                if (widetag_of(where)==CODE_HEADER_WIDETAG && header_rememberedp(*where))
-                    prefix = '#';
-                else if (card_dirtyp(addr_to_card_index(where)))
-                    prefix = '|';
-                fprintf(f, "%c%06x: %"OBJ_FMTX, prefix, (int)(uword_t)where & 0xffffff, *where);
-                int i;
-                int boxed_nwords = nwords;
-                // This is just a heuristic guess of pointee generation.
-                // For code it's (mostly) right, for other things it's slightly less right
-                // because we're really not respecting the tagged or raw nature of each word.
-                if (widetag_of(where)==CODE_HEADER_WIDETAG)
-                    boxed_nwords = code_header_words((struct code*)where);
-                for (i=0; i<boxed_nwords; ++i) {
-                    uword_t word = where[i];
-                    page_index_t pointee_page;
-                    if (is_lisp_pointer(word) && (pointee_page=find_page_index((void*)word))>=0
-                        && page_table[pointee_page].gen < min_gen)
-                        min_gen = page_table[pointee_page].gen;
-                }
-                if (min_gen != 8)
-                    fprintf(f, " (>g%d)\n", min_gen);
-                else
-                  fprintf(f, "\n");
-            }
-            where += nwords;
-        }
-        fprintf(f,"--\n");
-        firstpage = 1+lastpage;
-    }
-    hexdump_control_stacks(&reason, f);
-    fclose(f);
-    fprintf(stderr, "%s: wrote [%s]\n", reason, path);
-}
-
-int hexdump_enabled = 0;
-
-int hexdump_and_verify_heap(lispobj* cur_thread_approx_stackptr, int flags)
-{
-    if (hexdump_enabled) hexdump_spaces(0, flags & VERIFY_POST_GC ? "post-GC" : "pre-GC");
-#if 0
-    if (hexdump_counter >= 9) {
-        char pathname[128];
-        sprintf(pathname, "gc-%d-%d-%d-%s.bin",
-                getpid(), n_gcs, from_space,
-                flags & VERIFY_POST_GC ? "post" : "pre");
-        save_gc_crashdump(pathname, cur_thread_approx_stackptr);
-        fprintf(stderr, "Wrote [%s]\n", pathname);
-    }
-#endif
-    return verify_heap(cur_thread_approx_stackptr, flags);
-}
-
 static int count_immobile_objects(__attribute__((unused)) int gen, int res[4])
 {
 #ifdef LISP_FEATURE_IMMOBILE_SPACE
diff --git a/src/runtime/pmrgc.c b/src/runtime/pmrgc.c
index bab343b48..94bf081fc 100644
--- a/src/runtime/pmrgc.c
+++ b/src/runtime/pmrgc.c
@@ -44,18 +44,6 @@ int n_gcs;
  * and only a few rare messages are printed at level 1. */
 int gencgc_verbose = 0;

-/* FIXME: At some point enable the various error-checking things below
- * and see what they say. */
-
-/* We hunt for pointers to old-space, when GCing generations >= verify_gen.
- * Set verify_gens to HIGHEST_NORMAL_GENERATION + 2 to disable this kind of
- * check. */
-generation_index_t verify_gens = HIGHEST_NORMAL_GENERATION + 2;
-
-/* Should we do a pre-scan of the heap before it's GCed? */
-int pre_verify_gen_0 = 0; // FIXME: should be named 'pre_verify_gc'
-
-
 /*
  * GC structures and variables
  */
@@ -953,7 +941,8 @@ garbage_collect_generation(generation_index_t generation, int raise,
     // been on pages that got freed by free_oldspace.
     dynspace_codeblob_tree_snapshot = 0;
     if (generation >= verify_gens)
-        verify_heap(cur_thread_approx_stackptr, VERIFY_POST_GC | (generation<<16));
+        hexdump_and_verify_heap(cur_thread_approx_stackptr,
+                                VERIFY_POST_GC | (generation<<1) | raise);

     extern int n_unboxed_instances;
     n_unboxed_instances = 0;
@@ -1554,33 +1543,6 @@ static bool card_markedp(void* addr)
     return gc_card_mark[addr_to_card_index(addr)] != CARD_UNMARKED;
 }

-char *page_card_mark_string(page_index_t page, char *result)
-{
-    long card = addr_to_card_index(page_address(page));
-    if (cardseq_all_marked_nonsticky(card))
-        result[0] = '*', result[1] = 0;
-    else if (!cardseq_any_marked(card))
-        result[0] = '-', result[1] = 0;
-    else {
-        int i;
-        for(i=0; i<CARDS_PER_PAGE; ++i)
-        switch (gc_card_mark[card+i] & MARK_BYTE_MASK) {
-        case CARD_MARKED: result[i] = '*'; break;
-        case CARD_UNMARKED: result[i] = '-'; break;
-#ifdef LISP_FEATURE_SOFT_CARD_MARKS
-        case STICKY_MARK: result[i] = 'S'; break;
-#else
-        case WP_CLEARED_AND_MARKED: result[i] = 'd'; break; // "d" is for dirty
-#endif
-        default: result[i] = '?'; break; // illegal value
-        }
-        result[CARDS_PER_PAGE] = 0;
-    }
-    return result;
-}
-
-#define PRINT_HEADER_ON_FAILURE 2048
-
 // Check a single pointer. Return 1 if we should stop verifying due to too many errors.
 // (Otherwise continue showing errors until then)
 // NOTE: This function can produces false failure indications,
@@ -1590,10 +1552,10 @@ static void note_failure(lispobj thing, lispobj *where, struct verify_state *sta
                          char *str)
 {
     lock();
-    if (state->flags & PRINT_HEADER_ON_FAILURE) {
+    if (state->flags & VERIFY_PRINT_HEADER_ON_FAILURE) {
         if (state->flags & VERIFY_PRE_GC) fprintf(stderr, "pre-GC failure\n");
         if (state->flags & VERIFY_POST_GC) fprintf(stderr, "post-GC failure\n");
-        state->flags &= ~PRINT_HEADER_ON_FAILURE;
+        state->flags &= ~VERIFY_PRINT_HEADER_ON_FAILURE;
     }
     if (state->object_addr) {
         lispobj obj = compute_lispobj(state->object_addr);
@@ -2004,11 +1966,12 @@ int verify_heap(__attribute__((unused)) lispobj* cur_thread_approx_stackptr,
     if (verbose)
         fprintf(stderr,
                 flags & VERIFY_PRE_GC ? "Verify before GC" :
-                flags & VERIFY_POST_GC ? "Verify after GC(%d)" :
+                flags & VERIFY_POST_GC ? "Verify after GC(%d,%d)" :
                 "Heap check", // if called at a random time
-                (int)(flags>>16)); // generation number
+                flags >> 1, // generation number
+                flags & 1); // 'raise'
     else
-        state.flags |= PRINT_HEADER_ON_FAILURE;
+        state.flags |= VERIFY_PRINT_HEADER_ON_FAILURE;

 #ifdef LISP_FEATURE_IMMOBILE_SPACE
 #  ifdef __linux__
@@ -2107,11 +2070,6 @@ void gc_show_pte(lispobj obj)
     printf("not in GC'ed space\n");
 }

-int hexdump_and_verify_heap(lispobj* cur_thread_approx_stackptr, int flags)
-{
-    return verify_heap(cur_thread_approx_stackptr, flags);
-}
-
 /* The other implementation of gc_gen_report_to_file gets the generations
  * of small objects wrong, as it only checks the generations of pages. */
 void gc_gen_report_to_file(int filedes, FILE *file) {

-----------------------------------------------------------------------


hooks/post-receive
--
SBCL


_______________________________________________
Sbcl-commits mailing list
Sbcl-c...@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/sbcl-commits
Reply all
Reply to author
Forward
0 new messages