More fixes, including a fix to configure-with-threadsafe-mmgc suggested by bsmedberg.
authorjorendorff@mozilla.com
Wed, 28 Nov 2007 14:31:59 -0600
changeset 11 553e043f72afe2b76d49737b9c0b960bc0fb2e0e
parent 10 c5dfb5bb8df559a5a7cb7fc23fa86f23c23e9d33
child 12 af07ce9c5d6110146c21f1fa02909c89a644885b
push id1
push userbsmedberg@mozilla.com
push dateMon, 21 Apr 2008 01:54:18 +0000
More fixes, including a fix to configure-with-threadsafe-mmgc suggested by bsmedberg.
configure-with-threadsafe-mmgc
mmgc-bit-checks
mmgc-decref-microfix
mmgc-graphviz
mmgc-remove-precollect-hook
series
--- a/configure-with-threadsafe-mmgc
+++ b/configure-with-threadsafe-mmgc
@@ -14,44 +14,47 @@ diff --git a/configure b/configure
 +done
 +
 +echo "running $PYTHON $0.py --ignore-unknown-flags $args"
 +
 +eval "'$PYTHON' '$0.py' --ignore-unknown-flags $args"
 diff --git a/configure.py b/configure.py
 --- a/configure.py
 +++ b/configure.py
-@@ -75,14 +75,27 @@ DEBUG_CXXFLAGS = ""
+@@ -75,10 +75,13 @@ DEBUG_CXXFLAGS = ""
  DEBUG_CXXFLAGS = ""
  DEBUG_LDFLAGS = ""
  OS_LIBS = []
 +OS_LDFLAGS = ""
  MMGC_CPPFLAGS = ""
  AVMSHELL_CPPFLAGS = ""
  AVMSHELL_LDFLAGS = ""
  MMGC_DEFINES = {'SOFT_ASSERTS': None}
 +NSPR_INCLUDES = ""
 +NSPR_LDOPTS = ""
  
  MMGC_INTERIOR_PTRS = o.getBoolArg('mmgc-interior-pointers', True)
  if MMGC_INTERIOR_PTRS:
-     MMGC_DEFINES['MMGC_INTERIOR_PTRS'] = None
+@@ -88,6 +91,16 @@ if MMGC_DYNAMIC:
+ if MMGC_DYNAMIC:
+     MMGC_DEFINES['MMGC_DLL'] = None
+     MMGC_CPPFLAGS += "-DMMGC_IMPL "
 +
 +MMGC_THREADSAFE = o.getBoolArg('threadsafe-mmgc', False)
 +if MMGC_THREADSAFE:
 +    MMGC_DEFINES['MMGC_THREADSAFE'] = None
 +    NSPR_INCLUDES = o.getStringArg('nspr-includes')
 +    MMGC_CPPFLAGS += NSPR_INCLUDES + " "
 +    APP_CPPFLAGS += NSPR_INCLUDES + " "
 +
 +    NSPR_LDOPTS = o.getStringArg('nspr-ldopts')
 +    OS_LDFLAGS += " " + NSPR_LDOPTS
  
- MMGC_DYNAMIC = o.getBoolArg('mmgc-shared', False)
- if MMGC_DYNAMIC:
+ if config.COMPILER_IS_GCC:
+     APP_CXXFLAGS = "-fno-exceptions -Werror -Wall -Wno-reorder -Wno-switch -Wno-invalid-offsetof -Wno-uninitialized -Wno-strict-aliasing -fmessage-length=0 -finline-functions -finline-limit=65536 "
 @@ -188,6 +201,7 @@ config.subst("DEBUG_CXXFLAGS", DEBUG_CXX
  config.subst("DEBUG_CXXFLAGS", DEBUG_CXXFLAGS)
  config.subst("DEBUG_LDFLAGS", DEBUG_LDFLAGS)
  config.subst("OS_LIBS", " ".join(OS_LIBS))
 +config.subst("OS_LDFLAGS", OS_LDFLAGS)
  config.subst("MMGC_CPPFLAGS", MMGC_CPPFLAGS)
  config.subst("AVMSHELL_CPPFLAGS", AVMSHELL_CPPFLAGS)
  config.subst("AVMSHELL_LDFLAGS", AVMSHELL_LDFLAGS)
--- a/mmgc-bit-checks
+++ b/mmgc-bit-checks
@@ -1,12 +1,12 @@
-diff -r af09bd95194a MMgc/GC.cpp
---- a/MMgc/GC.cpp	Fri Aug 24 18:49:48 2007 -0400
-+++ b/MMgc/GC.cpp	Fri Aug 24 18:52:02 2007 -0400
-@@ -2388,27 +2388,6 @@ bail:
+diff --git a/MMgc/GC.cpp b/MMgc/GC.cpp
+--- a/MMgc/GC.cpp
++++ b/MMgc/GC.cpp
+@@ -2841,27 +2841,6 @@ bail:
  		collecting = false;
  		marking = false;
  	}
 -
 -	int GC::IsWhite(const void *item)
 -	{
 -		// back up to real beginning
 -		item = GetRealPointer((const void*) item);
@@ -24,200 +24,183 @@ diff -r af09bd95194a MMgc/GC.cpp
 -			// in the page map (ie use 2).
 -			return GCLargeAlloc::IsWhite(item);
 -		}
 -		return false;
 -	}
  	
  	// TODO: fix headers so this can be declared there and inlined
  	void GC::WriteBarrierWrite(const void *address, const void *value)
-@@ -2510,11 +2489,6 @@ bail:
+@@ -2963,11 +2942,6 @@ bail:
  	{
  		int bits = GetPageMapValue((uintptr)item);
  		return (bits != 0);
 -	}
 -
 -	bool GC::IsQueued(const void *item)
 -	{
 -		return !GetMark(item) && !IsWhite(item);
  	}
  
  	uint32 *GC::GetBits(int numBytes, int sizeClass)
-diff -r af09bd95194a MMgc/GC.h
---- a/MMgc/GC.h	Fri Aug 24 18:49:48 2007 -0400
-+++ b/MMgc/GC.h	Fri Aug 24 18:52:02 2007 -0400
-@@ -587,13 +587,31 @@ namespace MMgc
+diff --git a/MMgc/GC.h b/MMgc/GC.h
+--- a/MMgc/GC.h
++++ b/MMgc/GC.h
+@@ -735,6 +735,17 @@ namespace MMgc
  
  		}
  
-+#if defined(MEMORY_INFO)
-+#define MMGC_CHECK_ITEM(item) \
-+		do { \
-+			GCAssert(item != NULL); \
-+			GC *gc = GetGC(item); \
-+			item = GetRealPointer(item); \
-+			GCAssert(gc->IsPointerToGCPage(item)); \
-+		} while (0)
-+#elif defined(DEBUG)
-+#define MMGC_CHECK_ITEM(item) \
-+		do { \
-+			GCAssert(item != NULL); \
-+			item = GetRealPointer(item); \
-+		} while (0)
-+#else
-+#define MMGC_CHECK_ITEM(item)
++	private:
++		__forceinline static void CheckItem(const void *&item)
++		{
++#if defined(DEBUG) || defined(MEMORY_INFO)
++			GCAssert(item != NULL);
++			item = GetRealPointer(item);
++			GCAssert(GetGC(item)->IsPointerToGCPage(item));
 +#endif
++		}
 +
++	public:
  		/**
  		 * Tracers should employ GetMark and SetMark to
  		 * set the mark bits during the mark pass.
- 		 */
- 		static int GetMark(const void *item)
- 		{
--			item = GetRealPointer(item);
-+			MMGC_CHECK_ITEM(item);
- 			if (GCLargeAlloc::IsLargeBlock(item)) {
- 				return GCLargeAlloc::GetMark(item);
- 			} else {
-@@ -603,25 +621,27 @@ namespace MMgc
+@@ -753,25 +764,28 @@ namespace MMgc
  
  		static int SetMark(const void *item)
  		{
 -			GCAssert(item != NULL);
 -#ifdef MEMORY_INFO
 -			GC *gc = GetGC(item);	
 -			item = GetRealPointer(item);
 -			GCAssert(gc->IsPointerToGCPage(item));
 -#endif 			
-+			MMGC_CHECK_ITEM(item);
++			CheckItem(item);
  			if (GCLargeAlloc::IsLargeBlock(item)) {
  				return GCLargeAlloc::SetMark(item);
  			} else {
  				return GCAlloc::SetMark(item);
  			}
  		}
 -		
 -		void SetQueued(const void *item)
 -		{
 -#ifdef MEMORY_INFO
 -			item = GetRealPointer(item);
 -			GCAssert(IsPointerToGCPage(item));
 -#endif 			
 +
++		/** @access Requires(request || exclusiveGC) */
 +		static bool IsQueued(const void *item)
 +		{
-+			MMGC_CHECK_ITEM(item);
++			CheckItem(item);
 +			if (GCLargeAlloc::IsLargeBlock(item)) {
 +				return GCLargeAlloc::IsQueued(item);
 +			} else {
 +				return GCAlloc::IsQueued(item);
 +			}
 +		}
 +
 +		static void SetQueued(const void *item)
 +		{
-+			MMGC_CHECK_ITEM(item);
++			CheckItem(item);
  			if (GCLargeAlloc::IsLargeBlock(item)) {
  				GCLargeAlloc::SetQueued(item);
  			} else {
-@@ -629,13 +649,22 @@ namespace MMgc
+@@ -779,13 +793,24 @@ namespace MMgc
  			}
  		}
  
 +		/**
 +		 * True if the item is neither marked nor queued.
++		 *
++		 * @access Requires(request || exclusiveGC)
 +		 */
 +		static int IsWhite(const void *item)
 +		{
-+			MMGC_CHECK_ITEM(item);
++			CheckItem(item);
 +			if (GCLargeAlloc::IsLargeBlock(item)) {
 +				return GCLargeAlloc::IsWhite(item);
 +			} else {
 +				return GCAlloc::IsWhite(item);
 +			}
 +		}
 +
  		static void ClearFinalized(const void *item)
  		{
 -#ifdef MEMORY_INFO
 -			GC *gc = GetGC(item);	
 -			item = GetRealPointer(item);
 -			GCAssert(gc->IsPointerToGCPage(item));
 -#endif 			
-+			MMGC_CHECK_ITEM(item);
++			CheckItem(item);
  			if (GCLargeAlloc::IsLargeBlock(item)) {
  				GCLargeAlloc::ClearFinalized(item);
  			} else {
-@@ -645,11 +674,7 @@ namespace MMgc
+@@ -795,11 +820,7 @@ namespace MMgc
  
  		static void SetFinalize(const void *item)
  		{
 -#ifdef MEMORY_INFO
 -			GC *gc = GetGC(item);	
 -			item = GetRealPointer(item);
 -			GCAssert(gc->IsPointerToGCPage(item));
 -#endif 			
-+			MMGC_CHECK_ITEM(item);
++			CheckItem(item);
  			if (GCLargeAlloc::IsLargeBlock(item)) {
  				GCLargeAlloc::SetFinalize(item);
  			} else {
-@@ -659,11 +684,7 @@ namespace MMgc
+@@ -809,11 +830,7 @@ namespace MMgc
  
  		static int IsFinalized(const void *item)
  		{
 -#ifdef MEMORY_INFO
 -			GC *gc = GetGC(item);	
 -			item = GetRealPointer(item);
 -			GCAssert(gc->IsPointerToGCPage(item));
 -#endif 			
-+			MMGC_CHECK_ITEM(item);
++			CheckItem(item);
  			if (GCLargeAlloc::IsLargeBlock(item)) {
  				return GCLargeAlloc::IsFinalized(item);
  			} else {
-@@ -673,17 +694,15 @@ namespace MMgc
+@@ -823,11 +840,7 @@ namespace MMgc
  
  		static int HasWeakRef(const void *item)
  		{
 -#ifdef MEMORY_INFO
 -			GC *gc = GetGC(item);	
 -			item = GetRealPointer(item);
 -			GCAssert(gc->IsPointerToGCPage(item));
 -#endif 			
-+			MMGC_CHECK_ITEM(item);
++			CheckItem(item);
  			if (GCLargeAlloc::IsLargeBlock(item)) {
  				return GCLargeAlloc::HasWeakRef(item);
  			} else {
- 				return GCAlloc::HasWeakRef(item);
- 			}
- 		}
-+
-+#undef MMGC_CHECK_ITEM
- 
- 		/**
- 		 * Utility function: Returns the GC object
-@@ -824,8 +843,6 @@ namespace MMgc
- 
+@@ -1007,9 +1020,6 @@ namespace MMgc
+ 		/** @access Requires(request || exclusiveGC) */
  		bool IsGCMemory (const void *);
  
+-		/** @access Requires(request || exclusiveGC) */
 -		bool IsQueued(const void *item);
 -
  		static uint64 GetPerformanceCounter();
  		static uint64 GetPerformanceFrequency();
  		
-@@ -922,7 +939,6 @@ namespace MMgc
+@@ -1177,9 +1187,6 @@ namespace MMgc
  		GCStack<GCWorkItem> m_incrementalWork;
  		void StartIncrementalMark();
  		void FinishIncrementalMark();
+-
+-		/** @access Requires(request || exclusiveGC) */
 -		int IsWhite(const void *item);
- 		
+ 
+ 		/** @access ReadWrite(request, exclusiveGC) */
  		uint64 lastMarkTicks;
- 		uint64 lastSweepTicks;
-diff -r af09bd95194a MMgc/GCAlloc.h
---- a/MMgc/GCAlloc.h	Fri Aug 24 18:49:48 2007 -0400
-+++ b/MMgc/GCAlloc.h	Fri Aug 24 18:52:02 2007 -0400
+diff --git a/MMgc/GCAlloc.h b/MMgc/GCAlloc.h
+--- a/MMgc/GCAlloc.h
++++ b/MMgc/GCAlloc.h
 @@ -110,6 +110,13 @@ namespace MMgc
  			return SetBit(block, GetIndex(block, item), kQueued);
  		}
  		
 +		static bool IsQueued(const void *item)
 +		{
 +			// Zero low 12 bits of address to get to the Block header
 +			GCBlock *block = (GCBlock*) ((uintptr)item & ~0xFFF);
@@ -236,19 +219,19 @@ diff -r af09bd95194a MMgc/GCAlloc.h
 -
 -			if(FindBeginning(item) != item)
 -				return false;
 +			GCAssert(item >= block->items);
 +			GCAssert(FindBeginning(item) == item);
  
  			return IsWhite(block, GetIndex(block, item));
  		}
-diff -r af09bd95194a MMgc/GCLargeAlloc.h
---- a/MMgc/GCLargeAlloc.h	Fri Aug 24 18:49:48 2007 -0400
-+++ b/MMgc/GCLargeAlloc.h	Fri Aug 24 18:52:02 2007 -0400
+diff --git a/MMgc/GCLargeAlloc.h b/MMgc/GCLargeAlloc.h
+--- a/MMgc/GCLargeAlloc.h
++++ b/MMgc/GCLargeAlloc.h
 @@ -101,6 +101,12 @@ namespace MMgc
  			block->flags |= kQueuedFlag;
  		}
  
 +		static bool IsQueued(const void *item)
 +		{
 +			LargeBlock *block = GetBlockHeader(item);
 +			return (block->flags & kQueuedFlag) != 0;
deleted file mode 100644
--- a/mmgc-decref-microfix
+++ /dev/null
@@ -1,12 +0,0 @@
-diff --git a/MMgc/WriteBarrier.h b/MMgc/WriteBarrier.h
---- a/MMgc/WriteBarrier.h
-+++ b/MMgc/WriteBarrier.h
-@@ -147,7 +147,7 @@ namespace MMgc
- 		~WriteBarrierRC() 
- 		{
- 			if(t != 0) {
--				((RCObject*)t)->DecrementRef();
-+				t->DecrementRef();
- 				t=0;
- 			}
- 		}
--- a/mmgc-graphviz
+++ b/mmgc-graphviz
@@ -6,28 +6,28 @@ diff --git a/MMgc/GC.cpp b/MMgc/GC.cpp
  		  disableThreadCheck(false)
  #endif
 +#ifdef MMGC_GRAPHVIZ
 +		  , m_gvFile(NULL)
 +#endif
  	{
  		// sanity check for all our types
  		GCAssert (sizeof(int8) == 1);
-@@ -361,6 +364,10 @@ namespace MMgc
- 	
+@@ -352,6 +355,10 @@ namespace MMgc
+ 
  	GC::~GC()
  	{
 +#ifdef MMGC_GRAPHVIZ
 +		StopGraphing();
 +#endif
 +
  		// Force all objects to be destroyed
  		destroying = true;
  		ClearMarks();
-@@ -554,7 +561,19 @@ namespace MMgc
+@@ -541,7 +548,19 @@ namespace MMgc
  				cb->enterExclusiveGCNoLock();
  		}
  
 +#ifdef MMGC_GRAPHVIZ
 +		if (m_gvFile) {
 +			fprintf(m_gvFile, "digraph C%d {\n", sweeps);
 +			fprintf(m_gvFile, "    node [shape=box];\n");
 +		}
@@ -37,17 +37,17 @@ diff --git a/MMgc/GC.cpp b/MMgc/GC.cpp
 +
 +#ifdef MMGC_GRAPHVIZ
 +		if (m_gvFile)
 +			fprintf(m_gvFile, "}\n");
 +#endif
  
  #ifdef MMGC_THREADSAFE
  		m_lock.Acquire();
-@@ -628,6 +647,46 @@ namespace MMgc
+@@ -615,6 +634,46 @@ namespace MMgc
  #endif
  	}
  
 +#define GRAPHVIZ_ROOT_STYLE "style=\"filled\", color=\"#ccddbb\""
 +#define GRAPHVIZ_OBJECT_STYLE "style=\"filled\", color=\"#b3cc99\""
 +#define GRAPHVIZ_CONSERVATIVE_EDGE_STYLE "color=\"#808080\""
 +
 +#ifdef MMGC_GRAPHVIZ
@@ -84,74 +84,75 @@ diff --git a/MMgc/GC.cpp b/MMgc/GC.cpp
 +		if (m_gvFile)
 +			fprintf(m_gvFile, "    P%p -> P%p [%s];\n", fromObj, toObj, style);
 +	}
 +#endif
 +
  	void GC::Trace(const void *stackStart/*=NULL*/, size_t stackSize/*=0*/)
  	{
  		ASSERT_EXCLUSIVE_GC();
-@@ -647,6 +706,16 @@ namespace MMgc
+@@ -634,6 +693,16 @@ namespace MMgc
  			GCRoot *r = m_roots;
  			while(r) {
  				GCWorkItem item = r->GetWorkItem();
 +#ifdef MMGC_GRAPHVIZ
 +				if (m_gvFile) {
 +					fprintf(m_gvFile,
 +							"    P%p [label=\"root at %p\", %s];\n",
 +							item.ptr,
 +							item.ptr,
 +							GRAPHVIZ_ROOT_STYLE);
 +				}
 +#endif
 +
  				MarkItem(item, work);
  				r = r->next;
  			}
-@@ -2261,7 +2330,6 @@ bail:
+@@ -2248,7 +2317,6 @@ bail:
  #undef ALLOCA_AND_FILL_WITH_SPACES
  #endif
  
 -
  	void GC::StartIncrementalMark()
  	{
  		GCAssert(!marking);
-@@ -2419,6 +2487,11 @@ bail:
+@@ -2417,6 +2485,11 @@ bail:
  
  	void GC::MarkItem(GCWorkItem &wi, GCStack<GCWorkItem> &work)
  	{
 +#ifdef MMGC_GRAPHVIZ
 +		if (wi.IsGCItem())
 +			GraphNode(wi.ptr, GRAPHVIZ_OBJECT_STYLE);
 +#endif
 +
  		size_t size = wi.GetSize();
  		uintptr *p = (uintptr*) wi.ptr;
  
-@@ -2499,6 +2572,9 @@ bail:
+@@ -2503,6 +2576,9 @@ bail:
  				{
  					if(block->alloc->ContainsPointers())
  					{
 +#ifdef MMGC_GRAPHVIZ
 +						GraphEdge(wi.ptr, p, item, GRAPHVIZ_CONSERVATIVE_EDGE_STYLE);
 +#endif
  						// try custom marking
  						if ((bits2 & (GCAlloc::kFinalize<<shift)) != 0
  							&& ((GCFinalizedObject *) GetUserPointer(item))->CustomMark())
-@@ -2558,6 +2634,9 @@ bail:
- 						size_t usize = b->usableSize;
- 						if((b->flags & GCLargeAlloc::kContainsPointers) != 0) 
- 						{
+@@ -2581,6 +2657,10 @@ bail:
+ 					size_t usize = b->usableSize;
+ 					if((b->flags & GCLargeAlloc::kContainsPointers) != 0) 
+ 					{
 +#ifdef MMGC_GRAPHVIZ
-+							GraphEdge(wi.ptr, p, item, GRAPHVIZ_CONSERVATIVE_EDGE_STYLE);
++						GraphEdge(wi.ptr, p, item, GRAPHVIZ_CONSERVATIVE_EDGE_STYLE);
 +#endif
- 							// try custom marking
- 							if ((b->flags & GCLargeAlloc::kFinalizeFlag) != 0
- 								&& ((GCFinalizedObject *) GetUserPointer(item))->CustomMark())
-@@ -3182,5 +3261,4 @@ bail:
++
+ 						// try custom marking
+ 						if ((b->flags & GCLargeAlloc::kFinalizeFlag) != 0
+ 							&& ((GCFinalizedObject *) GetUserPointer(item))->CustomMark())
+@@ -3204,5 +3284,4 @@ bail:
  	}
  #endif
  
 -
  }
 diff --git a/MMgc/GC.h b/MMgc/GC.h
 --- a/MMgc/GC.h
 +++ b/MMgc/GC.h
@@ -161,35 +162,35 @@ diff --git a/MMgc/GC.h b/MMgc/GC.h
  #define __GC__
 +
 +#ifdef MMGC_GRAPHVIZ
 +#include <typeinfo>
 +#endif
  
  #if defined MMGC_IA32
  
-@@ -1526,8 +1530,8 @@ private:
+@@ -1519,8 +1523,8 @@ private:
  #endif
  #endif
  
 -public:
  #ifdef MEMORY_INFO
 +	public:
  		void DumpBackPointerChain(void *o);
  
  		// debugging routine that records who marked who, can be used to
-@@ -1537,6 +1541,7 @@ public:
+@@ -1530,6 +1534,7 @@ public:
  		static void WriteBackPointer(const void *item, const void *container, size_t itemSize);
  #endif
  #ifdef _DEBUG
 +	public:
  		// Dump a list of objects that have pointers to the given location.
  		void WhosPointingAtMe(void* me, int recurseDepth=0, int currentDepth=0);
  
-@@ -1720,6 +1725,31 @@ public:
+@@ -1713,6 +1718,31 @@ public:
  		 * @access Requires(m_lock)
  		 */
  		GCCondition m_condNoRequests;
 +#endif
 +
 +#ifdef MMGC_GRAPHVIZ
 +	public:
 +		void StartGraphing(const char *filename)
@@ -226,30 +227,38 @@ diff --git a/MMgc/GCObject.cpp b/MMgc/GC
 +	std::string GCFinalizedObject::GetRepr() const
 +	{
 +		std::string s;
 +		char buf[60];
 +		size_t n;
 +
 +		n = snprintf(buf, 60, "%s at %p",
 +							typeid(*this).name(),
-+							dynamic_cast<void *>(this));
++							dynamic_cast<const void *>(this));
 +		s.assign(buf, n);
 +		return s;
 +	}
 +
  	void* GCFinalizedObjectOptIn::operator new(size_t size, GC *gc, size_t extra)
  	{
  		return gc->Alloc(size + extra, GC::kContainsPointers|GC::kZero, 4);
 diff --git a/MMgc/GCObject.h b/MMgc/GCObject.h
 --- a/MMgc/GCObject.h
 +++ b/MMgc/GCObject.h
-@@ -136,6 +136,8 @@ namespace MMgc
- 		 */
- 		virtual bool CustomMark() { return false; }
+@@ -39,6 +39,7 @@
+ #ifndef __GCObject__
+ #define __GCObject__
+ 
++#include <string>
+ 
+ // VC++ wants these declared
+ //void *operator new(size_t size);
+@@ -136,6 +137,8 @@ namespace MMgc
+ 	public:
+ 		GCWeakRef *GetWeakRef() const;
  
 +		virtual std::string GetRepr() const;
 +
  		static void *operator new(size_t size, GC *gc, size_t extra = 0);
  		static void operator delete (void *gcObject);
  	};
 diff --git a/MMgc/macbuild.h b/MMgc/macbuild.h
 --- a/MMgc/macbuild.h
deleted file mode 100644
--- a/mmgc-remove-precollect-hook
+++ /dev/null
@@ -1,43 +0,0 @@
-diff -r 7b346c66ebc4 MMgc/GC.cpp
---- a/MMgc/GC.cpp	Wed Aug 08 11:51:24 2007 -0400
-+++ b/MMgc/GC.cpp	Wed Aug 08 11:51:30 2007 -0400
-@@ -383,16 +383,7 @@ namespace MMgc
- 
- 	void GC::Collect()
- 	{
--		// invoke precollect callback
--		bool vetoed = false;
--		GCCallback *cb = m_callbacks;
--		while (cb) {
--			if (!cb->precollect())
--				vetoed = true;
--			cb = cb->nextCB;
--		}
--
--		if (vetoed || nogc || collecting) {
-+		if (nogc || collecting) {
- 
- 			return;
- 		}
-diff -r 7b346c66ebc4 MMgc/GC.h
---- a/MMgc/GC.h	Wed Aug 08 11:51:24 2007 -0400
-+++ b/MMgc/GC.h	Wed Aug 08 11:51:30 2007 -0400
-@@ -208,18 +208,6 @@ namespace MMgc
- 		GC *GetGC() const { return gc; }
- 		/** if your object goes away after the GC is deleted this can be useful */
- 		void Destroy();
--
--		/**
--		 * This method is called from GC::Collect(), before
--		 * anything else, even in cases where it's logically
--		 * certain that collection <em>will not start</em>
--		 * (e.g. because we're already collecting, or GC is
--		 * disabled).
--		 *
--		 * Returns true to allow collection to happen, false
--		 * to veto.
--		 */
--		virtual bool precollect() { return true; }
- 
- 		/**
- 		 * This method is invoked during the last mark phase
--- a/series
+++ b/series
@@ -1,6 +1,4 @@
 configure-with-threadsafe-mmgc
 mmgc-threadsafe-take2
 mmgc-graphviz
-mmgc-decref-microfix
-mmgc-remove-precollect-hook
 mmgc-bit-checks