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

Commits:

1 changed file:

Changes:

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