Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • cmucl/cmucl
  • pfominykh/cmucl
  • yitzchak/cmucl
  • rkreuter/cmucl
  • cshapiro/cmucl
5 results
Show changes
Commits on Source (5)
......@@ -2130,6 +2130,7 @@ static lispobj(*transother[256]) (lispobj object);
static int (*sizetab[256]) (lispobj * where);
static struct weak_pointer *weak_pointers;
static struct weak_pointer *inuse_static_vector_list;
static struct scavenger_hook *scavenger_hooks = (struct scavenger_hook *) NIL;
/* Like (ceiling x y), but y is constrained to be a power of two */
......@@ -2734,7 +2735,7 @@ scav_static_vector(lispobj object)
int static_p;
if (debug_static_array_p) {
fprintf(stderr, "Possible static vector at %p. header = 0x%08lx\n",
fprintf(stderr, "Possible static vector at %p. header = 0x%lx\n",
ptr, (unsigned long) header);
}
......@@ -2745,9 +2746,9 @@ scav_static_vector(lispobj object)
* setting the MSB of the header. And clear out any
* possible visited bit.
*/
*ptr = (header | STATIC_VECTOR_MARK_BIT);
*ptr = (header | STATIC_VECTOR_MARK_BIT) & ~STATIC_VECTOR_VISITED_BIT;
if (debug_static_array_p) {
fprintf(stderr, "Scavenged static vector @%p, header = 0x%08lx\n",
fprintf(stderr, "Scavenged static vector @%p, header = 0x%lx\n",
ptr, (unsigned long) header);
}
}
......@@ -5388,14 +5389,6 @@ scav_weak_pointer(lispobj * where, lispobj object)
struct weak_pointer *this_wp = (struct weak_pointer *) where;
if (this_wp->mark_bit == NIL) {
lispobj *header = (lispobj *) PTR(this_wp->value);
if (maybe_static_array_p(*header)) {
printf("Scavenge wp %p to static array %p header 0x%08lx\n",
this_wp, (lispobj *) this_wp->value, *header);
*header &= ~STATIC_VECTOR_VISITED_BIT;
}
this_wp->mark_bit = T;
this_wp->next = weak_pointers;
weak_pointers = this_wp;
......@@ -5449,14 +5442,16 @@ push_weak_pointer(struct weak_pointer* wp, struct weak_pointer **list)
}
/*
* Phase 2: Process the list of weak pointers to unused static
* vectors. We find the unique static vectors and add each
* corresponding weak pointer to freeable_list. For the duplicates,
* the weak pointer is broken.
* Phase 2: Find the weak pointers to static vectors that are in use
* and not in use. The vectors that are in use are added to
* inuse_list. Those that are not in use are added to freeable_list.
* Only unique vectors are added to freeable list; a duplicate has its
* weak pointer to it broken.
*/
static void
scan_static_vectors_2(struct weak_pointer *static_vector_list,
struct weak_pointer **freeable_list)
struct weak_pointer **freeable_list,
struct weak_pointer **inuse_list)
{
DPRINTF(debug_static_array_p,
(stdout, "Phase 2: Find unused and unused static vectors\n"));
......@@ -5473,23 +5468,34 @@ scan_static_vectors_2(struct weak_pointer *static_vector_list,
(stdout, " wp %p value %p header 0x%08lx\n",
wp, (lispobj *) wp->value, *header));
/*
* If we haven't seen this vector before, set the visited flag
* and add it to freeable_list. If we have visited this
* vector before, break the weak pointer.
*/
if ((*header & STATIC_VECTOR_VISITED_BIT) == 0) {
if ((*header & STATIC_VECTOR_MARK_BIT) != 0) {
/*
* Static vector is in use. Add this to the in-use list.
*/
DPRINTF(debug_static_array_p,
(stdout, " Visit unused vector, add to freeable list\n"));
(stdout, " In-use vector; add to in-use list\n"));
*header |= STATIC_VECTOR_VISITED_BIT;
push_weak_pointer(wp, freeable_list);
push_weak_pointer(wp, inuse_list);
} else {
DPRINTF(debug_static_array_p,
(stdout, " Already visited unused vector; break weak pointer\n"));
/*
* Static vector not in use. If we haven't seen this
* vector before, set the visited flag and add it to
* freeable_list. If we have visited this vector before,
* break the weak pointer.
*/
if ((*header & STATIC_VECTOR_VISITED_BIT) == 0) {
DPRINTF(debug_static_array_p,
(stdout, " Visit unused vector, add to freeable list\n"));
wp->value = NIL;
wp->broken = T;
*header |= STATIC_VECTOR_VISITED_BIT;
push_weak_pointer(wp, freeable_list);
} else {
DPRINTF(debug_static_array_p,
(stdout, " Already visited unused vector; break weak pointer\n"));
wp->value = NIL;
wp->broken = T;
}
}
}
......@@ -5512,15 +5518,18 @@ scan_static_vectors_3(struct weak_pointer *freeable_list)
lispobj *header = (lispobj *) PTR(wp->value);
lispobj *static_array = (lispobj *) PTR(wp->value);
/*
* Invariant: weak pointer must not be broken
*/
gc_assert(wp->broken == NIL);
DPRINTF(debug_static_array_p,
(stdout, " wp %p value %p header 0x%08lx\n",
wp, (lispobj*) wp->value, *header));
/*
* Invariants: weak pointer must not be broken and the mark
* bit must be clear.
* Invariant: Mark bit must be clear
*/
gc_assert(wp->broken == NIL);
gc_assert(((*header & STATIC_VECTOR_MARK_BIT) == 0));
DPRINTF(debug_static_array_p,
......@@ -5536,6 +5545,49 @@ scan_static_vectors_3(struct weak_pointer *freeable_list)
(stdout, "Phase 3 done\n"));
}
/*
* Unmark all the vectors in inuse_list. This needs to be called at
* the end of GC to unmark any live static vectors so that for the
* next GC we can tell if the static vector is used or not.
* Otherwise, the vectors will always look as if they're in use
* because the mark bit is never changed.
*/
static void
unmark_static_vectors_in_use(struct weak_pointer *inuse_list)
{
struct weak_pointer *wp;
DPRINTF(debug_static_array_p,
(stdout, "Phase 4: unmark static vectors\n"));
for (wp = inuse_list; wp; wp = wp->next) {
lispobj *header = (lispobj *) PTR(wp->value);
/*
* Invariant: the weak pointer must not be broken.
*
* Note that we can't assert that the static vector is marked
* because we can have more than one weak pointer to the same
* static vector.
*/
gc_assert(wp->broken == NIL);
DPRINTF(debug_static_array_p,
(stdout, " wp %p value %p broken %d header 0x%08lx\n",
wp, (lispobj*) wp->value, wp->broken == T, *header));
/* Only clear if we haven't already */
if ((*header & STATIC_VECTOR_MARK_BIT) != 0) {
DPRINTF(debug_static_array_p,
(stdout, " Clearing mark bit\n"));
*header &= ~STATIC_VECTOR_MARK_BIT;
}
}
DPRINTF(debug_static_array_p,
(stdout, "Phase 4 done\n"));
}
static void
scan_static_vectors(struct weak_pointer *static_vector_list)
{
......@@ -5543,10 +5595,11 @@ scan_static_vectors(struct weak_pointer *static_vector_list)
struct weak_pointer *freeable_list = NULL;
/*
* For each weak pointer, either break it, or add it to the
* freeable list because it points to a unique static vector.
* For each weak pointer, add it either the inuse list or the
* freeable list.
*/
scan_static_vectors_2(static_vector_list, &freeable_list);
inuse_static_vector_list = NULL;
scan_static_vectors_2(static_vector_list, &freeable_list, &inuse_static_vector_list);
/* Free the unused unique static vectors. */
scan_static_vectors_3(freeable_list);
......@@ -5564,18 +5617,15 @@ scan_weak_pointers(void)
*
* Also find any weak pointers to static vectors. This
* destructively modifies the next slot of the weak pointer to
* chain all the weak pointers to unused static vectors together.
* chain all the weak pointers to static vectors together.
*/
DPRINTF(debug_static_array_p,
(stdout, "Phase 1: Process weak pointers\n"));
while (weak_pointers) {
lispobj value;
lispobj *first_pointer;
wp = pop_weak_pointer(&weak_pointers);
value = wp->value;
first_pointer = (lispobj *) PTR(value);
while (wp) {
struct weak_pointer *next = wp->next;
lispobj value = wp->value;
lispobj *first_pointer = (lispobj *) PTR(value);
wp->mark_bit = NIL;
if (Pointerp(value)) {
......@@ -5588,29 +5638,23 @@ scan_weak_pointers(void)
}
} else {
/* The value may be a static vector */
lispobj *header = (lispobj *) PTR(value);
if (maybe_static_array_p(*header)) {
if (*header & STATIC_VECTOR_MARK_BIT) {
DPRINTF(debug_static_array_p,
(stdout, " Update status bits for live vector: wp %p value %p header 0x%08lx\n",
wp, (lispobj *) wp->value, *header));
*header = (*header & ~STATIC_VECTOR_MARK_BIT) | STATIC_VECTOR_VISITED_BIT;
} else if ((*header & STATIC_VECTOR_VISITED_BIT) == 0) {
/* Only add the vector if it is unmarked and has not been visited */
DPRINTF(debug_static_array_p,
(stdout, " Add static vector: wp %p value %p header 0x%08lx\n",
wp, (lispobj *) wp->value, *header));
push_weak_pointer(wp, &static_vector_list);
}
lispobj header = *(lispobj *) PTR(value);
if (maybe_static_array_p(header)) {
DPRINTF(debug_static_array_p,
(stdout, " Add static vector: wp %p value %p header 0x%08lx\n",
wp, (lispobj *) wp->value, header));
push_weak_pointer(wp, &static_vector_list);
} else {
DPRINTF(debug_static_array_p,
(stdout, " Skip: wp %p value %p header 0x%08lx\n",
wp, (lispobj *) wp->value, *header));
wp, (lispobj *) wp->value, header));
}
}
}
wp = next;
}
scan_static_vectors(static_vector_list);
......@@ -8346,6 +8390,13 @@ collect_garbage(unsigned last_gen)
}
scavenger_hooks = (struct scavenger_hook *) NIL;
}
/*
* Unmark any live static vectors. This needs to be done at the
* very end when all GCs are done, lest we accidentally free a
* static vector that was actually in use.
*/
unmark_static_vectors_in_use(inuse_static_vector_list);
}
......