summaryrefslogtreecommitdiff
path: root/fnlz_mlc.c
diff options
context:
space:
mode:
authorPetter Urkedal <paurkedal@gmail.com>2014-05-25 15:57:03 +0200
committerIvan Maidanski <ivmai@mail.ru>2014-05-31 12:51:37 +0400
commit2a3cef3fa4c428ffd25b72b5190cbd3d8e35caa0 (patch)
treeb53d80fa080e5ff337ddbb9b0eb57f4b0693403b /fnlz_mlc.c
parent7b0be4885117b95a169274fd922680eb20d43ce8 (diff)
downloadbdwgc-2a3cef3fa4c428ffd25b72b5190cbd3d8e35caa0.tar.gz
Fix GC_finalized_malloc failure on disclaim_test
(revert part of commit 63fd11d) The finalizer closure is placed in the first word in order to use the lower bits to distinguish live objects from objects on the free list. The downside of this is that we need one-word offset interior pointers, and that GC_base does not return the start of the user region. * fnlz_mlc.c (GC_finalized_disclaim): Move finalizer closure for finalized object kinds back to the start of objects. * fnlz_mlc.c (GC_init_finalized_malloc): Call GC_register_displacement_inner() as GC_finalized_malloc returns displaced pointer. * fnlz_mlc.c (GC_core_finalized_malloc, GC_finalized_malloc): Store fclos in first word of created object (instead of the last word); return pointer to object displaced by 1 word.
Diffstat (limited to 'fnlz_mlc.c')
-rw-r--r--fnlz_mlc.c33
1 files changed, 18 insertions, 15 deletions
diff --git a/fnlz_mlc.c b/fnlz_mlc.c
index 5eb168a3..c191fbc7 100644
--- a/fnlz_mlc.c
+++ b/fnlz_mlc.c
@@ -28,13 +28,10 @@ STATIC int GC_finalized_kind = 0;
STATIC int GC_CALLBACK GC_finalized_disclaim(void *obj)
{
- void **fc_addr;
- const struct GC_finalizer_closure *fc;
+ word fc_word = *(word *)obj;
- 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 */
+ if ((fc_word & 1) != 0) {
+ /* 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 */
/* on such fragments are always even (a link to the next */
@@ -42,8 +39,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->proc)(obj, fc->cd);
- *fc_addr = NULL;
+ const struct GC_finalizer_closure *fc = (void *)(fc_word & ~(word)1);
+ (*fc->proc)((word *)obj + 1, fc->cd);
}
return 0;
}
@@ -62,6 +59,13 @@ GC_API void GC_CALL GC_init_finalized_malloc(void)
}
done_init = TRUE;
+ /* The finalizer closure is placed in the first word in order to */
+ /* use the lower bits to distinguish live objects from objects on */
+ /* the free list. The downside of this is that we need one-word */
+ /* offset interior pointers, and that GC_base does not return the */
+ /* start of the user region. */
+ GC_register_displacement_inner(sizeof(word));
+
GC_finalized_objfreelist = (ptr_t *)GC_new_free_list_inner();
GC_finalized_kind = GC_new_kind_inner((void **)GC_finalized_objfreelist,
GC_DS_LENGTH, TRUE, TRUE);
@@ -89,7 +93,7 @@ GC_API void GC_CALL GC_register_disclaim_proc(int kind, GC_disclaim_proc proc,
word lg;
DCL_LOCK_STATE;
- lb += sizeof(void *);
+ lb += sizeof(word);
GC_ASSERT(done_init);
if (SMALL_OBJ(lb)) {
GC_DBG_COLLECT_AT_MALLOC(lb);
@@ -110,7 +114,6 @@ GC_API void GC_CALL GC_register_disclaim_proc(int kind, GC_disclaim_proc proc,
UNLOCK();
}
GC_ASSERT(lg > 0);
- ((const void **)op)[GRANULES_TO_WORDS(lg) - 1] = fclos;
} else {
size_t op_sz;
@@ -119,16 +122,16 @@ GC_API void GC_CALL GC_register_disclaim_proc(int kind, GC_disclaim_proc proc,
return NULL;
op_sz = GC_size(op);
GC_ASSERT(op_sz >= lb);
- ((const void **)op)[op_sz / sizeof(void *) - 1] = fclos;
}
- return GC_clear_stack(op);
+ *(word *)op = (word)fclos | 1;
+ return GC_clear_stack((word *)op + 1);
}
#ifdef THREAD_LOCAL_ALLOC
GC_API GC_ATTR_MALLOC void * GC_CALL GC_finalized_malloc(size_t client_lb,
const struct GC_finalizer_closure *fclos)
{
- size_t lb = client_lb + sizeof(void *);
+ size_t lb = client_lb + sizeof(word);
size_t lg = ROUNDED_UP_GRANULES(lb);
GC_tlfs tsd;
void *result;
@@ -161,9 +164,9 @@ GC_API void GC_CALL GC_register_disclaim_proc(int kind, GC_disclaim_proc proc,
result = (void *)my_entry;
*my_fl = next;
obj_link(result) = 0;
- ((const void **)result)[GRANULES_TO_WORDS(lg) - 1] = fclos;
+ *(word *)result = (word)fclos | 1;
PREFETCH_FOR_WRITE(next);
- return result;
+ return (word *)result + 1;
}
#endif /* THREAD_LOCAL_ALLOC */