From c6aa07913db78733634b49d305f41bb8ae4f97e2 Mon Sep 17 00:00:00 2001 From: Alastair Bridgewater Date: Sun, 19 May 2013 13:00:52 -0400 Subject: [PATCH] gencgc: Decide earlier about pinning large object pages. * The old logic here called maybe_adjust_large_object(), and then re-checked the pointer to preserve for validity. This is non-optimal, as it means that maybe_adjust_large_object can't promote pages to newspace directly, it instead merely adjusts the page allocation to fit the possibly-shrunken object. * It turns out that large_object pages can contain bignums, vectors, code-objects, or in unusual cases instances. Neither bignums, vectors, nor instances can contain embedded objects. Code-objects can contain only functions or LRAs. None of these objects have list-pointer-lowtag on their references. The "tail" of a shrunken object is comprised of conses with both cells as fixnum zero. The minor catch is that we allow untagged pointers to pin code-allocated pages, but the saving grace here is that code-objects don't shrink. * Alter preserve_pointer() to test the lowtag and page type to check for invalid pointers to large-object pages before calling maybe_adjust_large_object() instead of bounds-checking the pointer after the fact. --- src/runtime/gencgc.c | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/src/runtime/gencgc.c b/src/runtime/gencgc.c index 27cca07..c082d38 100644 --- a/src/runtime/gencgc.c +++ b/src/runtime/gencgc.c @@ -2310,21 +2310,22 @@ preserve_pointer(void *addr) /* Adjust any large objects before promotion as they won't be * copied after promotion. */ if (page_table[first_page].large_object) { - maybe_adjust_large_object(page_address(first_page)); - /* If a large object has shrunk then addr may now point to a - * free area in which case it's ignored here. Note it gets - * through the valid pointer test above because the tail looks - * like conses. */ - if (page_free_p(addr_page_index) - || (page_table[addr_page_index].bytes_used == 0) - /* Check the offset within the page. */ - || (((uword_t)addr & (GENCGC_CARD_BYTES - 1)) - > page_table[addr_page_index].bytes_used)) { - FSHOW((stderr, - "weird? ignore ptr 0x%x to freed area of large object\n", - addr)); + /* Large objects (specifically vectors and bignums) can + * shrink, leaving a "tail" of zeroed space, which appears to + * the filter above as a seris of valid conses, both car and + * cdr of which contain the fixnum zero, but will be + * deallocated when the GC shrinks the large object region to + * fit the object within. We allow raw pointers within code + * space, but for boxed and unboxed space we do not, nor do + * pointers to within a non-code object appear valid above. A + * cons cell will never merit allocation to a large object + * page, so pick them off now, before we try to adjust the + * object. */ + if ((lowtag_of((lispobj)addr) == LIST_POINTER_LOWTAG) && + !code_page_p(first_page)) { return; } + maybe_adjust_large_object(page_address(first_page)); /* It may have moved to unboxed pages. */ region_allocation = page_table[first_page].allocated; } -- 1.7.10.4