Browse Source

still more meminfo fixes

David Rose 18 years ago
parent
commit
385e7be325
54 changed files with 564 additions and 268 deletions
  1. 2 1
      dtool/src/dtoolbase/Sources.pp
  2. 2 0
      dtool/src/dtoolbase/dlmalloc_src.cxx
  3. 10 4
      dtool/src/dtoolbase/dtoolbase_cc.h
  4. 4 4
      dtool/src/dtoolbase/memoryBase.h
  5. 54 5
      dtool/src/dtoolbase/memoryHook.I
  6. 124 20
      dtool/src/dtoolbase/memoryHook.cxx
  7. 33 10
      dtool/src/dtoolbase/memoryHook.h
  8. 2 2
      dtool/src/dtoolbase/pallocator.T
  9. 14 2
      dtool/src/dtoolbase/ptmalloc2_smp_src.cxx
  10. 22 0
      dtool/src/dtoolutil/pandaSystem.cxx
  11. 2 0
      dtool/src/dtoolutil/pandaSystem.h
  12. 7 4
      panda/src/downloader/bioStreamBuf.cxx
  13. 1 0
      panda/src/downloader/bioStreamBuf.h
  14. 7 4
      panda/src/downloader/chunkedStreamBuf.cxx
  15. 1 0
      panda/src/downloader/chunkedStreamBuf.h
  16. 7 4
      panda/src/downloader/identityStreamBuf.cxx
  17. 1 0
      panda/src/downloader/identityStreamBuf.h
  18. 0 8
      panda/src/downloader/multiplexStreamBuf.h
  19. 1 1
      panda/src/downloadertools/multify.cxx
  20. 2 2
      panda/src/express/buffer.cxx
  21. 44 7
      panda/src/express/memoryUsage.I
  22. 11 11
      panda/src/express/memoryUsage.cxx
  23. 5 3
      panda/src/express/memoryUsage.h
  24. 2 2
      panda/src/express/multifile.cxx
  25. 2 2
      panda/src/express/password_hash.cxx
  26. 13 13
      panda/src/express/patchfile.cxx
  27. 2 2
      panda/src/express/profileTimer.cxx
  28. 6 3
      panda/src/express/subStreamBuf.cxx
  29. 1 0
      panda/src/express/subStreamBuf.h
  30. 3 4
      panda/src/express/test_zstream.cxx
  31. 4 4
      panda/src/express/windowsRegistry.cxx
  32. 7 4
      panda/src/express/zStreamBuf.cxx
  33. 2 0
      panda/src/express/zStreamBuf.h
  34. 4 4
      panda/src/glstuff/glGraphicsStateGuardian_src.cxx
  35. 8 8
      panda/src/gobj/vertexDataBuffer.cxx
  36. 3 2
      panda/src/gobj/vertexDataPage.cxx
  37. 1 0
      panda/src/gobj/vertexDataPage.h
  38. 9 6
      panda/src/ode/odeTriMeshData.cxx
  39. 3 3
      panda/src/ode/odeUtil.cxx
  40. 2 2
      panda/src/osxdisplay/osxGraphicsPipe.cxx
  41. 2 2
      panda/src/particlesystem/spriteParticleRenderer.cxx
  42. 12 12
      panda/src/pnmimage/pnm-image-filter-core.cxx
  43. 2 2
      panda/src/pnmimage/pnm-image-filter.cxx
  44. 0 24
      panda/src/pnmimage/pnmFileType.cxx
  45. 2 2
      panda/src/pnmimage/pnmImage.I
  46. 3 3
      panda/src/pnmimage/pnmImage.cxx
  47. 2 2
      panda/src/pnmimage/pnmimage_base.cxx
  48. 6 6
      panda/src/pnmimagetypes/pnmFileTypePNG.cxx
  49. 7 7
      panda/src/pnmimagetypes/pnmFileTypeSGIWriter.cxx
  50. 73 36
      panda/src/pstatclient/pStatClient.cxx
  51. 13 8
      panda/src/pstatclient/pStatClient.h
  52. 9 8
      panda/src/pstatclient/pStatProperties.cxx
  53. 3 3
      panda/src/putil/datagramInputFile.cxx
  54. 2 2
      panda/src/putil/uniqueIdAllocator.cxx

+ 2 - 1
dtool/src/dtoolbase/Sources.pp

@@ -37,7 +37,8 @@
     typedObject.I typedObject.h \
     typedObject.I typedObject.h \
     pallocator.T pallocator.h \
     pallocator.T pallocator.h \
     pdeque.h plist.h pmap.h pset.h pvector.h \
     pdeque.h plist.h pmap.h pset.h pvector.h \
-    dlmalloc.c lookup3.h lookup3.c
+    lookup3.h lookup3.c \
+    dlmalloc_src.cxx ptmalloc2_smp_src.cxx
 
 
  #define INCLUDED_SOURCES  \
  #define INCLUDED_SOURCES  \
     addHash.cxx \
     addHash.cxx \

+ 2 - 0
dtool/src/dtoolbase/dlmalloc.c → dtool/src/dtoolbase/dlmalloc_src.cxx

@@ -3458,6 +3458,7 @@ static void* sys_alloc(mstate m, size_t nb) {
   }
   }
 
 
   if (tbase != CMFAIL) {
   if (tbase != CMFAIL) {
+    memory_hook->inc_heap(tsize);
 
 
     if ((m->footprint += tsize) > m->max_footprint)
     if ((m->footprint += tsize) > m->max_footprint)
       m->max_footprint = m->footprint;
       m->max_footprint = m->footprint;
@@ -3564,6 +3565,7 @@ static size_t release_unused_segments(mstate m) {
     pred = sp;
     pred = sp;
     sp = next;
     sp = next;
   }
   }
+  memory_hook->dec_heap(released);
   return released;
   return released;
 }
 }
 
 

+ 10 - 4
dtool/src/dtoolbase/dtoolbase_cc.h

@@ -152,11 +152,17 @@ EXPCL_DTOOL void init_memory_hook();
 // Now redefine some handy macros to hook into the above MemoryHook
 // Now redefine some handy macros to hook into the above MemoryHook
 // object.
 // object.
 #ifndef USE_MEMORY_NOWRAPPERS
 #ifndef USE_MEMORY_NOWRAPPERS
-#define PANDA_MALLOC(size) (memory_hook->heap_alloc(size))
-#define PANDA_FREE(ptr) memory_hook->heap_free(ptr)
+#define PANDA_MALLOC_SINGLE(size) (memory_hook->heap_alloc_single(size))
+#define PANDA_FREE_SINGLE(ptr) memory_hook->heap_free_single(ptr)
+#define PANDA_MALLOC_ARRAY(size) (memory_hook->heap_alloc_array(size))
+#define PANDA_REALLOC_ARRAY(ptr, size) (memory_hook->heap_realloc_array(ptr, size))
+#define PANDA_FREE_ARRAY(ptr) memory_hook->heap_free_array(ptr)
 #else
 #else
-#define PANDA_MALLOC(size) malloc(size)
-#define PANDA_FREE(ptr) free(ptr)
+#define PANDA_MALLOC_SINGLE(size) malloc(size)
+#define PANDA_FREE_SINGLE(ptr) free(ptr)
+#define PANDA_MALLOC_ARRAY(size) malloc(size)
+#define PANDA_REALLOC_ARRAY(ptr, size) realloc(ptr, size)
+#define PANDA_FREE_ARRAY(ptr) free(ptr)
 #endif  // USE_MEMORY_NOWRAPPERS
 #endif  // USE_MEMORY_NOWRAPPERS
 
 
 #if defined(HAVE_THREADS) && defined(SIMPLE_THREADS)
 #if defined(HAVE_THREADS) && defined(SIMPLE_THREADS)

+ 4 - 4
dtool/src/dtoolbase/memoryBase.h

@@ -32,24 +32,24 @@
 
 
 #define ALLOC_MEMORY_BASE                                    \
 #define ALLOC_MEMORY_BASE                                    \
   inline void *operator new(size_t size) {                   \
   inline void *operator new(size_t size) {                   \
-    return PANDA_MALLOC(size);                     \
+    return PANDA_MALLOC_SINGLE(size);                     \
   }                                                          \
   }                                                          \
   inline void *operator new(size_t size, void *ptr) {        \
   inline void *operator new(size_t size, void *ptr) {        \
     return ptr;                                              \
     return ptr;                                              \
   }                                                          \
   }                                                          \
   inline void operator delete(void *ptr) {                   \
   inline void operator delete(void *ptr) {                   \
-    PANDA_FREE(ptr);                          \
+    PANDA_FREE_SINGLE(ptr);                          \
   }                                                          \
   }                                                          \
   inline void operator delete(void *ptr, void *) {           \
   inline void operator delete(void *ptr, void *) {           \
   }                                                          \
   }                                                          \
   inline void *operator new[](size_t size) {                 \
   inline void *operator new[](size_t size) {                 \
-    return PANDA_MALLOC(size);                     \
+    return PANDA_MALLOC_ARRAY(size);                     \
   }                                                          \
   }                                                          \
   inline void *operator new[](size_t size, void *ptr) {      \
   inline void *operator new[](size_t size, void *ptr) {      \
     return ptr;                                              \
     return ptr;                                              \
   }                                                          \
   }                                                          \
   inline void operator delete[](void *ptr) {                 \
   inline void operator delete[](void *ptr) {                 \
-    PANDA_FREE(ptr);                          \
+    PANDA_FREE_ARRAY(ptr);                          \
   }                                                          \
   }                                                          \
   inline void operator delete[](void *, void *) {            \
   inline void operator delete[](void *, void *) {            \
   }
   }

+ 54 - 5
dtool/src/dtoolbase/memoryHook.I

@@ -17,6 +17,35 @@
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 
 
 
 
+////////////////////////////////////////////////////////////////////
+//     Function: MemoryHook::inc_heap
+//       Access: Public
+//  Description: Called by our alternative malloc implementations
+//               (dlmalloc and ptmalloc2) to indicate they have
+//               requested size bytes from the system for the heap.
+////////////////////////////////////////////////////////////////////
+INLINE void MemoryHook::
+inc_heap(size_t size) {
+#ifdef DO_MEMORY_USAGE
+  AtomicAdjust::add(_requested_heap_size, (PN_int32)size);
+#endif  // DO_MEMORY_USAGE
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: MemoryHook::dec_heap
+//       Access: Public
+//  Description: Called by our alternative malloc implementations
+//               (dlmalloc and ptmalloc2) to indicate they have
+//               returned size bytes to the system from the heap.
+////////////////////////////////////////////////////////////////////
+INLINE void MemoryHook::
+dec_heap(size_t size) {
+#ifdef DO_MEMORY_USAGE
+  assert(size <= _requested_heap_size);
+  AtomicAdjust::add(_requested_heap_size, -(PN_int32)size);
+#endif  // DO_MEMORY_USAGE
+}
+
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: MemoryHook::get_page_size
 //     Function: MemoryHook::get_page_size
 //       Access: Public
 //       Access: Public
@@ -41,35 +70,55 @@ round_up_to_page_size(size_t size) const {
   return  ((size + _page_size - 1) / _page_size) * _page_size;
   return  ((size + _page_size - 1) / _page_size) * _page_size;
 }
 }
 
 
+////////////////////////////////////////////////////////////////////
+//     Function: MemoryHook::inflate_size
+//       Access: Private, Static
+//  Description: Increments the amount of requested size as necessary
+//               to accomodate the extra data we might piggyback on
+//               each allocated block.
+////////////////////////////////////////////////////////////////////
+INLINE size_t MemoryHook::
+inflate_size(size_t size) {
 #ifdef DO_MEMORY_USAGE
 #ifdef DO_MEMORY_USAGE
+  return size + sizeof(size_t);
+#else
+  return size;
+#endif  // DO_MEMORY_USAGE
+}
+
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: MemoryHook::alloc_to_ptr
 //     Function: MemoryHook::alloc_to_ptr
-//       Access: Private
+//       Access: Private, Static
 //  Description: Converts an allocated pointer to a pointer returnable
 //  Description: Converts an allocated pointer to a pointer returnable
 //               to the application.  Stuffs size in the first n bytes
 //               to the application.  Stuffs size in the first n bytes
 //               of the allocated space.
 //               of the allocated space.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 INLINE void *MemoryHook::
 INLINE void *MemoryHook::
 alloc_to_ptr(void *alloc, size_t size) {
 alloc_to_ptr(void *alloc, size_t size) {
+#ifdef DO_MEMORY_USAGE
   size_t *root = (size_t *)alloc;
   size_t *root = (size_t *)alloc;
   root[0] = size;
   root[0] = size;
   return (void *)(root + 1);
   return (void *)(root + 1);
-}
+#else
+  return alloc;
 #endif  // DO_MEMORY_USAGE
 #endif  // DO_MEMORY_USAGE
+}
 
 
-#ifdef DO_MEMORY_USAGE
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: MemoryHook::ptr_to_alloc
 //     Function: MemoryHook::ptr_to_alloc
-//       Access: Private
+//       Access: Private, Static
 //  Description: Converts an application pointer back to the original
 //  Description: Converts an application pointer back to the original
 //               allocated pointer.  Extracts size from the first n
 //               allocated pointer.  Extracts size from the first n
 //               bytes of the allocated space.
 //               bytes of the allocated space.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 INLINE void *MemoryHook::
 INLINE void *MemoryHook::
 ptr_to_alloc(void *ptr, size_t &size) {
 ptr_to_alloc(void *ptr, size_t &size) {
+#ifdef DO_MEMORY_USAGE
   size_t *root = (size_t *)ptr;
   size_t *root = (size_t *)ptr;
   root -= 1;
   root -= 1;
   size = root[0];
   size = root[0];
   return (void *)root;
   return (void *)root;
-}
+#else
+  return ptr;
 #endif  // DO_MEMORY_USAGE
 #endif  // DO_MEMORY_USAGE
+}

+ 124 - 20
dtool/src/dtoolbase/memoryHook.cxx

@@ -52,8 +52,10 @@
 #define USE_DL_PREFIX 1
 #define USE_DL_PREFIX 1
 #define NO_MALLINFO 1
 #define NO_MALLINFO 1
 #include "dlmalloc.h"
 #include "dlmalloc.h"
+#include "dlmalloc_src.cxx"
 
 
 #define call_malloc dlmalloc
 #define call_malloc dlmalloc
+#define call_realloc dlrealloc
 #define call_free dlfree
 #define call_free dlfree
 
 
 #elif defined(USE_MEMORY_PTMALLOC2) && !defined(linux)
 #elif defined(USE_MEMORY_PTMALLOC2) && !defined(linux)
@@ -75,9 +77,10 @@
 
 
 #define USE_DL_PREFIX 1
 #define USE_DL_PREFIX 1
 #define NO_MALLINFO 1
 #define NO_MALLINFO 1
-#include "ptmalloc2_smp.c"
+#include "ptmalloc2_smp_src.cxx"
 
 
 #define call_malloc dlmalloc
 #define call_malloc dlmalloc
+#define call_realloc dlrealloc
 #define call_free dlfree
 #define call_free dlfree
 
 
 #else
 #else
@@ -92,6 +95,7 @@
 /////////////////////////////////////////////////////////////////////
 /////////////////////////////////////////////////////////////////////
 
 
 #define call_malloc malloc
 #define call_malloc malloc
+#define call_realloc realloc
 #define call_free free
 #define call_free free
 
 
 #endif  // USE_MEMORY_*
 #endif  // USE_MEMORY_*
@@ -120,7 +124,9 @@ MemoryHook() {
 #endif  // WIN32
 #endif  // WIN32
 
 
 #ifdef DO_MEMORY_USAGE
 #ifdef DO_MEMORY_USAGE
-  _total_heap_size = 0;
+  _total_heap_single_size = 0;
+  _total_heap_array_size = 0;
+  _requested_heap_size = 0;
   _total_mmap_size = 0;
   _total_mmap_size = 0;
 #endif
 #endif
 }
 }
@@ -135,7 +141,9 @@ MemoryHook(const MemoryHook &copy) :
   _page_size(copy._page_size)
   _page_size(copy._page_size)
 {
 {
 #ifdef DO_MEMORY_USAGE
 #ifdef DO_MEMORY_USAGE
-  _total_heap_size = copy._total_heap_size;
+  _total_heap_single_size = copy._total_heap_single_size;
+  _total_heap_array_size = copy._total_heap_array_size;
+  _requested_heap_size = copy._requested_heap_size;
   _total_mmap_size = copy._total_mmap_size;
   _total_mmap_size = copy._total_mmap_size;
 #endif
 #endif
 }
 }
@@ -152,52 +160,148 @@ MemoryHook::
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-//     Function: MemoryHook::heap_alloc
+//     Function: MemoryHook::heap_alloc_single
 //       Access: Public, Virtual
 //       Access: Public, Virtual
 //  Description: Allocates a block of memory from the heap, similar to
 //  Description: Allocates a block of memory from the heap, similar to
 //               malloc().  This will never return NULL; it will abort
 //               malloc().  This will never return NULL; it will abort
 //               instead if memory is not available.
 //               instead if memory is not available.
+//
+//               This particular function should be used to allocate
+//               memory for a single object, as opposed to an array.
+//               The only difference is in the bookkeeping.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 void *MemoryHook::
 void *MemoryHook::
-heap_alloc(size_t size) {
-  void *ptr;
-
+heap_alloc_single(size_t size) {
 #ifdef DO_MEMORY_USAGE
 #ifdef DO_MEMORY_USAGE
   // In the DO_MEMORY_USAGE case, we want to track the total size of
   // In the DO_MEMORY_USAGE case, we want to track the total size of
   // allocated bytes on the heap.
   // allocated bytes on the heap.
-  _total_heap_size += size;
-  ptr = alloc_to_ptr(call_malloc(size + sizeof(size)), size);
-#else
-  ptr = call_malloc(size);
+  AtomicAdjust::add(_total_heap_single_size, (PN_int32)size);
 #endif  // DO_MEMORY_USAGE
 #endif  // DO_MEMORY_USAGE
 
 
-  if (ptr == (void *)NULL) {
+  void *alloc = call_malloc(inflate_size(size));
+  if (alloc == (void *)NULL) {
     cerr << "Out of memory!\n";
     cerr << "Out of memory!\n";
     abort();
     abort();
   }
   }
-  return ptr;
+
+  return alloc_to_ptr(alloc, size);
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-//     Function: MemoryHook::heap_free
+//     Function: MemoryHook::heap_free_single
 //       Access: Public, Virtual
 //       Access: Public, Virtual
 //  Description: Releases a block of memory previously allocated via
 //  Description: Releases a block of memory previously allocated via
-//               heap_alloc.
+//               heap_alloc_single.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 void MemoryHook::
 void MemoryHook::
-heap_free(void *ptr) {
+heap_free_single(void *ptr) {
+  size_t size;
+  void *alloc = ptr_to_alloc(ptr, size);
 
 
+#ifdef DO_MEMORY_USAGE
+  assert(size <= _total_heap_single_size);
+  AtomicAdjust::add(_total_heap_single_size, -(PN_int32)size);
+#endif  // DO_MEMORY_USAGE
+
+  call_free(alloc);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: MemoryHook::heap_alloc_array
+//       Access: Public, Virtual
+//  Description: Allocates a block of memory from the heap, similar to
+//               malloc().  This will never return NULL; it will abort
+//               instead if memory is not available.
+//
+//               This particular function should be used to allocate
+//               memory for an array of objects, as opposed to a
+//               single object.  The only difference is in the
+//               bookkeeping.
+////////////////////////////////////////////////////////////////////
+void *MemoryHook::
+heap_alloc_array(size_t size) {
 #ifdef DO_MEMORY_USAGE
 #ifdef DO_MEMORY_USAGE
   // In the DO_MEMORY_USAGE case, we want to track the total size of
   // In the DO_MEMORY_USAGE case, we want to track the total size of
   // allocated bytes on the heap.
   // allocated bytes on the heap.
+  AtomicAdjust::add(_total_heap_array_size, (PN_int32)size);
+#endif  // DO_MEMORY_USAGE
+
+  void *alloc = call_malloc(inflate_size(size));
+  if (alloc == (void *)NULL) {
+    cerr << "Out of memory!\n";
+    abort();
+  }
+
+  return alloc_to_ptr(alloc, size);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: MemoryHook::heap_realloc_array
+//       Access: Public, Virtual
+//  Description: Resizes a block of memory previously returned from
+//               heap_alloc_array.
+////////////////////////////////////////////////////////////////////
+void *MemoryHook::
+heap_realloc_array(void *ptr, size_t size) {
+  size_t orig_size;
+  void *alloc = ptr_to_alloc(ptr, orig_size);
+
+#ifdef DO_MEMORY_USAGE
+  assert(orig_size <= _total_heap_array_size);
+  AtomicAdjust::add(_total_heap_array_size, (PN_int32)size-(PN_int32)orig_size);
+#endif  // DO_MEMORY_USAGE
+
+  alloc = call_realloc(alloc, inflate_size(size));
+  if (alloc == (void *)NULL) {
+    cerr << "Out of memory!\n";
+    abort();
+  }
+
+  return alloc_to_ptr(alloc, size);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: MemoryHook::heap_free_array
+//       Access: Public, Virtual
+//  Description: Releases a block of memory previously allocated via
+//               heap_alloc_array.
+////////////////////////////////////////////////////////////////////
+void MemoryHook::
+heap_free_array(void *ptr) {
   size_t size;
   size_t size;
-  ptr = ptr_to_alloc(ptr, size);
-  assert(size <= _total_heap_size);
-  _total_heap_size -= size;
+  void *alloc = ptr_to_alloc(ptr, size);
 
 
+#ifdef DO_MEMORY_USAGE
+  assert(size <= _total_heap_array_size);
+  AtomicAdjust::add(_total_heap_array_size, -(PN_int32)size);
 #endif  // DO_MEMORY_USAGE
 #endif  // DO_MEMORY_USAGE
 
 
-  call_free(ptr);
+  call_free(alloc);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: MemoryHook::heap_trim
+//       Access: Public
+//  Description: Attempts to release memory back to the system, if
+//               possible.  The pad argument is the minimum amount of
+//               unused memory to keep in the heap (against future
+//               allocations).  Any memory above that may be released
+//               to the system, reducing the memory size of this
+//               process.  There is no guarantee that any memory may
+//               be released.
+//
+//               Returns true if any memory was actually released,
+//               false otherwise.
+////////////////////////////////////////////////////////////////////
+bool MemoryHook::
+heap_trim(size_t pad) {
+#if defined(USE_MEMORY_DLMALLOC) || (defined(USE_MEMORY_PTMALLOC2) && !defined(linux))
+  return dlmalloc_trim(pad);
+#else
+  // Since malloc_trim() isn't standard C, we can't be sure it exists
+  // on a given platform.
+  return 0;
+#endif
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////

+ 33 - 10
dtool/src/dtoolbase/memoryHook.h

@@ -20,14 +20,25 @@
 #define MEMORYHOOK_H
 #define MEMORYHOOK_H
 
 
 #include "dtoolbase.h"
 #include "dtoolbase.h"
+#include "numeric_types.h"
+#include "atomicAdjust.h"
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //       Class : MemoryHook
 //       Class : MemoryHook
-// Description : This class is provided to allow the MemoryUsage class
-//               in Panda to insert callback hooks to track the size
-//               of allocated pointers.  Every low-level alloc and
-//               free operation (except in production builds) should
-//               vector through this class to facilitate that.
+// Description : This class provides a wrapper around the various
+//               possible malloc schemes Panda might employ.  It also
+//               exists to allow the MemoryUsage class in Panda to
+//               insert callback hooks to track the size of allocated
+//               pointers.
+//
+//               The PANDA_MALLOC_* and PANDA_FREE_* macros are
+//               defined to vector through through this class (except
+//               in production builds) to facilitate that.  Every
+//               memory allocation call in Panda should therefore use
+//               these macros instead of direct calls to malloc or
+//               free.  (C++ new and delete operators may be employed
+//               for classes which inherit from MemoryBase; otherwise,
+//               use the PANDA_MALLOC macros.)
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 class EXPCL_DTOOL MemoryHook {
 class EXPCL_DTOOL MemoryHook {
 public:
 public:
@@ -35,8 +46,17 @@ public:
   MemoryHook(const MemoryHook &copy);
   MemoryHook(const MemoryHook &copy);
   virtual ~MemoryHook();
   virtual ~MemoryHook();
 
 
-  virtual void *heap_alloc(size_t size);
-  virtual void heap_free(void *ptr);
+  virtual void *heap_alloc_single(size_t size);
+  virtual void heap_free_single(void *ptr);
+
+  virtual void *heap_alloc_array(size_t size);
+  virtual void *heap_realloc_array(void *ptr, size_t size);
+  virtual void heap_free_array(void *ptr);
+
+  INLINE void inc_heap(size_t size);
+  INLINE void dec_heap(size_t size);
+
+  bool heap_trim(size_t pad);
 
 
   virtual void *mmap_alloc(size_t size, bool allow_exec);
   virtual void *mmap_alloc(size_t size, bool allow_exec);
   virtual void mmap_free(void *ptr, size_t size);
   virtual void mmap_free(void *ptr, size_t size);
@@ -48,13 +68,16 @@ public:
 private:
 private:
   size_t _page_size;
   size_t _page_size;
 
 
-#ifdef DO_MEMORY_USAGE
+  INLINE static size_t inflate_size(size_t size);
   INLINE static void *alloc_to_ptr(void *alloc, size_t size);
   INLINE static void *alloc_to_ptr(void *alloc, size_t size);
   INLINE static void *ptr_to_alloc(void *ptr, size_t &size);
   INLINE static void *ptr_to_alloc(void *ptr, size_t &size);
 
 
+#ifdef DO_MEMORY_USAGE
 protected:
 protected:
-  size_t _total_heap_size;
-  size_t _total_mmap_size;
+  TVOLATILE PN_int32 _total_heap_single_size;
+  TVOLATILE PN_int32 _total_heap_array_size;
+  TVOLATILE PN_int32 _requested_heap_size;
+  TVOLATILE PN_int32 _total_mmap_size;
 #endif
 #endif
 };
 };
 
 

+ 2 - 2
dtool/src/dtoolbase/pallocator.T

@@ -55,7 +55,7 @@ allocate(TYPENAME pallocator_array<Type>::size_type n, TYPENAME allocator<void>:
   // We also need to store the total number of bytes we allocated.
   // We also need to store the total number of bytes we allocated.
   alloc_size += sizeof(size_t);
   alloc_size += sizeof(size_t);
   _type_handle.inc_memory_usage(TypeHandle::MC_array, (int)alloc_size);
   _type_handle.inc_memory_usage(TypeHandle::MC_array, (int)alloc_size);
-  void *ptr = (TYPENAME pallocator_array<Type>::pointer)PANDA_MALLOC(alloc_size);
+  void *ptr = (TYPENAME pallocator_array<Type>::pointer)PANDA_MALLOC_ARRAY(alloc_size);
   *((size_t *)ptr) = alloc_size;
   *((size_t *)ptr) = alloc_size;
   return (TYPENAME pallocator_array<Type>::pointer)(((size_t *)ptr) + 1);
   return (TYPENAME pallocator_array<Type>::pointer)(((size_t *)ptr) + 1);
 #else
 #else
@@ -71,7 +71,7 @@ deallocate(TYPENAME pallocator_array<Type>::pointer p, TYPENAME pallocator_array
   // Now we need to recover the total number of bytes.
   // Now we need to recover the total number of bytes.
   size_t alloc_size = *(((size_t *)p) - 1);
   size_t alloc_size = *(((size_t *)p) - 1);
   _type_handle.dec_memory_usage(TypeHandle::MC_array, (int)alloc_size);
   _type_handle.dec_memory_usage(TypeHandle::MC_array, (int)alloc_size);
-  PANDA_FREE(((size_t *)p) - 1);
+  PANDA_FREE_ARRAY(((size_t *)p) - 1);
 #else
 #else
   free(p);
   free(p);
 #endif  // DO_MEMORY_USAGE
 #endif  // DO_MEMORY_USAGE

+ 14 - 2
dtool/src/dtoolbase/ptmalloc2_smp.c → dtool/src/dtoolbase/ptmalloc2_smp_src.cxx

@@ -3473,6 +3473,7 @@ new_heap(size, top_pad) size_t size, top_pad;
   h = (heap_info *)p2;
   h = (heap_info *)p2;
   h->size = size;
   h->size = size;
   THREAD_STAT(stat_n_heaps++);
   THREAD_STAT(stat_n_heaps++);
+  memory_hook->inc_heap(size);
   return h;
   return h;
 }
 }
 
 
@@ -3491,12 +3492,14 @@ grow_heap(h, diff) heap_info *h; long diff;
 
 
   if(diff >= 0) {
   if(diff >= 0) {
     diff = (diff + page_mask) & ~page_mask;
     diff = (diff + page_mask) & ~page_mask;
+    memory_hook->inc_heap(diff);
     new_size = (long)h->size + diff;
     new_size = (long)h->size + diff;
     if(new_size > HEAP_MAX_SIZE)
     if(new_size > HEAP_MAX_SIZE)
       return -1;
       return -1;
     if(mprotect((char *)h + h->size, diff, PROT_READ|PROT_WRITE) != 0)
     if(mprotect((char *)h + h->size, diff, PROT_READ|PROT_WRITE) != 0)
       return -2;
       return -2;
   } else {
   } else {
+    memory_hook->dec_heap(-diff);
     new_size = (long)h->size + diff;
     new_size = (long)h->size + diff;
     if(new_size < (long)sizeof(*h))
     if(new_size < (long)sizeof(*h))
       return -1;
       return -1;
@@ -3513,7 +3516,10 @@ grow_heap(h, diff) heap_info *h; long diff;
 
 
 /* Delete a heap. */
 /* Delete a heap. */
 
 
-#define delete_heap(heap) munmap((char*)(heap), HEAP_MAX_SIZE)
+#define delete_heap(heap) { \
+  munmap((char*)(heap), HEAP_MAX_SIZE); \
+  memory_hook->dec_heap(heap->size); \
+}
 
 
 static int
 static int
 internal_function
 internal_function
@@ -4307,6 +4313,7 @@ top_check()
   /* Call the `morecore' hook if necessary.  */
   /* Call the `morecore' hook if necessary.  */
   if (__after_morecore_hook)
   if (__after_morecore_hook)
     (*__after_morecore_hook) ();
     (*__after_morecore_hook) ();
+  memory_hook->inc_heap(sbrk_size);
   main_arena.system_mem = (new_brk - mp_.sbrk_base) + sbrk_size;
   main_arena.system_mem = (new_brk - mp_.sbrk_base) + sbrk_size;
 
 
   top(&main_arena) = (mchunkptr)(brk + front_misalign);
   top(&main_arena) = (mchunkptr)(brk + front_misalign);
@@ -4920,6 +4927,7 @@ static Void_t* sYSMALLOc(nb, av) INTERNAL_SIZE_T nb; mstate av;
     /* Call the `morecore' hook if necessary.  */
     /* Call the `morecore' hook if necessary.  */
     if (__after_morecore_hook)
     if (__after_morecore_hook)
       (*__after_morecore_hook) ();
       (*__after_morecore_hook) ();
+    memory_hook->inc_heap(size);
   } else {
   } else {
   /*
   /*
     If have mmap, try using it as a backup when MORECORE fails or
     If have mmap, try using it as a backup when MORECORE fails or
@@ -5087,10 +5095,12 @@ static Void_t* sYSMALLOc(nb, av) INTERNAL_SIZE_T nb; mstate av;
           snd_brk = brk + size;
           snd_brk = brk + size;
           correction = 0;
           correction = 0;
           set_noncontiguous(av);
           set_noncontiguous(av);
-        } else
+        } else {
           /* Call the `morecore' hook if necessary.  */
           /* Call the `morecore' hook if necessary.  */
           if (__after_morecore_hook)
           if (__after_morecore_hook)
             (*__after_morecore_hook) ();
             (*__after_morecore_hook) ();
+          memory_hook->inc_heap(correction);
+        }
       }
       }
 
 
       /* handle non-contiguous cases */
       /* handle non-contiguous cases */
@@ -5240,6 +5250,7 @@ static int sYSTRIm(pad, av) size_t pad; mstate av;
       /* Call the `morecore' hook if necessary.  */
       /* Call the `morecore' hook if necessary.  */
       if (__after_morecore_hook)
       if (__after_morecore_hook)
         (*__after_morecore_hook) ();
         (*__after_morecore_hook) ();
+      memory_hook->dec_heap(extra);
       new_brk = (char*)(MORECORE(0));
       new_brk = (char*)(MORECORE(0));
       
       
       if (new_brk != (char*)MORECORE_FAILURE) {
       if (new_brk != (char*)MORECORE_FAILURE) {
@@ -5282,6 +5293,7 @@ munmap_chunk(p) mchunkptr p;
   mp_.mmapped_mem -= (size + p->prev_size);
   mp_.mmapped_mem -= (size + p->prev_size);
 
 
   ret = munmap((char *)p - p->prev_size, size + p->prev_size);
   ret = munmap((char *)p - p->prev_size, size + p->prev_size);
+  memory_hook->dec_heap(size + p->prev_size);
 
 
   /* munmap returns non-zero on failure */
   /* munmap returns non-zero on failure */
   assert(ret == 0);
   assert(ret == 0);

+ 22 - 0
dtool/src/dtoolutil/pandaSystem.cxx

@@ -297,6 +297,28 @@ set_system_tag(const string &system, const string &tag,
   tags[tag] = value;
   tags[tag] = value;
 }
 }
 
 
+////////////////////////////////////////////////////////////////////
+//     Function: PandaSystem::heap_trim
+//       Access: Published
+//  Description: Attempts to release memory back to the system, if
+//               possible.  The pad argument is the minimum amount of
+//               unused memory to keep in the heap (against future
+//               allocations).  Any memory above that may be released
+//               to the system, reducing the memory size of this
+//               process.  There is no guarantee that any memory may
+//               be released.
+//
+//               Returns true if any memory was actually released,
+//               false otherwise.
+////////////////////////////////////////////////////////////////////
+bool PandaSystem::
+heap_trim(size_t pad) {
+  // This actually just vectors into _memory_hook, which isn't
+  // published.  This method only exists on PandaSystem for the
+  // convenience of Python programmers.
+  return memory_hook->heap_trim(pad);
+}
+
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: PandaSystem::output
 //     Function: PandaSystem::output
 //       Access: Published
 //       Access: Published

+ 2 - 0
dtool/src/dtoolutil/pandaSystem.h

@@ -57,6 +57,8 @@ PUBLISHED:
   void set_system_tag(const string &system, const string &tag,
   void set_system_tag(const string &system, const string &tag,
                       const string &value);
                       const string &value);
 
 
+  bool heap_trim(size_t pad);
+
   void output(ostream &out) const;
   void output(ostream &out) const;
   void write(ostream &out) const;
   void write(ostream &out) const;
 
 

+ 7 - 4
panda/src/downloader/bioStreamBuf.cxx

@@ -44,10 +44,10 @@ BioStreamBuf() {
   _is_closed = false;
   _is_closed = false;
 
 
 #ifdef HAVE_IOSTREAM
 #ifdef HAVE_IOSTREAM
-  char *buf = new char[8192];
-  char *ebuf = buf + 8192;
-  char *mbuf = buf + 4096;
-  setg(buf, mbuf, mbuf);
+  _buffer = (char *)PANDA_MALLOC_ARRAY(8192);
+  char *ebuf = _buffer + 8192;
+  char *mbuf = _buffer + 4096;
+  setg(_buffer, mbuf, mbuf);
   setp(mbuf, ebuf);
   setp(mbuf, ebuf);
 
 
 #else
 #else
@@ -70,6 +70,9 @@ BioStreamBuf() {
 BioStreamBuf::
 BioStreamBuf::
 ~BioStreamBuf() {
 ~BioStreamBuf() {
   close();
   close();
+#ifdef HAVE_IOSTREAM
+  PANDA_FREE_ARRAY(_buffer);
+#endif
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////

+ 1 - 0
panda/src/downloader/bioStreamBuf.h

@@ -52,6 +52,7 @@ private:
 
 
   PT(BioPtr) _source;
   PT(BioPtr) _source;
   bool _is_closed;
   bool _is_closed;
+  char *_buffer;
 
 
   friend class IBioStream;
   friend class IBioStream;
   friend class OBioStream;
   friend class OBioStream;

+ 7 - 4
panda/src/downloader/chunkedStreamBuf.cxx

@@ -40,10 +40,10 @@ ChunkedStreamBuf() {
   _read_state = ISocketStream::RS_initial;
   _read_state = ISocketStream::RS_initial;
 
 
 #ifdef HAVE_IOSTREAM
 #ifdef HAVE_IOSTREAM
-  char *buf = new char[4096];
-  char *ebuf = buf + 4096;
-  setg(buf, ebuf, ebuf);
-  setp(buf, ebuf);
+  _buffer = (char *)PANDA_MALLOC_ARRAY(4096);
+  char *ebuf = _buffer + 4096;
+  setg(_buffer, ebuf, ebuf);
+  setp(_buffer, ebuf);
 
 
 #else
 #else
   allocate();
   allocate();
@@ -60,6 +60,9 @@ ChunkedStreamBuf() {
 ChunkedStreamBuf::
 ChunkedStreamBuf::
 ~ChunkedStreamBuf() {
 ~ChunkedStreamBuf() {
   close_read();
   close_read();
+#ifdef HAVE_IOSTREAM
+  PANDA_FREE_ARRAY(_buffer);
+#endif
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////

+ 1 - 0
panda/src/downloader/chunkedStreamBuf.h

@@ -60,6 +60,7 @@ private:
 
 
   PT(HTTPChannel) _doc;
   PT(HTTPChannel) _doc;
   int _read_index;
   int _read_index;
+  char *_buffer;
 
 
   friend class IChunkedStream;
   friend class IChunkedStream;
 };
 };

+ 7 - 4
panda/src/downloader/identityStreamBuf.cxx

@@ -38,10 +38,10 @@ IdentityStreamBuf() {
   _read_state = ISocketStream::RS_initial;
   _read_state = ISocketStream::RS_initial;
 
 
 #ifdef HAVE_IOSTREAM
 #ifdef HAVE_IOSTREAM
-  char *buf = new char[4096];
-  char *ebuf = buf + 4096;
-  setg(buf, ebuf, ebuf);
-  setp(buf, ebuf);
+  _buffer = (char *)PANDA_MALLOC_ARRAY(4096);
+  char *ebuf = _buffer + 4096;
+  setg(_buffer, ebuf, ebuf);
+  setp(_buffer, ebuf);
 
 
 #else
 #else
   allocate();
   allocate();
@@ -58,6 +58,9 @@ IdentityStreamBuf() {
 IdentityStreamBuf::
 IdentityStreamBuf::
 ~IdentityStreamBuf() {
 ~IdentityStreamBuf() {
   close_read();
   close_read();
+#ifdef HAVE_IOSTREAM
+  PANDA_FREE_ARRAY(_buffer);
+#endif
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////

+ 1 - 0
panda/src/downloader/identityStreamBuf.h

@@ -55,6 +55,7 @@ private:
   bool _has_content_length;
   bool _has_content_length;
   size_t _bytes_remaining;
   size_t _bytes_remaining;
   ISocketStream::ReadState _read_state;
   ISocketStream::ReadState _read_state;
+  char *_buffer;
 
 
   friend class IIdentityStream;
   friend class IIdentityStream;
 };
 };

+ 0 - 8
panda/src/downloader/multiplexStreamBuf.h

@@ -21,10 +21,6 @@
 
 
 #include "pandabase.h"
 #include "pandabase.h"
 
 
-#ifdef OLD_HAVE_IPC
-#include <ipc_mutex.h>
-#endif
-
 #include "pvector.h"
 #include "pvector.h"
 #include <stdio.h>
 #include <stdio.h>
 
 
@@ -81,10 +77,6 @@ private:
   Outputs _outputs;
   Outputs _outputs;
 
 
   string _line_buffer;
   string _line_buffer;
-
-#ifdef OLD_HAVE_IPC
-  mutex _lock;
-#endif
 };
 };
 
 
 #include "multiplexStreamBuf.I"
 #include "multiplexStreamBuf.I"

+ 1 - 1
panda/src/downloadertools/multify.cxx

@@ -622,7 +622,7 @@ main(int argc, char *argv[]) {
   // first argument if there is not one already.
   // first argument if there is not one already.
   if (argc >= 2) {
   if (argc >= 2) {
     if (*argv[1] != '-' && *argv[1] != '\0') {
     if (*argv[1] != '-' && *argv[1] != '\0') {
-      char *new_arg = new char[strlen(argv[1]) + 2];
+      char *new_arg = (char *)PANDA_MALLOC_ARRAY(strlen(argv[1]) + 2);
       new_arg[0] = '-';
       new_arg[0] = '-';
       strcpy(new_arg + 1, argv[1]);
       strcpy(new_arg + 1, argv[1]);
       argv[1] = new_arg;
       argv[1] = new_arg;

+ 2 - 2
panda/src/express/buffer.cxx

@@ -26,7 +26,7 @@
 Buffer::
 Buffer::
 Buffer(int size) {
 Buffer(int size) {
   _length = size;
   _length = size;
-  _buffer = new char[_length];
+  _buffer = (char *)PANDA_MALLOC_ARRAY(_length);
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
@@ -36,6 +36,6 @@ Buffer(int size) {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 Buffer::
 Buffer::
 ~Buffer() {
 ~Buffer() {
-  delete _buffer;
+  PANDA_FREE_ARRAY(_buffer);
 }
 }
 
 

+ 44 - 7
panda/src/express/memoryUsage.I

@@ -130,14 +130,43 @@ get_total_cpp_size() {
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-//     Function: MemoryUsage::get_panda_heap_size
+//     Function: MemoryUsage::get_panda_heap_single_size
 //       Access: Public, Static
 //       Access: Public, Static
 //  Description: Returns the total number of bytes allocated from the
 //  Description: Returns the total number of bytes allocated from the
-//               heap from code within Panda.
+//               heap from code within Panda, for individual objects.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 INLINE size_t MemoryUsage::
 INLINE size_t MemoryUsage::
-get_panda_heap_size() {
-  return get_global_ptr()->_total_heap_size;
+get_panda_heap_single_size() {
+  return get_global_ptr()->_total_heap_single_size;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: MemoryUsage::get_panda_heap_array_size
+//       Access: Public, Static
+//  Description: Returns the total number of bytes allocated from the
+//               heap from code within Panda, for arrays.
+////////////////////////////////////////////////////////////////////
+INLINE size_t MemoryUsage::
+get_panda_heap_array_size() {
+  return get_global_ptr()->_total_heap_array_size;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: MemoryUsage::get_panda_heap_overhead
+//       Access: Public, Static
+//  Description: Returns the extra bytes allocated from the system
+//               that are not immediately used for holding allocated
+//               objects.  This can only be determined if
+//               ALTERNATIVE_MALLOC is enabled.
+////////////////////////////////////////////////////////////////////
+INLINE size_t MemoryUsage::
+get_panda_heap_overhead() {
+#if defined(USE_MEMORY_DLMALLOC) || defined(USE_MEMORY_PTMALLOC2)
+  MemoryUsage *mu = get_global_ptr();
+  return mu->_requested_heap_size - mu->_total_heap_single_size - mu->_total_heap_array_size;
+#else
+  return 0;
+#endif
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
@@ -184,7 +213,11 @@ INLINE size_t MemoryUsage::
 get_external_size() {
 get_external_size() {
   MemoryUsage *mu = get_global_ptr();
   MemoryUsage *mu = get_global_ptr();
   if (mu->_count_memory_usage) {
   if (mu->_count_memory_usage) {
-    return mu->_total_size - mu->_total_heap_size;
+#if defined(USE_MEMORY_DLMALLOC) || defined(USE_MEMORY_PTMALLOC2)
+    return mu->_total_size - mu->_total_heap_single_size - mu->_total_heap_array_size - mu->_interpreter_size;
+#else
+    return mu->_total_size - mu->_interpreter_size;
+#endif
   } else {
   } else {
     return 0;
     return 0;
   }
   }
@@ -200,9 +233,13 @@ INLINE size_t MemoryUsage::
 get_total_size() {
 get_total_size() {
   MemoryUsage *mu = get_global_ptr();
   MemoryUsage *mu = get_global_ptr();
   if (mu->_count_memory_usage) {
   if (mu->_count_memory_usage) {
-    return mu->_total_size;
+    return mu->_total_size + mu->_requested_heap_size;
   } else {
   } else {
-    return mu->_total_heap_size;
+#if defined(USE_MEMORY_DLMALLOC) || defined(USE_MEMORY_PTMALLOC2)
+    return mu->_requested_heap_size;
+#else
+    return mu->_total_heap_single_size + mu->_total_heap_array_size;
+#endif
   }
   }
 }
 }
 
 

+ 11 - 11
panda/src/express/memoryUsage.cxx

@@ -187,18 +187,18 @@ choose_bucket(double age) const {
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-//     Function: MemoryUsage::heap_alloc
+//     Function: MemoryUsage::heap_alloc_single
 //       Access: Public, Virtual
 //       Access: Public, Virtual
 //  Description: Allocates a block of memory from the heap, similar to
 //  Description: Allocates a block of memory from the heap, similar to
 //               malloc().  This will never return NULL; it will abort
 //               malloc().  This will never return NULL; it will abort
 //               instead if memory is not available.
 //               instead if memory is not available.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 void *MemoryUsage::
 void *MemoryUsage::
-heap_alloc(size_t size) {
+heap_alloc_single(size_t size) {
   void *ptr;
   void *ptr;
 
 
   if (_recursion_protect) {
   if (_recursion_protect) {
-    ptr = MemoryHook::heap_alloc(size);
+    ptr = MemoryHook::heap_alloc_single(size);
     if (express_cat.is_spam()) {
     if (express_cat.is_spam()) {
       express_cat.spam()
       express_cat.spam()
         << "Allocating pointer " << (void *)ptr
         << "Allocating pointer " << (void *)ptr
@@ -207,7 +207,7 @@ heap_alloc(size_t size) {
 
 
   } else {
   } else {
     if (_track_memory_usage) {
     if (_track_memory_usage) {
-      ptr = MemoryHook::heap_alloc(size);
+      ptr = MemoryHook::heap_alloc_single(size);
       /*
       /*
       if (express_cat.is_spam()) {
       if (express_cat.is_spam()) {
         express_cat.spam()
         express_cat.spam()
@@ -219,7 +219,7 @@ heap_alloc(size_t size) {
       get_global_ptr()->ns_record_void_pointer(ptr, size);
       get_global_ptr()->ns_record_void_pointer(ptr, size);
 
 
     } else {
     } else {
-      ptr = MemoryHook::heap_alloc(size);
+      ptr = MemoryHook::heap_alloc_single(size);
     }
     }
   }
   }
 
 
@@ -227,20 +227,20 @@ heap_alloc(size_t size) {
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-//     Function: MemoryUsage::heap_free
+//     Function: MemoryUsage::heap_free_single
 //       Access: Public, Virtual
 //       Access: Public, Virtual
 //  Description: Releases a block of memory previously allocated via
 //  Description: Releases a block of memory previously allocated via
-//               heap_alloc.
+//               heap_alloc_single.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 void MemoryUsage::
 void MemoryUsage::
-heap_free(void *ptr) {
+heap_free_single(void *ptr) {
   if (_recursion_protect) {
   if (_recursion_protect) {
     if (express_cat.is_spam()) {
     if (express_cat.is_spam()) {
       express_cat.spam()
       express_cat.spam()
         << "Deleting pointer " << (void *)ptr
         << "Deleting pointer " << (void *)ptr
         << " during recursion protect.\n";
         << " during recursion protect.\n";
     }
     }
-    MemoryHook::heap_free(ptr);
+    MemoryHook::heap_free_single(ptr);
 
 
   } else {
   } else {
     if (_track_memory_usage) {
     if (_track_memory_usage) {
@@ -251,9 +251,9 @@ heap_free(void *ptr) {
       }
       }
       */
       */
       ns_remove_void_pointer(ptr);
       ns_remove_void_pointer(ptr);
-      MemoryHook::heap_free(ptr);
+      MemoryHook::heap_free_single(ptr);
     } else {
     } else {
-      MemoryHook::heap_free(ptr);
+      MemoryHook::heap_free_single(ptr);
     }
     }
   }
   }
 }
 }

+ 5 - 3
panda/src/express/memoryUsage.h

@@ -52,8 +52,8 @@ public:
   INLINE static void remove_pointer(ReferenceCount *ptr);
   INLINE static void remove_pointer(ReferenceCount *ptr);
 
 
 public:
 public:
-  virtual void *heap_alloc(size_t size);
-  virtual void heap_free(void *ptr);
+  virtual void *heap_alloc_single(size_t size);
+  virtual void heap_free_single(void *ptr);
   virtual void mark_pointer(void *ptr, size_t orig_size, ReferenceCount *ref_ptr);
   virtual void mark_pointer(void *ptr, size_t orig_size, ReferenceCount *ref_ptr);
 
 
 #if defined(WIN32_VC) && defined(_DEBUG)
 #if defined(WIN32_VC) && defined(_DEBUG)
@@ -68,7 +68,9 @@ PUBLISHED:
   INLINE static size_t get_current_cpp_size();
   INLINE static size_t get_current_cpp_size();
   INLINE static size_t get_total_cpp_size();
   INLINE static size_t get_total_cpp_size();
 
 
-  INLINE static size_t get_panda_heap_size();
+  INLINE static size_t get_panda_heap_single_size();
+  INLINE static size_t get_panda_heap_array_size();
+  INLINE static size_t get_panda_heap_overhead();
   INLINE static size_t get_panda_mmap_size();
   INLINE static size_t get_panda_mmap_size();
   INLINE static size_t get_interpreter_size();
   INLINE static size_t get_interpreter_size();
   INLINE static size_t get_external_size();
   INLINE static size_t get_external_size();

+ 2 - 2
panda/src/express/multifile.cxx

@@ -1611,13 +1611,13 @@ read_index(istream &read, streampos fpos, Multifile *multifile) {
   }
   }
 
 
   // And finally, get the rest of the name.
   // And finally, get the rest of the name.
-  char *name_buffer = new char[name_length];
+  char *name_buffer = (char *)PANDA_MALLOC_ARRAY(name_length);
   nassertr(name_buffer != (char *)NULL, next_index);
   nassertr(name_buffer != (char *)NULL, next_index);
   for (size_t ni = 0; ni < name_length; ni++) {
   for (size_t ni = 0; ni < name_length; ni++) {
     name_buffer[ni] = read.get() ^ 0xff;
     name_buffer[ni] = read.get() ^ 0xff;
   }
   }
   _name = string(name_buffer, name_length);
   _name = string(name_buffer, name_length);
-  delete[] name_buffer;
+  PANDA_FREE_ARRAY(name_buffer);
 
 
   if (read.eof() || read.fail()) {
   if (read.eof() || read.fail()) {
     _flags |= SF_index_invalid;
     _flags |= SF_index_invalid;

+ 2 - 2
panda/src/express/password_hash.cxx

@@ -62,7 +62,7 @@ string
 password_hash(const string &password, const string &salt,
 password_hash(const string &password, const string &salt,
               int iters, int keylen) {
               int iters, int keylen) {
   nassertr(iters > 0 && keylen > 0, string());
   nassertr(iters > 0 && keylen > 0, string());
-  unsigned char *dk = new unsigned char[keylen];
+  unsigned char *dk = (unsigned char *)PANDA_MALLOC_ARRAY(keylen);
   int result =
   int result =
     PKCS5_PBKDF2_HMAC_SHA1((const char *)password.data(), password.length(),
     PKCS5_PBKDF2_HMAC_SHA1((const char *)password.data(), password.length(),
                            (unsigned char *)salt.data(), salt.length(),
                            (unsigned char *)salt.data(), salt.length(),
@@ -70,7 +70,7 @@ password_hash(const string &password, const string &salt,
   nassertr(result > 0, string());
   nassertr(result > 0, string());
 
 
   string hash((char *)dk, keylen);
   string hash((char *)dk, keylen);
-  delete[] dk;
+  PANDA_FREE_ARRAY(dk);
   return hash;
   return hash;
 }
 }
 
 

+ 13 - 13
panda/src/express/patchfile.cxx

@@ -144,7 +144,7 @@ init(PT(Buffer) buffer) {
 Patchfile::
 Patchfile::
 ~Patchfile() {
 ~Patchfile() {
   if (_hash_table != (PN_uint32 *)NULL) {
   if (_hash_table != (PN_uint32 *)NULL) {
-    delete[] _hash_table;
+    PANDA_FREE_ARRAY(_hash_table);
   }
   }
 
 
   if (true == _initiated)
   if (true == _initiated)
@@ -993,7 +993,7 @@ compute_file_patches(ostream &write_stream,
       << "Allocating " << source_file_length << " bytes to read orig\n";
       << "Allocating " << source_file_length << " bytes to read orig\n";
   }
   }
 
 
-  char *buffer_orig = new char[source_file_length];
+  char *buffer_orig = (char *)PANDA_MALLOC_ARRAY(source_file_length);
   stream_orig.seekg(0, ios::beg);
   stream_orig.seekg(0, ios::beg);
   stream_orig.read(buffer_orig, source_file_length);
   stream_orig.read(buffer_orig, source_file_length);
 
 
@@ -1006,7 +1006,7 @@ compute_file_patches(ostream &write_stream,
       << "Allocating " << result_file_length << " bytes to read new\n";
       << "Allocating " << result_file_length << " bytes to read new\n";
   }
   }
 
 
-  char *buffer_new = new char[result_file_length];
+  char *buffer_new = (char *)PANDA_MALLOC_ARRAY(result_file_length);
   stream_new.seekg(0, ios::beg);
   stream_new.seekg(0, ios::beg);
   stream_new.read(buffer_new, result_file_length);
   stream_new.read(buffer_new, result_file_length);
 
 
@@ -1024,7 +1024,7 @@ compute_file_patches(ostream &write_stream,
       << "Allocating linktable of size " << source_file_length << " * 4\n";
       << "Allocating linktable of size " << source_file_length << " * 4\n";
   }
   }
 
 
-  PN_uint32* link_table = new PN_uint32[source_file_length];
+  PN_uint32 *link_table = (PN_uint32 *)PANDA_MALLOC_ARRAY(source_file_length * sizeof(PN_uint32));
 
 
   // build hash and link tables for original file
   // build hash and link tables for original file
   build_hash_link_tables(buffer_orig, source_file_length, _hash_table, link_table);
   build_hash_link_tables(buffer_orig, source_file_length, _hash_table, link_table);
@@ -1082,10 +1082,10 @@ compute_file_patches(ostream &write_stream,
     start_pos += remaining_bytes;
     start_pos += remaining_bytes;
   }
   }
 
 
-  delete[] link_table;
+  PANDA_FREE_ARRAY(link_table);
 
 
-  delete[] buffer_orig;
-  delete[] buffer_new;
+  PANDA_FREE_ARRAY(buffer_orig);
+  PANDA_FREE_ARRAY(buffer_new);
 
 
   return true;
   return true;
 }
 }
@@ -1148,11 +1148,11 @@ compute_mf_patches(ostream &write_stream,
 
 
       streampos new_start = mf_new.get_subfile_internal_start(ni);
       streampos new_start = mf_new.get_subfile_internal_start(ni);
       size_t new_size = mf_new.get_subfile_internal_length(ni);
       size_t new_size = mf_new.get_subfile_internal_length(ni);
-      char *buffer_new = new char[new_size];
+      char *buffer_new = (char *)PANDA_MALLOC_ARRAY(new_size);
       stream_new.seekg(new_start, ios::beg);
       stream_new.seekg(new_start, ios::beg);
       stream_new.read(buffer_new, new_size);
       stream_new.read(buffer_new, new_size);
       cache_add_and_copy(write_stream, new_size, buffer_new, 0, 0);
       cache_add_and_copy(write_stream, new_size, buffer_new, 0, 0);
-      delete[] buffer_new;
+      PANDA_FREE_ARRAY(buffer_new);
 
 
     } else {
     } else {
       // This subfile exists in both the original and the new files.
       // This subfile exists in both the original and the new files.
@@ -1283,11 +1283,11 @@ compute_tar_patches(ostream &write_stream,
 
 
       streampos new_start = sf_new._header_start;
       streampos new_start = sf_new._header_start;
       size_t new_size = sf_new._end - sf_new._header_start;
       size_t new_size = sf_new._end - sf_new._header_start;
-      char *buffer_new = new char[new_size];
+      char *buffer_new = (char *)PANDA_MALLOC_ARRAY(new_size);
       stream_new.seekg(new_start, ios::beg);
       stream_new.seekg(new_start, ios::beg);
       stream_new.read(buffer_new, new_size);
       stream_new.read(buffer_new, new_size);
       cache_add_and_copy(write_stream, new_size, buffer_new, 0, 0);
       cache_add_and_copy(write_stream, new_size, buffer_new, 0, 0);
-      delete[] buffer_new;
+      PANDA_FREE_ARRAY(buffer_new);
 
 
     } else {
     } else {
       // This subfile exists in both the original and the new files.
       // This subfile exists in both the original and the new files.
@@ -1486,7 +1486,7 @@ do_compute_patches(const Filename &file_orig, const Filename &file_new,
       // Read the first n bytes of both files for the Multifile magic
       // Read the first n bytes of both files for the Multifile magic
       // number.
       // number.
       string magic_number = Multifile::get_magic_number();
       string magic_number = Multifile::get_magic_number();
-      char *buffer = new char[magic_number.size()];
+      char *buffer = (char *)PANDA_MALLOC_ARRAY(magic_number.size());
       stream_orig.seekg(0, ios::beg);
       stream_orig.seekg(0, ios::beg);
       stream_orig.read(buffer, magic_number.size());
       stream_orig.read(buffer, magic_number.size());
       
       
@@ -1499,7 +1499,7 @@ do_compute_patches(const Filename &file_orig, const Filename &file_new,
           is_multifile = true;
           is_multifile = true;
         }
         }
       }
       }
-      delete[] buffer;
+      PANDA_FREE_ARRAY(buffer);
     }
     }
 #ifdef HAVE_TAR
 #ifdef HAVE_TAR
     if (strstr(file_orig.get_basename().c_str(), ".tar") != NULL ||
     if (strstr(file_orig.get_basename().c_str(), ".tar") != NULL ||

+ 2 - 2
panda/src/express/profileTimer.cxx

@@ -64,7 +64,7 @@ ProfileTimer(const ProfileTimer& other) {
 
 
 ProfileTimer::
 ProfileTimer::
 ~ProfileTimer() {
 ~ProfileTimer() {
-  delete [] _entries;
+  PANDA_FREE_ARRAY(_entries);
   // Remove this from the list:
   // Remove this from the list:
   if (_head==this) {
   if (_head==this) {
     _head=_next;
     _head=_next;
@@ -86,7 +86,7 @@ void ProfileTimer::
 init(const char* name, int maxEntries) {
 init(const char* name, int maxEntries) {
   _name=name;
   _name=name;
   _maxEntries=maxEntries;
   _maxEntries=maxEntries;
-  _entries=new TimerEntry[_maxEntries];
+  _entries = (TimerEntry *)PANDA_MALLOC_ARRAY(_maxEntries * sizeof(TimerEntry));
   _entryCount=0;
   _entryCount=0;
   _elapsedTime=0.0;
   _elapsedTime=0.0;
   _on=0.0;
   _on=0.0;

+ 6 - 3
panda/src/express/subStreamBuf.cxx

@@ -57,9 +57,9 @@ SubStreamBuf() {
 
 
 #ifdef HAVE_IOSTREAM
 #ifdef HAVE_IOSTREAM
   // The new-style iostream library doesn't seem to support allocate().
   // The new-style iostream library doesn't seem to support allocate().
-  char *buf = new char[4096];
-  char *ebuf = buf + 4096;
-  setg(buf, ebuf, ebuf);
+  _buffer = (char *)PANDA_MALLOC_ARRAY(4096);
+  char *ebuf = _buffer + 4096;
+  setg(_buffer, ebuf, ebuf);
 
 
 #else
 #else
   allocate();
   allocate();
@@ -75,6 +75,9 @@ SubStreamBuf() {
 SubStreamBuf::
 SubStreamBuf::
 ~SubStreamBuf() {
 ~SubStreamBuf() {
   close();
   close();
+#ifdef HAVE_IOSTREAM
+  PANDA_FREE_ARRAY(_buffer);
+#endif
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////

+ 1 - 0
panda/src/express/subStreamBuf.h

@@ -48,6 +48,7 @@ private:
   streampos _end;
   streampos _end;
   streampos _cur;
   streampos _cur;
   size_t _unused;
   size_t _unused;
+  char *_buffer;
   MutexImpl _lock;
   MutexImpl _lock;
 };
 };
 
 

+ 3 - 4
panda/src/express/test_zstream.cxx

@@ -59,7 +59,7 @@ zlib_decompress(istream &source) {
   size_t source_len = data.length();
   size_t source_len = data.length();
   // Take a stab on the appropriate size of the output buffer.
   // Take a stab on the appropriate size of the output buffer.
   size_t dest_len = source_len * 4;
   size_t dest_len = source_len * 4;
-  char *dest = new char[dest_len];
+  char *dest = (char *)PANDA_MALLOC_ARRAY(dest_len);
 
 
   uLongf actual_dest_len = dest_len;
   uLongf actual_dest_len = dest_len;
   int result = uncompress((Bytef *)dest, &actual_dest_len, 
   int result = uncompress((Bytef *)dest, &actual_dest_len, 
@@ -71,8 +71,7 @@ zlib_decompress(istream &source) {
   while (result == Z_BUF_ERROR) {
   while (result == Z_BUF_ERROR) {
     dest_len *= 2;
     dest_len *= 2;
     cerr << "Increasing buffer size to " << dest_len << "\n";
     cerr << "Increasing buffer size to " << dest_len << "\n";
-    delete[] dest;
-    dest = new char[dest_len];
+    dest = PANDA_REALLOC_ARRAY(dest, dest_len);
 
 
     actual_dest_len = dest_len;
     actual_dest_len = dest_len;
     result = uncompress((Bytef *)dest, &actual_dest_len, 
     result = uncompress((Bytef *)dest, &actual_dest_len, 
@@ -99,7 +98,7 @@ zlib_compress(istream &source) {
   // Now call zlib to compress the buffer directly.
   // Now call zlib to compress the buffer directly.
   size_t source_len = data.length();
   size_t source_len = data.length();
   size_t dest_len = (size_t)(source_len * 1.1) + 12;
   size_t dest_len = (size_t)(source_len * 1.1) + 12;
-  char *dest = new char[dest_len];
+  char *dest = (char *)PANDA_MALLOC_ARRAY(dest_len);
 
 
   uLongf actual_dest_len = dest_len;
   uLongf actual_dest_len = dest_len;
   int result = compress((Bytef *)dest, &actual_dest_len, 
   int result = compress((Bytef *)dest, &actual_dest_len, 

+ 4 - 4
panda/src/express/windowsRegistry.cxx

@@ -296,7 +296,7 @@ do_get(const string &key, const string &name, int &data_type, string &data) {
     // guessing bigger and bigger until we got it.  Since we're
     // guessing bigger and bigger until we got it.  Since we're
     // querying static data for now, we can just use the size Windows
     // querying static data for now, we can just use the size Windows
     // tells us.
     // tells us.
-    char *new_buffer = new char[buffer_size];
+    char *new_buffer = (char *)PANDA_MALLOC_ARRAY(buffer_size);
     error =
     error =
       RegQueryValueEx(hkey, name.c_str(), 0, &dw_data_type, 
       RegQueryValueEx(hkey, name.c_str(), 0, &dw_data_type, 
                       (BYTE *)new_buffer, &buffer_size);
                       (BYTE *)new_buffer, &buffer_size);
@@ -310,7 +310,7 @@ do_get(const string &key, const string &name, int &data_type, string &data) {
       }
       }
       data = string(new_buffer, buffer_size);
       data = string(new_buffer, buffer_size);
     }
     }
-    delete new_buffer;
+    PANDA_FREE_ARRAY(new_buffer);
   }
   }
 
 
   if (error != ERROR_SUCCESS) {
   if (error != ERROR_SUCCESS) {
@@ -331,10 +331,10 @@ do_get(const string &key, const string &name, int &data_type, string &data) {
     if (data_type == REG_EXPAND_SZ) {
     if (data_type == REG_EXPAND_SZ) {
       // Expand the string.
       // Expand the string.
       DWORD destSize=ExpandEnvironmentStrings(data.c_str(), 0, 0);
       DWORD destSize=ExpandEnvironmentStrings(data.c_str(), 0, 0);
-      char *dest = new char[destSize];
+      char *dest = (char *)PANDA_MALLOC_ARRAY(destSize);
       ExpandEnvironmentStrings(data.c_str(), dest, destSize);
       ExpandEnvironmentStrings(data.c_str(), dest, destSize);
       data = dest;
       data = dest;
-      delete[] dest;
+      PANDA_FREE_ARRAY(dest);
       data_type = REG_SZ;
       data_type = REG_SZ;
     }
     }
   }
   }

+ 7 - 4
panda/src/express/zStreamBuf.cxx

@@ -41,10 +41,10 @@ ZStreamBuf() {
   _owns_dest = false;
   _owns_dest = false;
 
 
 #ifdef HAVE_IOSTREAM
 #ifdef HAVE_IOSTREAM
-  char *buf = new char[4096];
-  char *ebuf = buf + 4096;
-  setg(buf, ebuf, ebuf);
-  setp(buf, ebuf);
+  _buffer = (char *)PANDA_MALLOC_ARRAY(4096);
+  char *ebuf = _buffer + 4096;
+  setg(_buffer, ebuf, ebuf);
+  setp(_buffer, ebuf);
 
 
 #else
 #else
   allocate();
   allocate();
@@ -62,6 +62,9 @@ ZStreamBuf::
 ~ZStreamBuf() {
 ~ZStreamBuf() {
   close_read();
   close_read();
   close_write();
   close_write();
+#ifdef HAVE_IOSTREAM
+  PANDA_FREE_ARRAY(_buffer);
+#endif
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////

+ 2 - 0
panda/src/express/zStreamBuf.h

@@ -62,6 +62,8 @@ private:
   z_stream _z_source;
   z_stream _z_source;
   z_stream _z_dest;
   z_stream _z_dest;
 
 
+  char *_buffer;
+
   // We need to store the decompression buffer on the class object,
   // We need to store the decompression buffer on the class object,
   // because zlib might not consume all of the input characters at
   // because zlib might not consume all of the input characters at
   // each call to inflate().  This isn't a problem on output because
   // each call to inflate().  This isn't a problem on output because

+ 4 - 4
panda/src/glstuff/glGraphicsStateGuardian_src.cxx

@@ -526,7 +526,7 @@ reset() {
 
 
     GLint num_compressed_formats;
     GLint num_compressed_formats;
     GLP(GetIntegerv)(GL_NUM_COMPRESSED_TEXTURE_FORMATS, &num_compressed_formats);
     GLP(GetIntegerv)(GL_NUM_COMPRESSED_TEXTURE_FORMATS, &num_compressed_formats);
-    GLint *formats = new GLint[num_compressed_formats];
+    GLint *formats = (GLint *)PANDA_MALLOC_ARRAY(num_compressed_formats * sizeof(GLint));
     GLP(GetIntegerv)(GL_COMPRESSED_TEXTURE_FORMATS, formats);
     GLP(GetIntegerv)(GL_COMPRESSED_TEXTURE_FORMATS, formats);
     for (int i = 0; i < num_compressed_formats; ++i) {
     for (int i = 0; i < num_compressed_formats; ++i) {
       switch (formats[i]) {
       switch (formats[i]) {
@@ -552,7 +552,7 @@ reset() {
         break;
         break;
       }
       }
     }
     }
-    delete[] formats;
+    PANDA_FREE_ARRAY(formats);
   }
   }
 
 
   _supports_bgr =
   _supports_bgr =
@@ -956,7 +956,7 @@ reset() {
       } else {
       } else {
         GLCAT.debug()
         GLCAT.debug()
           << "Supported compressed texture formats:\n";
           << "Supported compressed texture formats:\n";
-        GLint *formats = new GLint[num_compressed_formats];
+        GLint *formats = (GLint *)PANDA_MALLOC_ARRAY(num_compressed_formats * sizeof(GLint));
         GLP(GetIntegerv)(GL_COMPRESSED_TEXTURE_FORMATS, formats);
         GLP(GetIntegerv)(GL_COMPRESSED_TEXTURE_FORMATS, formats);
         for (int i = 0; i < num_compressed_formats; ++i) {
         for (int i = 0; i < num_compressed_formats; ++i) {
           switch (formats[i]) {
           switch (formats[i]) {
@@ -990,7 +990,7 @@ reset() {
               << dec << "\n";
               << dec << "\n";
           }
           }
         }
         }
-        delete[] formats;
+        PANDA_FREE_ARRAY(formats);
       }
       }
     }
     }
   }
   }

+ 8 - 8
panda/src/gobj/vertexDataBuffer.cxx

@@ -34,13 +34,13 @@ operator = (const VertexDataBuffer &copy) {
   if (_resident_data != (unsigned char *)NULL) {
   if (_resident_data != (unsigned char *)NULL) {
     nassertv(_size != 0);
     nassertv(_size != 0);
     get_class_type().dec_memory_usage(TypeHandle::MC_array, (int)_size);
     get_class_type().dec_memory_usage(TypeHandle::MC_array, (int)_size);
-    free(_resident_data);
+    PANDA_FREE_ARRAY(_resident_data);
     _resident_data = NULL;
     _resident_data = NULL;
   }
   }
   if (copy._resident_data != (unsigned char *)NULL) {
   if (copy._resident_data != (unsigned char *)NULL) {
     nassertv(copy._size != 0);
     nassertv(copy._size != 0);
     get_class_type().inc_memory_usage(TypeHandle::MC_array, (int)copy._size);
     get_class_type().inc_memory_usage(TypeHandle::MC_array, (int)copy._size);
-    _resident_data = (unsigned char *)malloc(copy._size);
+    _resident_data = (unsigned char *)PANDA_MALLOC_ARRAY(copy._size);
     memcpy(_resident_data, copy._resident_data, copy._size);
     memcpy(_resident_data, copy._resident_data, copy._size);
   }
   }
   _size = copy._size;
   _size = copy._size;
@@ -73,10 +73,10 @@ do_clean_realloc(size_t size) {
     get_class_type().inc_memory_usage(TypeHandle::MC_array, (int)size - (int)_size);
     get_class_type().inc_memory_usage(TypeHandle::MC_array, (int)size - (int)_size);
     if (_size == 0) {
     if (_size == 0) {
       nassertv(_resident_data == (unsigned char *)NULL);
       nassertv(_resident_data == (unsigned char *)NULL);
-      _resident_data = (unsigned char *)malloc(size);
+      _resident_data = (unsigned char *)PANDA_MALLOC_ARRAY(size);
     } else {
     } else {
       nassertv(_resident_data != (unsigned char *)NULL);
       nassertv(_resident_data != (unsigned char *)NULL);
-      _resident_data = (unsigned char *)realloc(_resident_data, size);
+      _resident_data = (unsigned char *)PANDA_REALLOC_ARRAY(_resident_data, size);
     }
     }
     nassertv(_resident_data != (unsigned char *)NULL);
     nassertv(_resident_data != (unsigned char *)NULL);
     _size = size;
     _size = size;
@@ -102,7 +102,7 @@ do_unclean_realloc(size_t size) {
       nassertv(_size != 0);
       nassertv(_size != 0);
 
 
       get_class_type().dec_memory_usage(TypeHandle::MC_array, (int)_size);
       get_class_type().dec_memory_usage(TypeHandle::MC_array, (int)_size);
-      free(_resident_data);
+      PANDA_FREE_ARRAY(_resident_data);
       _resident_data = NULL;
       _resident_data = NULL;
       _size = 0;
       _size = 0;
     }
     }
@@ -110,7 +110,7 @@ do_unclean_realloc(size_t size) {
     if (size != 0) {
     if (size != 0) {
       get_class_type().inc_memory_usage(TypeHandle::MC_array, (int)size);
       get_class_type().inc_memory_usage(TypeHandle::MC_array, (int)size);
       nassertv(_resident_data == (unsigned char *)NULL);
       nassertv(_resident_data == (unsigned char *)NULL);
-      _resident_data = (unsigned char *)malloc(size);
+      _resident_data = (unsigned char *)PANDA_MALLOC_ARRAY(size);
     }
     }
 
 
     _size = size;
     _size = size;
@@ -144,7 +144,7 @@ do_page_out(VertexDataBook &book) {
   memcpy(pointer, _resident_data, _size);
   memcpy(pointer, _resident_data, _size);
 
 
   get_class_type().dec_memory_usage(TypeHandle::MC_array, (int)_size);
   get_class_type().dec_memory_usage(TypeHandle::MC_array, (int)_size);
-  free(_resident_data);
+  PANDA_FREE_ARRAY(_resident_data);
   _resident_data = NULL;
   _resident_data = NULL;
 }
 }
 
 
@@ -167,7 +167,7 @@ do_page_in() {
   nassertv(_block != (VertexDataBlock *)NULL);
   nassertv(_block != (VertexDataBlock *)NULL);
 
 
   get_class_type().inc_memory_usage(TypeHandle::MC_array, (int)_size);
   get_class_type().inc_memory_usage(TypeHandle::MC_array, (int)_size);
-  _resident_data = (unsigned char *)malloc(_size);
+  _resident_data = (unsigned char *)PANDA_MALLOC_ARRAY(_size);
   nassertv(_resident_data != (unsigned char *)NULL);
   nassertv(_resident_data != (unsigned char *)NULL);
   
   
   memcpy(_resident_data, _block->get_pointer(true), _size);
   memcpy(_resident_data, _block->get_pointer(true), _size);

+ 3 - 2
panda/src/gobj/vertexDataPage.cxx

@@ -81,6 +81,7 @@ PStatCollector VertexDataPage::_vdata_decompress_pcollector("*:Vertex Data:Decom
 PStatCollector VertexDataPage::_vdata_save_pcollector("*:Vertex Data:Save");
 PStatCollector VertexDataPage::_vdata_save_pcollector("*:Vertex Data:Save");
 PStatCollector VertexDataPage::_vdata_restore_pcollector("*:Vertex Data:Restore");
 PStatCollector VertexDataPage::_vdata_restore_pcollector("*:Vertex Data:Restore");
 PStatCollector VertexDataPage::_thread_wait_pcollector("*:Wait:Idle");
 PStatCollector VertexDataPage::_thread_wait_pcollector("*:Wait:Idle");
+PStatCollector VertexDataPage::_alloc_pages_pcollector("System memory:MMap:Vertex data");
 
 
 TypeHandle VertexDataPage::_type_handle;
 TypeHandle VertexDataPage::_type_handle;
 
 
@@ -619,7 +620,7 @@ make_save_file() {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 unsigned char *VertexDataPage::
 unsigned char *VertexDataPage::
 alloc_page_data(size_t page_size) const {
 alloc_page_data(size_t page_size) const {
-  get_class_type().inc_memory_usage(TypeHandle::MC_array, page_size);
+  _alloc_pages_pcollector.add_level_now(page_size);
   return (unsigned char *)memory_hook->mmap_alloc(page_size, false);
   return (unsigned char *)memory_hook->mmap_alloc(page_size, false);
 }
 }
 
 
@@ -630,7 +631,7 @@ alloc_page_data(size_t page_size) const {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 void VertexDataPage::
 void VertexDataPage::
 free_page_data(unsigned char *page_data, size_t page_size) const {
 free_page_data(unsigned char *page_data, size_t page_size) const {
-  get_class_type().dec_memory_usage(TypeHandle::MC_array, page_size);
+  _alloc_pages_pcollector.sub_level_now(page_size);
   memory_hook->mmap_free(page_data, page_size);
   memory_hook->mmap_free(page_data, page_size);
 }
 }
  
  

+ 1 - 0
panda/src/gobj/vertexDataPage.h

@@ -160,6 +160,7 @@ private:
   static PStatCollector _vdata_save_pcollector;
   static PStatCollector _vdata_save_pcollector;
   static PStatCollector _vdata_restore_pcollector;
   static PStatCollector _vdata_restore_pcollector;
   static PStatCollector _thread_wait_pcollector;
   static PStatCollector _thread_wait_pcollector;
+  static PStatCollector _alloc_pages_pcollector;
 
 
 public:
 public:
   static TypeHandle get_class_type() {
   static TypeHandle get_class_type() {

+ 9 - 6
panda/src/ode/odeTriMeshData.cxx

@@ -74,7 +74,7 @@ OdeTriMeshData(const NodePath& model, bool use_normals) :
   _id(dGeomTriMeshDataCreate()),
   _id(dGeomTriMeshDataCreate()),
   _vertices(0),
   _vertices(0),
   _faces(0),
   _faces(0),
-  _normals(false),
+  _normals(0),
   _num_vertices(0),
   _num_vertices(0),
   _num_faces(0) {
   _num_faces(0) {
   odetrimeshdata_cat.debug() << get_type() << "(" << _id << ")" << "\n";
   odetrimeshdata_cat.debug() << get_type() << "(" << _id << ")" << "\n";
@@ -105,16 +105,19 @@ OdeTriMeshData::
   odetrimeshdata_cat.debug() << "~" << get_type() << "(" << _id << ")" << "\n";
   odetrimeshdata_cat.debug() << "~" << get_type() << "(" << _id << ")" << "\n";
   destroy();
   destroy();
   if (_vertices != 0) {
   if (_vertices != 0) {
-    delete[] _vertices;
+    PANDA_FREE_ARRAY(_vertices);
     _vertices = 0;
     _vertices = 0;
     _num_vertices = 0;
     _num_vertices = 0;
   }
   }
   if (_faces != 0) {
   if (_faces != 0) {
-    delete[] _faces;
+    PANDA_FREE_ARRAY(_faces);
     _faces = 0;
     _faces = 0;
   }
   }
   if (_normals != 0) {
   if (_normals != 0) {
-    delete[] _normals;
+    // This is never allocated?  Until we use _normals, assert that we
+    // don't accidentally free it here through some mistake.
+    nassertv(false);
+    PANDA_FREE_ARRAY(_normals);
   }
   }
 }
 }
 
 
@@ -151,8 +154,8 @@ process_model(const NodePath& model, bool &use_normals) {
   odetrimeshdata_cat.debug() << "Found " << _num_vertices << " vertices.\n";
   odetrimeshdata_cat.debug() << "Found " << _num_vertices << " vertices.\n";
   odetrimeshdata_cat.debug() << "Found " << _num_faces << " faces.\n";
   odetrimeshdata_cat.debug() << "Found " << _num_faces << " faces.\n";
   
   
-  _vertices = new StridedVertex[_num_vertices];
-  _faces = new StridedTri[_num_faces];
+  _vertices = (StridedVertex *)PANDA_MALLOC_ARRAY(_num_vertices * sizeof(StridedVertex));
+  _faces = (StridedTri *)PANDA_MALLOC_ARRAY(_num_faces * sizeof(StridedTri));
   
   
   _num_vertices = 0, _num_faces = 0;
   _num_vertices = 0, _num_faces = 0;
 
 

+ 3 - 3
panda/src/ode/odeUtil.cxx

@@ -29,15 +29,15 @@ OdeJointCollection OdeUtil::
 get_connecting_joint_list(const OdeBody &body1, const OdeBody &body2) {
 get_connecting_joint_list(const OdeBody &body1, const OdeBody &body2) {
   const int max_possible_joints = min(body1.get_num_joints(), body1.get_num_joints());
   const int max_possible_joints = min(body1.get_num_joints(), body1.get_num_joints());
 
 
-  dJointID *joint_list = new dJointID[max_possible_joints];
+  dJointID *joint_list = (dJointID *)PANDA_MALLOC_ARRAY(max_possible_joints * sizeof(dJointID));
   int num_joints = dConnectingJointList(body1.get_id(), body2.get_id(),
   int num_joints = dConnectingJointList(body1.get_id(), body2.get_id(),
 					joint_list);
 					joint_list);
   OdeJointCollection joints;
   OdeJointCollection joints;
   for (int i = 0; i < num_joints; i++) {
   for (int i = 0; i < num_joints; i++) {
     joints.add_joint(OdeJoint(joint_list[i]));
     joints.add_joint(OdeJoint(joint_list[i]));
   }
   }
-  
-  delete[] joint_list;
+
+  PANDA_FREE_ARRAY(joint_list);
   return joints;
   return joints;
 }
 }
 
 

+ 2 - 2
panda/src/osxdisplay/osxGraphicsPipe.cxx

@@ -136,7 +136,7 @@ create_cg_image(const PNMImage &pnm_image) {
 
 
   // Now convert the pixel data to a format friendly to
   // Now convert the pixel data to a format friendly to
   // CGImageCreate().
   // CGImageCreate().
-  char *char_array = new char[num_bytes];
+  char *char_array = (char *)PANDA_MALLOC_ARRAY(num_bytes);
 
 
   xelval *dp = (xelval *)char_array;
   xelval *dp = (xelval *)char_array;
   for (size_t yi = 0; yi < height; ++yi) {
   for (size_t yi = 0; yi < height; ++yi) {
@@ -180,7 +180,7 @@ create_cg_image(const PNMImage &pnm_image) {
 void osxGraphicsPipe::
 void osxGraphicsPipe::
 release_data(void *info, const void *data, size_t size) {
 release_data(void *info, const void *data, size_t size) {
   char *char_array = (char *)data;
   char *char_array = (char *)data;
-  delete[] char_array;
+  PANDA_FREE_ARRAY(char_array);
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////

+ 2 - 2
panda/src/particlesystem/spriteParticleRenderer.cxx

@@ -473,7 +473,7 @@ init_geoms() {
   
   
   // Reset render() data structures
   // Reset render() data structures
   for (i = 0; i < (int)_ttl_count.size(); ++i) {
   for (i = 0; i < (int)_ttl_count.size(); ++i) {
-    delete [] _ttl_count[i];
+    PANDA_FREE_ARRAY(_ttl_count[i]);
   }
   }
   _anim_size.resize(anim_count);
   _anim_size.resize(anim_count);
   _ttl_count.clear();
   _ttl_count.clear();
@@ -500,7 +500,7 @@ init_geoms() {
 
 
     // For each frame of the animation...
     // For each frame of the animation...
     for (j = 0; j < _anim_size[i]; ++j) {
     for (j = 0; j < _anim_size[i]; ++j) {
-      _ttl_count[i] = new int[_anim_size[i]];
+      _ttl_count[i] = (int *)PANDA_MALLOC_ARRAY(_anim_size[i] * sizeof(int));
       _vdata[i].push_back(new GeomVertexData("particles", format, Geom::UH_dynamic));
       _vdata[i].push_back(new GeomVertexData("particles", format, Geom::UH_dynamic));
       PT(Geom) geom = new Geom(_vdata[i][j]);
       PT(Geom) geom = new Geom(_vdata[i][j]);
       _sprite_primitive[i].push_back((Geom*)geom);
       _sprite_primitive[i].push_back((Geom*)geom);

+ 12 - 12
panda/src/pnmimage/pnm-image-filter-core.cxx

@@ -33,19 +33,19 @@ FUNCTION_NAME(PNMImage &dest, const PNMImage &source,
   // adjusted xel data from our first pass.
   // adjusted xel data from our first pass.
 
 
   typedef StoreType *StoreTypeP;
   typedef StoreType *StoreTypeP;
-  StoreType **matrix = new StoreTypeP[dest.ASIZE()];
+  StoreType **matrix = (StoreType **)PANDA_MALLOC_ARRAY(dest.ASIZE() * sizeof(StoreType *));
 
 
   int a, b;
   int a, b;
 
 
   for (a=0; a<dest.ASIZE(); a++) {
   for (a=0; a<dest.ASIZE(); a++) {
-    matrix[a] = new StoreType[source.BSIZE()];
+    matrix[a] = (StoreType *)PANDA_MALLOC_ARRAY(source.BSIZE() * sizeof(StoreType));
   }
   }
 
 
   // Now, scale the image in the A direction.
   // Now, scale the image in the A direction.
   double scale = (double)dest.ASIZE() / (double)source.ASIZE();
   double scale = (double)dest.ASIZE() / (double)source.ASIZE();
 
 
-  StoreType *temp_source = new StoreType[source.ASIZE()];
-  StoreType *temp_dest = new StoreType[dest.ASIZE()];
+  StoreType *temp_source = (StoreType *)PANDA_MALLOC_ARRAY(source.ASIZE() * sizeof(StoreType));
+  StoreType *temp_dest = (StoreType *)PANDA_MALLOC_ARRAY(dest.ASIZE() * sizeof(StoreType));
 
 
   WorkType *filter;
   WorkType *filter;
   double filter_width;
   double filter_width;
@@ -67,14 +67,14 @@ FUNCTION_NAME(PNMImage &dest, const PNMImage &source,
     }
     }
   }
   }
 
 
-  delete[] temp_source;
-  delete[] temp_dest;
-  delete[] filter;
+  PANDA_FREE_ARRAY(temp_source);
+  PANDA_FREE_ARRAY(temp_dest);
+  PANDA_FREE_ARRAY(filter);
 
 
   // Now, scale the image in the B direction.
   // Now, scale the image in the B direction.
   scale = (double)dest.BSIZE() / (double)source.BSIZE();
   scale = (double)dest.BSIZE() / (double)source.BSIZE();
 
 
-  temp_dest = new StoreType[dest.BSIZE()];
+  temp_dest = (StoreType *)PANDA_MALLOC_ARRAY(dest.BSIZE() * sizeof(StoreType));
 
 
   make_filter(scale, width, filter, filter_width);
   make_filter(scale, width, filter, filter_width);
 
 
@@ -90,14 +90,14 @@ FUNCTION_NAME(PNMImage &dest, const PNMImage &source,
     }
     }
   }
   }
 
 
-  delete[] temp_dest;
-  delete[] filter;
+  PANDA_FREE_ARRAY(temp_dest);
+  PANDA_FREE_ARRAY(filter);
 
 
   // Now, clean up our temp matrix and go home!
   // Now, clean up our temp matrix and go home!
 
 
   for (a=0; a<dest.ASIZE(); a++) {
   for (a=0; a<dest.ASIZE(); a++) {
-    delete[] matrix[a];
+    PANDA_FREE_ARRAY(matrix[a]);
   }
   }
-  delete[] matrix;
+  PANDA_FREE_ARRAY(matrix);
 }
 }
 
 

+ 2 - 2
panda/src/pnmimage/pnm-image-filter.cxx

@@ -199,7 +199,7 @@ box_filter_impl(double scale, double width,
   filter_width = width;
   filter_width = width;
   int actual_width = (int)cceil((filter_width+1) * fscale);
   int actual_width = (int)cceil((filter_width+1) * fscale);
 
 
-  filter = new WorkType[actual_width];
+  filter = (WorkType *)PANDA_MALLOC_ARRAY(actual_width * sizeof(WorkType));
 
 
   for (int i=0; i<actual_width; i++) {
   for (int i=0; i<actual_width; i++) {
     filter[i] = (i<=filter_width*fscale) ? filter_max : 0;
     filter[i] = (i<=filter_width*fscale) ? filter_max : 0;
@@ -232,7 +232,7 @@ gaussian_filter_impl(double scale, double width,
   // be normalized; and we're only computing a 1-dimensional function,
   // be normalized; and we're only computing a 1-dimensional function,
   // so we can ignore the y^2.)
   // so we can ignore the y^2.)
 
 
-  filter = new WorkType[actual_width];
+  filter = (WorkType *)PANDA_MALLOC_ARRAY(actual_width * sizeof(WorkType));
   double div = 2*sigma*sigma;
   double div = 2*sigma*sigma;
 
 
   for (int i=0; i<actual_width; i++) {
   for (int i=0; i<actual_width; i++) {

+ 0 - 24
panda/src/pnmimage/pnmFileType.cxx

@@ -145,30 +145,6 @@ init_pnm() {
     _did_init_pnm = true;
     _did_init_pnm = true;
 
 
     // No reason to do anything here nowadays.
     // No reason to do anything here nowadays.
-    /*
-      
-    // Make an argc/argv style copy of the ExecutionEnvironment's
-    // args.  We do this because pm_init() might attempt to change
-    // this (for instance, to remove arguments it finds).
-
-    int argc = ExecutionEnvironment::get_num_args() + 1;
-    char **argv = new char *[argc + 1];
-    argv[0] = strdup(ExecutionEnvironment::get_binary_name().c_str());
-    int i;
-    for (i = 1; i < argc; i++) {
-      argv[i] = strdup(ExecutionEnvironment::get_arg(i - 1).c_str());
-    }
-    argv[argc] = (char *)NULL;
-
-    pm_init(&argc, argv);
-
-    // We can delete the argv array itself, but we cannot free the
-    // results of the strdup() calls we just made, since the pnm
-    // library might keep pointers to it.  But this is a one-time
-    // leak.
-    delete[] argv;
-
-    */
   }
   }
 }
 }
 
 

+ 2 - 2
panda/src/pnmimage/pnmImage.I

@@ -839,7 +839,7 @@ gaussian_filter(double radius) {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 INLINE void PNMImage::
 INLINE void PNMImage::
 allocate_array() {
 allocate_array() {
-  _array = new xel[_x_size * _y_size];
+  _array = (xel *)PANDA_MALLOC_ARRAY(_x_size * _y_size * sizeof(xel));
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
@@ -850,7 +850,7 @@ allocate_array() {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 INLINE void PNMImage::
 INLINE void PNMImage::
 allocate_alpha() {
 allocate_alpha() {
-  _alpha = new xelval[_x_size * _y_size];
+  _alpha = (xelval *)PANDA_MALLOC_ARRAY(_x_size * _y_size * sizeof(xelval));
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////

+ 3 - 3
panda/src/pnmimage/pnmImage.cxx

@@ -49,11 +49,11 @@ PNMImage(const Filename &filename, PNMFileType *type) {
 void PNMImage::
 void PNMImage::
 clear() {
 clear() {
   if (_array != (xel *)NULL) {
   if (_array != (xel *)NULL) {
-    delete[] _array;
+    PANDA_FREE_ARRAY(_array);
     _array = (xel *)NULL;
     _array = (xel *)NULL;
   }
   }
   if (_alpha != (xelval *)NULL) {
   if (_alpha != (xelval *)NULL) {
-    delete[] _alpha;
+    PANDA_FREE_ARRAY(_alpha);
     _alpha = (xelval *)NULL;
     _alpha = (xelval *)NULL;
   }
   }
   _x_size = 0;
   _x_size = 0;
@@ -433,7 +433,7 @@ set_color_type(PNMImage::ColorType color_type) {
   if (has_alpha() && !has_alpha(color_type)) {
   if (has_alpha() && !has_alpha(color_type)) {
     // discard the alpha channel
     // discard the alpha channel
     if (_alpha!=NULL) {
     if (_alpha!=NULL) {
-      delete[] _alpha;
+      PANDA_FREE_ARRAY(_alpha);
       _alpha = NULL;
       _alpha = NULL;
     }
     }
 
 

+ 2 - 2
panda/src/pnmimage/pnmimage_base.cxx

@@ -111,7 +111,7 @@ pm_bitstomaxval(int bits) {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 char *
 char *
 pm_allocrow(int cols, int size) {
 pm_allocrow(int cols, int size) {
-  return new char[cols * size];
+  return (char *)PANDA_MALLOC_ARRAY(cols * size);
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
@@ -120,7 +120,7 @@ pm_allocrow(int cols, int size) {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 void
 void
 pm_freerow(char *itrow) {
 pm_freerow(char *itrow) {
-  delete[] itrow;
+  PANDA_FREE_ARRAY(itrow);
 }
 }
 
 
 
 

+ 6 - 6
panda/src/pnmimagetypes/pnmFileTypePNG.cxx

@@ -351,11 +351,11 @@ read_data(xel *array, xelval *alpha_data) {
   // 2-d array format, mainly because we keep array and alpha data
   // 2-d array format, mainly because we keep array and alpha data
   // separately, and there doesn't appear to be good support to get
   // separately, and there doesn't appear to be good support to get
   // this stuff out row-at-a-time for interlaced files.
   // this stuff out row-at-a-time for interlaced files.
-  png_bytep *rows = new png_bytep[num_rows];
+  png_bytep *rows = (png_bytep *)PANDA_MALLOC_ARRAY(num_rows * sizeof(png_bytep));
   int yi;
   int yi;
 
 
   for (yi = 0; yi < num_rows; yi++) {
   for (yi = 0; yi < num_rows; yi++) {
-    rows[yi] = new png_byte[row_byte_length];
+    rows[yi] = (png_byte *)PANDA_MALLOC_ARRAY(row_byte_length * sizeof(png_byte));
   }
   }
 
 
   png_read_image(_png, rows);
   png_read_image(_png, rows);
@@ -415,10 +415,10 @@ read_data(xel *array, xelval *alpha_data) {
     }
     }
 
 
     nassertr(source <= rows[yi] + row_byte_length, yi);
     nassertr(source <= rows[yi] + row_byte_length, yi);
-    delete[] rows[yi];
+    PANDA_FREE_ARRAY(rows[yi]);
   }
   }
 
 
-  delete[] rows;
+  PANDA_FREE_ARRAY(rows);
 
 
   png_read_end(_png, NULL);
   png_read_end(_png, NULL);
 
 
@@ -705,7 +705,7 @@ write_data(xel *array, xelval *alpha_data) {
   // If we were writing an interlaced file, we'd have to copy the
   // If we were writing an interlaced file, we'd have to copy the
   // whole image first.
   // whole image first.
 
 
-  png_bytep row = new png_byte[row_byte_length];
+  png_bytep row = (png_byte *)PANDA_MALLOC_ARRAY(row_byte_length * sizeof(png_byte));
 
 
   bool save_color = !is_grayscale();
   bool save_color = !is_grayscale();
   bool save_alpha = has_alpha();
   bool save_alpha = has_alpha();
@@ -779,7 +779,7 @@ write_data(xel *array, xelval *alpha_data) {
     Thread::consider_yield();
     Thread::consider_yield();
   }
   }
 
 
-  delete[] row;
+  PANDA_FREE_ARRAY(row);
 
 
   png_write_end(_png, NULL);
   png_write_end(_png, NULL);
 
 

+ 7 - 7
panda/src/pnmimagetypes/pnmFileTypeSGIWriter.cxx

@@ -98,7 +98,7 @@ PNMFileTypeSGI::Writer::
     // Rewrite the table with the correct values in it.
     // Rewrite the table with the correct values in it.
     _file->seekp(table_start);
     _file->seekp(table_start);
     write_table();
     write_table();
-    delete[] table;
+    PANDA_FREE_ARRAY(table);
   }
   }
 }
 }
 
 
@@ -163,7 +163,7 @@ write_header() {
   }
   }
 
 
   if( sgi_storage_type != STORAGE_VERBATIM ) {
   if( sgi_storage_type != STORAGE_VERBATIM ) {
-    table = new TabEntry[_num_channels * _y_size];
+    table = (TabEntry *)PANDA_MALLOC_ARRAY(_num_channels * _y_size * sizeof(TabEntry));
     memset(table, 0, _num_channels * _y_size * sizeof(TabEntry));
     memset(table, 0, _num_channels * _y_size * sizeof(TabEntry));
   }
   }
 
 
@@ -209,7 +209,7 @@ write_row(xel *row_data, xelval *alpha_data) {
     write_channels(channel, put_big_short);
     write_channels(channel, put_big_short);
 
 
   for (int i = 0; i < _num_channels; i++) {
   for (int i = 0; i < _num_channels; i++) {
-    delete[] channel[i].data;
+    PANDA_FREE_ARRAY(channel[i].data);
   }
   }
 
 
   current_row--;
   current_row--;
@@ -278,7 +278,7 @@ build_scanline(ScanLine output[], xel *row_data, xelval *alpha_data) {
   if( sgi_storage_type != STORAGE_VERBATIM ) {
   if( sgi_storage_type != STORAGE_VERBATIM ) {
     rletemp = (ScanElem *)alloca(WORSTCOMPR(_x_size) * sizeof(ScanElem));
     rletemp = (ScanElem *)alloca(WORSTCOMPR(_x_size) * sizeof(ScanElem));
   }
   }
-  temp = new ScanElem[_x_size];
+  temp = (ScanElem *)PANDA_MALLOC_ARRAY(_x_size * sizeof(ScanElem));
 
 
   if( _num_channels <= 2 ) {
   if( _num_channels <= 2 ) {
     for( col = 0; col < _x_size; col++ )
     for( col = 0; col < _x_size; col++ )
@@ -314,7 +314,7 @@ build_scanline(ScanLine output[], xel *row_data, xelval *alpha_data) {
     }
     }
   }
   }
 
 
-  delete[] temp;
+  PANDA_FREE_ARRAY(temp);
 }
 }
 
 
 
 
@@ -326,12 +326,12 @@ compress(ScanElem *temp, ScanLine &output) {
         case STORAGE_VERBATIM:
         case STORAGE_VERBATIM:
             output.length = _x_size;
             output.length = _x_size;
             output.data = temp;
             output.data = temp;
-            temp = new ScanElem[_x_size];
+            temp = (ScanElem *)PANDA_MALLOC_ARRAY(_x_size * sizeof(ScanElem));
             break;
             break;
         case STORAGE_RLE:
         case STORAGE_RLE:
             len = rle_compress(temp, _x_size);    /* writes result into rletemp */
             len = rle_compress(temp, _x_size);    /* writes result into rletemp */
             output.length = len;
             output.length = len;
-            output.data = new ScanElem[len];
+            output.data = (ScanElem *)PANDA_MALLOC_ARRAY(len * sizeof(ScanElem));
             memcpy(output.data, rletemp, len * sizeof(ScanElem));
             memcpy(output.data, rletemp, len * sizeof(ScanElem));
             break;
             break;
         default:
         default:

+ 73 - 36
panda/src/pstatclient/pStatClient.cxx

@@ -33,14 +33,19 @@
 #include "clockObject.h"
 #include "clockObject.h"
 #include "neverFreeMemory.h"
 #include "neverFreeMemory.h"
 
 
-PStatCollector PStatClient::_t1_nf_unused_size_pcollector("Track memory 1:NeverFree:Unused");
-PStatCollector PStatClient::_t1_nf_other_size_pcollector("Track memory 1:NeverFree:Other");
-PStatCollector PStatClient::_t1_cpp_other_size_pcollector("Track memory 1:Dynamic:Other");
-PStatCollector PStatClient::_t2_total_size_pcollector("Track memory 2");
-PStatCollector PStatClient::_t2_heap_size_pcollector("Track memory 2:Heap");
-PStatCollector PStatClient::_t2_mmap_size_pcollector("Track memory 2:MMap");
-PStatCollector PStatClient::_t2_interpreter_size_pcollector("Track memory 2:Interpreter");
-PStatCollector PStatClient::_t2_external_size_pcollector("Track memory 2:External");
+PStatCollector PStatClient::_heap_total_size_pcollector("System memory:Heap");
+PStatCollector PStatClient::_heap_overhead_size_pcollector("System memory:Heap:Overhead");
+PStatCollector PStatClient::_heap_single_size_pcollector("System memory:Heap:Single");
+PStatCollector PStatClient::_heap_single_other_size_pcollector("System memory:Heap:Single:Other");
+PStatCollector PStatClient::_heap_array_size_pcollector("System memory:Heap:Array");
+PStatCollector PStatClient::_heap_array_other_size_pcollector("System memory:Heap:Array:Other");
+PStatCollector PStatClient::_heap_interpreter_size_pcollector("System memory:Heap:Interpreter");
+PStatCollector PStatClient::_heap_external_size_pcollector("System memory:Heap:External");
+PStatCollector PStatClient::_mmap_size_pcollector("System memory:MMap");
+
+PStatCollector PStatClient::_mmap_nf_unused_size_pcollector("System memory:MMap:NeverFree:Unused");
+PStatCollector PStatClient::_mmap_dc_active_other_size_pcollector("System memory:MMap:NeverFree:Active:Other");
+PStatCollector PStatClient::_mmap_dc_inactive_other_size_pcollector("System memory:MMap:NeverFree:Inactive:Other");
 PStatCollector PStatClient::_pstats_pcollector("*:PStats");
 PStatCollector PStatClient::_pstats_pcollector("*:PStats");
 PStatCollector PStatClient::_clock_wait_pcollector("Wait:Clock Wait:Sleep");
 PStatCollector PStatClient::_clock_wait_pcollector("Wait:Clock Wait:Sleep");
 PStatCollector PStatClient::_clock_busy_wait_pcollector("Wait:Clock Wait:Spin");
 PStatCollector PStatClient::_clock_busy_wait_pcollector("Wait:Clock Wait:Spin");
@@ -217,13 +222,15 @@ main_tick() {
 
 
 #ifdef DO_MEMORY_USAGE
 #ifdef DO_MEMORY_USAGE
   if (is_connected()) {
   if (is_connected()) {
-    if (MemoryUsage::is_tracking()) {
-      _t2_total_size_pcollector.set_level(MemoryUsage::get_total_size());
-      _t2_heap_size_pcollector.set_level(MemoryUsage::get_panda_heap_size());
-      _t2_mmap_size_pcollector.set_level(MemoryUsage::get_panda_mmap_size());
-      _t2_interpreter_size_pcollector.set_level(MemoryUsage::get_interpreter_size());
-      _t2_external_size_pcollector.set_level(MemoryUsage::get_external_size());
-    }
+    _heap_total_size_pcollector.set_level(MemoryUsage::get_total_size());
+    _heap_overhead_size_pcollector.set_level(MemoryUsage::get_panda_heap_overhead());
+    _heap_single_size_pcollector.set_level(MemoryUsage::get_panda_heap_single_size());
+    _heap_array_size_pcollector.set_level(MemoryUsage::get_panda_heap_array_size());
+    _heap_interpreter_size_pcollector.set_level(MemoryUsage::get_interpreter_size());
+    _heap_external_size_pcollector.set_level(MemoryUsage::get_external_size());
+
+
+    _mmap_size_pcollector.set_level(MemoryUsage::get_panda_mmap_size());
     
     
     TypeRegistry *type_reg = TypeRegistry::ptr();
     TypeRegistry *type_reg = TypeRegistry::ptr();
     int num_typehandles = type_reg->get_num_typehandles();
     int num_typehandles = type_reg->get_num_typehandles();
@@ -232,8 +239,10 @@ main_tick() {
       type_handle_cols.push_back(TypeHandleCollector());
       type_handle_cols.push_back(TypeHandleCollector());
     }
     }
 
 
-    size_t cpp_total_usage = 0;
-    size_t nf_total_usage = 0;
+    size_t single_total_usage = 0;
+    size_t array_total_usage = 0;
+    size_t dc_active_total_usage = 0;
+    size_t dc_inactive_total_usage = 0;
     int i;
     int i;
     for (i = 0; i < num_typehandles; ++i) {
     for (i = 0; i < num_typehandles; ++i) {
       TypeHandle type = type_reg->get_typehandle(i);
       TypeHandle type = type_reg->get_typehandle(i);
@@ -242,22 +251,32 @@ main_tick() {
         size_t usage = type.get_memory_usage(mc);
         size_t usage = type.get_memory_usage(mc);
 
 
         switch (mc) {
         switch (mc) {
+        case TypeHandle::MC_singleton:
+          single_total_usage += usage;
+          break;
+
+        case TypeHandle::MC_array:
+          array_total_usage += usage;
+          break;
+
         case TypeHandle::MC_deleted_chain_active:
         case TypeHandle::MC_deleted_chain_active:
-        case TypeHandle::MC_deleted_chain_inactive:
-          nf_total_usage += usage;
+          dc_active_total_usage += usage;
           break;
           break;
 
 
-        default:
-          cpp_total_usage += usage;
+        case TypeHandle::MC_deleted_chain_inactive:
+          dc_inactive_total_usage += usage;
+          break;
         }          
         }          
       }
       }
     }
     }
-    size_t min_usage = (cpp_total_usage + nf_total_usage) / 1024;
+    size_t min_usage = (single_total_usage + array_total_usage + dc_active_total_usage + dc_inactive_total_usage) / 1024;
     if (!pstats_mem_other) {
     if (!pstats_mem_other) {
       min_usage = 0;
       min_usage = 0;
     }
     }
-    size_t cpp_other_usage = cpp_total_usage;
-    size_t nf_other_usage = nf_total_usage;
+    size_t single_other_usage = single_total_usage;
+    size_t array_other_usage = array_total_usage;
+    size_t dc_active_other_usage = dc_active_total_usage;
+    size_t dc_inactive_other_usage = dc_inactive_total_usage;
 
 
     for (i = 0; i < num_typehandles; ++i) {
     for (i = 0; i < num_typehandles; ++i) {
       TypeHandle type = type_reg->get_typehandle(i);
       TypeHandle type = type_reg->get_typehandle(i);
@@ -271,39 +290,57 @@ main_tick() {
           if (!col.is_valid()) {
           if (!col.is_valid()) {
             const char *category;
             const char *category;
             switch (mc) {
             switch (mc) {
+            case TypeHandle::MC_singleton:
+              category = "Heap:Single";
+              break;
+              
+            case TypeHandle::MC_array:
+              category = "Heap:Array";
+              break;
+
             case TypeHandle::MC_deleted_chain_active:
             case TypeHandle::MC_deleted_chain_active:
-            case TypeHandle::MC_deleted_chain_inactive:
-              category = "NeverFree";
+              category = "MMap:NeverFree:Active";
               break;
               break;
 
 
-            default:
-              category = "Dynamic";
+            case TypeHandle::MC_deleted_chain_inactive:
+              category = "MMap:NeverFree:Inactive";
+              break;
             }
             }
             ostringstream strm;
             ostringstream strm;
-            strm << "Track memory 1:" << category << ":" << type << ":" << mc;
+            strm << "System memory:" << category << ":" << type;
             col = PStatCollector(strm.str());
             col = PStatCollector(strm.str());
           }
           }
           col.set_level(usage);
           col.set_level(usage);
 
 
           switch (mc) {
           switch (mc) {
+          case TypeHandle::MC_singleton:
+            single_other_usage -= usage;
+            break;
+            
+          case TypeHandle::MC_array:
+            array_other_usage -= usage;
+            break;
+            
           case TypeHandle::MC_deleted_chain_active:
           case TypeHandle::MC_deleted_chain_active:
-          case TypeHandle::MC_deleted_chain_inactive:
-            nf_other_usage -= usage;
+            dc_active_other_usage -= usage;
             break;
             break;
 
 
-          default:
-            cpp_other_usage -= usage;
+          case TypeHandle::MC_deleted_chain_inactive:
+            dc_inactive_other_usage -= usage;
+            break;
           }
           }
         }
         }
       }
       }
     }
     }
 
 
-    _t1_nf_unused_size_pcollector.set_level(NeverFreeMemory::get_total_unused());
+    _mmap_nf_unused_size_pcollector.set_level(NeverFreeMemory::get_total_unused());
 
 
     // The remaining amount--all collectors smaller than 0.1% of the
     // The remaining amount--all collectors smaller than 0.1% of the
     // total--go into "other".
     // total--go into "other".
-    _t1_nf_other_size_pcollector.set_level(nf_other_usage);
-    _t1_cpp_other_size_pcollector.set_level(cpp_other_usage);
+    _heap_single_other_size_pcollector.set_level(single_other_usage);
+    _heap_array_other_size_pcollector.set_level(array_other_usage);
+    _mmap_dc_active_other_size_pcollector.set_level(dc_active_other_usage);
+    _mmap_dc_inactive_other_size_pcollector.set_level(dc_inactive_other_usage);
   }
   }
 #endif  // DO_MEMORY_USAGE
 #endif  // DO_MEMORY_USAGE
 
 

+ 13 - 8
panda/src/pstatclient/pStatClient.h

@@ -227,14 +227,19 @@ private:
 
 
   PStatClientImpl *_impl;
   PStatClientImpl *_impl;
 
 
-  static PStatCollector _t1_nf_unused_size_pcollector;
-  static PStatCollector _t1_nf_other_size_pcollector;
-  static PStatCollector _t1_cpp_other_size_pcollector;
-  static PStatCollector _t2_total_size_pcollector;
-  static PStatCollector _t2_heap_size_pcollector;
-  static PStatCollector _t2_mmap_size_pcollector;
-  static PStatCollector _t2_interpreter_size_pcollector;
-  static PStatCollector _t2_external_size_pcollector;
+  static PStatCollector _heap_total_size_pcollector;
+  static PStatCollector _heap_overhead_size_pcollector;
+  static PStatCollector _heap_single_size_pcollector;
+  static PStatCollector _heap_single_other_size_pcollector;
+  static PStatCollector _heap_array_size_pcollector;
+  static PStatCollector _heap_array_other_size_pcollector;
+  static PStatCollector _heap_interpreter_size_pcollector;
+  static PStatCollector _heap_external_size_pcollector;
+  static PStatCollector _mmap_size_pcollector;
+
+  static PStatCollector _mmap_nf_unused_size_pcollector;
+  static PStatCollector _mmap_dc_active_other_size_pcollector;
+  static PStatCollector _mmap_dc_inactive_other_size_pcollector;
   static PStatCollector _pstats_pcollector;
   static PStatCollector _pstats_pcollector;
   static PStatCollector _clock_wait_pcollector;
   static PStatCollector _clock_wait_pcollector;
   static PStatCollector _clock_busy_wait_pcollector;
   static PStatCollector _clock_busy_wait_pcollector;

+ 9 - 8
panda/src/pstatclient/pStatProperties.cxx

@@ -196,14 +196,15 @@ static LevelCollectorProperties level_properties[] = {
   { 1, "State changes:Textures",           { 0.8, 0.2, 0.2 } },
   { 1, "State changes:Textures",           { 0.8, 0.2, 0.2 } },
   { 1, "Occlusion tests",                  { 0.9, 0.8, 0.3 },  "", 500.0 },
   { 1, "Occlusion tests",                  { 0.9, 0.8, 0.3 },  "", 500.0 },
   { 1, "Occlusion results",                { 0.3, 0.9, 0.8 },  "", 500.0 },
   { 1, "Occlusion results",                { 0.3, 0.9, 0.8 },  "", 500.0 },
-  { 1, "Track memory 1",                   { 0.5, 1.0, 0.5 },  "MB", 64, 1048576 },
-  { 1, "Track memory 1:Dynamic",           { 0.8, 0.2, 1.0 } },
-  { 1, "Track memory 1:NeverFree",         { 0.2, 0.5, 0.8 } },
-  { 1, "Track memory 2",                   { 0.5, 1.0, 0.5 },  "MB", 64, 1048576 },
-  { 1, "Track memory 2:Heap",              { 0.2, 0.2, 1.0 } },
-  { 1, "Track memory 2:MMap",              { 0.9, 0.4, 0.7 } },
-  { 1, "Track memory 2:Interpreter",       { 0.8, 0.2, 0.5 } },
-  { 1, "Track memory 2:External",          { 1.0, 1.0, 0.1 } },
+  { 1, "System memory",                    { 0.5, 1.0, 0.5 },  "MB", 64, 1048576 },
+  { 1, "System memory:Heap",               { 0.2, 0.2, 1.0 } },
+  { 1, "System memory:Heap:Overhead",      { 0.3, 0.4, 0.6 } },
+  { 1, "System memory:Heap:Single",        { 0.8, 0.3, 0.3 } },
+  { 1, "System memory:Heap:Array",         { 0.1, 0.3, 1.0 } },
+  { 1, "System memory:Heap:Overhead",      { 0.9, 0.7, 0.8 } },
+  { 1, "System memory:Heap:Interpreter",   { 0.6, 1.0, 0.9 } },
+  { 1, "System memory:Heap:External",      { 0.2, 0.2, 0.5 } },
+  { 1, "System memory:MMap",               { 0.9, 0.4, 0.7 } },
   { 1, "Vertex Data",                      { 1.0, 0.4, 0.0 },  "MB", 64, 1048576 },
   { 1, "Vertex Data",                      { 1.0, 0.4, 0.0 },  "MB", 64, 1048576 },
   { 1, "Vertex Data:Independent",          { 0.9, 0.1, 0.9 } },
   { 1, "Vertex Data:Independent",          { 0.9, 0.1, 0.9 } },
   { 1, "Vertex Data:Small",                { 0.2, 0.3, 0.4 } },
   { 1, "Vertex Data:Small",                { 0.2, 0.3, 0.4 } },

+ 3 - 3
panda/src/putil/datagramInputFile.cxx

@@ -149,18 +149,18 @@ get_datagram(Datagram &data) {
   // temporary buffer from the heap.  Otherwise, we can get away with
   // temporary buffer from the heap.  Otherwise, we can get away with
   // allocating it on the stack, via alloca().
   // allocating it on the stack, via alloca().
   if (num_bytes > 65536) {
   if (num_bytes > 65536) {
-    char *buffer = new char[num_bytes];
+    char *buffer = (char *)PANDA_MALLOC_ARRAY(num_bytes);
     nassertr(buffer != (char *)NULL, false);
     nassertr(buffer != (char *)NULL, false);
 
 
     _in->read(buffer, num_bytes);
     _in->read(buffer, num_bytes);
     if (_in->fail() || _in->eof()) {
     if (_in->fail() || _in->eof()) {
       _error = true;
       _error = true;
-      delete[] buffer;
+      PANDA_FREE_ARRAY(buffer);
       return false;
       return false;
     }
     }
 
 
     data = Datagram(buffer, num_bytes);
     data = Datagram(buffer, num_bytes);
-    delete[] buffer;
+    PANDA_FREE_ARRAY(buffer);
 
 
   } else {
   } else {
     char *buffer = (char *)alloca(num_bytes);
     char *buffer = (char *)alloca(num_bytes);

+ 2 - 2
panda/src/putil/uniqueIdAllocator.cxx

@@ -66,7 +66,7 @@ UniqueIdAllocator(PN_uint32 min, PN_uint32 max)
   _size = _max-_min+1; // +1 because min and max are inclusive.
   _size = _max-_min+1; // +1 because min and max are inclusive.
   nassertv(_size != 0); // size must be > 0.
   nassertv(_size != 0); // size must be > 0.
 
 
-  _table = new PN_uint32[_size];
+  _table = (PN_uint32 *)PANDA_MALLOC_ARRAY(_size * sizeof(PN_uint32));
   nassertv(_table); // This should be redundant if new throws an exception.
   nassertv(_table); // This should be redundant if new throws an exception.
 
 
   for (PN_uint32 i = 0; i < _size; ++i) {
   for (PN_uint32 i = 0; i < _size; ++i) {
@@ -86,7 +86,7 @@ UniqueIdAllocator(PN_uint32 min, PN_uint32 max)
 UniqueIdAllocator::
 UniqueIdAllocator::
 ~UniqueIdAllocator() {
 ~UniqueIdAllocator() {
   uniqueIdAllocator_debug("~UniqueIdAllocator()");
   uniqueIdAllocator_debug("~UniqueIdAllocator()");
-  delete [] _table;
+  PANDA_FREE_ARRAY(_table);
 }
 }