Raymond Toy pushed to branch issue-243-weak-pointer-to-static-array at cmucl / cmucl

Commits:

1 changed file:

Changes:

  • src/lisp/gencgc.c
    ... ... @@ -5397,94 +5397,107 @@ size_weak_pointer(lispobj * where)
    5397 5397
     }
    
    5398 5398
     
    
    5399 5399
     
    
    5400
    -#if 0
    
    5401 5400
     static void
    
    5402
    -update_static_vector_list(lispobj value, lispobj* vectors_to_free, int* num_static_vectors)
    
    5401
    +scan_static_vectors(void)
    
    5403 5402
     {
    
    5403
    +    struct weak_pointer *wp;
    
    5404
    +    struct weak_pointer *clearable_list = NULL;
    
    5405
    +
    
    5406
    +    printf("Phase 1: build clearable list\n");
    
    5407
    +
    
    5404 5408
         /*
    
    5405
    -     * We have a static array with the mark cleared which means it's
    
    5406
    -     * not used.
    
    5409
    +     * Find weak pointers to unmarked static arrays, using a linked
    
    5410
    +     * list.  We reuse the next slot ofthe weak pointer to chain these
    
    5411
    +     * weak pointers together.
    
    5407 5412
          *
    
    5408
    -     * Only add it if we don't already have it.  We don't want
    
    5409
    -     * duplicates because we'll end up trying to free things multiple
    
    5410
    -     * times.
    
    5413
    +     * Invariant: clearable_list only has weak pointers to unmarked
    
    5414
    +     * static vectors.
    
    5411 5415
          */
    
    5412
    -    int m;
    
    5413
    -    int found = 0;
    
    5414
    -                        
    
    5415
    -    for (m = 0; m < *num_static_vectors; ++m) {
    
    5416
    -        if (value == vectors_to_free[m]) {
    
    5417
    -            printf("Found %p at %d\n", (lispobj *) value, m);
    
    5418
    -            found = 1;
    
    5419
    -            break;
    
    5416
    +    wp = weak_pointers;
    
    5417
    +    while (wp) {
    
    5418
    +	lispobj value = wp->value;
    
    5419
    +        struct weak_pointer *next = wp->next;
    
    5420
    +
    
    5421
    +	if (Pointerp(value)) {
    
    5422
    +            /* The value may be a static vector */
    
    5423
    +            lispobj *header = (lispobj *) PTR(value);
    
    5424
    +
    
    5425
    +            if (maybe_static_array_p(*header)
    
    5426
    +                && (HeaderValue(*header) == 1)) {
    
    5427
    +                printf("Adding %p header = 0x%08lx, next = %p\n",
    
    5428
    +                       wp, *header, wp->next);
    
    5429
    +                wp->next = clearable_list;
    
    5430
    +                clearable_list = wp;
    
    5431
    +            } else {
    
    5432
    +                printf("Skipping %p header = 0x%08lx\n", wp, *header);
    
    5433
    +            }
    
    5420 5434
             }
    
    5435
    +        wp = next;
    
    5421 5436
         }
    
    5422
    -    if (!found) {
    
    5423
    -        printf("Adding %p at %d\n", (lispobj *) value, *num_static_vectors);
    
    5424
    -        vectors_to_free[*num_static_vectors] = value;
    
    5425
    -        ++*num_static_vectors;
    
    5426
    -    }
    
    5427
    -}
    
    5428
    -#endif
    
    5429
    -
    
    5430
    -void
    
    5431
    -scan_weak_pointers(void)
    
    5432
    -{
    
    5433
    -    struct weak_pointer *wp;
    
    5434 5437
     
    
    5438
    +    printf("Phase 2\n");
    
    5439
    +    
    
    5435 5440
         /*
    
    5436
    -     * Array of weak pointers to unmarked static vectors that can be
    
    5437
    -     * freed.
    
    5441
    +     * clearable_list now points to all weak pointers to unmarked
    
    5442
    +     * static vectors.  Go through the list.  If it's not marked, mark
    
    5443
    +     * it.  If it's marked, break the weak pointer.
    
    5444
    +     *
    
    5445
    +     * Invariant: clearable_list contains only weak pointers that have
    
    5446
    +     * been broken or that point to a unique dead static vector.
    
    5438 5447
          */
    
    5439
    -    struct weak_pointer **clearable_list;
    
    5448
    +    for (wp = clearable_list; wp; wp = wp->next) {
    
    5449
    +        lispobj *header = (lispobj *) PTR(wp->value);
    
    5440 5450
     
    
    5441
    -    /* Total number of weak pointers */
    
    5442
    -    int num_weak_pointers = 0;
    
    5451
    +        printf("wp %p value 0x%08lx header 0x%08lx\n",
    
    5452
    +               wp, wp->value, *header);
    
    5453
    +        if (HeaderValue(*header) == 1) {
    
    5454
    +            printf("  Mark vector\n");
    
    5455
    +            *header |= 0x80000000;
    
    5456
    +        } else {
    
    5457
    +            printf("  Break weak pointer %p\n", wp);
    
    5458
    +            wp->value = NIL;
    
    5459
    +            wp->broken = T;
    
    5460
    +        }
    
    5461
    +    }
    
    5462
    +
    
    5463
    +    printf("Phase 3: Free static vectors\n");
    
    5443 5464
     
    
    5444
    -    /* Number of static vectors that we can free */
    
    5445
    -    int num_static_vectors = 0;
    
    5446
    -    int n;
    
    5447
    -    
    
    5448 5465
         /*
    
    5449
    -     * Count the number of weak pointers so we can allocate enough
    
    5450
    -     * space for clearable_list.
    
    5466
    +     * Free up space.  Go through clearable_list and for each weak
    
    5467
    +     * pointer that has not been broken, we can free the space.  Then
    
    5468
    +     * break the weak pointer too, since the space has been freed.
    
    5451 5469
          */
    
    5470
    +    for (wp = clearable_list; wp; wp = wp->next) {
    
    5471
    +        if (wp->broken == NIL) {
    
    5472
    +            lispobj *static_array = (lispobj *) PTR(wp->value);
    
    5473
    +            printf("free wp %p: %p\n", wp, static_array);
    
    5452 5474
     
    
    5453
    -    if (debug_static_array_p) {
    
    5454
    -        printf("Phase 0\n");
    
    5455
    -    }
    
    5456
    -    
    
    5457
    -    for (wp = weak_pointers; wp; wp = wp->next) {
    
    5458
    -        num_weak_pointers++;
    
    5459
    -    }
    
    5475
    +            wp->value = NIL;
    
    5476
    +            wp->broken = T;
    
    5460 5477
     
    
    5461
    -    if (debug_static_array_p) {
    
    5462
    -        printf("weak pointer count = %d\n", num_weak_pointers);
    
    5478
    +            free(static_array);
    
    5479
    +        }
    
    5463 5480
         }
    
    5481
    +}
    
    5464 5482
     
    
    5465
    -    /* Nothing to do if there are no weak pointers */
    
    5466
    -    if (num_weak_pointers == 0) {
    
    5467
    -        return;
    
    5468
    -    }
    
    5469
    -    
    
    5470
    -    /*
    
    5471
    -     * Allocate enough space to hold all weak pointers in case they
    
    5472
    -     * all point to static vectors.
    
    5473
    -     */
    
    5474
    -    clearable_list = (struct weak_pointer **) malloc(num_weak_pointers * sizeof(struct weak_pointer *));
    
    5475
    -    gc_assert(clearable_list);
    
    5483
    +void
    
    5484
    +scan_weak_pointers(void)
    
    5485
    +{
    
    5486
    +    struct weak_pointer *wp;
    
    5476 5487
     
    
    5477 5488
         /*
    
    5478 5489
          * Now process the weak pointers.
    
    5479 5490
          */
    
    5480
    -    if (debug_static_array_p) {
    
    5481
    -        printf("Phase 1\n");
    
    5482
    -    }
    
    5483 5491
     
    
    5492
    +    printf("scan_weak_pointers...\n");
    
    5493
    +    
    
    5484 5494
         for (wp = weak_pointers; wp; wp = wp->next) {
    
    5485 5495
     	lispobj value = wp->value;
    
    5486 5496
     	lispobj *first_pointer = (lispobj *) PTR(value);
    
    5487 5497
     
    
    5498
    +        printf("scan_weak: wp = %p value %p header 0x%08lx\n",
    
    5499
    +               wp, (lispobj*) value, *first_pointer);
    
    5500
    +
    
    5488 5501
     	wp->mark_bit = NIL;
    
    5489 5502
     	if (Pointerp(value)) {
    
    5490 5503
                 if (from_space_p(value)) {
    
    ... ... @@ -5494,111 +5507,12 @@ scan_weak_pointers(void)
    5494 5507
                         wp->value = NIL;
    
    5495 5508
                         wp->broken = T;
    
    5496 5509
                     }
    
    5497
    -            } else {
    
    5498
    -                /* The value may be a static vector */
    
    5499
    -                lispobj *header = (lispobj *) PTR(value);
    
    5500
    -
    
    5501
    -                if (debug_static_array_p) {
    
    5502
    -                    printf("wp %p: value %p, header = 0x%08lx\n",
    
    5503
    -                           wp, (lispobj*) value, *header);
    
    5504
    -                }
    
    5505
    -                
    
    5506
    -                if (maybe_static_array_p(*header)) {
    
    5507
    -                    /*
    
    5508
    -                     * A header value of 1 means we have a static
    
    5509
    -                     * vector with the in-use bit cleared, so we can
    
    5510
    -                     * add this weak pointer to the clearable list.
    
    5511
    -                     */
    
    5512
    -                    if (HeaderValue(*header) == 1) {
    
    5513
    -                        if (debug_static_array_p) {
    
    5514
    -                            printf("  clearable_list[%d] = %p\n", num_static_vectors, wp);
    
    5515
    -                        }
    
    5516
    -
    
    5517
    -                        clearable_list[num_static_vectors] = wp;
    
    5518
    -                        ++num_static_vectors;
    
    5519
    -                    }
    
    5520
    -                }
    
    5521
    -            }
    
    5522
    -        }
    
    5523
    -    }
    
    5524
    -
    
    5525
    -    /*
    
    5526
    -     * At this point, clearable_list contains all the weak pointers to
    
    5527
    -     * unmarked (unused) static vecotors.
    
    5528
    -     *
    
    5529
    -     * Traverse the clearable list.  If the weak pointer points to an
    
    5530
    -     * unmarked static vector, mark it.  If it points to a marked
    
    5531
    -     * static vector, then we know it shares a referent with another
    
    5532
    -     * weak pointer.  Break this weak pointer and remove it from the
    
    5533
    -     * clearable list by setting it to NIL.
    
    5534
    -     */
    
    5535
    -    if (debug_static_array_p) {
    
    5536
    -        printf("Phase 2: %d pointers\n", num_static_vectors);
    
    5537
    -    }
    
    5538
    -
    
    5539
    -    for (n = 0; n < num_static_vectors; ++n) {
    
    5540
    -        struct weak_pointer *wp = clearable_list[n];
    
    5541
    -        lispobj *header = (lispobj *) PTR(wp->value);
    
    5542
    -
    
    5543
    -        if (debug_static_array_p) {
    
    5544
    -            printf("%2d: wp = %p, header = 0x%08lx\n", n, wp, *header);
    
    5545
    -        }
    
    5546
    -        
    
    5547
    -        if (HeaderValue(*header) == 1) {
    
    5548
    -            /*
    
    5549
    -             * If the header value is 1, we have an unmarked static
    
    5550
    -             * vector.  Mark it now.
    
    5551
    -             */
    
    5552
    -            if (debug_static_array_p) {
    
    5553
    -                printf("  Mark vector\n");
    
    5554
    -            }
    
    5555
    -
    
    5556
    -            *header |= 0x80000000;
    
    5557
    -        } else {
    
    5558
    -            /*
    
    5559
    -             * We have a marked static vector.  Break this weak
    
    5560
    -             * pointer and remove it from the list by setting it to
    
    5561
    -             * NIL.
    
    5562
    -             */
    
    5563
    -            if (debug_static_array_p) {
    
    5564
    -                printf("  Break weak pointer %p\n", wp);
    
    5565
    -            }
    
    5566
    -
    
    5567
    -            wp->value = NIL;
    
    5568
    -            wp->broken = T;
    
    5569
    -            clearable_list[n] = NULL;
    
    5570
    -        }
    
    5571
    -    }
    
    5572
    -
    
    5573
    -    /*
    
    5574
    -     * At this point, the clearable list is either NIL or a weak
    
    5575
    -     * pointer that references a unique dead static vector.
    
    5576
    -     *
    
    5577
    -     * Traverse the clearable list skipping over any NIL entries.  For
    
    5578
    -     * all other entries, free the static vector and break the weak
    
    5579
    -     * pointer.
    
    5580
    -     */
    
    5581
    -
    
    5582
    -    if (debug_static_array_p) {
    
    5583
    -        printf("Phase 3: Free static vectors\n");
    
    5584
    -    }
    
    5585
    -    
    
    5586
    -    for (n = 0; n < num_static_vectors; ++n) {
    
    5587
    -        struct weak_pointer *wp = clearable_list[n];
    
    5588
    -        if (wp != NULL) {
    
    5589
    -            lispobj *static_array = (lispobj *) PTR(wp->value);
    
    5590
    -
    
    5591
    -            if (debug_static_array_p) {
    
    5592
    -                printf("%2d: free wp %p: %p\n", n, (void*) wp, static_array);
    
    5593 5510
                 }
    
    5594
    -
    
    5595
    -            free(static_array);
    
    5596
    -            wp->value = NIL;
    
    5597
    -            wp->broken = T;
    
    5598 5511
             }
    
    5599 5512
         }
    
    5513
    +    printf("scan_weak_pointers done\n");
    
    5600 5514
     
    
    5601
    -    free(clearable_list);
    
    5515
    +    scan_static_vectors();
    
    5602 5516
     }
    
    5603 5517
     
    
    5604 5518