Skip to content

Commit

Permalink
[boehm] Add toggleref support for boehm. This is line by line port of…
Browse files Browse the repository at this point in the history
… the sgen code, so keep them in sync.
  • Loading branch information
kumpera committed Feb 26, 2014
1 parent 2136f8f commit ae15e93
Show file tree
Hide file tree
Showing 5 changed files with 173 additions and 1 deletion.
1 change: 1 addition & 0 deletions libgc/darwin_stop_world.c
Expand Up @@ -580,6 +580,7 @@ void GC_stop_world()


if (GC_notify_event) if (GC_notify_event)
GC_notify_event (GC_EVENT_PRE_STOP_WORLD); GC_notify_event (GC_EVENT_PRE_STOP_WORLD);
GC_process_togglerefs ();


# if DEBUG_THREADS # if DEBUG_THREADS
GC_printf1("Stopping the world from 0x%lx\n", mach_thread_self()); GC_printf1("Stopping the world from 0x%lx\n", mach_thread_self());
Expand Down
164 changes: 163 additions & 1 deletion libgc/finalize.c
Expand Up @@ -307,6 +307,164 @@ signed_word * log_size_ptr;
return(0); return(0);
} }


/* toggleref support */
typedef struct {
GC_PTR strong_ref;
GC_hidden_pointer weak_ref;
} GCToggleRef;

static int (*GC_toggleref_callback) (GC_PTR obj);
static GCToggleRef *GC_toggleref_array;
static int GC_toggleref_array_size;
static int GC_toggleref_array_capacity;


void
GC_process_togglerefs (void)
{
int i, w;
int toggle_ref_counts [3] = { 0, 0, 0 };

for (i = w = 0; i < GC_toggleref_array_size; ++i) {
int res;
GCToggleRef r = GC_toggleref_array [i];

GC_PTR obj;

if (r.strong_ref)
obj = r.strong_ref;
else if (r.weak_ref)
obj = REVEAL_POINTER (r.weak_ref);
else
continue;

res = GC_toggleref_callback (obj);
++toggle_ref_counts [res];
switch (res) {
case 0:
break;
case 1:
GC_toggleref_array [w].strong_ref = obj;
GC_toggleref_array [w].weak_ref = (GC_hidden_pointer)NULL;
++w;
break;
case 2:
GC_toggleref_array [w].strong_ref = NULL;
GC_toggleref_array [w].weak_ref = HIDE_POINTER (obj);
++w;
break;
default:
ABORT("Invalid callback result");
}
}

for (i = w; i < GC_toggleref_array_size; ++i) {
GC_toggleref_array [w].strong_ref = NULL;
GC_toggleref_array [w].weak_ref = (GC_hidden_pointer)NULL;
}

GC_toggleref_array_size = w;
}


static void push_and_mark_object (GC_PTR p)
{
hdr * hhdr = HDR(p);

PUSH_OBJ((word *)p, hhdr, GC_mark_stack_top,
&(GC_mark_stack[GC_mark_stack_size]));

while (!GC_mark_stack_empty()) MARK_FROM_MARK_STACK();
GC_set_mark_bit (p);
if (GC_mark_state != MS_NONE)
while (!GC_mark_some((ptr_t)0)) {}
}

static void GC_mark_togglerefs ()
{
int i;
if (!GC_toggleref_array)
return;

GC_set_mark_bit (GC_toggleref_array);
for (i = 0; i < GC_toggleref_array_size; ++i) {
if (GC_toggleref_array [i].strong_ref) {
GC_PTR object = GC_toggleref_array [i].strong_ref;

push_and_mark_object (object);
}
}
}

static void GC_clear_togglerefs ()
{
int i;
for (i = 0; i < GC_toggleref_array_size; ++i) {
if (GC_toggleref_array [i].weak_ref) {
GC_PTR object = REVEAL_POINTER (GC_toggleref_array [i].weak_ref);

if (!GC_is_marked (object)) {
GC_toggleref_array [i].weak_ref = (GC_hidden_pointer)NULL; /* We defer compaction to only happen on the callback step. */
} else {
/*No need to copy, boehm is non-moving */
}
}
}
}



void GC_toggleref_register_callback(int (*proccess_toggleref) (GC_PTR obj))
{
GC_toggleref_callback = proccess_toggleref;
}

static void
ensure_toggleref_capacity (int capacity)
{
if (!GC_toggleref_array) {
GC_toggleref_array_capacity = 32;
GC_toggleref_array = (GCToggleRef *) GC_INTERNAL_MALLOC (GC_toggleref_array_capacity * sizeof (GCToggleRef), NORMAL);
}
if (GC_toggleref_array_size + capacity >= GC_toggleref_array_capacity) {
GCToggleRef *tmp;
int old_capacity = GC_toggleref_array_capacity;
while (GC_toggleref_array_capacity < GC_toggleref_array_size + capacity)
GC_toggleref_array_capacity *= 2;

tmp = (GCToggleRef *) GC_INTERNAL_MALLOC (GC_toggleref_array_capacity * sizeof (GCToggleRef), NORMAL);
memcpy (tmp, GC_toggleref_array, GC_toggleref_array_size * sizeof (GCToggleRef));

GC_free((GC_PTR)GC_toggleref_array);
GC_toggleref_array = tmp;
}
}

void
GC_toggleref_add (GC_PTR object, int strong_ref)
{
DCL_LOCK_STATE;
# ifdef THREADS
DISABLE_SIGNALS();
LOCK();
# endif

if (!GC_toggleref_callback)
goto end;

ensure_toggleref_capacity (1);
GC_toggleref_array [GC_toggleref_array_size].strong_ref = strong_ref ? object : NULL;
GC_toggleref_array [GC_toggleref_array_size].weak_ref = strong_ref ? (GC_hidden_pointer)NULL : HIDE_POINTER (object);
++GC_toggleref_array_size;

end:
# ifdef THREADS
UNLOCK();
ENABLE_SIGNALS();
# endif
}




# if defined(__STDC__) || defined(__cplusplus) # if defined(__STDC__) || defined(__cplusplus)
int GC_register_long_link(GC_PTR * link, GC_PTR obj) int GC_register_long_link(GC_PTR * link, GC_PTR obj)
Expand Down Expand Up @@ -679,7 +837,9 @@ void GC_finalize()
ptr_t real_ptr; ptr_t real_ptr;
register int i; register int i;
int fo_size = (log_fo_table_size == -1 ) ? 0 : (1 << log_fo_table_size); int fo_size = (log_fo_table_size == -1 ) ? 0 : (1 << log_fo_table_size);


GC_mark_togglerefs();

/* Make non-tracking disappearing links disappear */ /* Make non-tracking disappearing links disappear */
GC_make_disappearing_links_disappear(&GC_dl_hashtbl); GC_make_disappearing_links_disappear(&GC_dl_hashtbl);


Expand Down Expand Up @@ -755,6 +915,8 @@ void GC_finalize()
/* Remove dangling disappearing links. */ /* Remove dangling disappearing links. */
GC_remove_dangling_disappearing_links(&GC_dl_hashtbl); GC_remove_dangling_disappearing_links(&GC_dl_hashtbl);


GC_clear_togglerefs ();

/* Make long links disappear and remove dangling ones. */ /* Make long links disappear and remove dangling ones. */
GC_make_disappearing_links_disappear(&GC_ll_hashtbl); GC_make_disappearing_links_disappear(&GC_ll_hashtbl);
GC_remove_dangling_disappearing_links(&GC_ll_hashtbl); GC_remove_dangling_disappearing_links(&GC_ll_hashtbl);
Expand Down
5 changes: 5 additions & 0 deletions libgc/include/gc.h
Expand Up @@ -769,6 +769,11 @@ GC_API int GC_unregister_disappearing_link GC_PROTO((GC_PTR * /* link */));
GC_API int GC_register_long_link GC_PROTO((GC_PTR * /* link */, GC_PTR obj)); GC_API int GC_register_long_link GC_PROTO((GC_PTR * /* link */, GC_PTR obj));
GC_API int GC_unregister_long_link GC_PROTO((GC_PTR * /* link */)); GC_API int GC_unregister_long_link GC_PROTO((GC_PTR * /* link */));



/* toggleref support */
GC_API void GC_toggleref_register_callback GC_PROTO((int (*proccess_toggleref) (GC_PTR obj)));
GC_API void GC_toggleref_add (GC_PTR object, int strong_ref);

/* Returns !=0 if GC_invoke_finalizers has something to do. */ /* Returns !=0 if GC_invoke_finalizers has something to do. */
GC_API int GC_should_invoke_finalizers GC_PROTO((void)); GC_API int GC_should_invoke_finalizers GC_PROTO((void));


Expand Down
3 changes: 3 additions & 0 deletions libgc/include/private/gc_priv.h
Expand Up @@ -1688,6 +1688,9 @@ void GC_finalize GC_PROTO((void));
/* for processing by GC_invoke_finalizers. */ /* for processing by GC_invoke_finalizers. */
/* Invoked with lock. */ /* Invoked with lock. */


void GC_process_togglerefs (void);
/*Process the togglerefs before GC starts */

void GC_notify_or_invoke_finalizers GC_PROTO((void)); void GC_notify_or_invoke_finalizers GC_PROTO((void));
/* If GC_finalize_on_demand is not set, invoke */ /* If GC_finalize_on_demand is not set, invoke */
/* eligible finalizers. Otherwise: */ /* eligible finalizers. Otherwise: */
Expand Down
1 change: 1 addition & 0 deletions libgc/pthread_stop_world.c
Expand Up @@ -611,6 +611,7 @@ void GC_stop_world()
{ {
if (GC_notify_event) if (GC_notify_event)
GC_notify_event (GC_EVENT_PRE_STOP_WORLD); GC_notify_event (GC_EVENT_PRE_STOP_WORLD);
GC_process_togglerefs ();
/* Make sure all free list construction has stopped before we start. */ /* Make sure all free list construction has stopped before we start. */
/* No new construction can start, since free list construction is */ /* No new construction can start, since free list construction is */
/* required to acquire and release the GC lock before it starts, */ /* required to acquire and release the GC lock before it starts, */
Expand Down

0 comments on commit ae15e93

Please sign in to comment.