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

Commits:

1 changed file:

Changes:

  • src/lisp/gencgc.c
    ... ... @@ -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