summaryrefslogtreecommitdiff
path: root/fnlz_mlc.c
diff options
context:
space:
mode:
authorPetter Urkedal <paurkedal@gmail.com>2012-01-17 04:51:35 +0800
committerIvan Maidanski <ivmai@mail.ru>2012-01-18 14:47:24 +0800
commit63fd11df9468ac94373ba74e7bd4a97b9cc4044b (patch)
tree5dc088f624b53ac2375f4b9e4a31b7c9a3d3b35c /fnlz_mlc.c
parent293d927f27280b8e371384dd530d5df3e8536672 (diff)
downloadbdwgc-63fd11df9468ac94373ba74e7bd4a97b9cc4044b.tar.gz
Move finalizer closure to the end of objects.
* fnlz_mlc.c: Move finalizer closure for finalized object kinds to the end of objects. This way, we don't require all interior pointers, and GC_base returns the expected address. * tests/disclaim_test.c: Improve test coverage.
Diffstat (limited to 'fnlz_mlc.c')
-rw-r--r--fnlz_mlc.c21
1 files changed, 13 insertions, 8 deletions
diff --git a/fnlz_mlc.c b/fnlz_mlc.c
index 4c7a4501..e79605d7 100644
--- a/fnlz_mlc.c
+++ b/fnlz_mlc.c
@@ -29,8 +29,11 @@ STATIC int GC_finalized_kind = 0;
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 */
@@ -39,8 +42,8 @@ STATIC int GC_CALLBACK GC_finalized_disclaim(void *obj,
/* 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;
}
@@ -95,11 +98,12 @@ GC_API void GC_CALL GC_init_finalized_malloc(void)
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
@@ -143,9 +147,10 @@ GC_API void GC_CALL GC_init_finalized_malloc(void)
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 */