STATIC int GC_CALLBACK GC_finalized_disclaim(void *obj,
void *cd GC_ATTR_UNUSED)
{
- struct GC_finalizer_closure *fc = *(void **)obj;
- if (((word)fc & 1) != 0) {
+ void **fc_addr;
+ struct GC_finalizer_closure *fc;
+ fc_addr = &((void **)obj)[GC_size(obj) / sizeof(void *) - 1];
+ fc = *fc_addr;
+ if (fc != NULL) {
/* [1] The disclaim function may be passed fragments from the */
/* free-list, on which it should not run finalization. */
/* To recognize this case, we use the fact that the first word */
/* which does not use the first word for storing finalization */
/* info, GC_reclaim_with_finalization must be extended to clear */
/* fragments so that the assumption holds for the selected word. */
- fc = (void *)((word)fc & ~(word)1);
- (*fc->proc)((void **)obj + 1, fc->cd);
+ (*fc->proc)(obj, fc->cd);
+ *fc_addr = NULL;
}
return 0;
}
GC_bytes_allocd += GRANULES_TO_BYTES(lg);
UNLOCK();
}
+ ((void **)op)[GRANULES_TO_WORDS(lg) - 1] = fclos;
} else {
op = GC_generic_malloc((word)lb, GC_finalized_kind);
+ ((void **)op)[GC_size(op) / sizeof(void *) - 1] = fclos;
}
- *(void **)op = (ptr_t)fclos + 1; /* See [1] */
- return GC_clear_stack(op + sizeof(void *));
+ return GC_clear_stack(op);
}
#ifdef THREAD_LOCAL_ALLOC
next = obj_link(my_entry);
result = (void *)my_entry;
*my_fl = next;
- *(void **)result = (ptr_t)fclos + 1;
+ obj_link(result) = 0;
+ ((void **)result)[GRANULES_TO_WORDS(lg) - 1] = fclos;
PREFETCH_FOR_WRITE(next);
- return (void **)result + 1;
+ return result;
}
#endif /* THREAD_LOCAL_ALLOC */
#include "gc_disclaim.h"
+int memeq(void *s, int c, size_t len)
+{
+ while (len--) {
+ if (*(char *)s != c)
+ return 0;
+ s = (char *)s + 1;
+ }
+ return 1;
+}
+
+void GC_CALLBACK misc_sizes_dct(void *obj, void *cd)
+{
+ size_t size = (size_t)1 << *(unsigned char *)obj;
+ assert(memeq((char *)obj + 1, 0x56, size - 1));
+}
+
+void
+test_misc_sizes()
+{
+ static struct GC_finalizer_closure fc = { misc_sizes_dct, NULL };
+ int i;
+ for (i = 1; i <= 20; ++i) { /* Up to 1 MiB. */
+ void *p = GC_finalized_malloc((size_t)1 << i, &fc);
+ assert(memeq(p, 0, (size_t)1 << i));
+ memset(p, 0x56, (size_t)1 << i);
+ *(unsigned char *)p = i;
+ }
+}
+
typedef struct pair_s *pair_t;
struct pair_s {
static struct GC_finalizer_closure fc = { pair_dct, NULL };
p = GC_finalized_malloc(sizeof(struct pair_s), &fc);
+ assert(memeq(p, 0, sizeof(struct pair_s)));
p->is_valid = 1;
p->checksum = 782 + (car? car->checksum : 0) + (cdr? cdr->checksum : 0);
p->car = car;
int i;
#endif
+ GC_set_all_interior_pointers(0); /* for a stricter test */
GC_INIT();
GC_init_finalized_malloc();
+ test_misc_sizes();
+
#if THREAD_CNT > 1
printf("Threaded disclaim test.\n");
for (i = 0; i < THREAD_CNT; ++i) {