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