Merge with actionmonkey-tamarin (several things were upstreamed) and prepare for merging pieces of jorendorff's mmgcts repository
authorbenjamin@smedbergs.us
Wed, 28 Nov 2007 11:25:36 -0500
changeset 6 b0246d10657e45b3622cad612f53a2b6d5efce1d
parent 5 399ff94b3d77e32c0b43ba646ea5ebc54f86589d
child 13 6a29ec7e67a19d85a0800edaa50ce47243b56e53
push id1
push userbsmedberg@mozilla.com
push dateMon, 21 Apr 2008 01:54:18 +0000
Merge with actionmonkey-tamarin (several things were upstreamed) and prepare for merging pieces of jorendorff's mmgcts repository
alloc-backtrace
explicit-namespaces.patch
finalized-base.patch
gc-graph
mmgc-threasafe-build.patch
series
x86-64
--- a/alloc-backtrace
+++ b/alloc-backtrace
@@ -1,28 +1,79 @@
+diff --git a/MMgc/GC.cpp b/MMgc/GC.cpp
 --- a/MMgc/GC.cpp
 +++ b/MMgc/GC.cpp
-@@ -95,6 +96,8 @@
- #include <sys/stack.h>
+@@ -97,6 +97,11 @@ extern "C" greg_t _getsp(void);
  extern "C" greg_t _getsp(void);
  #endif
-+
+ 
 +#include <execinfo.h>
- 
++
++#include <map>
++#include <string>
++
  #if defined(_MSC_VER) && defined(_DEBUG)
  // we turn on exceptions in DEBUG builds
---- a/MMgc/GC.cpp
-+++ b/MMgc/GC.cpp
-@@ -568,6 +575,14 @@ namespace MMgc
+ #pragma warning(disable:4291) // no matching operator delete found; memory will not be freed if initialization throws an exception
+@@ -112,6 +117,8 @@ extern "C" greg_t _getsp(void);
+ 
+ namespace MMgc
+ {
++	typedef std::map<const void*, std::string> AllocNameSet;
++	static AllocNameSet sAllocNameSet;
+ 
+ 	static const char kGraphvizRootStyle[] = "style=\"filled\", color=\"#ccddbb\"";
+ 	static const char kGraphvizStackStyle[] = "style=\"filled\", color=\"#bbddcc\"";
+@@ -589,6 +596,36 @@ namespace MMgc
  			memset(item, 0, Size(item));
  		}
  #endif
-+		static FILE* logf = fdopen(3, "a");
++		static char const *const kSkipFrames[] = {
++			"_ZN4MMgc17GCFinalizedObjectnwEjPNS_2GCEj",
++			"_ZN4MMgc8GCObjectnwEjPNS_2GCEj",
++			"_ZN13XPCOMGCObjectnwEj",
++			"_ZN22XPCOMGCFinalizedObjectnwEj",
++			NULL
++		};
++
++		void *btbuf[4];
++		int btsize = backtrace(btbuf, 4);
++		char **btarray = backtrace_symbols(btbuf, btsize);
++
++		char **frame = btarray;
 +
-+		fprintf(logf, "GC::Alloc(%i, %x, %i) = %p\n",
-+			(int) size, flags, skip, item);
-+		fflush(logf);
-+		void *btbuf[10];
-+		int btsize = backtrace(btbuf, 10);
-+		backtrace_symbols_fd(btbuf, btsize, 3);
++		// skip btbuf[0] which is this func!
++		++frame;
++
++		for (char const *const *skipFrame = kSkipFrames; *skipFrame; ++skipFrame) {
++			if (strstr(*frame, *skipFrame))
++				++frame;
++		}
++
++		sAllocNameSet[item] = *frame;
++		
++		static FILE *sAllocLog = getenv("MMGC_ALLOC_LOG") ? fopen(getenv("MMGC_ALLOC_LOG"), "w") : NULL;
++
++		if (sAllocLog)
++			fprintf(sAllocLog, "Item\t%p\t%s\n", item, *frame);
++
++		free(btarray);
  
  		return item;
  	}
+@@ -2993,8 +3030,15 @@ bail:
+ 
+ 	void GC::GraphNode(const void *obj, const char *style)
+ 	{
+-		if (m_gvFile)
+-			fprintf(m_gvFile, "    P%p [%s];\n", obj, style);
++		if (m_gvFile) {
++			const char *type = "";
++
++			AllocNameSet::iterator i = sAllocNameSet.find(obj);
++			if (i != sAllocNameSet.end())
++				type = i->second.c_str();
++
++			fprintf(m_gvFile, "    P%p [label=\"%s\", %s];\n", obj, type, style);
++		}
+ 	}
+ 
+ 	void GC::GraphEdge(const void *fromObj,
deleted file mode 100644
--- a/explicit-namespaces.patch
+++ /dev/null
@@ -1,16 +0,0 @@
-diff --git a/MMgc/WriteBarrier.h b/MMgc/WriteBarrier.h
---- a/MMgc/WriteBarrier.h
-+++ b/MMgc/WriteBarrier.h
-@@ -45,10 +45,10 @@
- #ifdef WRITE_BARRIERS
- 
- // inline write barrier
--#define WB(gc, container, addr, value) gc->writeBarrier(container, addr, (const void *)(uintptr)(value))
-+#define WB(gc, container, addr, value) gc->writeBarrier(container, addr, (const void *)(MMgc::uintptr)(value))
- 
- // fast manual RC write barrier
--#define WBRC(gc, container, addr, value) gc->writeBarrierRC(container, addr, (const void *)(uintptr)(value))
-+#define WBRC(gc, container, addr, value) gc->writeBarrierRC(container, addr, (const void *)(MMgc::uintptr)(value))
- 
- // declare write barrier
- #define DWB(type) MMgc::WriteBarrier<type>
deleted file mode 100644
--- a/finalized-base.patch
+++ /dev/null
@@ -1,136 +0,0 @@
-diff --git a/MMgc/GC.cpp b/MMgc/GC.cpp
---- a/MMgc/GC.cpp
-+++ b/MMgc/GC.cpp
-@@ -1201,7 +1201,7 @@ bail:
- 				cb = cb->nextCB;
- 			}
- 			if(gc->IsFinalized(obj))
--				((GCFinalizedObject*)obj)->~GCFinalizedObject();
-+				((GCFinalizedBase*)obj)->~GCFinalizedBase();
- 			gc->Free(obj);
- 			return;
- 		}
-@@ -1441,7 +1441,7 @@ bail:
- 
- 				GCAssert(*(int*)rcobj != 0);
- 				GCAssert(gc->IsFinalized(rcobj));
--				((GCFinalizedObject*)rcobj)->~GCFinalizedObject();
-+				((GCFinalizedBase*)rcobj)->~GCFinalizedBase();
- #ifdef DEBUGGER
- 				numObjects++;
- 				objSize += GC::Size(rcobj);
-diff --git a/MMgc/GC.h b/MMgc/GC.h
---- a/MMgc/GC.h
-+++ b/MMgc/GC.h
-@@ -896,6 +896,7 @@ namespace MMgc
- 
- 		bool Destroying() { return destroying; }
- 
-+		static GCWeakRef *GetWeakRef(const void *obj);
- 		void ClearWeakRef(const void *obj);
- 
- 		uintptr	GetStackTop() const;		
-@@ -924,9 +925,6 @@ namespace MMgc
- 		uint32 *m_bitsNext;
- 
- 		GCHashtable weakRefs;
--		friend class GCObject;
--		friend class GCFinalizedObject;
--		static GCWeakRef *GetWeakRef(const void *obj);
- 
- 		bool destroying;
- 
-diff --git a/MMgc/GCAlloc.cpp b/MMgc/GCAlloc.cpp
---- a/MMgc/GCAlloc.cpp
-+++ b/MMgc/GCAlloc.cpp
-@@ -428,9 +428,9 @@ start:
- 
- 					if (marks & kFinalize)
- 					{     
--						GCFinalizedObject *obj = (GCFinalizedObject*)GetUserPointer(item);
-+						GCFinalizedBase *obj = (GCFinalizedObject*)GetUserPointer(item);
- 						GCAssert(*(int*)obj != 0);
--						obj->~GCFinalizedObject();
-+						obj->~GCFinalizedBase();
- 
- 						bits[i] &= ~(kFinalize<<(j*4));
- 
-diff --git a/MMgc/GCLargeAlloc.cpp b/MMgc/GCLargeAlloc.cpp
---- a/MMgc/GCLargeAlloc.cpp
-+++ b/MMgc/GCLargeAlloc.cpp
-@@ -127,9 +127,9 @@ namespace MMgc
- 			if ((b->flags & kMarkFlag) == 0) {
- 				void *item = b+1;
- 				if (NeedsFinalize(b)) {
--					GCFinalizedObject *obj = (GCFinalizedObject *) item;
--					obj = (GCFinalizedObject *) GetUserPointer(obj);
--					obj->~GCFinalizedObject();
-+					GCFinalizedBase *obj = (GCFinalizedBase *) item;
-+					obj = (GCFinalizedBase *) GetUserPointer(obj);
-+					obj->~GCFinalizedBase();
- #if defined(_DEBUG) && defined(MMGC_DRC)
- 					if((b->flags & kRCObject) != 0) {
- 						b->gc->RCObjectZeroCheck((RCObject*)obj);
-diff --git a/MMgc/GCObject.h b/MMgc/GCObject.h
---- a/MMgc/GCObject.h
-+++ b/MMgc/GCObject.h
-@@ -65,16 +65,6 @@ namespace MMgc
- namespace MMgc
- {
- 	/**
--	 *
--	 */
--	class GCCustomSizer
--	{
--	public:
--		virtual ~GCCustomSizer() {} // here since gcc complains otherwise
--		virtual size_t Size() = 0;
--	};
--
--	/**
- 	 * Baseclass for GC managed objects that aren't finalized
- 	 */
- 	class MMGC_API GCObject
-@@ -108,16 +98,15 @@ namespace MMgc
- 	};
- 
- 	/**
--	 *	Baseclass for GC managed objects that are finalized 
-+	 * Base class for GC-managed objects that are finalized
-+	 * @note This class does not provider operator new/delete: derive from GCFinalizedObject
-+	 *       or GCFinalizedObjectOptIn to provide correct handling of "new Class"
- 	 */
--	class MMGC_API GCFinalizedObject
--	//: public GCObject can't do this, get weird compile errors in AVM plus, I think it has to do with
--	// the most base class (GCObject) not having any virtual methods)
--	{
--	public:
--		virtual ~GCFinalizedObject() {}
--		GCWeakRef *GetWeakRef() const;
--
-+	class MMGC_API GCFinalizedBase
-+	{
-+	public:
-+		virtual ~GCFinalizedBase() { }
-+	
- 		/**
- 		 * A hook allowing objects to participate in the Mark phase
- 		 * of garbage collection.  It is called only if the object
-@@ -135,6 +124,17 @@ namespace MMgc
- 		 * nothing and returns false.
- 		 */
- 		virtual bool CustomMark() { return false; }
-+	};
-+
-+	/**
-+	 *	Baseclass for GC managed objects that are finalized 
-+	 */
-+	class MMGC_API GCFinalizedObject : public GCFinalizedBase
-+	//: public GCObject can't do this, get weird compile errors in AVM plus, I think it has to do with
-+	// the most base class (GCObject) not having any virtual methods)
-+	{
-+	public:
-+		GCWeakRef *GetWeakRef() const;
- 
- 		static void *operator new(size_t size, GC *gc, size_t extra = 0);
- 		static void operator delete (void *gcObject);
new file mode 100644
--- /dev/null
+++ b/gc-graph
@@ -0,0 +1,191 @@
+diff --git a/MMgc/GC.cpp b/MMgc/GC.cpp
+--- a/MMgc/GC.cpp
++++ b/MMgc/GC.cpp
+@@ -113,6 +113,11 @@ namespace MMgc
+ namespace MMgc
+ {
+ 
++	static const char kGraphvizRootStyle[] = "style=\"filled\", color=\"#ccddbb\"";
++	static const char kGraphvizStackStyle[] = "style=\"filled\", color=\"#bbddcc\"";
++	static const char kGraphvizObjectStyle[] = "style=\"filled\", color=\"#b3cc99\"";
++	static const char kGraphvizConservativeEdge[] = "color=\"#808080\"";
++
+ #ifdef MMGC_DRC
+ 
+ 	// how many objects trigger a reap, should be high
+@@ -257,6 +262,8 @@ namespace MMgc
+ 		  finalizedValue(true),
+ 		  // Expand, don't collect, until we hit this threshold
+ 		  collectThreshold(256)
++		, m_gvFile(NULL)
++		  
+ 	{		
+ 		// sanity check for all our types
+ 		GCAssert (sizeof(int8) == 1);
+@@ -325,10 +332,15 @@ namespace MMgc
+ 		// keep GC::Size honest
+ 		GCAssert(offsetof(GCLargeAlloc::LargeBlock, usableSize) == offsetof(GCAlloc::GCBlock, size));
+ 
++		const char *gvFile = getenv("MMGC_GRAPHVIZ_LOG");
++		if (gvFile)
++			StartGraphing(gvFile);
+ 	}
+ 
+ 	GC::~GC()
+ 	{
++		StopGraphing();
++
+ 		// Force all objects to be destroyed
+ 		destroying = true;
+ 		ClearMarks();
+@@ -381,6 +393,12 @@ namespace MMgc
+ 
+ 	void GC::Collect()
+ 	{
++		static int cnum = 0;
++
++		if (m_gvFile)
++			fprintf(m_gvFile, "subgraph GC%i {\n", ++cnum);
++			
++
+ 		// invoke precollect callback
+ 		bool vetoed = false;
+ 		GCCallback *cb = m_callbacks;
+@@ -434,6 +452,8 @@ namespace MMgc
+ #ifdef DEBUGGER
+ 		StopGCActivity();
+ #endif
++		if (m_gvFile)
++			fprintf(m_gvFile, "}\n");
+ 	}
+ 
+ 	void GC::Trace(const void *stackStart/*=NULL*/, size_t stackSize/*=0*/)
+@@ -455,6 +475,15 @@ namespace MMgc
+ 			GCRoot *r = m_roots;
+ 			while(r) {
+ 				GCWorkItem item = r->GetWorkItem();
++
++				if (m_gvFile) {
++					fprintf(m_gvFile,
++						"    P%p [label=\"root at %p\", %s];\n",
++						item.ptr,
++						item.ptr,
++						(const char*) kGraphvizRootStyle);
++				}
++
+ 				MarkItem(item, work);
+ 				r = r->next;
+ 			}
+@@ -1034,6 +1063,14 @@ bail:
+ 		// this is where we will clear to when CleanStack is called
+ 		if(rememberedStackTop == 0 || rememberedStackTop > item.ptr) {
+ 			rememberedStackTop = item.ptr;
++		}
++
++		if (m_gvFile) {
++			fprintf(m_gvFile,
++				"    P%p [label=\"stack at %p\", %s];\n",
++				item.ptr,
++				item.ptr,
++				(const char*) kGraphvizStackStyle);
+ 		}
+ 
+ 		PushWorkItem(work, item);
+@@ -2176,6 +2213,8 @@ bail:
+ 		// set the mark bits on this guy
+ 		if(wi.IsGCItem())
+ 		{
++			GraphNode(wi.ptr, kGraphvizObjectStyle);
++
+ 			int b = SetMark(wi.ptr);
+ 			(void)b;
+ #ifdef _DEBUG
+@@ -2250,6 +2289,8 @@ bail:
+ 				//if(GCAlloc::IsWhite(block, itemNum)) 
+ 				if((bits2 & ((GCAlloc::kMark|GCAlloc::kQueued)<<shift)) == 0)
+ 				{
++					GraphEdge(wi.ptr, p, item, kGraphvizConservativeEdge);
++
+ 					if(block->alloc->ContainsPointers())
+ 					{
+ 						// try custom marking
+@@ -2324,6 +2365,8 @@ bail:
+ 				GCLargeAlloc::LargeBlock *b = GCLargeAlloc::GetBlockHeader(item);
+ 				if((b->flags & (GCLargeAlloc::kQueuedFlag|GCLargeAlloc::kMarkFlag)) == 0) 
+ 				{
++					GraphEdge(wi.ptr, p, item, kGraphvizConservativeEdge);
++
+ 					if (m_edgeCallbacks)
+ 						FireFoundEdgeTo(item);
+ 
+@@ -2931,5 +2974,35 @@ bail:
+ 	}
+ #endif
+ 
+-
++	void GC::StartGraphing(const char *filename)
++	{
++		StopGraphing();
++		m_gvFile = fopen(filename, "w");
++		fprintf(m_gvFile, "digraph GC {\n    node [shape=box];\n");
++	}
++
++	void GC::StopGraphing()
++	{
++		if (m_gvFile) {
++			fprintf(m_gvFile, ";\n");
++
++			fclose(m_gvFile);
++			m_gvFile = NULL;
++		}
++	}
++
++	void GC::GraphNode(const void *obj, const char *style)
++	{
++		if (m_gvFile)
++			fprintf(m_gvFile, "    P%p [%s];\n", obj, style);
++	}
++
++	void GC::GraphEdge(const void *fromObj,
++			   const void *fromField,
++			   const void *toObj,
++			   const char *style)
++	{
++		if (m_gvFile)
++			fprintf(m_gvFile, "    P%p -> P%p [%s];\n", fromObj, toObj, style);
++	}
+ }
+diff --git a/MMgc/GC.h b/MMgc/GC.h
+--- a/MMgc/GC.h
++++ b/MMgc/GC.h
+@@ -1139,6 +1139,18 @@ public:
+ 		void WhosPointingAtMe(void* me, int recurseDepth=0, int currentDepth=0);
+     	void ProbeForMatch(const void *mem, size_t size, uintptr value, int recurseDepth, int currentDepth);
+ #endif
++
++	public:
++		void StartGraphing(const char *filename);
++		void StopGraphing();
++		void GraphNode(const void *obj, const char *style);
++		void GraphEdge(const void *fromObj,
++			       const void *fromField,
++			       const void *toObj,
++			       const char *style);
++
++	private:
++		FILE *m_gvFile;
+ 	};
+ 
+ 	// helper class to wipe out vtable pointer of members for DRC
+diff --git a/MMgc/GCTypes.h b/MMgc/GCTypes.h
+--- a/MMgc/GCTypes.h
++++ b/MMgc/GCTypes.h
+@@ -42,6 +42,8 @@
+ #ifdef _MAC
+ #include <stdint.h>
+ #endif
++
++#include <stdio.h>
+ 
+ #if defined(HAVE_VISIBILITY_ATTRIBUTE)
+ #define MMGC_VISIBILITY_DEFAULT __attribute__ ((visibility ("default")))
deleted file mode 100644
--- a/mmgc-threasafe-build.patch
+++ /dev/null
@@ -1,69 +0,0 @@
-diff --git a/configure.py b/configure.py
---- a/configure.py
-+++ b/configure.py
-@@ -71,15 +71,28 @@ 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_DYNAMIC = o.getBoolArg('mmgc-shared', False)
- 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
- 
- 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 "
-@@ -178,6 +191,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)
-diff --git a/pcre/config.h b/pcre/config.h
---- a/pcre/config.h
-+++ b/pcre/config.h
-@@ -40,7 +40,9 @@ them both to 0; an emulation function wi
- #define HAVE_LIMITS_H 1
- 
- /* Define to 1 if the system has the type `long long'. */
-+#ifndef HAVE_LONG_LONG
- #define HAVE_LONG_LONG 1
-+#endif
- 
- /* Define to 1 if you have the `memmove' function. */
- #define HAVE_MEMMOVE 1
-diff --git a/shell/avmshell.h b/shell/avmshell.h
---- a/shell/avmshell.h
-+++ b/shell/avmshell.h
-@@ -48,6 +48,12 @@
- // #define AVMPLUS_INTERACTIVE
- 
- using namespace avmplus;
-+
-+// avmplus and NSPR both typedef some basic types: we must disambiguate
-+using avmplus::uint64;
-+using avmplus::uint32;
-+using avmplus::uint16;
-+using avmplus::uint8;
- 
- namespace avmshell
- {
--- a/series
+++ b/series
@@ -1,8 +1,5 @@
-mmgc-threasafe-build.patch
-finalized-base.patch
-explicit-namespaces.patch
-x86-64
 const-workitem.patch
 gcstack-access
 workitems-notgc-noassert
-alloc-backtrace
+gc-graph #+graphviz
+alloc-backtrace #+graphviz
deleted file mode 100644
--- a/x86-64
+++ /dev/null
@@ -1,116 +0,0 @@
-diff --git a/MMgc/GC.cpp b/MMgc/GC.cpp
---- a/MMgc/GC.cpp
-+++ b/MMgc/GC.cpp
-@@ -1548,7 +1548,7 @@ bail:
- #elif defined(AVMPLUS_UNIX) // SOLARIS
- 	pthread_key_t stackTopKey = 0;
- 
--	uint32 GC::GetStackTop() const
-+	uintptr GC::GetStackTop() const
- 	{
- 		if(stackTopKey == 0)
- 		{
-@@ -1561,7 +1561,7 @@ bail:
- 
- 		void *stackTop = pthread_getspecific(stackTopKey);
- 		if(stackTop)
--			return (uint32)stackTop;
-+			return (uintptr)stackTop;
- 
- 		size_t sz;
- 		void *s_base;
-@@ -1590,7 +1590,7 @@ bail:
- 		// stackTop has to be greater than current stack pointer
- 		GCAssert(stackTop > &sz);
- 		pthread_setspecific(stackTopKey, stackTop);
--		return (uint32)stackTop;
-+		return (uintptr)stackTop;
- 		
- 	}
- #endif // AVMPLUS_UNIX
-diff --git a/MMgc/GCHeapUnix.cpp b/MMgc/GCHeapUnix.cpp
---- a/MMgc/GCHeapUnix.cpp
-+++ b/MMgc/GCHeapUnix.cpp
-@@ -42,8 +42,8 @@
- 
- #include <unistd.h>
- 
-+#include "MMgc.h"
- #include "GCDebug.h"
--#include "MMgc.h"
- #include "GC.h"
- 
- #ifdef USE_MMAP
-@@ -178,7 +178,7 @@ namespace MMgc
- 		res = address;
- 		
- 		if (res == address)
--			address = (void*)( (int)address + size );
-+			address = (void*)( (uintptr)address + size );
- 		else
- 			address = 0;
- 		return address;
-diff --git a/MMgc/linuxbuild.h b/MMgc/linuxbuild.h
---- a/MMgc/linuxbuild.h
-+++ b/MMgc/linuxbuild.h
-@@ -49,7 +49,14 @@
- /**
-  * IA-32
-  */
-+#ifdef __i386__
- #define MMGC_IA32
-+#elif defined(__x86_64__)
-+#define MMGC_AMD64
-+#define MMGC_64BIT
-+#else
-+#error Unknown CPU type
-+#endif
- 
- /**
-  * Define this to get stack traces.  Helps with memory leaks.
-diff --git a/configure.py b/configure.py
---- a/configure.py
-+++ b/configure.py
-@@ -55,6 +55,10 @@ o = build.getopt.Options()
- 
- config = Configuration(thisdir, options = o,
-                        sourcefile = 'core/avmplus.h')
-+
-+buildTamarin = o.getBoolArg('tamarin', True)
-+if buildTamarin:
-+    config.subst("ENABLE_TAMARIN", 1)
- 
- buildShell = o.getBoolArg("shell", False)
- if (buildShell):
-@@ -161,6 +165,8 @@ elif cpu == "powerpc":
-     APP_CPPFLAGS += "-DAVMPLUS_PPC "
- elif cpu == "sparc":
-     APP_CPPFLAGS += "-DAVMPLUS_SPARC "
-+elif cpu == "x86_64":
-+    APP_CPPFLAGS += "-DAVMPLUS_AMD64 "
- else:
-     raise Exception("Unsupported OS")
- 
-diff --git a/manifest.mk b/manifest.mk
---- a/manifest.mk
-+++ b/manifest.mk
-@@ -42,7 +42,10 @@ INCLUDES += \
-   -I$(topsrcdir)/pcre \
-   $(NULL)
- 
--$(call RECURSE_DIRS,MMgc core pcre codegen)
-+$(call RECURSE_DIRS,MMgc)
-+
-+ifdef ENABLE_TAMARIN
-+$(call RECURSE_DIRS,core pcre codegen)
- 
- ifeq (darwin,$(TARGET_OS))
- $(call RECURSE_DIRS,platform/mac)
-@@ -53,6 +56,7 @@ ifeq (linux,$(TARGET_OS))
- ifeq (linux,$(TARGET_OS))
- $(call RECURSE_DIRS,platform/unix)
- endif
-+endif
- 
- $(call RECURSE_DIRS,shell)
-