... |
... |
@@ -5417,113 +5417,154 @@ size_weak_pointer(lispobj * where) |
5417
|
5417
|
return WEAK_POINTER_NWORDS;
|
5418
|
5418
|
}
|
5419
|
5419
|
|
|
5420
|
+static inline struct weak_pointer *
|
|
5421
|
+pop(struct weak_pointer **list)
|
|
5422
|
+{
|
|
5423
|
+ /*
|
|
5424
|
+ * Pop the first element from the list `list`, updating `list`, like CL POP.
|
|
5425
|
+ */
|
|
5426
|
+ struct weak_pointer *wp = *list;
|
|
5427
|
+ *list = (*list)->next;
|
|
5428
|
+
|
|
5429
|
+ return wp;
|
|
5430
|
+}
|
|
5431
|
+
|
|
5432
|
+static inline void
|
|
5433
|
+push(struct weak_pointer* wp, struct weak_pointer **list)
|
|
5434
|
+{
|
|
5435
|
+ /*
|
|
5436
|
+ * Push wp to the head of the list, updating list, like CL PUSH.
|
|
5437
|
+ */
|
|
5438
|
+ wp->next = *list;
|
|
5439
|
+ *list = wp;
|
|
5440
|
+}
|
5420
|
5441
|
|
5421
|
5442
|
static void
|
5422
|
5443
|
scan_static_vectors(struct weak_pointer *static_vector_list)
|
5423
|
5444
|
{
|
|
5445
|
+ /* List of weak pointers to static vectors that can be freed. */
|
|
5446
|
+ struct weak_pointer *freeable_list = NULL;
|
|
5447
|
+
|
|
5448
|
+ /* List of weak pointers to static vectors that are in in use. */
|
|
5449
|
+ struct weak_pointer *inuse_list = NULL;
|
5424
|
5450
|
struct weak_pointer *wp;
|
5425
|
5451
|
|
5426
|
5452
|
DPRINTF(debug_static_array_p,
|
5427
|
|
- (stdout, "Phase 2: Visit unused static vectors\n"));
|
|
5453
|
+ (stdout, "Phase 2: Find unused and unused static vectors\n"));
|
5428
|
5454
|
|
5429
|
5455
|
/*
|
5430
|
|
- * static_vector_list now points to all weak pointers to static
|
5431
|
|
- * vectors. For unmarked (unused) static vectors, set another bit
|
5432
|
|
- * in the header to say we've visited it. If we've already
|
5433
|
|
- * visited the static vector, break the weak pointer.
|
|
5456
|
+ * static_vector_list points to all weak pointers to static
|
|
5457
|
+ * vectors. If the static vector is in use, add it to the in-use
|
|
5458
|
+ * list. If the static vector is not in use, and has not been
|
|
5459
|
+ * visited, mark it as visited and add it to the freeable list.
|
|
5460
|
+ * If it has been visited, just break the weak pointer.
|
5434
|
5461
|
*/
|
5435
|
|
- for (wp = static_vector_list; wp; wp = wp->next) {
|
5436
|
|
- lispobj *header = (lispobj *) PTR(wp->value);
|
|
5462
|
+ while (static_vector_list) {
|
|
5463
|
+ struct weak_pointer *this_wp;
|
|
5464
|
+ lispobj *header;
|
|
5465
|
+
|
|
5466
|
+ /* Pop weak pointer from the list */
|
|
5467
|
+ this_wp = pop(&static_vector_list);
|
|
5468
|
+ header = (lispobj *) PTR(this_wp->value);
|
5437
|
5469
|
|
5438
|
5470
|
DPRINTF(debug_static_array_p,
|
5439
|
5471
|
(stdout, " wp %p value %p header 0x%08lx\n",
|
5440
|
|
- wp, (lispobj *) wp->value, *header));
|
|
5472
|
+ this_wp, (lispobj *) this_wp->value, *header));
|
5441
|
5473
|
|
5442
|
5474
|
/*
|
5443
|
5475
|
* If the static vector is unused (mark bit clear) and if we
|
5444
|
5476
|
* haven't seen this vector before, set the visited flag. If
|
5445
|
5477
|
* we have visited this vector before, break the weak pointer.
|
5446
|
5478
|
*/
|
5447
|
|
- if ((*header & STATIC_VECTOR_MARK_BIT) == 0) {
|
|
5479
|
+ if ((*header & STATIC_VECTOR_MARK_BIT) != 0) {
|
|
5480
|
+ /*
|
|
5481
|
+ * Static vector is in use. Add this to the in-use list.
|
|
5482
|
+ */
|
|
5483
|
+ printf(" In-use vector; add to in-use list\n");
|
|
5484
|
+ push(this_wp, &inuse_list);
|
|
5485
|
+ } else {
|
5448
|
5486
|
/* Unused static vector */
|
5449
|
5487
|
if ((*header & STATIC_VECTOR_VISITED_BIT) == 0) {
|
5450
|
|
- DPRINTF(debug_static_array_p, (stdout, " Mark vector\n"));
|
|
5488
|
+ DPRINTF(debug_static_array_p,
|
|
5489
|
+ (stdout, " Visit unused vector, add to freeable list\n"));
|
5451
|
5490
|
|
5452
|
5491
|
*header |= STATIC_VECTOR_VISITED_BIT;
|
|
5492
|
+
|
|
5493
|
+ /*
|
|
5494
|
+ * Add this to the freeable list because it's a static
|
|
5495
|
+ * vector that we can free.
|
|
5496
|
+ */
|
|
5497
|
+ push(this_wp, &freeable_list);
|
5453
|
5498
|
} else {
|
5454
|
5499
|
DPRINTF(debug_static_array_p,
|
5455
|
|
- (stdout, " Break weak pointer %p\n", wp));
|
|
5500
|
+ (stdout, " Already visited unused vector; break weak pointer\n"));
|
5456
|
5501
|
|
5457
|
|
- wp->value = NIL;
|
5458
|
|
- wp->broken = T;
|
|
5502
|
+ this_wp->value = NIL;
|
|
5503
|
+ this_wp->broken = T;
|
5459
|
5504
|
}
|
5460
|
5505
|
}
|
5461
|
5506
|
}
|
5462
|
|
-
|
5463
|
5507
|
|
5464
|
5508
|
DPRINTF(debug_static_array_p,
|
5465
|
5509
|
(stdout, "Phase 3: Free static vectors\n"));
|
5466
|
5510
|
|
5467
|
5511
|
/*
|
5468
|
|
- * static_vector_list now contains either broken weak pointers or
|
5469
|
|
- * weak pointers to static arrays (whether alive or not).
|
5470
|
|
- *
|
5471
|
|
- * Free up space. Go through static_vector_list and for each weak
|
5472
|
|
- * pointer that hasn't been broken and is an unused static array,
|
5473
|
|
- * free the static vector. Also break the weak pointer too, since
|
5474
|
|
- * the space has been freed.
|
|
5512
|
+ * freeable_list now contains weak pointers to unique static
|
|
5513
|
+ * vectors that are not in use. Break the weak pointer and free
|
|
5514
|
+ * the static vector.
|
5475
|
5515
|
*/
|
5476
|
|
- for (wp = static_vector_list; wp; wp = wp->next) {
|
5477
|
|
- /* Skip over broken weak pointers */
|
5478
|
|
- if (wp->broken == NIL) {
|
5479
|
|
- lispobj *header = (lispobj *) PTR(wp->value);
|
|
5516
|
+ for (wp = freeable_list; wp; wp = wp->next) {
|
|
5517
|
+ /* Invariant: weak pointer must not be broken */
|
|
5518
|
+ gc_assert(wp->broken == NIL);
|
|
5519
|
+
|
|
5520
|
+ lispobj *header = (lispobj *) PTR(wp->value);
|
5480
|
5521
|
|
5481
|
|
- DPRINTF(debug_static_array_p,
|
5482
|
|
- (stdout, " wp %p value %p header 0x%08lx\n",
|
5483
|
|
- wp, (lispobj*) wp->value, *header));
|
|
5522
|
+ DPRINTF(debug_static_array_p,
|
|
5523
|
+ (stdout, " wp %p value %p header 0x%08lx\n",
|
|
5524
|
+ wp, (lispobj*) wp->value, *header));
|
5484
|
5525
|
|
5485
|
|
- /*
|
5486
|
|
- * Only free the arrays where the mark bit is clear.
|
5487
|
|
- */
|
5488
|
|
- if ((*header & STATIC_VECTOR_MARK_BIT) == 0) {
|
5489
|
|
- lispobj *static_array = (lispobj *) PTR(wp->value);
|
5490
|
|
- DPRINTF(debug_static_array_p,
|
5491
|
|
- (stdout, " Free static vector\n"));
|
|
5526
|
+ /*
|
|
5527
|
+ * Invariant: Mark bit must be clear
|
|
5528
|
+ */
|
|
5529
|
+ gc_assert(((*header & STATIC_VECTOR_MARK_BIT) == 0));
|
|
5530
|
+
|
|
5531
|
+ lispobj *static_array = (lispobj *) PTR(wp->value);
|
|
5532
|
+ DPRINTF(debug_static_array_p,
|
|
5533
|
+ (stdout, " Free static vector\n"));
|
5492
|
5534
|
|
5493
|
|
- wp->value = NIL;
|
5494
|
|
- wp->broken = T;
|
|
5535
|
+ wp->value = NIL;
|
|
5536
|
+ wp->broken = T;
|
5495
|
5537
|
|
5496
|
|
- free(static_array);
|
5497
|
|
- }
|
5498
|
|
- }
|
|
5538
|
+ free(static_array);
|
5499
|
5539
|
}
|
5500
|
|
-
|
5501
|
5540
|
|
5502
|
5541
|
DPRINTF(debug_static_array_p,
|
5503
|
5542
|
(stdout, "Phase 4: unmark static vectors\n"));
|
5504
|
5543
|
|
5505
|
5544
|
/*
|
5506
|
|
- * At this point, static_vector_list contains weak pointers that
|
5507
|
|
- * have been broken or weak pointres to live static vectors. Go
|
5508
|
|
- * through all the weak pointers and if it hasn't been broken and
|
5509
|
|
- * if the mark bit of the static vector is set, then clear the
|
5510
|
|
- * mark bit .
|
|
5545
|
+ * At this point, inuse_list is a list of weak pointers to static
|
|
5546
|
+ * vectors that are still in use. Clear the mark bit.
|
5511
|
5547
|
*/
|
5512
|
|
- for (wp = static_vector_list; wp; wp = wp->next) {
|
5513
|
|
- /* Skip over broken weak pointers */
|
5514
|
|
- if (wp->broken == NIL) {
|
5515
|
|
- lispobj *header = (lispobj *) PTR(wp->value);
|
|
5548
|
+ for (wp = inuse_list; wp; wp = wp->next) {
|
|
5549
|
+ lispobj *header = (lispobj *) PTR(wp->value);
|
|
5550
|
+ /*
|
|
5551
|
+ * Invariant: the weak pointer must not be broken.
|
|
5552
|
+ *
|
|
5553
|
+ * Note that we can't assert that the static vector is marked
|
|
5554
|
+ * because we can have more than one weak pointer to the same
|
|
5555
|
+ * static vector.
|
|
5556
|
+ */
|
|
5557
|
+ gc_assert(wp->broken == NIL);
|
|
5558
|
+
|
|
5559
|
+ DPRINTF(debug_static_array_p,
|
|
5560
|
+ (stdout, " wp %p value %p broken %d header 0x%08lx\n",
|
|
5561
|
+ wp, (lispobj*) wp->value, wp->broken == T, *header));
|
5516
|
5562
|
|
|
5563
|
+ if ((*header & STATIC_VECTOR_MARK_BIT) != 0) {
|
5517
|
5564
|
DPRINTF(debug_static_array_p,
|
5518
|
|
- (stdout, " wp %p value %p broken %d header 0x%08lx\n",
|
5519
|
|
- wp, (lispobj*) wp->value, wp->broken == T, *header));
|
|
5565
|
+ (stdout, " Clearing mark bit\n"));
|
5520
|
5566
|
|
5521
|
|
- if ((*header & STATIC_VECTOR_MARK_BIT) != 0) {
|
5522
|
|
- DPRINTF(debug_static_array_p,
|
5523
|
|
- (stdout, " Clearing mark bit\n"));
|
5524
|
|
-
|
5525
|
|
- *header &= ~STATIC_VECTOR_MARK_BIT;
|
5526
|
|
- }
|
|
5567
|
+ *header &= ~STATIC_VECTOR_MARK_BIT;
|
5527
|
5568
|
}
|
5528
|
5569
|
}
|
5529
|
5570
|
}
|
... |
... |
@@ -5543,7 +5584,7 @@ scan_weak_pointers(void) |
5543
|
5584
|
* chain all the weak pointers to static vectors together.
|
5544
|
5585
|
*/
|
5545
|
5586
|
DPRINTF(debug_static_array_p,
|
5546
|
|
- (stdout, "Phase 0: Process weak pointers\n"));
|
|
5587
|
+ (stdout, "Phase 1: Process weak pointers\n"));
|
5547
|
5588
|
|
5548
|
5589
|
while (wp) {
|
5549
|
5590
|
struct weak_pointer *next = wp->next;
|