summaryrefslogtreecommitdiff
path: root/finalize.c
diff options
context:
space:
mode:
authorIvan Maidanski <ivmai@mail.ru>2015-08-28 23:21:23 +0300
committerIvan Maidanski <ivmai@mail.ru>2015-08-28 23:21:23 +0300
commitc0eb996c6d77a08cfe143fcbf7416673be712509 (patch)
treef12f0ecc67fd98ae0db577984f155290e1d9198f /finalize.c
parent86991cba3cbce83bfd3a0619f11f86cc1ee56917 (diff)
downloadbdwgc-c0eb996c6d77a08cfe143fcbf7416673be712509.tar.gz
Reduce GCToggleRef size twice (convert struct to union)
* finalize.c (GCToggleRef): Replace struct with union; update comment. * finalize.c (GC_process_togglerefs): Check lowest bit of strong_ref to select between strong_ref and weak_ref. * finalize.c (GC_mark_togglerefs, GC_clear_togglerefs): Likewise. * finalize.c (GC_process_togglerefs): Store only strong_ref or weak_ref to GC_toggleref_arr elements. * finalize.c (GC_toggleref_add): Likewise.
Diffstat (limited to 'finalize.c')
-rw-r--r--finalize.c35
1 files changed, 14 insertions, 21 deletions
diff --git a/finalize.c b/finalize.c
index 986d5e51..429f37ee 100644
--- a/finalize.c
+++ b/finalize.c
@@ -262,8 +262,8 @@ GC_API int GC_CALL GC_unregister_disappearing_link(void * * link)
/* Toggle-ref support. */
#ifndef GC_TOGGLE_REFS_NOT_NEEDED
- typedef struct {
- /* Only one of the two fields can be non-NULL at a time. */
+ typedef union {
+ /* Lowest bit is used to distinguish between choices. */
void *strong_ref;
GC_hidden_pointer weak_ref;
} GCToggleRef;
@@ -283,25 +283,20 @@ GC_API int GC_CALL GC_unregister_disappearing_link(void * * link)
GCToggleRef r = GC_toggleref_arr[i];
void *obj = r.strong_ref;
+ if (((word)obj & 1) != 0) {
+ obj = GC_REVEAL_POINTER(r.weak_ref);
+ }
if (NULL == obj) {
- if (r.weak_ref != 0) {
- obj = GC_REVEAL_POINTER(r.weak_ref);
- } else {
- continue;
- }
+ continue;
}
switch (GC_toggleref_callback(obj)) {
case GC_TOGGLE_REF_DROP:
break;
case GC_TOGGLE_REF_STRONG:
- GC_toggleref_arr[new_size].strong_ref = obj;
- GC_toggleref_arr[new_size].weak_ref = 0;
- ++new_size;
+ GC_toggleref_arr[new_size++].strong_ref = obj;
break;
case GC_TOGGLE_REF_WEAK:
- GC_toggleref_arr[new_size].strong_ref = NULL;
- GC_toggleref_arr[new_size].weak_ref = GC_HIDE_POINTER(obj);
- ++new_size;
+ GC_toggleref_arr[new_size++].weak_ref = GC_HIDE_POINTER(obj);
break;
default:
ABORT("Bad toggle-ref status returned by callback");
@@ -340,8 +335,9 @@ GC_API int GC_CALL GC_unregister_disappearing_link(void * * link)
/* TODO: Hide GC_toggleref_arr to avoid its marking from roots. */
GC_set_mark_bit(GC_toggleref_arr);
for (i = 0; i < GC_toggleref_array_size; ++i) {
- if (GC_toggleref_arr[i].strong_ref != NULL) {
- push_and_mark_object(GC_toggleref_arr[i].strong_ref);
+ void *obj = GC_toggleref_arr[i].strong_ref;
+ if (obj != NULL && ((word)obj & 1) == 0) {
+ push_and_mark_object(obj);
}
}
}
@@ -350,7 +346,7 @@ GC_API int GC_CALL GC_unregister_disappearing_link(void * * link)
{
int i;
for (i = 0; i < GC_toggleref_array_size; ++i) {
- if (GC_toggleref_arr[i].weak_ref != 0) {
+ if ((GC_toggleref_arr[i].weak_ref & 1) != 0) {
if (!GC_is_marked(GC_REVEAL_POINTER(GC_toggleref_arr[i].weak_ref))) {
GC_toggleref_arr[i].weak_ref = 0;
} else {
@@ -425,11 +421,8 @@ GC_API int GC_CALL GC_unregister_disappearing_link(void * * link)
if (!ensure_toggleref_capacity(1)) {
res = GC_NO_MEMORY;
} else {
- GC_toggleref_arr[GC_toggleref_array_size].strong_ref =
- is_strong_ref ? obj : NULL;
- GC_toggleref_arr[GC_toggleref_array_size].weak_ref =
- is_strong_ref ? 0 : GC_HIDE_POINTER(obj);
- ++GC_toggleref_array_size;
+ GC_toggleref_arr[GC_toggleref_array_size++].strong_ref =
+ is_strong_ref ? obj : (void *)GC_HIDE_POINTER(obj);
}
}
UNLOCK();