* cord/cordbscs.c (CORD_cat_char_star, CORD_cat, CORD_from_fn_inner,
CORD_substr_closure): Replace the last store to the heap-allocated
object, GC_END_STUBBORN_CHANGE() and GC_reachable_here() with
GC_PTR_STORE_AND_DIRTY() call.
* cord/tests/de.c (prune_map, add_map, replace_line): Likewise.
* include/gc_inline.h (GC_CONS): Likewise.
* tests/disclaim_test.c (pair_dct, pair_new): Likewise.
* tests/test.c [!VERY_SMALL_CONFIG] (cons): Likewise.
* tests/test.c (small_cons, small_cons_uncollectable,
reverse_test_inner, mktree): Likewise.
* tests/test.c [GC_GCJ_SUPPORT] (gcj_cons): Likewise.
* tests/test.c [GC_PTHREADS && !SMALL_CONFIG && !GC_DEBUG]
(alloc8bytes): Likewise.
* tests/test.c [!NO_TYPED_TEST] (typed_test): Likewise.
* tests/test_cpp.cc (main): Likewise.
* dbg_mlc.c (GC_debug_ptr_store_and_dirty): Implement.
* mallocx.c (GC_ptr_store_and_dirty): Likewise.
* include/gc.h (GC_PTR_STORE_AND_DIRTY): New public macro.
* include/gc.h (GC_debug_ptr_store_and_dirty, GC_ptr_store_and_dirty):
Declare new public API function; add comment.
* tests/test.c (reverse_test_inner): Remove tmp local variable.
* tests/test.c (mktree): Remove right_left local variable.
result->left_len = (unsigned char)lenx;
result->len = (word)result_len;
result->left = x;
result->left_len = (unsigned char)lenx;
result->len = (word)result_len;
result->left = x;
- result->right = y;
- GC_END_STUBBORN_CHANGE(result);
+ GC_PTR_STORE_AND_DIRTY(&result->right, y);
if (depth >= MAX_DEPTH) {
return(CORD_balance((CORD)result));
} else {
if (depth >= MAX_DEPTH) {
return(CORD_balance((CORD)result));
} else {
result->left_len = (unsigned char)lenx;
result->len = (word)result_len;
result->left = x;
result->left_len = (unsigned char)lenx;
result->len = (word)result_len;
result->left = x;
- result->right = y;
- GC_END_STUBBORN_CHANGE(result);
+ GC_PTR_STORE_AND_DIRTY(&result->right, y);
if (depth >= MAX_DEPTH) {
return(CORD_balance((CORD)result));
} else {
if (depth >= MAX_DEPTH) {
return(CORD_balance((CORD)result));
} else {
/* depth is already 0 */
result->len = (word)len;
result->fn = fn;
/* depth is already 0 */
result->len = (word)len;
result->fn = fn;
- result->client_data = client_data;
- GC_END_STUBBORN_CHANGE(result);
- GC_reachable_here(client_data);
+ GC_PTR_STORE_AND_DIRTY(&result->client_data, client_data);
return (CordRep *)result;
}
}
return (CordRep *)result;
}
}
CordRep * result;
if (sa == 0) OUT_OF_MEMORY;
CordRep * result;
if (sa == 0) OUT_OF_MEMORY;
- sa->sa_cord = (CordRep *)x;
- GC_END_STUBBORN_CHANGE(sa);
- GC_reachable_here(x);
+ GC_PTR_STORE_AND_DIRTY(&sa->sa_cord, x);
result = CORD_from_fn_inner(f, (void *)sa, n);
if ((CORD)result != CORD_EMPTY && 0 == result -> function.null)
result -> function.header = SUBSTR_HDR;
result = CORD_from_fn_inner(f, (void *)sa, n);
if ((CORD)result != CORD_EMPTY && 0 == result -> function.null)
result -> function.header = SUBSTR_HDR;
if (map -> line < start_line - LINES && map -> previous != 0) {
line_map pred = map -> previous -> previous;
if (map -> line < start_line - LINES && map -> previous != 0) {
line_map pred = map -> previous -> previous;
- map -> previous = pred;
- GC_END_STUBBORN_CHANGE(map);
- GC_reachable_here(pred);
+ GC_PTR_STORE_AND_DIRTY(&map->previous, pred);
}
map = map -> previous;
} while (map != 0);
}
map = map -> previous;
} while (map != 0);
new_map -> line = line_arg;
new_map -> pos = pos;
cur_map = current_map;
new_map -> line = line_arg;
new_map -> pos = pos;
cur_map = current_map;
- new_map -> previous = cur_map;
- GC_END_STUBBORN_CHANGE(new_map);
- GC_reachable_here(cur_map);
+ GC_PTR_STORE_AND_DIRTY(&new_map->previous, cur_map);
current_map = new_map;
current_map_size++;
}
current_map = new_map;
current_map_size++;
}
- screen[i] = s;
- GC_END_STUBBORN_CHANGE(screen + i);
- GC_reachable_here(s);
+ GC_PTR_STORE_AND_DIRTY(screen + i, s);
GC_end_stubborn_change(q);
}
GC_end_stubborn_change(q);
}
+GC_API void GC_CALL GC_debug_ptr_store_and_dirty(void *p, const void *q)
+{
+ *(void **)GC_is_visible(p) = GC_is_valid_displacement((void *)q);
+ GC_debug_end_stubborn_change(p);
+ REACHABLE_AFTER_DIRTY(q);
+}
+
GC_API GC_ATTR_MALLOC void * GC_CALL GC_debug_malloc_atomic(size_t lb,
GC_EXTRA_PARAMS)
{
GC_API GC_ATTR_MALLOC void * GC_CALL GC_debug_malloc_atomic(size_t lb,
GC_EXTRA_PARAMS)
{
# define GC_REGISTER_FINALIZER_UNREACHABLE(p, f, d, of, od) \
GC_debug_register_finalizer_unreachable(p, f, d, of, od)
# define GC_END_STUBBORN_CHANGE(p) GC_debug_end_stubborn_change(p)
# define GC_REGISTER_FINALIZER_UNREACHABLE(p, f, d, of, od) \
GC_debug_register_finalizer_unreachable(p, f, d, of, od)
# define GC_END_STUBBORN_CHANGE(p) GC_debug_end_stubborn_change(p)
+# define GC_PTR_STORE_AND_DIRTY(p, q) GC_debug_ptr_store_and_dirty(p, q)
# define GC_GENERAL_REGISTER_DISAPPEARING_LINK(link, obj) \
GC_general_register_disappearing_link(link, \
GC_base((/* no const */ void *)(obj)))
# define GC_GENERAL_REGISTER_DISAPPEARING_LINK(link, obj) \
GC_general_register_disappearing_link(link, \
GC_base((/* no const */ void *)(obj)))
# define GC_REGISTER_FINALIZER_UNREACHABLE(p, f, d, of, od) \
GC_register_finalizer_unreachable(p, f, d, of, od)
# define GC_END_STUBBORN_CHANGE(p) GC_end_stubborn_change(p)
# define GC_REGISTER_FINALIZER_UNREACHABLE(p, f, d, of, od) \
GC_register_finalizer_unreachable(p, f, d, of, od)
# define GC_END_STUBBORN_CHANGE(p) GC_end_stubborn_change(p)
+# define GC_PTR_STORE_AND_DIRTY(p, q) GC_ptr_store_and_dirty(p, q)
# define GC_GENERAL_REGISTER_DISAPPEARING_LINK(link, obj) \
GC_general_register_disappearing_link(link, obj)
# define GC_REGISTER_LONG_LINK(link, obj) \
# define GC_GENERAL_REGISTER_DISAPPEARING_LINK(link, obj) \
GC_general_register_disappearing_link(link, obj)
# define GC_REGISTER_LONG_LINK(link, obj) \
# define GC_PTR_STORE(p, q) (*(void **)(p) = (void *)(q))
#endif
# define GC_PTR_STORE(p, q) (*(void **)(p) = (void *)(q))
#endif
+/* GC_PTR_STORE_AND_DIRTY(p,q) is equivalent to GC_PTR_STORE(p,q) */
+/* followed by GC_END_STUBBORN_CHANGE(p) and GC_reachable_here(q) */
+/* (assuming p and q do not have side effects). */
+GC_API void GC_CALL GC_ptr_store_and_dirty(void * /* p */,
+ const void * /* q */);
+GC_API void GC_CALL GC_debug_ptr_store_and_dirty(void * /* p */,
+ const void * /* q */);
+
/* Functions called to report pointer checking errors */
GC_API void (GC_CALLBACK * GC_same_obj_print_proc)(void * /* p */,
void * /* q */);
/* Functions called to report pointer checking errors */
GC_API void (GC_CALLBACK * GC_same_obj_print_proc)(void * /* p */,
void * /* q */);
GC_MALLOC_WORDS_KIND(result, 2, tiny_fl, GC_I_NORMAL, (void)0); \
if ((result) != NULL) { \
*(void **)(result) = l; \
GC_MALLOC_WORDS_KIND(result, 2, tiny_fl, GC_I_NORMAL, (void)0); \
if ((result) != NULL) { \
*(void **)(result) = l; \
- ((void **)(result))[1] = r; \
- GC_end_stubborn_change(result); \
+ GC_PTR_STORE_AND_DIRTY((void **)(result) + 1, r); \
- GC_reachable_here(r); \
{
GC_dirty(p); /* entire object */
}
{
GC_dirty(p); /* entire object */
}
+
+GC_API void GC_CALL GC_ptr_store_and_dirty(void *p, const void *q)
+{
+ *(const void **)p = q;
+ GC_dirty(p);
+ REACHABLE_AFTER_DIRTY(q);
+}
/* Invalidate it. */
memset(p->magic, '*', sizeof(p->magic));
p->checksum = 0;
/* Invalidate it. */
memset(p->magic, '*', sizeof(p->magic));
p->checksum = 0;
- GC_end_stubborn_change(p);
- GC_reachable_here(cd);
+ GC_ptr_store_and_dirty(&p->car, cd);
memcpy(p->magic, pair_magic, sizeof(p->magic));
p->checksum = 782 + (car? car->checksum : 0) + (cdr? cdr->checksum : 0);
p->car = car;
memcpy(p->magic, pair_magic, sizeof(p->magic));
p->checksum = 782 + (car? car->checksum : 0) + (cdr? cdr->checksum : 0);
p->car = car;
- p->cdr = cdr;
- GC_end_stubborn_change(p);
+ GC_ptr_store_and_dirty(&p->cdr, cdr);
- GC_reachable_here(cdr);
# ifdef DEBUG_DISCLAIM_DESTRUCT
printf("Construct %p = (%p, %p)\n",
(void *)p, (void *)p->car, (void *)p->cdr);
# ifdef DEBUG_DISCLAIM_DESTRUCT
printf("Construct %p = (%p, %p)\n",
(void *)p, (void *)p->car, (void *)p->cdr);
r = (sexpr)((char *)r + (my_extra & ~7));
# endif
r -> sexpr_car = x;
r = (sexpr)((char *)r + (my_extra & ~7));
# endif
r -> sexpr_car = x;
- r -> sexpr_cdr = y;
- GC_END_STUBBORN_CHANGE(r);
+ GC_PTR_STORE_AND_DIRTY(&r->sexpr_cdr, y);
CHECK_OUT_OF_MEMORY(r);
AO_fetch_and_add1(&collectable_count);
r -> sexpr_car = x;
CHECK_OUT_OF_MEMORY(r);
AO_fetch_and_add1(&collectable_count);
r -> sexpr_car = x;
- r -> sexpr_cdr = y;
- GC_END_STUBBORN_CHANGE(r);
+ GC_PTR_STORE_AND_DIRTY(&r->sexpr_cdr, y);
CHECK_OUT_OF_MEMORY(r);
AO_fetch_and_add1(&uncollectable_count);
CHECK_OUT_OF_MEMORY(r);
AO_fetch_and_add1(&uncollectable_count);
r -> sexpr_cdr = (sexpr)(~(GC_word)y);
r -> sexpr_cdr = (sexpr)(~(GC_word)y);
- GC_END_STUBBORN_CHANGE(r);
- GC_reachable_here(x);
+ GC_PTR_STORE_AND_DIRTY(&r->sexpr_car, x);
CHECK_OUT_OF_MEMORY(r);
result = (sexpr)(r + 1);
result -> sexpr_car = x;
CHECK_OUT_OF_MEMORY(r);
result = (sexpr)(r + 1);
result -> sexpr_car = x;
- result -> sexpr_cdr = y;
- GC_END_STUBBORN_CHANGE(r);
+ GC_PTR_STORE_AND_DIRTY(&result->sexpr_cdr, y);
return result;
}
#endif /* GC_GCJ_SUPPORT */
return result;
}
#endif /* GC_GCJ_SUPPORT */
sexpr d;
sexpr e;
sexpr *f, *g, *h;
sexpr d;
sexpr e;
sexpr *f, *g, *h;
if (data == 0) {
/* This stack frame is not guaranteed to be scanned. */
if (data == 0) {
/* This stack frame is not guaranteed to be scanned. */
f = (sexpr *)GC_REALLOC((void *)f, 6 * sizeof(sexpr));
CHECK_OUT_OF_MEMORY(f);
AO_fetch_and_add1(&realloc_count);
f = (sexpr *)GC_REALLOC((void *)f, 6 * sizeof(sexpr));
CHECK_OUT_OF_MEMORY(f);
AO_fetch_and_add1(&realloc_count);
- tmp = ints(1,17);
- f[5] = tmp;
- GC_END_STUBBORN_CHANGE(f + 5);
- GC_reachable_here(tmp);
+ GC_PTR_STORE_AND_DIRTY(f + 5, ints(1, 17));
AO_fetch_and_add1(&collectable_count);
g = (sexpr *)GC_MALLOC(513 * sizeof(sexpr));
test_generic_malloc_or_special(g);
g = (sexpr *)GC_REALLOC((void *)g, 800 * sizeof(sexpr));
CHECK_OUT_OF_MEMORY(g);
AO_fetch_and_add1(&realloc_count);
AO_fetch_and_add1(&collectable_count);
g = (sexpr *)GC_MALLOC(513 * sizeof(sexpr));
test_generic_malloc_or_special(g);
g = (sexpr *)GC_REALLOC((void *)g, 800 * sizeof(sexpr));
CHECK_OUT_OF_MEMORY(g);
AO_fetch_and_add1(&realloc_count);
- tmp = ints(1,18);
- g[799] = tmp;
- GC_END_STUBBORN_CHANGE(g + 799);
- GC_reachable_here(tmp);
+ GC_PTR_STORE_AND_DIRTY(g + 799, ints(1, 18));
AO_fetch_and_add1(&collectable_count);
h = (sexpr *)GC_MALLOC(1025 * sizeof(sexpr));
h = (sexpr *)GC_REALLOC((void *)h, 2000 * sizeof(sexpr));
CHECK_OUT_OF_MEMORY(h);
AO_fetch_and_add1(&realloc_count);
# ifdef GC_GCJ_SUPPORT
AO_fetch_and_add1(&collectable_count);
h = (sexpr *)GC_MALLOC(1025 * sizeof(sexpr));
h = (sexpr *)GC_REALLOC((void *)h, 2000 * sizeof(sexpr));
CHECK_OUT_OF_MEMORY(h);
AO_fetch_and_add1(&realloc_count);
# ifdef GC_GCJ_SUPPORT
- tmp = gcj_ints(1,200);
- h[1999] = tmp;
- GC_END_STUBBORN_CHANGE(h + 1999);
- GC_reachable_here(tmp);
+ GC_PTR_STORE_AND_DIRTY(h + 1999, gcj_ints(1, 200));
for (i = 0; i < 51; ++i) {
for (i = 0; i < 51; ++i) {
- tmp = gcj_reverse(h[1999]);
- h[1999] = tmp;
- GC_END_STUBBORN_CHANGE(h + 1999);
- GC_reachable_here(tmp);
+ GC_PTR_STORE_AND_DIRTY(h + 1999, gcj_reverse(h[1999]));
}
/* Leave it as the reversed list for now. */
# else
}
/* Leave it as the reversed list for now. */
# else
- tmp = ints(1,200);
- h[1999] = tmp;
- GC_END_STUBBORN_CHANGE(h + 1999);
- GC_reachable_here(tmp);
+ GC_PTR_STORE_AND_DIRTY(h + 1999, ints(1, 200));
# endif
/* Try to force some collections and reuse of small list elements */
for (i = 0; i < 10; i++) {
# endif
/* Try to force some collections and reuse of small list elements */
for (i = 0; i < 10; i++) {
check_ints(f[5], 1,17);
check_ints(g[799], 1,18);
# ifdef GC_GCJ_SUPPORT
check_ints(f[5], 1,17);
check_ints(g[799], 1,18);
# ifdef GC_GCJ_SUPPORT
- tmp = gcj_reverse(h[1999]);
- h[1999] = tmp;
- GC_END_STUBBORN_CHANGE(h + 1999);
- GC_reachable_here(tmp);
+ GC_PTR_STORE_AND_DIRTY(h + 1999, gcj_reverse(h[1999]));
# endif
check_ints(h[1999], 1,200);
# ifndef THREADS
# endif
check_ints(h[1999], 1,200);
# ifndef THREADS
result -> lchild = left = mktree(n - 1);
result -> rchild = right = mktree(n - 1);
if (AO_fetch_and_add1(&extra_count) % 17 == 0 && n >= 2) {
result -> lchild = left = mktree(n - 1);
result -> rchild = right = mktree(n - 1);
if (AO_fetch_and_add1(&extra_count) % 17 == 0 && n >= 2) {
- tn * tmp, * right_left;
CHECK_OUT_OF_MEMORY(left);
tmp = left -> rchild;
CHECK_OUT_OF_MEMORY(right);
CHECK_OUT_OF_MEMORY(left);
tmp = left -> rchild;
CHECK_OUT_OF_MEMORY(right);
- right_left = right -> lchild;
- left -> rchild = right_left;
- right -> lchild = tmp;
- GC_END_STUBBORN_CHANGE(left);
- GC_reachable_here(right_left);
- GC_END_STUBBORN_CHANGE(right);
- GC_reachable_here(tmp);
+ GC_PTR_STORE_AND_DIRTY(&left->rchild, right->lchild);
+ GC_PTR_STORE_AND_DIRTY(&right->lchild, tmp);
}
if (AO_fetch_and_add1(&extra_count) % 119 == 0) {
# ifndef GC_NO_FINALIZATION
}
if (AO_fetch_and_add1(&extra_count) % 119 == 0) {
# ifndef GC_NO_FINALIZATION
CHECK_OUT_OF_MEMORY(my_free_list);
}
next = GC_NEXT(my_free_list);
CHECK_OUT_OF_MEMORY(my_free_list);
}
next = GC_NEXT(my_free_list);
- *my_free_list_ptr = next;
+ GC_PTR_STORE_AND_DIRTY(my_free_list_ptr, next);
GC_NEXT(my_free_list) = 0;
GC_NEXT(my_free_list) = 0;
- GC_END_STUBBORN_CHANGE(my_free_list_ptr);
- GC_reachable_here(next);
AO_fetch_and_add1(&collectable_count);
return(my_free_list);
# endif
AO_fetch_and_add1(&collectable_count);
return(my_free_list);
# endif
newP = (GC_word *)GC_malloc_explicitly_typed(4 * sizeof(GC_word), d2);
CHECK_OUT_OF_MEMORY(newP);
newP[0] = 17;
newP = (GC_word *)GC_malloc_explicitly_typed(4 * sizeof(GC_word), d2);
CHECK_OUT_OF_MEMORY(newP);
newP[0] = 17;
- newP[1] = (GC_word)old;
- GC_END_STUBBORN_CHANGE(newP);
- GC_reachable_here(old);
+ GC_PTR_STORE_AND_DIRTY(newP + 1, old);
old = newP;
AO_fetch_and_add1(&collectable_count);
newP = (GC_word*)GC_malloc_explicitly_typed(33 * sizeof(GC_word), d3);
CHECK_OUT_OF_MEMORY(newP);
newP[0] = 17;
old = newP;
AO_fetch_and_add1(&collectable_count);
newP = (GC_word*)GC_malloc_explicitly_typed(33 * sizeof(GC_word), d3);
CHECK_OUT_OF_MEMORY(newP);
newP[0] = 17;
- newP[1] = (GC_word)old;
- GC_END_STUBBORN_CHANGE(newP);
- GC_reachable_here(old);
+ GC_PTR_STORE_AND_DIRTY(newP + 1, old);
old = newP;
AO_fetch_and_add1(&collectable_count);
newP = (GC_word *)GC_calloc_explicitly_typed(4, 2 * sizeof(GC_word),
d1);
CHECK_OUT_OF_MEMORY(newP);
newP[0] = 17;
old = newP;
AO_fetch_and_add1(&collectable_count);
newP = (GC_word *)GC_calloc_explicitly_typed(4, 2 * sizeof(GC_word),
d1);
CHECK_OUT_OF_MEMORY(newP);
newP[0] = 17;
- newP[1] = (GC_word)old;
- GC_END_STUBBORN_CHANGE(newP);
- GC_reachable_here(old);
+ GC_PTR_STORE_AND_DIRTY(newP + 1, old);
old = newP;
AO_fetch_and_add1(&collectable_count);
if (i & 0xff) {
old = newP;
AO_fetch_and_add1(&collectable_count);
if (i & 0xff) {
}
CHECK_OUT_OF_MEMORY(newP);
newP[0] = 17;
}
CHECK_OUT_OF_MEMORY(newP);
newP[0] = 17;
- newP[1] = (GC_word)old;
- GC_END_STUBBORN_CHANGE(newP);
- GC_reachable_here(old);
+ GC_PTR_STORE_AND_DIRTY(newP + 1, old);
old = newP;
}
for (i = 0; i < 20000; i++) {
old = newP;
}
for (i = 0; i < 20000; i++) {
fprintf(stderr, "Out of memory!\n");
exit(3);
}
fprintf(stderr, "Out of memory!\n");
exit(3);
}
- *xptr = x;
- GC_END_STUBBORN_CHANGE(xptr);
- GC_reachable_here(x);
+ GC_PTR_STORE_AND_DIRTY(xptr, x);
x = 0;
# endif
if (argc != 2
x = 0;
# endif
if (argc != 2