alloc-backtrace
author benjamin@smedbergs.us
Wed, 12 Dec 2007 11:54:22 -0500
changeset 22 0ca31a2285356f7802d7a2ecda77ba7591f833cc
parent 6 b0246d10657e45b3622cad612f53a2b6d5efce1d
permissions -rw-r--r--
Merge changes from jorendorff

diff --git a/MMgc/GC.cpp b/MMgc/GC.cpp
--- a/MMgc/GC.cpp
+++ b/MMgc/GC.cpp
@@ -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
 #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 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;
+
+		// 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,