diff --git a/racket/src/ChezScheme/c/alloc.c b/racket/src/ChezScheme/c/alloc.c index ed9b89c089..172f2eba96 100644 --- a/racket/src/ChezScheme/c/alloc.c +++ b/racket/src/ChezScheme/c/alloc.c @@ -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) diff --git a/racket/src/ChezScheme/c/scheme.c b/racket/src/ChezScheme/c/scheme.c index d2c2d1c565..d9af390a6c 100644 --- a/racket/src/ChezScheme/c/scheme.c +++ b/racket/src/ChezScheme/c/scheme.c @@ -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; } diff --git a/racket/src/ChezScheme/c/segment.c b/racket/src/ChezScheme/c/segment.c index 39faab489f..5f4608dbd5 100644 --- a/racket/src/ChezScheme/c/segment.c +++ b/racket/src/ChezScheme/c/segment.c @@ -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"); } diff --git a/racket/src/ChezScheme/c/segment.h b/racket/src/ChezScheme/c/segment.h index ce2a5e085a..5dbd3a4833 100644 --- a/racket/src/ChezScheme/c/segment.h +++ b/racket/src/ChezScheme/c/segment.h @@ -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). */