mirror of
https://github.com/ashinn/chibi-scheme.git
synced 2025-05-20 14:19:18 +02:00
more precise heap end checks
This commit is contained in:
parent
3804c0ecb2
commit
ca46c64be5
2 changed files with 72 additions and 20 deletions
88
gc.c
88
gc.c
|
@ -55,6 +55,34 @@ sexp_uint_t sexp_allocated_bytes (sexp ctx, sexp x) {
|
|||
}
|
||||
|
||||
#if SEXP_USE_SAFE_GC_MARK
|
||||
|
||||
#if SEXP_USE_DEBUG_GC > 2
|
||||
int sexp_valid_heap_position(sexp ctx, sexp_heap h, sexp x) {
|
||||
sexp p = sexp_heap_first_block(h), end = sexp_heap_end(h);
|
||||
sexp_free_list q = h->free_list, r;
|
||||
while (p < end) {
|
||||
for (r=q->next; r && ((char*)r<(char*)p); q=r, r=r->next)
|
||||
;
|
||||
if ((char*)r == (char*)p) {
|
||||
p = (sexp) (((char*)p) + r->size);
|
||||
continue;
|
||||
}
|
||||
if (p == x) {
|
||||
return 1;
|
||||
} else if (p > x) {
|
||||
fprintf(stderr, SEXP_BANNER("bad heap position: %p free: %p-%p : %p-%p"),
|
||||
x, q, ((char*)q)+q->size, r, ((char*)r)+r->size);
|
||||
return 0;
|
||||
}
|
||||
p = (sexp) (((char*)p)+sexp_heap_align(sexp_allocated_bytes(ctx, p)));
|
||||
}
|
||||
fprintf(stderr, SEXP_BANNER("bad heap position: %p heap: %p-%p"), x, h, end);
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
#define sexp_valid_heap_position(ctx, h, x) 1
|
||||
#endif
|
||||
|
||||
int sexp_in_heap_p(sexp ctx, sexp x) {
|
||||
sexp_heap h;
|
||||
if ((sexp_uint_t)x & (sexp_heap_align(1)-1)) {
|
||||
|
@ -63,7 +91,7 @@ int sexp_in_heap_p(sexp ctx, sexp x) {
|
|||
}
|
||||
for (h=sexp_context_heap(ctx); h; h=h->next)
|
||||
if (((sexp)h < x) && (x < (sexp)(h->data + h->size)))
|
||||
return 1;
|
||||
return sexp_valid_heap_position(ctx, h, x);
|
||||
fprintf(stderr, SEXP_BANNER("invalid object outside heap: %p"), x);
|
||||
return 0;
|
||||
}
|
||||
|
@ -78,6 +106,8 @@ int sexp_valid_object_type_p (sexp ctx, sexp x) {
|
|||
}
|
||||
return 1;
|
||||
}
|
||||
#else
|
||||
#define sexp_valid_object_type_p(ctx, x) 1
|
||||
#endif
|
||||
|
||||
#if SEXP_USE_HEADER_MAGIC
|
||||
|
@ -120,7 +150,7 @@ void sexp_mark (sexp ctx, sexp x) {
|
|||
for (i=0; i<len; i++)
|
||||
sexp_mark(ctx, p[i]);
|
||||
x = p[len];
|
||||
/* goto loop; */
|
||||
goto loop;
|
||||
sexp_mark(ctx, x);
|
||||
}
|
||||
}
|
||||
|
@ -140,9 +170,9 @@ void sexp_conservative_mark (sexp ctx) {
|
|||
sexp p, end;
|
||||
sexp_free_list q, r;
|
||||
for ( ; h; h=h->next) { /* just scan the whole heap */
|
||||
p = (sexp) (h->data + sexp_heap_align(sexp_sizeof(pair)));
|
||||
p = sexp_heap_first_block(h);
|
||||
q = h->free_list;
|
||||
end = (sexp) ((char*)h->data + h->size - sexp_heap_align(sexp_sizeof(pair)));
|
||||
end = sexp_heap_end(h);
|
||||
while (p < end) {
|
||||
for (r=q->next; r && ((char*)r<(char*)p); q=r, r=r->next)
|
||||
;
|
||||
|
@ -178,9 +208,9 @@ void sexp_reset_weak_references(sexp ctx) {
|
|||
sexp p, t, end, *v;
|
||||
sexp_free_list q, r;
|
||||
for ( ; h; h=h->next) { /* just scan the whole heap */
|
||||
p = (sexp) (h->data + sexp_heap_align(sexp_sizeof(pair)));
|
||||
p = sexp_heap_first_block(h);
|
||||
q = h->free_list;
|
||||
end = (sexp) ((char*)h->data + h->size - sexp_heap_align(sexp_sizeof(pair)));
|
||||
end = sexp_heap_end(h);
|
||||
while (p < end) {
|
||||
/* find the preceding and succeeding free list pointers */
|
||||
for (r=q->next; r && ((char*)r<(char*)p); q=r, r=r->next)
|
||||
|
@ -189,7 +219,7 @@ void sexp_reset_weak_references(sexp ctx) {
|
|||
p = (sexp) (((char*)p) + r->size);
|
||||
continue;
|
||||
}
|
||||
if (sexp_markedp(p)) {
|
||||
if (sexp_valid_object_p(ctx, p) && sexp_markedp(p)) {
|
||||
t = sexp_object_type(ctx, p);
|
||||
if (sexp_type_weak_base(t) > 0) {
|
||||
all_reset_p = 1;
|
||||
|
@ -225,9 +255,9 @@ sexp sexp_sweep (sexp ctx, size_t *sum_freed_ptr) {
|
|||
sexp_proc2 finalizer;
|
||||
/* scan over the whole heap */
|
||||
for ( ; h; h=h->next) {
|
||||
p = (sexp) (h->data + sexp_heap_align(sexp_sizeof(pair)));
|
||||
p = sexp_heap_first_block(h);
|
||||
q = h->free_list;
|
||||
end = (sexp) ((char*)h->data + h->size - sexp_heap_align(sexp_sizeof(pair)));
|
||||
end = sexp_heap_end(h);
|
||||
while (p < end) {
|
||||
/* find the preceding and succeeding free list pointers */
|
||||
for (r=q->next; r && ((char*)r<(char*)p); q=r, r=r->next)
|
||||
|
@ -236,21 +266,24 @@ sexp sexp_sweep (sexp ctx, size_t *sum_freed_ptr) {
|
|||
p = (sexp) (((char*)p) + r->size);
|
||||
continue;
|
||||
}
|
||||
sexp_valid_object_p(ctx, p);
|
||||
size = sexp_heap_align(sexp_allocated_bytes(ctx, p));
|
||||
#if SEXP_USE_DEBUG_GC
|
||||
sexp_valid_object_p(ctx, p);
|
||||
if ((char*)q + q->size > (char*)p)
|
||||
fprintf(stderr, SEXP_BANNER("%p sweep: bad size at %p < %p + %lu"),
|
||||
ctx, p, q, q->size);
|
||||
if (r && ((char*)p)+size > (char*)r)
|
||||
fprintf(stderr, SEXP_BANNER("%p sweep: bad size at %p + %d > %p"),
|
||||
ctx, p, sexp_pointer_tag(p), r);
|
||||
fprintf(stderr, SEXP_BANNER("%p sweep: bad size at %p + %lu > %p"),
|
||||
ctx, p, size, r);
|
||||
#endif
|
||||
if (! sexp_markedp(p)) {
|
||||
if (!sexp_markedp(p)) {
|
||||
/* free p */
|
||||
finalizer = sexp_type_finalize(sexp_object_type(ctx, p));
|
||||
if (finalizer) finalizer(ctx sexp_api_pass(NULL, 1), p);
|
||||
sum_freed += size;
|
||||
if (((((char*)q) + q->size) == (char*)p) && (q != h->free_list)) {
|
||||
/* merge q with p */
|
||||
if (r && ((((char*)p)+size) == (char*)r)) {
|
||||
if (r && r->size && ((((char*)p)+size) == (char*)r)) {
|
||||
/* ... and with r */
|
||||
q->next = r->next;
|
||||
freed = q->size + size + r->size;
|
||||
|
@ -262,7 +295,7 @@ sexp sexp_sweep (sexp ctx, size_t *sum_freed_ptr) {
|
|||
q->size = freed;
|
||||
} else {
|
||||
s = (sexp_free_list)p;
|
||||
if (r && ((((char*)p)+size) == (char*)r)) {
|
||||
if (r && r->size && ((((char*)p)+size) == (char*)r)) {
|
||||
/* merge p with r */
|
||||
s->size = size + r->size;
|
||||
s->next = r->next;
|
||||
|
@ -327,11 +360,19 @@ sexp_heap sexp_make_heap (size_t size, size_t max_size) {
|
|||
h->data = (char*) sexp_heap_align(sizeof(h->data)+(sexp_uint_t)&(h->data));
|
||||
free = h->free_list = (sexp_free_list) h->data;
|
||||
h->next = NULL;
|
||||
next = (sexp_free_list) (((char*)free) + sexp_heap_align(sexp_sizeof(pair)));
|
||||
free->size = 0; /* actually sexp_sizeof(pair) */
|
||||
next = (sexp_free_list) (((char*)free)+sexp_heap_align(sexp_free_chunk_size));
|
||||
free->size = 0; /* actually sexp_heap_align(sexp_free_chunk_size) */
|
||||
free->next = next;
|
||||
next->size = size - sexp_heap_align(sexp_sizeof(pair));
|
||||
next->size = size - sexp_heap_align(sexp_free_chunk_size);
|
||||
next->next = NULL;
|
||||
#if SEXP_USE_DEBUG_GC
|
||||
fprintf(stderr, SEXP_BANNER("heap: %p-%p data: %p-%p"),
|
||||
h, ((char*)h)+sexp_heap_pad_size(size), h->data, h->data + size);
|
||||
fprintf(stderr, SEXP_BANNER("first: %p end: %p"),
|
||||
sexp_heap_first_block(h), sexp_heap_end(h));
|
||||
fprintf(stderr, SEXP_BANNER("free1: %p-%p free2: %p-%p"),
|
||||
free, ((char*)free)+free->size, next, ((char*)next)+next->size);
|
||||
#endif
|
||||
return h;
|
||||
}
|
||||
|
||||
|
@ -350,6 +391,13 @@ void* sexp_try_alloc (sexp ctx, size_t size) {
|
|||
for (h=sexp_context_heap(ctx); h; h=h->next)
|
||||
for (ls1=h->free_list, ls2=ls1->next; ls2; ls1=ls2, ls2=ls2->next)
|
||||
if (ls2->size >= size) {
|
||||
#if SEXP_USE_DEBUG_GC
|
||||
ls3 = (sexp_free_list) sexp_heap_end(h);
|
||||
if (ls2 >= ls3)
|
||||
fprintf(stderr, "alloced %lu bytes past end of heap: %p (%lu) >= %p"
|
||||
" next: %p (%lu)\n", size, ls2, ls2->size, ls3, ls2->next,
|
||||
(ls2->next ? ls2->next->size : 0));
|
||||
#endif
|
||||
if (ls2->size >= (size + SEXP_MINIMUM_OBJECT_SIZE)) {
|
||||
ls3 = (sexp_free_list) (((char*)ls2)+size); /* the tail after ls2 */
|
||||
ls3->size = ls2->size - size;
|
||||
|
@ -367,7 +415,7 @@ void* sexp_try_alloc (sexp ctx, size_t size) {
|
|||
void* sexp_alloc (sexp ctx, size_t size) {
|
||||
void *res;
|
||||
size_t max_freed, sum_freed, total_size;
|
||||
sexp_heap h;
|
||||
sexp_heap h = sexp_context_heap(ctx);
|
||||
size = sexp_heap_align(size);
|
||||
res = sexp_try_alloc(ctx, size);
|
||||
if (! res) {
|
||||
|
@ -431,7 +479,7 @@ sexp sexp_copy_context (sexp ctx, sexp dst, sexp flags) {
|
|||
}
|
||||
|
||||
/* adjust data by traversing over the _original_ heap */
|
||||
p = (sexp) (from->data + sexp_heap_align(sexp_sizeof(pair)));
|
||||
p = (sexp) (from->data + sexp_heap_align(sexp_free_chunk_size));
|
||||
q = from->free_list;
|
||||
while (p < end) {
|
||||
/* find the next free list pointer */
|
||||
|
|
|
@ -149,6 +149,10 @@ typedef int sexp_sint_t;
|
|||
typedef struct sexp_struct *sexp;
|
||||
|
||||
#define sexp_heap_pad_size(s) (sizeof(struct sexp_heap_t) + (s) + sexp_heap_align(1))
|
||||
#define sexp_free_chunk_size (sizeof(struct sexp_free_list_t))
|
||||
#define sexp_heap_first_block(h) ((sexp)(h->data + sexp_heap_align(sexp_free_chunk_size)))
|
||||
#define sexp_heap_last_block(h) ((sexp)((char*)h->data + h->size - sexp_heap_align(sexp_free_chunk_size)))
|
||||
#define sexp_heap_end(h) ((sexp)((char*)h->data + h->size))
|
||||
|
||||
#define __HALF_MAX_SIGNED(type) ((type)1 << (sizeof(type)*8-2))
|
||||
#define __MAX_SIGNED(type) (__HALF_MAX_SIGNED(type) - 1 + __HALF_MAX_SIGNED(type))
|
||||
|
|
Loading…
Add table
Reference in a new issue