From 263ffbbfd303ac0a62e272ff23baa04139f2009b Mon Sep 17 00:00:00 2001 From: Ivan Maidanski Date: Fri, 22 Jun 2018 00:57:09 +0300 Subject: [PATCH] Add GC_reachable_here after GC_END_STUBBORN_CHANGE in tests (fix of commits b52c140d3, f72fc9d43, 08a380c3a) * tests/disclaim_test.c (pair_dct, pair_new): Call GC_reachable_here for the stored pointers after GC_end_stubborn_change call. * tests/staticrootslib.c (libsrl_mktree): Call GC_reachable_here for the stored pointers after GC_END_STUBBORN_CHANGE call. * tests/test.c (cons, small_cons, small_cons_uncollectable, mktree, typed_test): Likewise. * tests/test.c [GC_GCJ_SUPPORT] (gcj_cons): Likewise. * tests/test.c [!SMALL_CONFIG && !GC_DEBUG] (alloc8bytes): Likewise. * tests/test_cpp.cc [!DONT_USE_STD_ALLOCATOR] (main): Likewise. * tests/trace_test.c (mktree): Likewise. * tests/test.c (reverse_test_inner): Declare tmp local variable; call GC_END_STUBBORN_CHANGE() and GC_reachable_here() after storing pointers to f[5], g[799] and h[1999]. * tests/test_cpp.cc (C_INIT_LEFT_RIGHT): New macro (to call GC_END_STUBBORN_CHANGE and GC_reachable_here). * tests/test_cpp.cc (C::C): Use C_INIT_LEFT_RIGHT(). * tests/test_cpp.cc (main): Remove GC_end_stubborn_change(c) call after because GC_END_STUBBORN_CHANGE() is now called for this (in C_INIT_LEFT_RIGHT) of the heap-allocated objects. --- tests/disclaim_test.c | 3 ++ tests/staticrootslib.c | 13 ++++++--- tests/test.c | 76 +++++++++++++++++++++++++++++++++++++------------- tests/test_cpp.cc | 37 ++++++++++++------------ tests/trace_test.c | 14 +++++++--- 5 files changed, 98 insertions(+), 45 deletions(-) diff --git a/tests/disclaim_test.c b/tests/disclaim_test.c index 8cfb539..0a67892 100644 --- a/tests/disclaim_test.c +++ b/tests/disclaim_test.c @@ -129,6 +129,7 @@ void GC_CALLBACK pair_dct(void *obj, void *cd) p->car = (pair_t)cd; p->cdr = NULL; GC_end_stubborn_change(p); + GC_reachable_here(cd); } pair_t @@ -149,6 +150,8 @@ pair_new(pair_t car, pair_t cdr) p->car = car; p->cdr = cdr; GC_end_stubborn_change(p); + 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); diff --git a/tests/staticrootslib.c b/tests/staticrootslib.c index a445a09..c7c0725 100644 --- a/tests/staticrootslib.c +++ b/tests/staticrootslib.c @@ -37,10 +37,15 @@ static struct treenode *root_nz[10] = { (struct treenode *)(GC_word)2 }; if (1 == i) r = (struct treenode *)GC_MALLOC_ATOMIC(sizeof(struct treenode)); if (r) { - r -> x = libsrl_mktree(i-1); - r -> y = libsrl_mktree(i-1); - if (i != 1) - GC_end_stubborn_change(r); + struct treenode *x = libsrl_mktree(i - 1); + struct treenode *y = libsrl_mktree(i - 1); + r -> x = x; + r -> y = y; + if (i != 1) { + GC_END_STUBBORN_CHANGE(r); + GC_reachable_here(x); + GC_reachable_here(y); + } } return r; } diff --git a/tests/test.c b/tests/test.c index cdded72..9a9780b 100644 --- a/tests/test.c +++ b/tests/test.c @@ -326,7 +326,9 @@ sexpr cons (sexpr x, sexpr y) r -> sexpr_car = x; r -> sexpr_cdr = y; GC_END_STUBBORN_CHANGE(r); - return(r); + GC_reachable_here(x); + GC_reachable_here(y); + return r; } # endif @@ -382,7 +384,9 @@ sexpr small_cons (sexpr x, sexpr y) r -> sexpr_car = x; r -> sexpr_cdr = y; GC_END_STUBBORN_CHANGE(r); - return(r); + GC_reachable_here(x); + GC_reachable_here(y); + return r; } #ifdef NO_CONS_ATOMIC_LEAF @@ -409,7 +413,8 @@ sexpr small_cons_uncollectable (sexpr x, sexpr y) r -> sexpr_car = x; r -> sexpr_cdr = (sexpr)(~(GC_word)y); GC_END_STUBBORN_CHANGE(r); - return(r); + GC_reachable_here(x); + return r; } #ifdef GC_GCJ_SUPPORT @@ -427,7 +432,9 @@ sexpr small_cons_uncollectable (sexpr x, sexpr y) result -> sexpr_car = x; result -> sexpr_cdr = y; GC_END_STUBBORN_CHANGE(r); - return(result); + GC_reachable_here(x); + GC_reachable_here(y); + return result; } #endif /* GC_GCJ_SUPPORT */ @@ -708,6 +715,7 @@ 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. */ @@ -745,26 +753,42 @@ 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); - f[5] = ints(1,17); + tmp = ints(1,17); + f[5] = tmp; + GC_END_STUBBORN_CHANGE(f + 5); + GC_reachable_here(tmp); 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); - g[799] = ints(1,18); + tmp = ints(1,18); + g[799] = tmp; + GC_END_STUBBORN_CHANGE(g + 799); + GC_reachable_here(tmp); 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 - h[1999] = gcj_ints(1,200); - for (i = 0; i < 51; ++i) - h[1999] = gcj_reverse(h[1999]); + tmp = gcj_ints(1,200); + h[1999] = tmp; + GC_END_STUBBORN_CHANGE(h + 1999); + GC_reachable_here(tmp); + for (i = 0; i < 51; ++i) { + tmp = gcj_reverse(h[1999]); + h[1999] = tmp; + GC_END_STUBBORN_CHANGE(h + 1999); + GC_reachable_here(tmp); + } /* Leave it as the reversed list for now. */ # else - h[1999] = ints(1,200); + tmp = ints(1,200); + h[1999] = tmp; + GC_END_STUBBORN_CHANGE(h + 1999); + GC_reachable_here(tmp); # endif /* Try to force some collections and reuse of small list elements */ for (i = 0; i < 10; i++) { @@ -813,7 +837,10 @@ void *GC_CALLBACK reverse_test_inner(void *data) check_ints(f[5], 1,17); check_ints(g[799], 1,18); # ifdef GC_GCJ_SUPPORT - h[1999] = gcj_reverse(h[1999]); + tmp = gcj_reverse(h[1999]); + h[1999] = tmp; + GC_END_STUBBORN_CHANGE(h + 1999); + GC_reachable_here(tmp); # endif check_ints(h[1999], 1,200); # ifndef THREADS @@ -878,6 +905,7 @@ int live_indicators_count = 0; tn * mktree(int n) { tn * result = GC_NEW(tn); + tn * left, * right; AO_fetch_and_add1(&collectable_count); # if defined(MACOS) @@ -891,20 +919,21 @@ tn * mktree(int n) if (n == 0) return(0); CHECK_OUT_OF_MEMORY(result); result -> level = n; - result -> lchild = mktree(n-1); - result -> rchild = mktree(n-1); + 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; - tn * left = result -> lchild; - tn * right = result -> rchild; + tn * tmp, * right_left; CHECK_OUT_OF_MEMORY(left); tmp = left -> rchild; CHECK_OUT_OF_MEMORY(right); - left -> rchild = right -> lchild; + 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); } if (AO_fetch_and_add1(&extra_count) % 119 == 0) { # ifndef GC_NO_FINALIZATION @@ -996,6 +1025,8 @@ tn * mktree(int n) GC_reachable_here(result); } GC_END_STUBBORN_CHANGE(result); + GC_reachable_here(left); + GC_reachable_here(right); return(result); } @@ -1035,6 +1066,7 @@ void * alloc8bytes(void) # else void ** my_free_list_ptr; void * my_free_list; + void * next; my_free_list_ptr = (void **)pthread_getspecific(fl_key); if (my_free_list_ptr == 0) { @@ -1051,9 +1083,11 @@ void * alloc8bytes(void) my_free_list = GC_malloc_many(8); CHECK_OUT_OF_MEMORY(my_free_list); } - *my_free_list_ptr = GC_NEXT(my_free_list); + next = GC_NEXT(my_free_list); + *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 @@ -1123,7 +1157,7 @@ void tree_test(void) } dropped_something = 1; FINALIZER_UNLOCK(); - GC_noop1((word)root); /* Root needs to remain live until */ + GC_reachable_here(root); /* Root needs to remain live until */ /* dropped_something is set. */ root = mktree(TREE_HEIGHT); chktree(root, TREE_HEIGHT); @@ -1199,6 +1233,7 @@ void typed_test(void) newP[0] = 17; newP[1] = (GC_word)old; GC_END_STUBBORN_CHANGE(newP); + GC_reachable_here(old); old = newP; AO_fetch_and_add1(&collectable_count); newP = (GC_word*)GC_malloc_explicitly_typed(33 * sizeof(GC_word), d3); @@ -1206,6 +1241,7 @@ void typed_test(void) newP[0] = 17; newP[1] = (GC_word)old; GC_END_STUBBORN_CHANGE(newP); + GC_reachable_here(old); old = newP; AO_fetch_and_add1(&collectable_count); newP = (GC_word *)GC_calloc_explicitly_typed(4, 2 * sizeof(GC_word), @@ -1214,6 +1250,7 @@ void typed_test(void) newP[0] = 17; newP[1] = (GC_word)old; GC_END_STUBBORN_CHANGE(newP); + GC_reachable_here(old); old = newP; AO_fetch_and_add1(&collectable_count); if (i & 0xff) { @@ -1232,6 +1269,7 @@ void typed_test(void) newP[0] = 17; newP[1] = (GC_word)old; GC_END_STUBBORN_CHANGE(newP); + GC_reachable_here(old); old = newP; } for (i = 0; i < 20000; i++) { diff --git a/tests/test_cpp.cc b/tests/test_cpp.cc index 493ec33..840442f 100644 --- a/tests/test_cpp.cc +++ b/tests/test_cpp.cc @@ -104,6 +104,18 @@ class B: public GC_NS_QUALIFY(gc), public A { public: int B::deleting = 0; +#define C_INIT_LEFT_RIGHT(arg_l, arg_r) \ + { \ + C *l = new C(arg_l); \ + C *r = new C(arg_r); \ + left = l; \ + right = r; \ + if (GC_is_heap_ptr(this)) { \ + GC_END_STUBBORN_CHANGE(this); \ + GC_reachable_here(l); \ + GC_reachable_here(r); \ + } \ + } class C: public GC_NS_QUALIFY(gc_cleanup), public A { public: /* A collectible class with cleanup and virtual multiple inheritance. */ @@ -112,12 +124,8 @@ class C: public GC_NS_QUALIFY(gc_cleanup), public A { public: // a copy constructor and an assignment operator to workaround a cppcheck // warning. C(const C& c) : A(c.i), level(c.level), left(0), right(0) { - if (level > 0) { - left = new C(*c.left); - right = new C(*c.right); - GC_end_stubborn_change(left); - GC_end_stubborn_change(right); - } + if (level > 0) + C_INIT_LEFT_RIGHT(*c.left, *c.right); } C& operator=(const C& c) { @@ -128,12 +136,8 @@ class C: public GC_NS_QUALIFY(gc_cleanup), public A { public: level = c.level; left = 0; right = 0; - if (level > 0) { - left = new C(*c.left); - right = new C(*c.right); - GC_end_stubborn_change(left); - GC_end_stubborn_change(right); - } + if (level > 0) + C_INIT_LEFT_RIGHT(*c.left, *c.right); } return *this; } @@ -141,10 +145,7 @@ class C: public GC_NS_QUALIFY(gc_cleanup), public A { public: GC_ATTR_EXPLICIT C( int levelArg ): A( levelArg ), level( levelArg ) { nAllocated++; if (level > 0) { - left = new C( level - 1 ); - right = new C( level - 1 ); - GC_end_stubborn_change(left); - GC_end_stubborn_change(right); + C_INIT_LEFT_RIGHT(level - 1, level - 1); } else { left = right = 0;}} ~C() { @@ -319,7 +320,8 @@ void* Undisguise( GC_word i ) { exit(3); } *xptr = x; - GC_end_stubborn_change(xptr); + GC_END_STUBBORN_CHANGE(xptr); + GC_reachable_here(x); x = 0; # endif if (argc != 2 @@ -345,7 +347,6 @@ void* Undisguise( GC_word i ) { Later we'll check to make sure they've gone away. */ for (i = 0; i < 1000; i++) { C* c = new C( 2 ); - GC_end_stubborn_change(c); C c1( 2 ); /* stack allocation should work too */ D* d; F* f; diff --git a/tests/trace_test.c b/tests/trace_test.c index 1bcf07b..726519d 100644 --- a/tests/trace_test.c +++ b/tests/trace_test.c @@ -15,6 +15,7 @@ struct treenode { struct treenode * mktree(int i) { struct treenode * r = GC_NEW(struct treenode); + struct treenode *x, *y; if (0 == i) return 0; if (1 == i) @@ -23,10 +24,15 @@ struct treenode * mktree(int i) { fprintf(stderr, "Out of memory\n"); exit(1); } - r -> x = mktree(i-1); - r -> y = mktree(i-1); - if (i != 1) - GC_end_stubborn_change(r); + x = mktree(i - 1); + y = mktree(i - 1); + r -> x = x; + r -> y = y; + if (i != 1) { + GC_END_STUBBORN_CHANGE(r); + GC_reachable_here(x); + GC_reachable_here(y); + } return r; } -- 2.7.4