-
-/* to copy large unboxed objects
- *
- * If the object is in a large object region then it is simply
- * promoted, else it is copied. If it's large enough then it's copied
- * to a large object region.
- *
- * Bignums and vectors may have shrunk. If the object is not copied
- * the space needs to be reclaimed, and the page_tables corrected.
- *
- * KLUDGE: There's a lot of cut-and-paste duplication between this
- * function and copy_large_object(..). -- WHN 20000619 */
-lispobj
-copy_large_unboxed_object(lispobj object, long nwords)
-{
- int tag;
- lispobj *new;
- page_index_t first_page;
-
- gc_assert(is_lisp_pointer(object));
- gc_assert(from_space_p(object));
- gc_assert((nwords & 0x01) == 0);
-
- if ((nwords > 1024*1024) && gencgc_verbose) {
- FSHOW((stderr, "/copy_large_unboxed_object: %d bytes\n",
- nwords*N_WORD_BYTES));
- }
-
- /* Check whether it's a large object. */
- first_page = find_page_index((void *)object);
- gc_assert(first_page >= 0);
-
- if (page_table[first_page].large_object) {
- /* Promote the object. Note: Unboxed objects may have been
- * allocated to a BOXED region so it may be necessary to
- * change the region to UNBOXED. */
- unsigned long remaining_bytes;
- page_index_t next_page;
- unsigned long bytes_freed;
- unsigned long old_bytes_used;
-
- gc_assert(page_table[first_page].region_start_offset == 0);
-
- next_page = first_page;
- remaining_bytes = nwords*N_WORD_BYTES;
- while (remaining_bytes > GENCGC_CARD_BYTES) {
- gc_assert(page_table[next_page].gen == from_space);
- gc_assert(page_allocated_no_region_p(next_page));
- gc_assert(page_table[next_page].large_object);
- gc_assert(page_table[next_page].region_start_offset ==
- npage_bytes(next_page-first_page));
- gc_assert(page_table[next_page].bytes_used == GENCGC_CARD_BYTES);
-
- page_table[next_page].gen = new_space;
- page_table[next_page].allocated = UNBOXED_PAGE_FLAG;
- remaining_bytes -= GENCGC_CARD_BYTES;
- next_page++;
- }
-
- /* Now only one page remains, but the object may have shrunk so
- * there may be more unused pages which will be freed. */
-
- /* Object may have shrunk but shouldn't have grown - check. */
- gc_assert(page_table[next_page].bytes_used >= remaining_bytes);
-
- page_table[next_page].gen = new_space;
- page_table[next_page].allocated = UNBOXED_PAGE_FLAG;
-
- /* Adjust the bytes_used. */
- old_bytes_used = page_table[next_page].bytes_used;
- page_table[next_page].bytes_used = remaining_bytes;
-
- bytes_freed = old_bytes_used - remaining_bytes;
-
- /* Free any remaining pages; needs care. */
- next_page++;
- while ((old_bytes_used == GENCGC_CARD_BYTES) &&
- (page_table[next_page].gen == from_space) &&
- page_allocated_no_region_p(next_page) &&
- page_table[next_page].large_object &&
- (page_table[next_page].region_start_offset ==
- npage_bytes(next_page - first_page))) {
- /* Checks out OK, free the page. Don't need to both zeroing
- * pages as this should have been done before shrinking the
- * object. These pages shouldn't be write-protected, even if
- * boxed they should be zero filled. */
- gc_assert(page_table[next_page].write_protected == 0);
-
- old_bytes_used = page_table[next_page].bytes_used;
- page_table[next_page].allocated = FREE_PAGE_FLAG;
- page_table[next_page].bytes_used = 0;
- bytes_freed += old_bytes_used;
- next_page++;
- }
-
- if ((bytes_freed > 0) && gencgc_verbose) {
- FSHOW((stderr,
- "/copy_large_unboxed bytes_freed=%d\n",
- bytes_freed));
- }
-
- generations[from_space].bytes_allocated -=
- nwords*N_WORD_BYTES + bytes_freed;
- generations[new_space].bytes_allocated += nwords*N_WORD_BYTES;
- bytes_allocated -= bytes_freed;
-
- return(object);
- }
- else {
- /* Get tag of object. */
- tag = lowtag_of(object);
-
- /* Allocate space. */
- new = gc_quick_alloc_large_unboxed(nwords*N_WORD_BYTES);
-
- /* Copy the object. */
- memcpy(new,native_pointer(object),nwords*N_WORD_BYTES);
-
- /* Return Lisp pointer of new object. */
- return ((lispobj) new) | tag;
- }
-}
-
-
-