New public API (PTR_STORE_AND_DIRTY) to simplify store-and-dirty operation
authorIvan Maidanski <ivmai@mail.ru>
Sun, 1 Jul 2018 13:53:15 +0000 (16:53 +0300)
committerIvan Maidanski <ivmai@mail.ru>
Sun, 1 Jul 2018 13:53:15 +0000 (16:53 +0300)
* 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.

cord/cordbscs.c
cord/tests/de.c
dbg_mlc.c
include/gc.h
include/gc_inline.h
mallocx.c
tests/disclaim_test.c
tests/test.c
tests/test_cpp.cc

index 7979ff7..117dd9f 100644 (file)
@@ -231,10 +231,8 @@ CORD CORD_cat_char_star(CORD x, const char * y, size_t leny)
             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);
         GC_reachable_here(x);
-        GC_reachable_here(y);
         if (depth >= MAX_DEPTH) {
             return(CORD_balance((CORD)result));
         } else {
@@ -275,10 +273,8 @@ CORD CORD_cat(CORD x, CORD y)
             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);
         GC_reachable_here(x);
-        GC_reachable_here(y);
         if (depth >= MAX_DEPTH) {
             return(CORD_balance((CORD)result));
         } else {
@@ -318,9 +314,7 @@ static CordRep *CORD_from_fn_inner(CORD_fn fn, void * client_data, size_t len)
         /* 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;
     }
 }
@@ -369,10 +363,8 @@ CORD CORD_substr_closure(CORD x, size_t i, size_t n, CORD_fn f)
     CordRep * result;
 
     if (sa == 0) OUT_OF_MEMORY;
-    sa->sa_cord = (CordRep *)x;
     sa->sa_index = i;
-    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;
index 522da91..2fd8c48 100644 (file)
@@ -139,9 +139,7 @@ void prune_map(void)
         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);
@@ -158,9 +156,7 @@ void add_map(int line_arg, size_t pos)
     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++;
 }
@@ -260,9 +256,7 @@ void replace_line(int i, CORD s)
                 addch(c);
             }
         }
-        screen[i] = s;
-        GC_END_STUBBORN_CHANGE(screen + i);
-        GC_reachable_here(s);
+        GC_PTR_STORE_AND_DIRTY(screen + i, s);
     }
 }
 #else
index 0471662..50eda33 100644 (file)
--- a/dbg_mlc.c
+++ b/dbg_mlc.c
@@ -630,6 +630,13 @@ GC_API void GC_CALL GC_debug_end_stubborn_change(const void *p)
     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)
 {
index cfe9f6b..fd3e426 100644 (file)
@@ -960,6 +960,7 @@ GC_API /* 'realloc' attr */ GC_ATTR_ALLOC_SIZE(2) void * GC_CALL
 # 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)))
@@ -986,6 +987,7 @@ GC_API /* 'realloc' attr */ GC_ATTR_ALLOC_SIZE(2) void * GC_CALL
 # 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) \
@@ -1635,6 +1637,14 @@ GC_API void GC_CALL GC_dump_finalization(void);
 # 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 */);
index 6527c3e..9dc783d 100644 (file)
@@ -194,10 +194,8 @@ GC_API GC_ATTR_MALLOC GC_ATTR_ALLOC_SIZE(1) void * GC_CALL
       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(l); \
-        GC_reachable_here(r); \
       } \
     } while (0)
 
index 6888609..a318d5b 100644 (file)
--- a/mallocx.c
+++ b/mallocx.c
@@ -628,3 +628,10 @@ GC_API void GC_CALL GC_end_stubborn_change(const void *p)
 {
   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);
+}
index 0a67892..5176bee 100644 (file)
@@ -126,10 +126,8 @@ void GC_CALLBACK pair_dct(void *obj, void *cd)
     /* Invalidate it. */
     memset(p->magic, '*', sizeof(p->magic));
     p->checksum = 0;
-    p->car = (pair_t)cd;
     p->cdr = NULL;
-    GC_end_stubborn_change(p);
-    GC_reachable_here(cd);
+    GC_ptr_store_and_dirty(&p->car, cd);
 }
 
 pair_t
@@ -148,10 +146,8 @@ pair_new(pair_t car, pair_t cdr)
     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(car);
-    GC_reachable_here(cdr);
 #   ifdef DEBUG_DISCLAIM_DESTRUCT
       printf("Construct %p = (%p, %p)\n",
              (void *)p, (void *)p->car, (void *)p->cdr);
index 9a9780b..bda3834 100644 (file)
@@ -324,10 +324,8 @@ sexpr cons (sexpr x, sexpr y)
         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);
     GC_reachable_here(x);
-    GC_reachable_here(y);
     return r;
 }
 # endif
@@ -382,10 +380,8 @@ sexpr small_cons (sexpr x, sexpr y)
     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);
     GC_reachable_here(x);
-    GC_reachable_here(y);
     return r;
 }
 
@@ -410,10 +406,8 @@ sexpr small_cons_uncollectable (sexpr x, sexpr y)
 
     CHECK_OUT_OF_MEMORY(r);
     AO_fetch_and_add1(&uncollectable_count);
-    r -> sexpr_car = x;
     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);
     return r;
 }
 
@@ -430,10 +424,8 @@ sexpr small_cons_uncollectable (sexpr x, sexpr y)
     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);
     GC_reachable_here(x);
-    GC_reachable_here(y);
     return result;
   }
 #endif /* GC_GCJ_SUPPORT */
@@ -715,7 +707,6 @@ void *GC_CALLBACK reverse_test_inner(void *data)
     sexpr d;
     sexpr e;
     sexpr *f, *g, *h;
-    sexpr tmp;
 
     if (data == 0) {
       /* This stack frame is not guaranteed to be scanned. */
@@ -753,42 +744,27 @@ void *GC_CALLBACK reverse_test_inner(void *data)
     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);
-    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
-      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) {
-        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
-      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++) {
@@ -837,10 +813,7 @@ void *GC_CALLBACK reverse_test_inner(void *data)
     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
@@ -922,18 +895,13 @@ tn * mktree(int n)
     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;
+        tn * tmp;
 
         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
@@ -1084,10 +1052,8 @@ void * alloc8bytes(void)
         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_END_STUBBORN_CHANGE(my_free_list_ptr);
-    GC_reachable_here(next);
     AO_fetch_and_add1(&collectable_count);
     return(my_free_list);
 # endif
@@ -1231,26 +1197,20 @@ void typed_test(void)
         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;
-        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;
-        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) {
@@ -1267,9 +1227,7 @@ void typed_test(void)
         }
         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++) {
index 43f034b..f97be6f 100644 (file)
@@ -319,9 +319,7 @@ void* Undisguise( GC_word i ) {
         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