GC finalization bug fix

Matthias Hopf (@Home) mshopf at ftpamiga.dialin.rrze.uni-erlangen.de
Tue May 27 01:04:22 PDT 1997


Hi!

I have invested quite some time to investigate an obscure bug I noticed
within the garbage collector. When compiling GetInterfaces.java in
test/regression, Sun's compiler class would just enter an infinite loop.
However, this was not the case on my friends' computers.


What happened is the following:

After the main garbage collection a white memory block contained an object
that needed finalization. The garbage collector walked this object in order
to preserve potentially addressed objects (kaffevm/gc-incremental.c:319-).

The walked object seemed to have a reference to another white object, that
happened to be in the same memory block. Thus this object was greyed, and
the block was moved to the grey list.

Now as the GC tried to continue with the next block, it was stuck in the grey
list. Because the termination expression could never be fullfilled, it looped
endlessly...


It's possible that other wired garbage collector problems had the same
source. Well, now, find a patch enclosed which fixes the problem. I think
that was the most important sentence of this mail ;^)

The patch is not tested in incremental mode, but as the code is the same as
for non-incremental mode, there shouldn't be any noticable differences.


BTW - the patch also includes two Makefile.in that seemed to be lost -
'make distclean' at least needed them...
And there's a (small) patch for test/Makefile.in for cleaning up
test/regression included, too.

CU

Matthias

-- 
    //             |   Matthias Hopf - "Hoeppel"   |    _      __
\\ //    Amiga     |  student of computer science  |  _|cience |-iction
 \X/ by conviction |      in Erlangen/Germany      | by belief in Future

 EMail:  mshopf at informatik.uni-erlangen.de
 Aminet: ftpamiga at epix.rrze.uni-erlangen.de
 WWW:    http://wwwcip.informatik.uni-erlangen.de/user/mshopf/

-------------- next part --------------
diff -bcrN amiga_kaffe-0.9.0/kaffe/kaffevm/gc-incremental.c gc_kaffe-0.9.0/kaffe/kaffevm/gc-incremental.c
*** amiga_kaffe-0.9.0/kaffe/kaffevm/gc-incremental.c	Mon May 12 21:22:48 1997
--- gc_kaffe-0.9.0/kaffe/kaffevm/gc-incremental.c	Tue May 27 00:04:39 1997
***************
*** 251,257 ****
  void
  gcMan(void)
  {
! 	gc_block* info;
  	int idx;
  
  	/* All threads start with interrupts disabled */
--- 251,257 ----
  void
  gcMan(void)
  {
! 	gc_block *info, *lastinfo, *testinfo;
  	int idx;
  
  	/* All threads start with interrupts disabled */
***************
*** 287,298 ****
--- 287,326 ----
  		 * be live just in case.
  		 */
  		for (info = white.cnext; info != &white; info = info->cnext) {
+ 			lastinfo = NULL;
  			for (idx = 0; idx < info->nr; idx++) {
  				if (GC_GET_STATE(info, idx) == GC_STATE_NEEDFINALIZE) {
  					gcStats.markedobj += 1;
+ 					if (! lastinfo) {
+ 						lastinfo = info->cprev;
+ 					}
  					(*GC_GET_FUNCS(info, idx)->walk)(GCBLOCK2MEM(info, idx), GCBLOCKSIZE(info));
  				}
  			}
+ 			/* Now check whether we have been moved to the grey
+ 			 * list again, if that is the case, we may not just
+ 			 * continue scanning because we would now scan the
+ 			 * grey list...
+ 			 * Instead we continue scaning from the successor of
+ 			 * the block scaned before this block when available.
+ 			 */
+ 			if (lastinfo) {
+ 				for (testinfo = grey.cnext; testinfo != &grey; testinfo = testinfo->cnext) {
+ 					if (info == testinfo) {
+ 						/* we're moved to grey list */
+ 						for (info = white.cnext; info != &white; info = info->cnext) {
+ 							if (info == lastinfo) {
+ 								break;
+ 							}
+ 						}
+ 						/* info is now either &white
+ 						 * (restart scaning when
+ 						 * lastinfo not found) or
+ 						 * the last scaned block */
+ 						break;
+ 					}
+ 				}
+ 			}
  		}
  
  		/* We may now have more grey objects, so walk them */
***************
*** 321,332 ****
--- 349,388 ----
  		 * be live just in case.
  		 */
  		for (info = white.cnext; info != &white; info = info->cnext) {
+ 			lastinfo = NULL;
  			for (idx = 0; idx < info->nr; idx++) {
  				if (GC_GET_STATE(info, idx) == GC_STATE_NEEDFINALIZE) {
  					gcStats.markedobj += 1;
+ 					if (! lastinfo) {
+ 						lastinfo = info->cprev;
+ 					}
  					(*GC_GET_FUNCS(info, idx)->walk)(GCBLOCK2MEM(info, idx), GCBLOCKSIZE(info));
  				}
  			}
+ 			/* Now check whether we have been moved to the grey
+ 			 * list again, if that is the case, we may not just
+ 			 * continue scanning because we would now scan the
+ 			 * grey list...
+ 			 * Instead we continue scaning from the successor of
+ 			 * the block scaned before this block when available.
+ 			 */
+ 			if (lastinfo) {
+ 				for (testinfo = grey.cnext; testinfo != &grey; testinfo = testinfo->cnext) {
+ 					if (info == testinfo) {
+ 						/* we're moved to grey list */
+ 						for (info = white.cnext; info != &white; info = info->cnext) {
+ 							if (info == lastinfo) {
+ 								break;
+ 							}
+ 						}
+ 						/* info is now either &white
+ 						 * (restart scaning when
+ 						 * lastinfo not found) or
+ 						 * the last scaned block */
+ 						break;
+ 					}
+ 				}
+ 			}
  		}
  
  		/* We may now have more grey objects, so walk them */
diff -bcrN amiga_kaffe-0.9.0/packages/tjwassoc.co.uk/APIcore/classes/Makefile.in gc_kaffe-0.9.0/packages/tjwassoc.co.uk/APIcore/classes/Makefile.in
*** amiga_kaffe-0.9.0/packages/tjwassoc.co.uk/APIcore/classes/Makefile.in	Wed Dec 31 23:00:00 1969
--- gc_kaffe-0.9.0/packages/tjwassoc.co.uk/APIcore/classes/Makefile.in	Wed Apr 16 08:12:26 1997
***************
*** 0 ****
--- 1,19 ----
+ # Build a Java library.
+ #
+ # Copyright (c) 1997 T. J. Wilkinson & Associates, London, UK.
+ #
+ # See the file "license.terms" for information on usage and redistribution
+ # of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ #
+ # Written by Tim Wilkinson <tim at tjwassoc.demon.co.uk>, 1997.
+ 
+ all:
+ 
+ all-classes:
+ 
+ clean:
+ 
+ distclean:
+ 		rm -f Makefile
+ 
+ install:
diff -bcrN amiga_kaffe-0.9.0/packages/tjwassoc.co.uk/APInet/classes/Makefile.in gc_kaffe-0.9.0/packages/tjwassoc.co.uk/APInet/classes/Makefile.in
*** amiga_kaffe-0.9.0/packages/tjwassoc.co.uk/APInet/classes/Makefile.in	Wed Dec 31 23:00:00 1969
--- gc_kaffe-0.9.0/packages/tjwassoc.co.uk/APInet/classes/Makefile.in	Wed Apr 16 08:12:26 1997
***************
*** 0 ****
--- 1,19 ----
+ # Build a Java library.
+ #
+ # Copyright (c) 1997 T. J. Wilkinson & Associates, London, UK.
+ #
+ # See the file "license.terms" for information on usage and redistribution
+ # of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ #
+ # Written by Tim Wilkinson <tim at tjwassoc.demon.co.uk>, 1997.
+ 
+ all:
+ 
+ all-classes:
+ 
+ clean:
+ 
+ distclean:
+ 		rm -f Makefile
+ 
+ install:
diff -bcrN amiga_kaffe-0.9.0/test/Makefile.in gc_kaffe-0.9.0/test/Makefile.in
*** amiga_kaffe-0.9.0/test/Makefile.in	Wed Apr 16 08:11:14 1997
--- gc_kaffe-0.9.0/test/Makefile.in	Mon May 26 23:58:14 1997
***************
*** 28,32 ****
--- 28,33 ----
  
  distclean:
  		rm -f *.class Makefile kaffe.core core
+ 		rm -f regression/*.class
  
  install:
-------------- next part --------------
Mon May 26 23:10:24 MET1 1997   Matthias Hopf   <mshopf at informatik.uni-erlangen.de>

	* kaffevm/gc-incremental.c: fixed wired GC finalization bug that
	  could get the GC into a livelock.
	* {APIcore,APInet}/classes/Makefile.in: added lost files
	* test/Makefile.in: cleaning up regression now.



More information about the kaffe mailing list