Chez Scheme: fix check on reference displacement

There is no danger of a displcement going off the end of an allocaiton
page, but the reason is a little more subtle for a 32-bit platform.
This commit is contained in:
Matthew Flatt 2021-05-10 18:05:39 -06:00
parent 7a81ff13c2
commit 7c27ef2ab0
4 changed files with 19 additions and 7 deletions

View File

@ -244,7 +244,7 @@ ptr S_find_more_gc_room(thread_gc *tgc, ISPC s, IGEN g, iptr n, ptr old) {
tgc->during_alloc += 1;
nsegs = (uptr)(n + ptr_bytes + bytes_per_segment - 1) >> segment_offset_bits;
nsegs = (uptr)(n + allocation_segment_tail_padding + bytes_per_segment - 1) >> segment_offset_bits;
/* block requests to minimize fragmentation and improve cache locality */
if (s == space_code && nsegs < 16) nsegs = 16;
@ -256,7 +256,7 @@ ptr S_find_more_gc_room(thread_gc *tgc, ISPC s, IGEN g, iptr n, ptr old) {
tgc->base_loc[g][s] = new;
tgc->sweep_loc[g][s] = new;
tgc->bytes_left[g][s] = (new_bytes - n) - ptr_bytes;
tgc->bytes_left[g][s] = (new_bytes - n) - allocation_segment_tail_padding;
tgc->next_loc[g][s] = (ptr)((uptr)new + n);
#if defined(WRITE_XOR_EXECUTE_CODE)

View File

@ -338,8 +338,15 @@ static void idiot_checks() {
fprintf(stderr, "reference displacement does not match bytevector or flvector displacement\n");
oops = 1;
}
if (reference_disp >= (2 * ptr_bytes)) {
fprintf(stderr, "reference displacement is larger than two words\n");
if (reference_disp >= (allocation_segment_tail_padding
/* to determine the minimum distince from the start of an
alocated object to the end of its alloted space, take the
smaller of the allocation alignment or sizeof(double), where
the latter is relevant for a flonum that points into the
imaginary half of an inexactnum */
+ ((byte_alignment < sizeof(double)) ? byte_alignment : sizeof(double)))) {
fprintf(stderr, "reference displacement can extend past the end of an allocation page\n");
oops = 1;
}

View File

@ -666,7 +666,8 @@ static void enable_code_write(ptr tc, IGEN maxg, IBOOL on, IBOOL current, void *
if (addr == NULL) {
return;
}
bytes = (char*)tgc->next_loc[0][space_code] - (char*)tgc->base_loc[0][space_code] + tgc->bytes_left[0][space_code] + ptr_bytes;
bytes = ((char*)tgc->next_loc[0][space_code] - (char*)tgc->base_loc[0][space_code]
+ tgc->bytes_left[0][space_code] + allocation_segment_tail_padding);
if (mprotect(addr, bytes, flags) != 0) {
S_error_abort("failed to protect current allocation segments");
}

View File

@ -112,8 +112,12 @@ FORCEINLINE ptr S_reference_to_object(ptr p) {
return ((ptr)((uptr)(p) - reference_disp));
}
/* We take advantage of the fact `reference_disp` is less than two
words and that every allocation region has a one-word padding, so
/* An allocation region needs room at the end of a formarding pointer
as a terminator */
#define allocation_segment_tail_padding ptr_bytes
/* We take advantage of the fact `reference_disp` is less than the
minimum allocation size plus `allocation_segment_tail_padding`, so
there's no possibility that the referece address for an object will
be off of its GC-managed page (even for a pair or an bytevector
with an empty payload). */