... |
... |
@@ -2130,6 +2130,7 @@ static lispobj(*transother[256]) (lispobj object); |
2130
|
2130
|
static int (*sizetab[256]) (lispobj * where);
|
2131
|
2131
|
|
2132
|
2132
|
static struct weak_pointer *weak_pointers;
|
|
2133
|
+static struct weak_pointer *inuse_static_vector_list;
|
2133
|
2134
|
static struct scavenger_hook *scavenger_hooks = (struct scavenger_hook *) NIL;
|
2134
|
2135
|
|
2135
|
2136
|
/* Like (ceiling x y), but y is constrained to be a power of two */
|
... |
... |
@@ -2734,7 +2735,7 @@ scav_static_vector(lispobj object) |
2734
|
2735
|
int static_p;
|
2735
|
2736
|
|
2736
|
2737
|
if (debug_static_array_p) {
|
2737
|
|
- fprintf(stderr, "Possible static vector at %p. header = 0x%08lx\n",
|
|
2738
|
+ fprintf(stderr, "Possible static vector at %p. header = 0x%lx\n",
|
2738
|
2739
|
ptr, (unsigned long) header);
|
2739
|
2740
|
}
|
2740
|
2741
|
|
... |
... |
@@ -2745,9 +2746,9 @@ scav_static_vector(lispobj object) |
2745
|
2746
|
* setting the MSB of the header. And clear out any
|
2746
|
2747
|
* possible visited bit.
|
2747
|
2748
|
*/
|
2748
|
|
- *ptr = (header | STATIC_VECTOR_MARK_BIT);
|
|
2749
|
+ *ptr = (header | STATIC_VECTOR_MARK_BIT) & ~STATIC_VECTOR_VISITED_BIT;
|
2749
|
2750
|
if (debug_static_array_p) {
|
2750
|
|
- fprintf(stderr, "Scavenged static vector @%p, header = 0x%08lx\n",
|
|
2751
|
+ fprintf(stderr, "Scavenged static vector @%p, header = 0x%lx\n",
|
2751
|
2752
|
ptr, (unsigned long) header);
|
2752
|
2753
|
}
|
2753
|
2754
|
}
|
... |
... |
@@ -5388,14 +5389,6 @@ scav_weak_pointer(lispobj * where, lispobj object) |
5388
|
5389
|
struct weak_pointer *this_wp = (struct weak_pointer *) where;
|
5389
|
5390
|
|
5390
|
5391
|
if (this_wp->mark_bit == NIL) {
|
5391
|
|
- lispobj *header = (lispobj *) PTR(this_wp->value);
|
5392
|
|
- if (maybe_static_array_p(*header)) {
|
5393
|
|
- printf("Scavenge wp %p to static array %p header 0x%08lx\n",
|
5394
|
|
- this_wp, (lispobj *) this_wp->value, *header);
|
5395
|
|
-
|
5396
|
|
- *header &= ~STATIC_VECTOR_VISITED_BIT;
|
5397
|
|
- }
|
5398
|
|
-
|
5399
|
5392
|
this_wp->mark_bit = T;
|
5400
|
5393
|
this_wp->next = weak_pointers;
|
5401
|
5394
|
weak_pointers = this_wp;
|
... |
... |
@@ -5449,14 +5442,16 @@ push_weak_pointer(struct weak_pointer* wp, struct weak_pointer **list) |
5449
|
5442
|
}
|
5450
|
5443
|
|
5451
|
5444
|
/*
|
5452
|
|
- * Phase 2: Process the list of weak pointers to unused static
|
5453
|
|
- * vectors. We find the unique static vectors and add each
|
5454
|
|
- * corresponding weak pointer to freeable_list. For the duplicates,
|
5455
|
|
- * the weak pointer is broken.
|
|
5445
|
+ * Phase 2: Find the weak pointers to static vectors that are in use
|
|
5446
|
+ * and not in use. The vectors that are in use are added to
|
|
5447
|
+ * inuse_list. Those that are not in use are added to freeable_list.
|
|
5448
|
+ * Only unique vectors are added to freeable list; a duplicate has its
|
|
5449
|
+ * weak pointer to it broken.
|
5456
|
5450
|
*/
|
5457
|
5451
|
static void
|
5458
|
5452
|
scan_static_vectors_2(struct weak_pointer *static_vector_list,
|
5459
|
|
- struct weak_pointer **freeable_list)
|
|
5453
|
+ struct weak_pointer **freeable_list,
|
|
5454
|
+ struct weak_pointer **inuse_list)
|
5460
|
5455
|
{
|
5461
|
5456
|
DPRINTF(debug_static_array_p,
|
5462
|
5457
|
(stdout, "Phase 2: Find unused and unused static vectors\n"));
|
... |
... |
@@ -5473,23 +5468,34 @@ scan_static_vectors_2(struct weak_pointer *static_vector_list, |
5473
|
5468
|
(stdout, " wp %p value %p header 0x%08lx\n",
|
5474
|
5469
|
wp, (lispobj *) wp->value, *header));
|
5475
|
5470
|
|
5476
|
|
- /*
|
5477
|
|
- * If we haven't seen this vector before, set the visited flag
|
5478
|
|
- * and add it to freeable_list. If we have visited this
|
5479
|
|
- * vector before, break the weak pointer.
|
5480
|
|
- */
|
5481
|
|
- if ((*header & STATIC_VECTOR_VISITED_BIT) == 0) {
|
|
5471
|
+ if ((*header & STATIC_VECTOR_MARK_BIT) != 0) {
|
|
5472
|
+ /*
|
|
5473
|
+ * Static vector is in use. Add this to the in-use list.
|
|
5474
|
+ */
|
5482
|
5475
|
DPRINTF(debug_static_array_p,
|
5483
|
|
- (stdout, " Visit unused vector, add to freeable list\n"));
|
|
5476
|
+ (stdout, " In-use vector; add to in-use list\n"));
|
5484
|
5477
|
|
5485
|
|
- *header |= STATIC_VECTOR_VISITED_BIT;
|
5486
|
|
- push_weak_pointer(wp, freeable_list);
|
|
5478
|
+ push_weak_pointer(wp, inuse_list);
|
5487
|
5479
|
} else {
|
5488
|
|
- DPRINTF(debug_static_array_p,
|
5489
|
|
- (stdout, " Already visited unused vector; break weak pointer\n"));
|
|
5480
|
+ /*
|
|
5481
|
+ * Static vector not in use. If we haven't seen this
|
|
5482
|
+ * vector before, set the visited flag and add it to
|
|
5483
|
+ * freeable_list. If we have visited this vector before,
|
|
5484
|
+ * break the weak pointer.
|
|
5485
|
+ */
|
|
5486
|
+ if ((*header & STATIC_VECTOR_VISITED_BIT) == 0) {
|
|
5487
|
+ DPRINTF(debug_static_array_p,
|
|
5488
|
+ (stdout, " Visit unused vector, add to freeable list\n"));
|
5490
|
5489
|
|
5491
|
|
- wp->value = NIL;
|
5492
|
|
- wp->broken = T;
|
|
5490
|
+ *header |= STATIC_VECTOR_VISITED_BIT;
|
|
5491
|
+ push_weak_pointer(wp, freeable_list);
|
|
5492
|
+ } else {
|
|
5493
|
+ DPRINTF(debug_static_array_p,
|
|
5494
|
+ (stdout, " Already visited unused vector; break weak pointer\n"));
|
|
5495
|
+
|
|
5496
|
+ wp->value = NIL;
|
|
5497
|
+ wp->broken = T;
|
|
5498
|
+ }
|
5493
|
5499
|
}
|
5494
|
5500
|
}
|
5495
|
5501
|
|
... |
... |
@@ -5512,15 +5518,18 @@ scan_static_vectors_3(struct weak_pointer *freeable_list) |
5512
|
5518
|
lispobj *header = (lispobj *) PTR(wp->value);
|
5513
|
5519
|
lispobj *static_array = (lispobj *) PTR(wp->value);
|
5514
|
5520
|
|
|
5521
|
+ /*
|
|
5522
|
+ * Invariant: weak pointer must not be broken
|
|
5523
|
+ */
|
|
5524
|
+ gc_assert(wp->broken == NIL);
|
|
5525
|
+
|
5515
|
5526
|
DPRINTF(debug_static_array_p,
|
5516
|
5527
|
(stdout, " wp %p value %p header 0x%08lx\n",
|
5517
|
5528
|
wp, (lispobj*) wp->value, *header));
|
5518
|
5529
|
|
5519
|
5530
|
/*
|
5520
|
|
- * Invariants: weak pointer must not be broken and the mark
|
5521
|
|
- * bit must be clear.
|
|
5531
|
+ * Invariant: Mark bit must be clear
|
5522
|
5532
|
*/
|
5523
|
|
- gc_assert(wp->broken == NIL);
|
5524
|
5533
|
gc_assert(((*header & STATIC_VECTOR_MARK_BIT) == 0));
|
5525
|
5534
|
|
5526
|
5535
|
DPRINTF(debug_static_array_p,
|
... |
... |
@@ -5536,6 +5545,49 @@ scan_static_vectors_3(struct weak_pointer *freeable_list) |
5536
|
5545
|
(stdout, "Phase 3 done\n"));
|
5537
|
5546
|
}
|
5538
|
5547
|
|
|
5548
|
+/*
|
|
5549
|
+ * Unmark all the vectors in inuse_list. This needs to be called at
|
|
5550
|
+ * the end of GC to unmark any live static vectors so that for the
|
|
5551
|
+ * next GC we can tell if the static vector is used or not.
|
|
5552
|
+ * Otherwise, the vectors will always look as if they're in use
|
|
5553
|
+ * because the mark bit is never changed.
|
|
5554
|
+ */
|
|
5555
|
+static void
|
|
5556
|
+unmark_static_vectors_in_use(struct weak_pointer *inuse_list)
|
|
5557
|
+{
|
|
5558
|
+ struct weak_pointer *wp;
|
|
5559
|
+
|
|
5560
|
+ DPRINTF(debug_static_array_p,
|
|
5561
|
+ (stdout, "Phase 4: unmark static vectors\n"));
|
|
5562
|
+
|
|
5563
|
+ for (wp = inuse_list; wp; wp = wp->next) {
|
|
5564
|
+ lispobj *header = (lispobj *) PTR(wp->value);
|
|
5565
|
+ /*
|
|
5566
|
+ * Invariant: the weak pointer must not be broken.
|
|
5567
|
+ *
|
|
5568
|
+ * Note that we can't assert that the static vector is marked
|
|
5569
|
+ * because we can have more than one weak pointer to the same
|
|
5570
|
+ * static vector.
|
|
5571
|
+ */
|
|
5572
|
+ gc_assert(wp->broken == NIL);
|
|
5573
|
+
|
|
5574
|
+ DPRINTF(debug_static_array_p,
|
|
5575
|
+ (stdout, " wp %p value %p broken %d header 0x%08lx\n",
|
|
5576
|
+ wp, (lispobj*) wp->value, wp->broken == T, *header));
|
|
5577
|
+
|
|
5578
|
+ /* Only clear if we haven't already */
|
|
5579
|
+ if ((*header & STATIC_VECTOR_MARK_BIT) != 0) {
|
|
5580
|
+ DPRINTF(debug_static_array_p,
|
|
5581
|
+ (stdout, " Clearing mark bit\n"));
|
|
5582
|
+
|
|
5583
|
+ *header &= ~STATIC_VECTOR_MARK_BIT;
|
|
5584
|
+ }
|
|
5585
|
+ }
|
|
5586
|
+
|
|
5587
|
+ DPRINTF(debug_static_array_p,
|
|
5588
|
+ (stdout, "Phase 4 done\n"));
|
|
5589
|
+}
|
|
5590
|
+
|
5539
|
5591
|
static void
|
5540
|
5592
|
scan_static_vectors(struct weak_pointer *static_vector_list)
|
5541
|
5593
|
{
|
... |
... |
@@ -5543,10 +5595,11 @@ scan_static_vectors(struct weak_pointer *static_vector_list) |
5543
|
5595
|
struct weak_pointer *freeable_list = NULL;
|
5544
|
5596
|
|
5545
|
5597
|
/*
|
5546
|
|
- * For each weak pointer, either break it, or add it to the
|
5547
|
|
- * freeable list because it points to a unique static vector.
|
|
5598
|
+ * For each weak pointer, add it either the inuse list or the
|
|
5599
|
+ * freeable list.
|
5548
|
5600
|
*/
|
5549
|
|
- scan_static_vectors_2(static_vector_list, &freeable_list);
|
|
5601
|
+ inuse_static_vector_list = NULL;
|
|
5602
|
+ scan_static_vectors_2(static_vector_list, &freeable_list, &inuse_static_vector_list);
|
5550
|
5603
|
|
5551
|
5604
|
/* Free the unused unique static vectors. */
|
5552
|
5605
|
scan_static_vectors_3(freeable_list);
|
... |
... |
@@ -5564,18 +5617,15 @@ scan_weak_pointers(void) |
5564
|
5617
|
*
|
5565
|
5618
|
* Also find any weak pointers to static vectors. This
|
5566
|
5619
|
* destructively modifies the next slot of the weak pointer to
|
5567
|
|
- * chain all the weak pointers to unused static vectors together.
|
|
5620
|
+ * chain all the weak pointers to static vectors together.
|
5568
|
5621
|
*/
|
5569
|
5622
|
DPRINTF(debug_static_array_p,
|
5570
|
5623
|
(stdout, "Phase 1: Process weak pointers\n"));
|
5571
|
5624
|
|
5572
|
|
- while (weak_pointers) {
|
5573
|
|
- lispobj value;
|
5574
|
|
- lispobj *first_pointer;
|
5575
|
|
-
|
5576
|
|
- wp = pop_weak_pointer(&weak_pointers);
|
5577
|
|
- value = wp->value;
|
5578
|
|
- first_pointer = (lispobj *) PTR(value);
|
|
5625
|
+ while (wp) {
|
|
5626
|
+ struct weak_pointer *next = wp->next;
|
|
5627
|
+ lispobj value = wp->value;
|
|
5628
|
+ lispobj *first_pointer = (lispobj *) PTR(value);
|
5579
|
5629
|
|
5580
|
5630
|
wp->mark_bit = NIL;
|
5581
|
5631
|
if (Pointerp(value)) {
|
... |
... |
@@ -5588,29 +5638,23 @@ scan_weak_pointers(void) |
5588
|
5638
|
}
|
5589
|
5639
|
} else {
|
5590
|
5640
|
/* The value may be a static vector */
|
5591
|
|
- lispobj *header = (lispobj *) PTR(value);
|
5592
|
|
-
|
5593
|
|
- if (maybe_static_array_p(*header)) {
|
5594
|
|
- if (*header & STATIC_VECTOR_MARK_BIT) {
|
5595
|
|
- DPRINTF(debug_static_array_p,
|
5596
|
|
- (stdout, " Update status bits for live vector: wp %p value %p header 0x%08lx\n",
|
5597
|
|
- wp, (lispobj *) wp->value, *header));
|
5598
|
|
- *header = (*header & ~STATIC_VECTOR_MARK_BIT) | STATIC_VECTOR_VISITED_BIT;
|
5599
|
|
- } else if ((*header & STATIC_VECTOR_VISITED_BIT) == 0) {
|
5600
|
|
- /* Only add the vector if it is unmarked and has not been visited */
|
5601
|
|
- DPRINTF(debug_static_array_p,
|
5602
|
|
- (stdout, " Add static vector: wp %p value %p header 0x%08lx\n",
|
5603
|
|
- wp, (lispobj *) wp->value, *header));
|
5604
|
|
-
|
5605
|
|
- push_weak_pointer(wp, &static_vector_list);
|
5606
|
|
- }
|
|
5641
|
+ lispobj header = *(lispobj *) PTR(value);
|
|
5642
|
+
|
|
5643
|
+ if (maybe_static_array_p(header)) {
|
|
5644
|
+
|
|
5645
|
+ DPRINTF(debug_static_array_p,
|
|
5646
|
+ (stdout, " Add static vector: wp %p value %p header 0x%08lx\n",
|
|
5647
|
+ wp, (lispobj *) wp->value, header));
|
|
5648
|
+
|
|
5649
|
+ push_weak_pointer(wp, &static_vector_list);
|
5607
|
5650
|
} else {
|
5608
|
5651
|
DPRINTF(debug_static_array_p,
|
5609
|
5652
|
(stdout, " Skip: wp %p value %p header 0x%08lx\n",
|
5610
|
|
- wp, (lispobj *) wp->value, *header));
|
|
5653
|
+ wp, (lispobj *) wp->value, header));
|
5611
|
5654
|
}
|
5612
|
5655
|
}
|
5613
|
5656
|
}
|
|
5657
|
+ wp = next;
|
5614
|
5658
|
}
|
5615
|
5659
|
|
5616
|
5660
|
scan_static_vectors(static_vector_list);
|
... |
... |
@@ -8346,6 +8390,13 @@ collect_garbage(unsigned last_gen) |
8346
|
8390
|
}
|
8347
|
8391
|
scavenger_hooks = (struct scavenger_hook *) NIL;
|
8348
|
8392
|
}
|
|
8393
|
+
|
|
8394
|
+ /*
|
|
8395
|
+ * Unmark any live static vectors. This needs to be done at the
|
|
8396
|
+ * very end when all GCs are done, lest we accidentally free a
|
|
8397
|
+ * static vector that was actually in use.
|
|
8398
|
+ */
|
|
8399
|
+ unmark_static_vectors_in_use(inuse_static_vector_list);
|
8349
|
8400
|
}
|
8350
|
8401
|
|
8351
|
8402
|
|