Skip to content

Commit

Permalink
Checkpoint: Skip blocks of pages allocated by third parties
Browse files Browse the repository at this point in the history
  • Loading branch information
kg committed May 6, 2024
1 parent 97ac907 commit 30a2abf
Show file tree
Hide file tree
Showing 2 changed files with 50 additions and 8 deletions.
44 changes: 42 additions & 2 deletions src/mono/mono/utils/mono-wasm-pagemgr.c
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,12 @@ transition_page_states (mwpm_page_state from_state, mwpm_page_state to_state, ui
// effect, so we need to make sure that it's harmless to try and unmap pages we
// don't control. We can't use memset since it might trample UNKNOWN pages.
for (uint32_t i = first_page; i <= last_page; i++) {
if (page_table[i] != from_state)
mwpm_page_state page_state = page_table[i];
// Normalize skip data
if (page_state > MWPM_UNKNOWN)
page_state = MWPM_UNKNOWN;

if (page_state != from_state)
continue;

page_table[i] = to_state;
Expand Down Expand Up @@ -120,6 +125,28 @@ print_stats () {
#endif
}

static void
optimize_unknown_pages (uint8_t *start, uint8_t *end) {
g_assert (end > start);

uint32_t first_page = first_page_from_address (start),
page_count = page_count_from_size (end - start);

for (uint32_t i = 0, skip_count = page_count - 1; i < page_count; i++, skip_count--) {
uint32_t j = i + first_page, skip_value = MWPM_UNKNOWN + skip_count;
if (skip_value > 255)
skip_value = 255;
g_assert (page_table[j] >= MWPM_UNKNOWN);
g_print (
"#%u = %u ",
j, skip_value
);
page_table[j] = skip_value;
}

g_print ("\n");
}

static void *
acquire_new_pages_initialized (uint32_t page_count) {
if (page_count < 1)
Expand Down Expand Up @@ -147,6 +174,8 @@ acquire_new_pages_initialized (uint32_t page_count) {
if (prev_waste_start && (prev_waste_end == allocation)) {
recovered_bytes = allocation - prev_waste_start;
allocation = prev_waste_start;
} else {
optimize_unknown_pages (prev_waste_end, allocation);
}

uint8_t *result = allocation;
Expand Down Expand Up @@ -207,7 +236,18 @@ find_n_free_pages_in_range (uint32_t start_scan_where, uint32_t end_scan_where,
// Scan backwards from the last candidate page to look for any non-free pages
// the first non-free page we find is the next place we will search from.
for (; j >= i; j--) {
if (page_table[j] < MWPM_FREE_ZEROED) {
mwpm_page_state page_state = page_table[j];
if (page_state > MWPM_UNKNOWN) {
// Skip multiple pages
uint32_t skip_count = page_state - MWPM_UNKNOWN;
i = j + skip_count;
g_print (
"scan skipping %u unknown page(s); new page is #%u with state %u\n",
skip_count, i, page_table[i]
);
found_obstruction = 1;
break;
} else if (page_state >= MWPM_ALLOCATED) {
i = j + 1;
found_obstruction = 1;
break;
Expand Down
14 changes: 8 additions & 6 deletions src/mono/mono/utils/mono-wasm-pagemgr.h
Original file line number Diff line number Diff line change
Expand Up @@ -57,14 +57,16 @@
#define MWPM_MINIMUM_PAGE_COUNT 32

typedef enum {
// We don't know the state of this page
MWPM_UNKNOWN = 0,
// We control this page, it's in use
MWPM_ALLOCATED,
// We control this page, it's unused, and it's zeroed (fresh pages)
MWPM_FREE_ZEROED,
MWPM_FREE_ZEROED = 0,
// We control this page, it's unused, and it contains garbage
MWPM_FREE_DIRTY,
MWPM_FREE_DIRTY = 1,
// We control this page, it's in use
MWPM_ALLOCATED = 2,
// We don't know the state of this page
MWPM_UNKNOWN = 3,
// Values above MWPM_UNKNOWN indicate that the page is followed by more
// UNKNOWN pages and you can skip them by subtracting 3
} mwpm_page_state;

// Allocate enough pages to hold size bytes of data, optionally ensuring they are zeroed.
Expand Down

0 comments on commit 30a2abf

Please sign in to comment.