565ea704f9
Resolves: #1101996 Version: 7.4.0-4
119 lines
4.6 KiB
Diff
119 lines
4.6 KiB
Diff
From 33535060b4898c7883c3d98c4591bfc964541830 Mon Sep 17 00:00:00 2001
|
|
From: Petter Urkedal <paurkedal@gmail.com>
|
|
Date: Sun, 25 May 2014 15:57:03 +0200
|
|
Subject: [PATCH 1/3] 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.
|
|
---
|
|
|
|
diff --git a/fnlz_mlc.c b/fnlz_mlc.c
|
|
old mode 100755
|
|
new mode 100644
|
|
index 0dad28a..b8478d2
|
|
--- 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);
|
|
@@ -90,7 +94,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);
|
|
@@ -112,7 +116,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;
|
|
|
|
@@ -121,16 +124,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 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;
|
|
@@ -163,9 +166,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 */
|
|
|