diff options
author | Kaz Kylheku <kaz@kylheku.com> | 2019-09-12 20:38:43 -0700 |
---|---|---|
committer | Kaz Kylheku <kaz@kylheku.com> | 2019-09-12 20:38:43 -0700 |
commit | 350cd2e935aafb949892384db1451accf2d398c1 (patch) | |
tree | 8b2b97064c74d808e4a6ac0a2f6db6f46fba3892 /gc.c | |
parent | 71d01ae185d95888e3908cce5dba99890e970931 (diff) | |
download | txr-350cd2e935aafb949892384db1451accf2d398c1.tar.gz txr-350cd2e935aafb949892384db1451accf2d398c1.tar.bz2 txr-350cd2e935aafb949892384db1451accf2d398c1.zip |
gc: align objects more strictly.
In this commit, we ensure that objects in the heap are aligned
to at east eight byte boundaries (the minimum alignment from
most malloc implementations on 32 and 64 bit systems). If
possible, we align objects to a multiple of their size, sizeof
(obj_t), which is 16 bytes on 32 bit platforms and 32 bytes
on 64 bit platforms. We do this by making the object array the
first field of the heap structure, and by allocating it with
an aligned allocator function, if possible.
* configure: detect memory alignment function: either
memalign (preferred) or else posix_memalign (ugly duckling).
We conditionally add either HAVE_MEMALIGN or
HAVE_POSIX_MEMALIGN into config.h.
* gc.c (OBJ_ALIGN): New macro.
(struct heap, heap_t): Put the block member first, so objects
are aligned with the containing heap.
(in_heap): If the pointer is not aligned to a multiple of
OBJ_ALIGN, it can't be a heap object; return zero.
If allocations of the heap are aligned, then we don't need the
additional alignment check in the loop body; if the pointer
lands in the array, then the earlier OBJ_ALIGN check assures
us it must be aligned. If we have only malloc alignment, we
must do the check; the pointer could be to an address
divisible by 8 which is in the middle of an obj_t.
* lib.c: If HAVE_MEMALIGN is true, then include <malloc.h> so
we have it declared.
(memalign): If HAVE_POSIX_MEMALIGN is true,
this static function is defined; it's compatible with the
Glibc memalign. If HAVE_MEMALIGN and HAVE_POSIX_MEMALIGN are
false, then memalign is defined as a malloc wrapper which
doesn't align.
(chk_malloc_gc_more): Use memalign instead of malloc. If
aligned allocation is available, this will cause the heap to
be aligned to a multiple of the object size.
Diffstat (limited to 'gc.c')
-rw-r--r-- | gc.c | 21 |
1 files changed, 18 insertions, 3 deletions
@@ -57,9 +57,15 @@ #define STACK_TOP_EXTRA_WORDS 0 #endif +#if HAVE_MEMALIGN || HAVE_POSIX_MEMALIGN +#define OBJ_ALIGN (sizeof (obj_t)) +#else +#define OBJ_ALIGN 8 +#endif + typedef struct heap { - struct heap *next; obj_t block[HEAP_SIZE]; + struct heap *next; } heap_t; typedef struct mach_context { @@ -427,13 +433,22 @@ static int in_heap(val ptr) if (!is_ptr(ptr)) return 0; + if (coerce(uint_ptr_t, ptr) % OBJ_ALIGN != 0) + return 0; + if (ptr < heap_min_bound || ptr >= heap_max_bound) return 0; for (heap = heap_list; heap != 0; heap = heap->next) { - if (ptr >= heap->block && ptr < heap->block + HEAP_SIZE) - if ((coerce(char *, ptr) - coerce(char *, heap->block)) % sizeof (obj_t) == 0) + if (ptr >= heap->block && ptr < heap->block + HEAP_SIZE) { +#if HAVE_MEMALIGN || HAVE_POSIX_MEMALIGN + return 1; +#else + if ((coerce(char *, ptr) - + coerce(char *, heap->block)) % sizeof (obj_t) == 0) return 1; +#endif + } } return 0; |