diff --git a/src/mongo/util/tcmalloc_server_status_section.cpp b/src/mongo/util/tcmalloc_server_status_section.cpp
index 0ee4670..4badaee 100644
--- a/src/mongo/util/tcmalloc_server_status_section.cpp
+++ b/src/mongo/util/tcmalloc_server_status_section.cpp
@@ -95,6 +95,9 @@ public:
     virtual BSONObj generateSection(OperationContext* txn, const BSONElement& configElement) const {
         BSONObjBuilder builder;
 
+        // detail level for formattedString
+        int level = configElement.numberInt();
+
         // For a list of properties see the "Generic Tcmalloc Status" section of
         // http://google-perftools.googlecode.com/svn/trunk/doc/tcmalloc.html and
         // http://code.google.com/p/gperftools/source/browse/src/gperftools/malloc_extension.h
@@ -127,7 +130,8 @@ public:
                 sub, "aggressive_memory_decommit", "tcmalloc.aggressive_memory_decommit");
         }
 
-        char buffer[4096];
+        // it's a bit funky, but GetStats uses buffer size to control detail level
+        char buffer[level>=3? 100000 : level>=2? 20000 : 4096];
         MallocExtension::instance()->GetStats(buffer, sizeof(buffer));
         builder.append("formattedString", buffer);
 
diff --git a/src/third_party/gperftools-2.2/src/gperftools/tcmalloc.h b/src/third_party/gperftools-2.2/src/gperftools/tcmalloc.h
index c471cd6..1e1d595 100644
--- a/src/third_party/gperftools-2.2/src/gperftools/tcmalloc.h
+++ b/src/third_party/gperftools-2.2/src/gperftools/tcmalloc.h
@@ -108,6 +108,13 @@ extern "C" {
   PERFTOOLS_DLL_DECL struct mallinfo tc_mallinfo(void) __THROW;
 #endif
 
+  PERFTOOLS_DLL_DECL void* tc_malloc_tag(size_t size, const char *tag) __THROW;
+  PERFTOOLS_DLL_DECL void tc_free_tag(void *p) __THROW;
+  PERFTOOLS_DLL_DECL void* tc_realloc_tag(void *p, size_t size, const char *tag) __THROW;
+  PERFTOOLS_DLL_DECL void* tc_calloc_tag(size_t n, size_t size, const char *tag) __THROW;
+  PERFTOOLS_DLL_DECL int tc_posix_memalign_tag(void** result_ptr, size_t align, size_t size,
+                                               const char *tag) __THROW;
+
   // This is an alias for MallocExtension::instance()->GetAllocatedSize().
   // It is equivalent to
   //    OS X: malloc_size()
diff --git a/src/third_party/gperftools-2.2/src/page_heap.cc b/src/third_party/gperftools-2.2/src/page_heap.cc
index a60df4a..7e639b5 100644
--- a/src/third_party/gperftools-2.2/src/page_heap.cc
+++ b/src/third_party/gperftools-2.2/src/page_heap.cc
@@ -31,6 +31,7 @@
 // ---
 // Author: Sanjay Ghemawat <opensource@google.com>
 
+#include <typeinfo>
 #include <config.h>
 #ifdef HAVE_INTTYPES_H
 #include <inttypes.h>                   // for PRIuPTR
@@ -59,6 +60,8 @@ DEFINE_int64(tcmalloc_heap_limit_mb,
               "to the system more aggressively (more minor page faults). "
               "Zero means to allocate as long as system allows.");
 
+extern char etext, end;
+
 namespace tcmalloc {
 
 PageHeap::PageHeap()
@@ -587,6 +590,137 @@ static void RecordGrowth(size_t growth) {
   Static::set_growth_stacks(t);
 }
 
+const char* PageHeap::kCxxTag = "C++";
+
+void PageHeap::DumpHeap(TCMalloc_Printer* out) {
+
+  // per-class allocation site stats
+  const static int MAXSITES = 100; // usually very much smaller
+  static struct class_info {	// info per allocation class
+    int spans;			// # of spans for this class
+    size_t bytes;		// # of bytes in the spans for this class
+    int refcount;		// total refcount for spans of this class
+    int block_count;		// # of allocated blocks for this class
+    size_t block_bytes;		// # of allocated bytes for this class
+    struct site_info {		// info per call allocation site per allocation class
+      const char *tag;		// tag identifying an allocation call site
+      int block_count;		// # of allocated blocks for that tag
+      size_t block_bytes;	// # of allocated bytes for that tag
+      int span_count;		// # of spans that have at least one block for that tag
+      size_t span_bytes;	// # of bytes in spans that have at least one block for that tag
+      Span *span;		// temp used to determine whether a span has an allocation call site
+    } sites[MAXSITES];
+    int nsites;			// # of sites for that class
+  } class_info[kNumClasses];
+  memset(class_info, 0, sizeof(class_info));
+
+  out->printf("------------------------------------------------\n");
+  out->printf("tagged allocation info\n");
+  out->printf("------------------------------------------------\n");
+
+  // iterate over spans
+  Span *span = reinterpret_cast<Span*>(pagemap_.Next(1));
+  while (span) {
+
+    // get span info
+    int cl = span->sizeclass;
+    char *start = (char *) (span->start << kPageShift);
+    char *end = (char *) ((span->start + span->length) << kPageShift);
+    size_t span_bytes = span->length << kPageShift;
+    size_t size = cl>0 ? Static::sizemap()->ByteSizeForClass(span->sizeclass) : end - start;
+
+    // bump class counts
+    struct class_info *ci = &class_info[cl];
+    ci->spans++;
+    ci->bytes += span_bytes;
+    ci->refcount += span->refcount;
+
+    // for each block in the span
+    for (char *block = start; block < end; block += size) {
+
+      // get the tag for this block
+      AllocTag *a = (AllocTag *) (block + size - sizeof(AllocTag));
+
+      // is this an allocated block?
+      if (a->signature != kAllocSignature)
+        continue;
+
+      // signature ensures with very high probability we ignore non-allocated blocks
+      // following ensures that in the unlikely event of a spurious signature we don't segfault
+      // but this requires tags to be initialized data (i.e. constant strings) - could generalize
+      if (! (&::etext <= a->tag && a->tag < &::end))
+        continue;
+
+      // if C++ object use rtti type name as tag
+      const char* tag = a->tag;
+      if (tag==kCxxTag)
+        tag = typeid(block).name();
+
+      // simple linear search; number of allocation sites per class is very small
+      // could possibly make faster by swapping found site to front of list
+      int i;
+      for (i = 0; i < ci->nsites; i++)
+        if (ci->sites[i].tag==tag)
+          break;
+      
+      // silengtly ignore in the unlike event we have a huge number of sites
+      if (i >= MAXSITES)
+        continue;
+
+      // new site
+      struct class_info::site_info *si = &ci->sites[i];
+      if (i==ci->nsites) {
+        si->tag = tag;
+        ci->nsites++;
+      }
+      
+      // bump class and site counts
+      ci->block_count++;
+      ci->block_bytes += size;
+      si->block_count++;
+      si->block_bytes += size;
+      si->span = span;
+    }
+
+    // bump span counts for all sites that were seen in this span
+    for (int i = 0; i < ci->nsites; i++) {
+      if (ci->sites[i].span==span) {
+        ci->sites[i].span_count += 1;
+        ci->sites[i].span_bytes += span_bytes;
+      }
+    }
+
+    // next span
+    span = reinterpret_cast<Span*>(pagemap_.Next(span->start+span->length));
+  }
+  
+  // print alloc tag info
+  const double MiB = 1024.0 * 1024.0;
+  for (int cl=0; cl<kNumClasses; cl++) {
+    struct class_info *ci = &class_info[cl];
+    if (ci->nsites) {
+      if (cl>0) {
+        size_t size = Static::sizemap()->ByteSizeForClass(cl);
+        out->printf("class %d (%lu bytes); ", cl, size);
+      } else {
+        out->printf("class %d (large); ", cl);
+      }
+      out->printf("%d spans, %lu bytes, %.3f MiB free+allocated; %d allocated objects; "
+                  "tagged objects follow:\n",
+                  ci->spans, ci->bytes, ci->bytes / MiB, ci->refcount);
+      out->printf("  total: %d objs, %lu bytes, %.3f MiB\n",
+                  ci->block_count, ci->block_bytes, ci->block_bytes/MiB);
+      for (int i=0; i<ci->nsites; i++) {
+        class_info::site_info *si = &(ci->sites[i]);
+        out->printf("  tag %s:", si->tag);
+        out->printf("  %d objs, %lu bytes, %.3f MiB; %d spans, %lu span bytes, %.3f MiB\n",
+                    si->block_count, si->block_bytes, si->block_bytes/MiB,
+                    si->span_count, si->span_bytes, si->span_bytes/MiB);
+      }  
+    }
+  }
+}
+
 bool PageHeap::GrowHeap(Length n) {
   ASSERT(kMaxPages >= kMinSystemAlloc);
   if (n > kMaxValidPages) return false;
diff --git a/src/third_party/gperftools-2.2/src/page_heap.h b/src/third_party/gperftools-2.2/src/page_heap.h
index 18abed1..0ea2bcf 100644
--- a/src/third_party/gperftools-2.2/src/page_heap.h
+++ b/src/third_party/gperftools-2.2/src/page_heap.h
@@ -152,6 +152,15 @@ class PERFTOOLS_DLL_DECL PageHeap {
   };
   inline Stats stats() const { return stats_; }
 
+  // Maintain and dump heap stats using per-block application-supplied tags
+  struct AllocTag {
+    int64_t signature;
+    const char *tag;
+  };
+  static const uint64_t kAllocSignature = 0x08192a3b4c5d6e7fULL; // marks allocated blocks
+  static const char *kCxxTag;  // used to tag a c++ allocation for later rtti
+  void DumpHeap(TCMalloc_Printer* out);
+
   struct SmallSpanStats {
     // For each free list of small spans, the length (in spans) of the
     // normal and returned free lists for that size.
diff --git a/src/third_party/gperftools-2.2/src/tcmalloc.cc b/src/third_party/gperftools-2.2/src/tcmalloc.cc
index 82024b3..bbcc3df 100644
--- a/src/third_party/gperftools-2.2/src/tcmalloc.cc
+++ b/src/third_party/gperftools-2.2/src/tcmalloc.cc
@@ -472,6 +472,11 @@ static void DumpStats(TCMalloc_Printer* out, int level) {
                 PagesToMiB(large.returned_pages),
                 PagesToMiB(total_returned));
   }
+
+  if (level >= 3) {
+    SpinLockHolder h(Static::pageheap_lock());
+    Static::pageheap()->DumpHeap(out);
+  }
 }
 
 static void PrintStats(int level) {
@@ -581,8 +586,10 @@ class TCMallocImplementation : public MallocExtension {
     // Print level one stats unless lots of space is available
     if (buffer_length < 10000) {
       DumpStats(&printer, 1);
-    } else {
+    } else if (buffer_length < 100000) {
       DumpStats(&printer, 2);
+    } else {
+      DumpStats(&printer, 3);
     }
   }
 
@@ -1438,6 +1445,13 @@ inline struct mallinfo do_mallinfo() {
 static SpinLock set_new_handler_lock(SpinLock::LINKER_INITIALIZED);
 
 inline void* cpp_alloc(size_t size, bool nothrow) {
+
+  // here's general idea for tracking C++ allocations by type
+  // tag each allocation with PageHeap::kCxxTag (instead of filename:lineno)
+  // PageHeap::DumpHeap uses kCxxTag as signal to use C++ rtti to get the type
+  // more work is required to hook this up
+  //return tc_malloc_tag(size, PageHeap::kCxxTag);
+
 #ifdef PREANSINEW
   return do_malloc(size);
 #else
@@ -1748,4 +1762,64 @@ extern "C" PERFTOOLS_DLL_DECL void* tc_malloc_skip_new_handler(size_t size)  __T
   return result;
 }
 
+//
+// tagged allocations
+//
+// we put AllocTag at the end so that it isn't overwritten by tcmalloc on free,
+// and so that we don't change the alignment of the returned buffer
+// adds sizeof(AllocTag)==16 bytes to allocation size
+//
+
+static inline PageHeap::AllocTag* get_tag(void *p) {
+  size_t size = MallocExtension::instance()->GetAllocatedSize(p);
+  return (PageHeap::AllocTag *) ((char*)p + size - sizeof(PageHeap::AllocTag));  
+}
+
+// tag a an allocated block
+static inline void alloc_tag(void *p, const char *tag) {
+  PageHeap::AllocTag *a =  get_tag(p);
+  a->signature = PageHeap::kAllocSignature;
+  a->tag = tag;
+}
+
+// tag a freed block
+static inline void free_tag(void *p) {
+  PageHeap::AllocTag *a =  get_tag(p);
+  a->signature = 0;
+  a->tag = 0;
+}
+
+extern "C" PERFTOOLS_DLL_DECL void* tc_malloc_tag(size_t size, const char *tag) __THROW {
+  void *p = tc_malloc(size + sizeof(PageHeap::AllocTag));
+  alloc_tag(p, tag);
+  return p;
+}
+
+extern "C" PERFTOOLS_DLL_DECL void* tc_realloc_tag(void *p, size_t size, const char *tag) __THROW {
+  if (p) free_tag(p);
+  p = tc_realloc(p, size + sizeof(PageHeap::AllocTag));
+  alloc_tag(p, tag);
+  return p;
+}
+
+extern "C" PERFTOOLS_DLL_DECL void* tc_calloc_tag(size_t nmemb, size_t size, const char *tag) __THROW {
+  void *p = tc_calloc(1, size*nmemb + sizeof(PageHeap::AllocTag));
+  alloc_tag(p, tag);
+  return p;
+}
+
+extern "C" PERFTOOLS_DLL_DECL void tc_free_tag(void *p) __THROW {
+  free_tag(p);
+  tc_free(p);
+}
+
+extern "C" PERFTOOLS_DLL_DECL int tc_posix_memalign_tag(
+  void** result_ptr, size_t align, size_t size, const char *tag
+) __THROW {
+  int rc = tc_posix_memalign(result_ptr, align, size + sizeof(PageHeap::AllocTag));
+  if (rc==0)
+    alloc_tag(*result_ptr, tag);
+  return rc;
+}
+
 #endif  // TCMALLOC_USING_DEBUGALLOCATION
diff --git a/src/third_party/wiredtiger/src/include/extern.h b/src/third_party/wiredtiger/src/include/extern.h
index 845102c..3e7f8ca 100644
--- a/src/third_party/wiredtiger/src/include/extern.h
+++ b/src/third_party/wiredtiger/src/include/extern.h
@@ -447,9 +447,9 @@ extern int __wt_turtle_init(WT_SESSION_IMPL *session);
 extern int __wt_turtle_read(WT_SESSION_IMPL *session, const char *key, char **valuep);
 extern int __wt_turtle_update( WT_SESSION_IMPL *session, const char *key, const char *value);
 extern void __wt_abort(WT_SESSION_IMPL *session) WT_GCC_FUNC_DECL_ATTRIBUTE((noreturn));
-extern int __wt_calloc(WT_SESSION_IMPL *session, size_t number, size_t size, void *retp);
-extern int __wt_realloc(WT_SESSION_IMPL *session, size_t *bytes_allocated_ret, size_t bytes_to_allocate, void *retp);
-extern int __wt_realloc_aligned(WT_SESSION_IMPL *session, size_t *bytes_allocated_ret, size_t bytes_to_allocate, void *retp);
+extern int __wt_calloc_int(WT_SESSION_IMPL *session, size_t number, size_t size, void *retp, const char *tag);
+extern int __wt_realloc_int(WT_SESSION_IMPL *session, size_t *bytes_allocated_ret, size_t bytes_to_allocate, void *retp, const char *tag);
+extern int __wt_realloc_aligned_int(WT_SESSION_IMPL *session, size_t *bytes_allocated_ret, size_t bytes_to_allocate, void *retp, const char *tag);
 extern int __wt_strndup(WT_SESSION_IMPL *session, const void *str, size_t len, void *retp);
 extern int __wt_strdup(WT_SESSION_IMPL *session, const char *str, void *retp);
 extern void __wt_free_int(WT_SESSION_IMPL *session, const void *p_arg);
diff --git a/src/third_party/wiredtiger/src/include/misc.h b/src/third_party/wiredtiger/src/include/misc.h
index e2b46d0..f1035d6 100644
--- a/src/third_party/wiredtiger/src/include/misc.h
+++ b/src/third_party/wiredtiger/src/include/misc.h
@@ -89,6 +89,27 @@
 	if ((p) != NULL)						\
 		__wt_free_int(session, (void *)&(p));			\
 } while (0)
+
+
+// 
+// tagged allocation
+// TBD: wrap in appropriate ifdef
+//
+
+#define QUOTE(x) #x
+#define _TAG_FNLN(fn, ln) (fn ":" QUOTE(ln))
+#define TAG_FNLN _TAG_FNLN(__FILE__, __LINE__)
+
+#define	__wt_calloc(session, number, size, retp)		\
+	__wt_calloc_int(session, number, size, retp, TAG_FNLN)
+
+#define	__wt_realloc(session, bar, bta, retp)			\
+	__wt_realloc_int(session, bar, bta, retp, TAG_FNLN)
+
+#define	__wt_realloc_aligned(session, bar, bta, retp)		\
+	__wt_realloc_aligned_int(session, bar, bta, retp, TAG_FNLN)
+
+
 #ifdef HAVE_DIAGNOSTIC
 #define	__wt_overwrite_and_free(session, p) do {			\
 	memset(p, WT_DEBUG_BYTE, sizeof(*(p)));				\
diff --git a/src/third_party/wiredtiger/src/os_posix/os_alloc.c b/src/third_party/wiredtiger/src/os_posix/os_alloc.c
index 182320f..4f658bd 100644
--- a/src/third_party/wiredtiger/src/os_posix/os_alloc.c
+++ b/src/third_party/wiredtiger/src/os_posix/os_alloc.c
@@ -29,6 +29,14 @@
 
 #endif
 
+//
+// TBD:
+// pick up the correct tcmalloc.h using -I
+// wrap with appropriate ifdefs
+// hook it all up via scons flag
+//
+#include "../../../gperftools-2.2/src/gperftools/tcmalloc.h"
+
 /*
  * There's no malloc interface, WiredTiger never calls malloc.
  *
@@ -44,7 +52,7 @@
  *	ANSI calloc function.
  */
 int
-__wt_calloc(WT_SESSION_IMPL *session, size_t number, size_t size, void *retp)
+__wt_calloc_int(WT_SESSION_IMPL *session, size_t number, size_t size, void *retp, const char* tag)
 {
 	void *p;
 
@@ -57,7 +65,7 @@ __wt_calloc(WT_SESSION_IMPL *session, size_t number, size_t size, void *retp)
 	if (session != NULL)
 		WT_STAT_FAST_CONN_INCR(session, memory_allocation);
 
-	if ((p = calloc(number, size)) == NULL)
+	if ((p = tc_calloc_tag(number, size, tag)) == NULL)
 		WT_RET_MSG(session, __wt_errno(), "memory allocation");
 
 	*(void **)retp = p;
@@ -69,8 +77,8 @@ __wt_calloc(WT_SESSION_IMPL *session, size_t number, size_t size, void *retp)
  *	ANSI realloc function.
  */
 int
-__wt_realloc(WT_SESSION_IMPL *session,
-    size_t *bytes_allocated_ret, size_t bytes_to_allocate, void *retp)
+__wt_realloc_int(WT_SESSION_IMPL *session,
+    size_t *bytes_allocated_ret, size_t bytes_to_allocate, void *retp, const char* tag)
 {
 	void *p;
 	size_t bytes_allocated;
@@ -99,7 +107,7 @@ __wt_realloc(WT_SESSION_IMPL *session,
 			WT_STAT_FAST_CONN_INCR(session, memory_grow);
 	}
 
-	if ((p = realloc(p, bytes_to_allocate)) == NULL)
+	if ((p = tc_realloc_tag(p, bytes_to_allocate, tag)) == NULL)
 		WT_RET_MSG(session, __wt_errno(), "memory allocation");
 
 	/*
@@ -127,8 +135,8 @@ __wt_realloc(WT_SESSION_IMPL *session,
  *	the "buffer_alignment" key to wiredtiger_open.
  */
 int
-__wt_realloc_aligned(WT_SESSION_IMPL *session,
-    size_t *bytes_allocated_ret, size_t bytes_to_allocate, void *retp)
+__wt_realloc_aligned_int(WT_SESSION_IMPL *session,
+    size_t *bytes_allocated_ret, size_t bytes_to_allocate, void *retp, const char* tag)
 {
 #if defined(HAVE_POSIX_MEMALIGN)
 	WT_DECL_RET;
@@ -168,9 +176,9 @@ __wt_realloc_aligned(WT_SESSION_IMPL *session,
 
 		WT_STAT_FAST_CONN_INCR(session, memory_allocation);
 
-		if ((ret = posix_memalign(&newp,
+		if ((ret = tc_posix_memalign_tag(&newp,
 		    S2C(session)->buffer_alignment,
-		    bytes_to_allocate)) != 0)
+		    bytes_to_allocate, tag)) != 0)
 			WT_RET_MSG(session, ret, "memory allocation");
 
 		if (p != NULL)
@@ -197,8 +205,8 @@ __wt_realloc_aligned(WT_SESSION_IMPL *session,
 	 * Windows note: Visual C CRT memalign does not match Posix behavior
 	 * and would also double each allocation so it is bad for memory use
 	 */
-	return (__wt_realloc(
-	    session, bytes_allocated_ret, bytes_to_allocate, retp));
+	return (__wt_realloc_int(
+		 session, bytes_allocated_ret, bytes_to_allocate, retp, tag));
 }
 
 /*
@@ -266,5 +274,5 @@ __wt_free_int(WT_SESSION_IMPL *session, const void *p_arg)
 	if (session != NULL)
 		WT_STAT_FAST_CONN_INCR(session, memory_free);
 
-	free(p);
+	tc_free_tag(p);
 }
