return (wp_it);
}
-/* Scavenge a generation.
- *
- * This will not resolve all pointers when generation is the new
- * space, as new objects may be added which are not checked here - use
- * scavenge_newspace generation.
+/* Scavenge all generations from FROM to TO, inclusive, except for
+ * new_space which needs special handling, as new objects may be
+ * added which are not checked here - use scavenge_newspace generation.
*
* Write-protected pages should not have any pointers to the
* from_space so do need scavenging; thus write-protected pages are
* pointers as the objects contain a link to the next and are written
* if a weak pointer is scavenged. Still it's a useful check. */
static void
-scavenge_generation(generation_index_t generation)
+scavenge_generations(generation_index_t from, generation_index_t to)
{
page_index_t i;
int num_wp = 0;
#endif
for (i = 0; i < last_free_page; i++) {
+ generation_index_t generation = page_table[i].gen;
if ((page_table[i].allocated & BOXED_PAGE_FLAG)
&& (page_table[i].bytes_used != 0)
- && (page_table[i].gen == generation)) {
+ && (generation != new_space)
+ && (generation >= from)
+ && (generation <= to)) {
page_index_t last_page,j;
int write_protected=1;
static void
write_protect_generation_pages(generation_index_t generation)
{
- page_index_t i;
+ page_index_t start;
gc_assert(generation < SCRATCH_GENERATION);
- for (i = 0; i < last_free_page; i++)
- if ((page_table[i].allocated == BOXED_PAGE_FLAG)
- && (page_table[i].bytes_used != 0)
- && !page_table[i].dont_move
- && (page_table[i].gen == generation)) {
+ for (start = 0; start < last_free_page; start++) {
+ if ((page_table[start].allocated == BOXED_PAGE_FLAG)
+ && (page_table[start].bytes_used != 0)
+ && !page_table[start].dont_move
+ && (page_table[start].gen == generation)) {
void *page_start;
+ page_index_t last;
- page_start = (void *)page_address(i);
+ /* Note the page as protected in the page tables. */
+ page_table[start].write_protected = 1;
+
+ for (last = start + 1; last < last_free_page; last++) {
+ if ((page_table[last].allocated != BOXED_PAGE_FLAG)
+ || (page_table[last].bytes_used == 0)
+ || page_table[last].dont_move
+ || (page_table[last].gen != generation))
+ break;
+ page_table[last].write_protected = 1;
+ }
+
+ page_start = (void *)page_address(start);
os_protect(page_start,
- PAGE_BYTES,
+ PAGE_BYTES * (last - start),
OS_VM_PROT_READ | OS_VM_PROT_EXECUTE);
- /* Note the page as protected in the page tables. */
- page_table[i].write_protected = 1;
+ start = last;
}
+ }
if (gencgc_verbose > 1) {
FSHOW((stderr,
/* All generations but the generation being GCed need to be
* scavenged. The new_space generation needs special handling as
* objects may be moved in - it is handled separately below. */
- for (i = 0; i <= PSEUDO_STATIC_GENERATION; i++) {
- if ((i != generation) && (i != new_space)) {
- scavenge_generation(i);
- }
- }
+ scavenge_generations(generation+1, PSEUDO_STATIC_GENERATION);
/* Finally scavenge the new_space generation. Keep going until no
* more objects are moved into the new generation */