churchyard / rpms / python38

Forked from rpms/python38 5 years ago
Clone
ab415c6
diff -up Python-3.2.2/Include/dictobject.h.add-debug-malloc-stats Python-3.2.2/Include/dictobject.h
ab415c6
--- Python-3.2.2/Include/dictobject.h.add-debug-malloc-stats	2011-09-03 12:16:40.000000000 -0400
ab415c6
+++ Python-3.2.2/Include/dictobject.h	2011-09-16 18:57:24.969825060 -0400
ab415c6
@@ -156,6 +156,8 @@ PyAPI_FUNC(PyObject *) PyDict_GetItemStr
ab415c6
 PyAPI_FUNC(int) PyDict_SetItemString(PyObject *dp, const char *key, PyObject *item);
ab415c6
 PyAPI_FUNC(int) PyDict_DelItemString(PyObject *dp, const char *key);
ab415c6
 
ab415c6
+PyAPI_FUNC(void) _PyDict_DebugMallocStats(FILE *out);
ab415c6
+
ab415c6
 #ifdef __cplusplus
ab415c6
 }
ab415c6
 #endif
ab415c6
diff -up Python-3.2.2/Include/floatobject.h.add-debug-malloc-stats Python-3.2.2/Include/floatobject.h
ab415c6
--- Python-3.2.2/Include/floatobject.h.add-debug-malloc-stats	2011-09-03 12:16:40.000000000 -0400
ab415c6
+++ Python-3.2.2/Include/floatobject.h	2011-09-16 18:57:24.970825060 -0400
ab415c6
@@ -110,6 +110,8 @@ PyAPI_FUNC(double) _PyFloat_Unpack8(cons
ab415c6
 /* free list api */
ab415c6
 PyAPI_FUNC(int) PyFloat_ClearFreeList(void);
ab415c6
 
ab415c6
+PyAPI_FUNC(void) _PyFloat_DebugMallocStats(FILE* out);
ab415c6
+
ab415c6
 /* Format the object based on the format_spec, as defined in PEP 3101
ab415c6
    (Advanced String Formatting). */
ab415c6
 PyAPI_FUNC(PyObject *) _PyFloat_FormatAdvanced(PyObject *obj,
ab415c6
diff -up Python-3.2.2/Include/frameobject.h.add-debug-malloc-stats Python-3.2.2/Include/frameobject.h
ab415c6
--- Python-3.2.2/Include/frameobject.h.add-debug-malloc-stats	2011-09-03 12:16:40.000000000 -0400
ab415c6
+++ Python-3.2.2/Include/frameobject.h	2011-09-16 18:57:24.970825060 -0400
ab415c6
@@ -79,6 +79,8 @@ PyAPI_FUNC(void) PyFrame_FastToLocals(Py
ab415c6
 
ab415c6
 PyAPI_FUNC(int) PyFrame_ClearFreeList(void);
ab415c6
 
ab415c6
+PyAPI_FUNC(void) _PyFrame_DebugMallocStats(FILE *out);
ab415c6
+
ab415c6
 /* Return the line of code the frame is currently executing. */
ab415c6
 PyAPI_FUNC(int) PyFrame_GetLineNumber(PyFrameObject *);
ab415c6
 
ab415c6
diff -up Python-3.2.2/Include/listobject.h.add-debug-malloc-stats Python-3.2.2/Include/listobject.h
ab415c6
--- Python-3.2.2/Include/listobject.h.add-debug-malloc-stats	2011-09-03 12:16:40.000000000 -0400
ab415c6
+++ Python-3.2.2/Include/listobject.h	2011-09-16 18:57:24.971825060 -0400
ab415c6
@@ -71,6 +71,8 @@ PyAPI_FUNC(PyObject *) _PyList_Extend(Py
ab415c6
 #define PyList_GET_SIZE(op)    Py_SIZE(op)
ab415c6
 #endif
ab415c6
 
ab415c6
+PyAPI_FUNC(void) _PyList_DebugMallocStats(FILE *out);
ab415c6
+
ab415c6
 #ifdef __cplusplus
ab415c6
 }
ab415c6
 #endif
ab415c6
diff -up Python-3.2.2/Include/methodobject.h.add-debug-malloc-stats Python-3.2.2/Include/methodobject.h
ab415c6
--- Python-3.2.2/Include/methodobject.h.add-debug-malloc-stats	2011-09-03 12:16:40.000000000 -0400
ab415c6
+++ Python-3.2.2/Include/methodobject.h	2011-09-16 18:57:24.971825060 -0400
ab415c6
@@ -81,6 +81,10 @@ typedef struct {
ab415c6
 
ab415c6
 PyAPI_FUNC(int) PyCFunction_ClearFreeList(void);
ab415c6
 
ab415c6
+PyAPI_FUNC(void) _PyCFunction_DebugMallocStats(FILE *out);
ab415c6
+PyAPI_FUNC(void) _PyMethod_DebugMallocStats(FILE *out);
ab415c6
+
ab415c6
+
ab415c6
 #ifdef __cplusplus
ab415c6
 }
ab415c6
 #endif
ab415c6
diff -up Python-3.2.2/Include/object.h.add-debug-malloc-stats Python-3.2.2/Include/object.h
ab415c6
--- Python-3.2.2/Include/object.h.add-debug-malloc-stats	2011-09-03 12:16:40.000000000 -0400
ab415c6
+++ Python-3.2.2/Include/object.h	2011-09-16 18:57:24.972825060 -0400
ab415c6
@@ -919,6 +919,13 @@ PyAPI_DATA(PyObject *) _PyTrash_delete_l
ab415c6
     else \
ab415c6
         _PyTrash_deposit_object((PyObject*)op);
ab415c6
 
ab415c6
+PyAPI_FUNC(void)
ab415c6
+_PyDebugAllocatorStats(FILE *out, const char *block_name, int num_blocks,
ab415c6
+		       size_t sizeof_block);
ab415c6
+
ab415c6
+PyAPI_FUNC(void)
ab415c6
+_PyObject_DebugTypeStats(FILE *out);
ab415c6
+
ab415c6
 #ifdef __cplusplus
ab415c6
 }
ab415c6
 #endif
ab415c6
diff -up Python-3.2.2/Include/objimpl.h.add-debug-malloc-stats Python-3.2.2/Include/objimpl.h
ab415c6
--- Python-3.2.2/Include/objimpl.h.add-debug-malloc-stats	2011-09-03 12:16:40.000000000 -0400
ab415c6
+++ Python-3.2.2/Include/objimpl.h	2011-09-16 18:57:24.972825060 -0400
ab415c6
@@ -101,13 +101,13 @@ PyAPI_FUNC(void) PyObject_Free(void *);
ab415c6
 
ab415c6
 /* Macros */
ab415c6
 #ifdef WITH_PYMALLOC
ab415c6
+PyAPI_FUNC(void) _PyObject_DebugMallocStats(FILE *out);
ab415c6
 #ifdef PYMALLOC_DEBUG   /* WITH_PYMALLOC && PYMALLOC_DEBUG */
ab415c6
 PyAPI_FUNC(void *) _PyObject_DebugMalloc(size_t nbytes);
ab415c6
 PyAPI_FUNC(void *) _PyObject_DebugRealloc(void *p, size_t nbytes);
ab415c6
 PyAPI_FUNC(void) _PyObject_DebugFree(void *p);
ab415c6
 PyAPI_FUNC(void) _PyObject_DebugDumpAddress(const void *p);
ab415c6
 PyAPI_FUNC(void) _PyObject_DebugCheckAddress(const void *p);
ab415c6
-PyAPI_FUNC(void) _PyObject_DebugMallocStats(void);
ab415c6
 PyAPI_FUNC(void *) _PyObject_DebugMallocApi(char api, size_t nbytes);
ab415c6
 PyAPI_FUNC(void *) _PyObject_DebugReallocApi(char api, void *p, size_t nbytes);
ab415c6
 PyAPI_FUNC(void) _PyObject_DebugFreeApi(char api, void *p);
ab415c6
diff -up Python-3.2.2/Include/setobject.h.add-debug-malloc-stats Python-3.2.2/Include/setobject.h
ab415c6
--- Python-3.2.2/Include/setobject.h.add-debug-malloc-stats	2011-09-16 19:10:58.448817301 -0400
ab415c6
+++ Python-3.2.2/Include/setobject.h	2011-09-16 19:12:16.343816559 -0400
ab415c6
@@ -101,6 +101,8 @@ PyAPI_FUNC(PyObject *) PySet_Pop(PyObjec
ab415c6
 PyAPI_FUNC(int) _PySet_Update(PyObject *set, PyObject *iterable);
ab415c6
 #endif
ab415c6
 
ab415c6
+PyAPI_FUNC(void) _PySet_DebugMallocStats(FILE *out);
ab415c6
+
ab415c6
 #ifdef __cplusplus
ab415c6
 }
ab415c6
 #endif
ab415c6
diff -up Python-3.2.2/Include/tupleobject.h.add-debug-malloc-stats Python-3.2.2/Include/tupleobject.h
ab415c6
--- Python-3.2.2/Include/tupleobject.h.add-debug-malloc-stats	2011-09-16 19:10:45.540817425 -0400
ab415c6
+++ Python-3.2.2/Include/tupleobject.h	2011-09-16 19:12:41.446816320 -0400
ab415c6
@@ -63,6 +63,7 @@ PyAPI_FUNC(void) _PyTuple_MaybeUntrack(P
ab415c6
 #endif
ab415c6
 
ab415c6
 PyAPI_FUNC(int) PyTuple_ClearFreeList(void);
ab415c6
+PyAPI_FUNC(void) _PyTuple_DebugMallocStats(FILE *out);
ab415c6
 
ab415c6
 #ifdef __cplusplus
ab415c6
 }
ab415c6
diff -up Python-3.2.2/Include/unicodeobject.h.add-debug-malloc-stats Python-3.2.2/Include/unicodeobject.h
ab415c6
--- Python-3.2.2/Include/unicodeobject.h.add-debug-malloc-stats	2011-09-03 12:16:40.000000000 -0400
ab415c6
+++ Python-3.2.2/Include/unicodeobject.h	2011-09-16 18:57:24.973825060 -0400
ab415c6
@@ -1670,6 +1670,8 @@ PyAPI_FUNC(Py_UNICODE*) PyUnicode_AsUnic
ab415c6
     );
ab415c6
 #endif /* Py_LIMITED_API */
ab415c6
 
ab415c6
+PyAPI_FUNC(void) _PyUnicode_DebugMallocStats(FILE *out);
ab415c6
+
ab415c6
 #ifdef __cplusplus
ab415c6
 }
ab415c6
 #endif
ab415c6
diff -up Python-3.2.2/Lib/test/test_sys.py.add-debug-malloc-stats Python-3.2.2/Lib/test/test_sys.py
ab415c6
--- Python-3.2.2/Lib/test/test_sys.py.add-debug-malloc-stats	2011-09-16 18:57:24.940825060 -0400
ab415c6
+++ Python-3.2.2/Lib/test/test_sys.py	2011-09-16 19:23:50.415809940 -0400
ab415c6
@@ -564,6 +564,18 @@ class SysModuleTest(unittest.TestCase):
ab415c6
             expected = None
ab415c6
         self.check_fsencoding(fs_encoding, expected)
ab415c6
 
ab415c6
+    def test_debugmallocstats(self):
ab415c6
+        # Test sys._debugmallocstats()
ab415c6
+
ab415c6
+        import subprocess
ab415c6
+
ab415c6
+        # Verify writing to stderr:
ab415c6
+        p = subprocess.Popen([sys.executable,
ab415c6
+                              '-c', 'import sys; sys._debugmallocstats()'],
ab415c6
+                             stderr=subprocess.PIPE)
ab415c6
+        out, err = p.communicate()
ab415c6
+        p.wait()
ab415c6
+        self.assertIn(b"arenas allocated current", err)
ab415c6
 
ab415c6
 class SizeofTest(unittest.TestCase):
ab415c6
 
ab415c6
diff -up Python-3.2.2/Objects/classobject.c.add-debug-malloc-stats Python-3.2.2/Objects/classobject.c
ab415c6
--- Python-3.2.2/Objects/classobject.c.add-debug-malloc-stats	2011-09-03 12:16:47.000000000 -0400
ab415c6
+++ Python-3.2.2/Objects/classobject.c	2011-09-16 18:57:24.975825060 -0400
ab415c6
@@ -399,6 +399,15 @@ PyMethod_Fini(void)
ab415c6
     (void)PyMethod_ClearFreeList();
ab415c6
 }
ab415c6
 
ab415c6
+/* Print summary info about the state of the optimized allocator */
ab415c6
+void
ab415c6
+_PyMethod_DebugMallocStats(FILE *out)
ab415c6
+{
ab415c6
+    _PyDebugAllocatorStats(out,
ab415c6
+                           "free PyMethodObject",
ab415c6
+                           numfree, sizeof(PyMethodObject));
ab415c6
+}
ab415c6
+
ab415c6
 /* ------------------------------------------------------------------------
ab415c6
  * instance method
ab415c6
  */
ab415c6
diff -up Python-3.2.2/Objects/dictobject.c.add-debug-malloc-stats Python-3.2.2/Objects/dictobject.c
ab415c6
--- Python-3.2.2/Objects/dictobject.c.add-debug-malloc-stats	2011-09-03 12:16:47.000000000 -0400
ab415c6
+++ Python-3.2.2/Objects/dictobject.c	2011-09-16 18:57:24.976825060 -0400
ab415c6
@@ -217,6 +217,15 @@ show_track(void)
ab415c6
 static PyDictObject *free_list[PyDict_MAXFREELIST];
ab415c6
 static int numfree = 0;
ab415c6
 
ab415c6
+/* Print summary info about the state of the optimized allocator */
ab415c6
+void
ab415c6
+_PyDict_DebugMallocStats(FILE *out)
ab415c6
+{
ab415c6
+    _PyDebugAllocatorStats(out,
ab415c6
+                           "free PyDictObject", numfree, sizeof(PyDictObject));
ab415c6
+}
ab415c6
+
ab415c6
+
ab415c6
 void
ab415c6
 PyDict_Fini(void)
ab415c6
 {
ab415c6
diff -up Python-3.2.2/Objects/floatobject.c.add-debug-malloc-stats Python-3.2.2/Objects/floatobject.c
ab415c6
--- Python-3.2.2/Objects/floatobject.c.add-debug-malloc-stats	2011-09-03 12:16:47.000000000 -0400
ab415c6
+++ Python-3.2.2/Objects/floatobject.c	2011-09-16 18:57:24.981825060 -0400
ab415c6
@@ -50,6 +50,22 @@ typedef struct _floatblock PyFloatBlock;
ab415c6
 static PyFloatBlock *block_list = NULL;
ab415c6
 static PyFloatObject *free_list = NULL;
ab415c6
 
ab415c6
+/* Print summary info about the state of the optimized allocator */
ab415c6
+void
ab415c6
+_PyFloat_DebugMallocStats(FILE *out)
ab415c6
+{
ab415c6
+  int num_blocks = 0;
ab415c6
+  PyFloatBlock *block;
ab415c6
+
ab415c6
+  /* Walk the block list, counting */
ab415c6
+  for (block = block_list; block ; block = block->next) {
ab415c6
+      num_blocks++;
ab415c6
+  }
ab415c6
+
ab415c6
+  _PyDebugAllocatorStats(out,
ab415c6
+                         "PyFloatBlock", num_blocks, sizeof(PyFloatBlock));
ab415c6
+}
ab415c6
+
ab415c6
 static PyFloatObject *
ab415c6
 fill_free_list(void)
ab415c6
 {
ab415c6
diff -up Python-3.2.2/Objects/frameobject.c.add-debug-malloc-stats Python-3.2.2/Objects/frameobject.c
ab415c6
--- Python-3.2.2/Objects/frameobject.c.add-debug-malloc-stats	2011-09-03 12:16:47.000000000 -0400
ab415c6
+++ Python-3.2.2/Objects/frameobject.c	2011-09-16 18:57:24.982825060 -0400
ab415c6
@@ -953,3 +953,13 @@ PyFrame_Fini(void)
ab415c6
     Py_XDECREF(builtin_object);
ab415c6
     builtin_object = NULL;
ab415c6
 }
ab415c6
+
ab415c6
+/* Print summary info about the state of the optimized allocator */
ab415c6
+void
ab415c6
+_PyFrame_DebugMallocStats(FILE *out)
ab415c6
+{
ab415c6
+    _PyDebugAllocatorStats(out,
ab415c6
+                           "free PyFrameObject",
ab415c6
+                           numfree, sizeof(PyFrameObject));
ab415c6
+}
ab415c6
+
ab415c6
diff -up Python-3.2.2/Objects/listobject.c.add-debug-malloc-stats Python-3.2.2/Objects/listobject.c
ab415c6
--- Python-3.2.2/Objects/listobject.c.add-debug-malloc-stats	2011-09-03 12:16:47.000000000 -0400
ab415c6
+++ Python-3.2.2/Objects/listobject.c	2011-09-16 18:57:24.983825060 -0400
ab415c6
@@ -109,6 +109,15 @@ PyList_Fini(void)
ab415c6
     }
ab415c6
 }
ab415c6
 
ab415c6
+/* Print summary info about the state of the optimized allocator */
ab415c6
+void
ab415c6
+_PyList_DebugMallocStats(FILE *out)
ab415c6
+{
ab415c6
+    _PyDebugAllocatorStats(out,
ab415c6
+                           "free PyListObject",
ab415c6
+                           numfree, sizeof(PyListObject));
ab415c6
+}
ab415c6
+
ab415c6
 PyObject *
ab415c6
 PyList_New(Py_ssize_t size)
ab415c6
 {
ab415c6
diff -up Python-3.2.2/Objects/methodobject.c.add-debug-malloc-stats Python-3.2.2/Objects/methodobject.c
ab415c6
--- Python-3.2.2/Objects/methodobject.c.add-debug-malloc-stats	2011-09-03 12:16:47.000000000 -0400
ab415c6
+++ Python-3.2.2/Objects/methodobject.c	2011-09-16 18:57:24.983825060 -0400
ab415c6
@@ -303,6 +303,15 @@ PyCFunction_Fini(void)
ab415c6
     (void)PyCFunction_ClearFreeList();
ab415c6
 }
ab415c6
 
ab415c6
+/* Print summary info about the state of the optimized allocator */
ab415c6
+void
ab415c6
+_PyCFunction_DebugMallocStats(FILE *out)
ab415c6
+{
ab415c6
+    _PyDebugAllocatorStats(out,
ab415c6
+                           "free PyCFunction",
ab415c6
+                           numfree, sizeof(PyCFunction));
ab415c6
+}
ab415c6
+
ab415c6
 /* PyCFunction_New() is now just a macro that calls PyCFunction_NewEx(),
ab415c6
    but it's part of the API so we need to keep a function around that
ab415c6
    existing C extensions can call.
ab415c6
diff -up Python-3.2.2/Objects/object.c.add-debug-malloc-stats Python-3.2.2/Objects/object.c
ab415c6
--- Python-3.2.2/Objects/object.c.add-debug-malloc-stats	2011-09-03 12:16:47.000000000 -0400
ab415c6
+++ Python-3.2.2/Objects/object.c	2011-09-16 19:04:20.351821098 -0400
ab415c6
@@ -1781,6 +1781,19 @@ PyMem_Free(void *p)
ab415c6
     PyMem_FREE(p);
ab415c6
 }
ab415c6
 
ab415c6
+void
ab415c6
+_PyObject_DebugTypeStats(FILE *out)
ab415c6
+{
ab415c6
+    _PyCFunction_DebugMallocStats(out);
ab415c6
+    _PyDict_DebugMallocStats(out);
ab415c6
+    _PyFloat_DebugMallocStats(out);
ab415c6
+    _PyFrame_DebugMallocStats(out);
ab415c6
+    _PyList_DebugMallocStats(out);
ab415c6
+    _PyMethod_DebugMallocStats(out);
ab415c6
+    _PySet_DebugMallocStats(out);
ab415c6
+    _PyTuple_DebugMallocStats(out);
ab415c6
+    _PyUnicode_DebugMallocStats(out);
ab415c6
+}
ab415c6
 
ab415c6
 /* These methods are used to control infinite recursion in repr, str, print,
ab415c6
    etc.  Container objects that may recursively contain themselves,
ab415c6
diff -up Python-3.2.2/Objects/obmalloc.c.add-debug-malloc-stats Python-3.2.2/Objects/obmalloc.c
ab415c6
--- Python-3.2.2/Objects/obmalloc.c.add-debug-malloc-stats	2011-09-03 12:16:47.000000000 -0400
ab415c6
+++ Python-3.2.2/Objects/obmalloc.c	2011-09-16 18:57:24.985825060 -0400
ab415c6
@@ -508,12 +508,10 @@ static struct arena_object* usable_arena
ab415c6
 /* Number of arenas allocated that haven't been free()'d. */
ab415c6
 static size_t narenas_currently_allocated = 0;
ab415c6
 
ab415c6
-#ifdef PYMALLOC_DEBUG
ab415c6
 /* Total number of times malloc() called to allocate an arena. */
ab415c6
 static size_t ntimes_arena_allocated = 0;
ab415c6
 /* High water mark (max value ever seen) for narenas_currently_allocated. */
ab415c6
 static size_t narenas_highwater = 0;
ab415c6
-#endif
ab415c6
 
ab415c6
 /* Allocate a new arena.  If we run out of memory, return NULL.  Else
ab415c6
  * allocate a new arena, and return the address of an arena_object
ab415c6
@@ -528,7 +526,7 @@ new_arena(void)
ab415c6
 
ab415c6
 #ifdef PYMALLOC_DEBUG
ab415c6
     if (Py_GETENV("PYTHONMALLOCSTATS"))
ab415c6
-        _PyObject_DebugMallocStats();
ab415c6
+        _PyObject_DebugMallocStats(stderr);
ab415c6
 #endif
ab415c6
     if (unused_arena_objects == NULL) {
ab415c6
         uint i;
ab415c6
@@ -588,11 +586,9 @@ new_arena(void)
ab415c6
     }
ab415c6
 
ab415c6
     ++narenas_currently_allocated;
ab415c6
-#ifdef PYMALLOC_DEBUG
ab415c6
     ++ntimes_arena_allocated;
ab415c6
     if (narenas_currently_allocated > narenas_highwater)
ab415c6
         narenas_highwater = narenas_currently_allocated;
ab415c6
-#endif
ab415c6
     arenaobj->freepools = NULL;
ab415c6
     /* pool_address <- first pool-aligned address in the arena
ab415c6
        nfreepools <- number of whole pools that fit after alignment */
ab415c6
@@ -1694,17 +1690,19 @@ _PyObject_DebugDumpAddress(const void *p
ab415c6
     }
ab415c6
 }
ab415c6
 
ab415c6
+#endif  /* PYMALLOC_DEBUG */
ab415c6
+
ab415c6
 static size_t
ab415c6
-printone(const char* msg, size_t value)
ab415c6
+printone(FILE *out, const char* msg, size_t value)
ab415c6
 {
ab415c6
     int i, k;
ab415c6
     char buf[100];
ab415c6
     size_t origvalue = value;
ab415c6
 
ab415c6
-    fputs(msg, stderr);
ab415c6
+    fputs(msg, out);
ab415c6
     for (i = (int)strlen(msg); i < 35; ++i)
ab415c6
-        fputc(' ', stderr);
ab415c6
-    fputc('=', stderr);
ab415c6
+        fputc(' ', out);
ab415c6
+    fputc('=', out);
ab415c6
 
ab415c6
     /* Write the value with commas. */
ab415c6
     i = 22;
ab415c6
@@ -1725,17 +1723,32 @@ printone(const char* msg, size_t value)
ab415c6
 
ab415c6
     while (i >= 0)
ab415c6
         buf[i--] = ' ';
ab415c6
-    fputs(buf, stderr);
ab415c6
+    fputs(buf, out);
ab415c6
 
ab415c6
     return origvalue;
ab415c6
 }
ab415c6
 
ab415c6
-/* Print summary info to stderr about the state of pymalloc's structures.
ab415c6
+void
ab415c6
+_PyDebugAllocatorStats(FILE *out,
ab415c6
+                       const char *block_name, int num_blocks, size_t sizeof_block)
ab415c6
+{
ab415c6
+       char buf1[128];
ab415c6
+       char buf2[128];
ab415c6
+       PyOS_snprintf(buf1, sizeof(buf1),
ab415c6
+                     "%d %ss * %zd bytes each",
ab415c6
+                     num_blocks, block_name, sizeof_block);
ab415c6
+       PyOS_snprintf(buf2, sizeof(buf2),
ab415c6
+                     "%48s ", buf1);
ab415c6
+      (void)printone(out, buf2, num_blocks * sizeof_block);
ab415c6
+}
ab415c6
+
ab415c6
+
ab415c6
+/* Print summary info to "out" about the state of pymalloc's structures.
ab415c6
  * In Py_DEBUG mode, also perform some expensive internal consistency
ab415c6
  * checks.
ab415c6
  */
ab415c6
 void
ab415c6
-_PyObject_DebugMallocStats(void)
ab415c6
+_PyObject_DebugMallocStats(FILE *out)
ab415c6
 {
ab415c6
     uint i;
ab415c6
     const uint numclasses = SMALL_REQUEST_THRESHOLD >> ALIGNMENT_SHIFT;
ab415c6
@@ -1764,7 +1777,7 @@ _PyObject_DebugMallocStats(void)
ab415c6
     size_t total;
ab415c6
     char buf[128];
ab415c6
 
ab415c6
-    fprintf(stderr, "Small block threshold = %d, in %u size classes.\n",
ab415c6
+    fprintf(out, "Small block threshold = %d, in %u size classes.\n",
ab415c6
             SMALL_REQUEST_THRESHOLD, numclasses);
ab415c6
 
ab415c6
     for (i = 0; i < numclasses; ++i)
ab415c6
@@ -1820,10 +1833,10 @@ _PyObject_DebugMallocStats(void)
ab415c6
     }
ab415c6
     assert(narenas == narenas_currently_allocated);
ab415c6
 
ab415c6
-    fputc('\n', stderr);
ab415c6
+    fputc('\n', out);
ab415c6
     fputs("class   size   num pools   blocks in use  avail blocks\n"
ab415c6
           "-----   ----   ---------   -------------  ------------\n",
ab415c6
-          stderr);
ab415c6
+          out);
ab415c6
 
ab415c6
     for (i = 0; i < numclasses; ++i) {
ab415c6
         size_t p = numpools[i];
ab415c6
@@ -1834,7 +1847,7 @@ _PyObject_DebugMallocStats(void)
ab415c6
             assert(b == 0 && f == 0);
ab415c6
             continue;
ab415c6
         }
ab415c6
-        fprintf(stderr, "%5u %6u "
ab415c6
+        fprintf(out, "%5u %6u "
ab415c6
                         "%11" PY_FORMAT_SIZE_T "u "
ab415c6
                         "%15" PY_FORMAT_SIZE_T "u "
ab415c6
                         "%13" PY_FORMAT_SIZE_T "u\n",
ab415c6
@@ -1844,36 +1857,35 @@ _PyObject_DebugMallocStats(void)
ab415c6
         pool_header_bytes += p * POOL_OVERHEAD;
ab415c6
         quantization += p * ((POOL_SIZE - POOL_OVERHEAD) % size);
ab415c6
     }
ab415c6
-    fputc('\n', stderr);
ab415c6
-    (void)printone("# times object malloc called", serialno);
ab415c6
-
ab415c6
-    (void)printone("# arenas allocated total", ntimes_arena_allocated);
ab415c6
-    (void)printone("# arenas reclaimed", ntimes_arena_allocated - narenas);
ab415c6
-    (void)printone("# arenas highwater mark", narenas_highwater);
ab415c6
-    (void)printone("# arenas allocated current", narenas);
ab415c6
+    fputc('\n', out);
ab415c6
+#ifdef PYMALLOC_DEBUG
ab415c6
+    (void)printone(out, "# times object malloc called", serialno);
ab415c6
+#endif
ab415c6
+    (void)printone(out, "# arenas allocated total", ntimes_arena_allocated);
ab415c6
+    (void)printone(out, "# arenas reclaimed", ntimes_arena_allocated - narenas);
ab415c6
+    (void)printone(out, "# arenas highwater mark", narenas_highwater);
ab415c6
+    (void)printone(out, "# arenas allocated current", narenas);
ab415c6
 
ab415c6
     PyOS_snprintf(buf, sizeof(buf),
ab415c6
         "%" PY_FORMAT_SIZE_T "u arenas * %d bytes/arena",
ab415c6
         narenas, ARENA_SIZE);
ab415c6
-    (void)printone(buf, narenas * ARENA_SIZE);
ab415c6
+    (void)printone(out, buf, narenas * ARENA_SIZE);
ab415c6
 
ab415c6
-    fputc('\n', stderr);
ab415c6
+    fputc('\n', out);
ab415c6
 
ab415c6
-    total = printone("# bytes in allocated blocks", allocated_bytes);
ab415c6
-    total += printone("# bytes in available blocks", available_bytes);
ab415c6
+    total = printone(out, "# bytes in allocated blocks", allocated_bytes);
ab415c6
+    total += printone(out, "# bytes in available blocks", available_bytes);
ab415c6
 
ab415c6
     PyOS_snprintf(buf, sizeof(buf),
ab415c6
         "%u unused pools * %d bytes", numfreepools, POOL_SIZE);
ab415c6
-    total += printone(buf, (size_t)numfreepools * POOL_SIZE);
ab415c6
+    total += printone(out, buf, (size_t)numfreepools * POOL_SIZE);
ab415c6
 
ab415c6
-    total += printone("# bytes lost to pool headers", pool_header_bytes);
ab415c6
-    total += printone("# bytes lost to quantization", quantization);
ab415c6
-    total += printone("# bytes lost to arena alignment", arena_alignment);
ab415c6
-    (void)printone("Total", total);
ab415c6
+    total += printone(out, "# bytes lost to pool headers", pool_header_bytes);
ab415c6
+    total += printone(out, "# bytes lost to quantization", quantization);
ab415c6
+    total += printone(out, "# bytes lost to arena alignment", arena_alignment);
ab415c6
+    (void)printone(out, "Total", total);
ab415c6
 }
ab415c6
 
ab415c6
-#endif  /* PYMALLOC_DEBUG */
ab415c6
-
ab415c6
 #ifdef Py_USING_MEMORY_DEBUGGER
ab415c6
 /* Make this function last so gcc won't inline it since the definition is
ab415c6
  * after the reference.
ab415c6
diff -up Python-3.2.2/Objects/setobject.c.add-debug-malloc-stats Python-3.2.2/Objects/setobject.c
ab415c6
--- Python-3.2.2/Objects/setobject.c.add-debug-malloc-stats	2011-09-03 12:16:47.000000000 -0400
ab415c6
+++ Python-3.2.2/Objects/setobject.c	2011-09-16 18:57:24.986825060 -0400
ab415c6
@@ -1090,6 +1090,16 @@ PySet_Fini(void)
ab415c6
     Py_CLEAR(emptyfrozenset);
ab415c6
 }
ab415c6
 
ab415c6
+/* Print summary info about the state of the optimized allocator */
ab415c6
+void
ab415c6
+_PySet_DebugMallocStats(FILE *out)
ab415c6
+{
ab415c6
+    _PyDebugAllocatorStats(out,
ab415c6
+                           "free PySetObject",
ab415c6
+                           numfree, sizeof(PySetObject));
ab415c6
+}
ab415c6
+
ab415c6
+
ab415c6
 static PyObject *
ab415c6
 set_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
ab415c6
 {
ab415c6
diff -up Python-3.2.2/Objects/tupleobject.c.add-debug-malloc-stats Python-3.2.2/Objects/tupleobject.c
ab415c6
--- Python-3.2.2/Objects/tupleobject.c.add-debug-malloc-stats	2011-09-03 12:16:47.000000000 -0400
ab415c6
+++ Python-3.2.2/Objects/tupleobject.c	2011-09-16 18:57:24.987825060 -0400
ab415c6
@@ -44,6 +44,22 @@ show_track(void)
ab415c6
 }
ab415c6
 #endif
ab415c6
 
ab415c6
+/* Print summary info about the state of the optimized allocator */
ab415c6
+void
ab415c6
+_PyTuple_DebugMallocStats(FILE *out)
ab415c6
+{
ab415c6
+#if PyTuple_MAXSAVESIZE > 0
ab415c6
+    int i;
ab415c6
+    char buf[128];
ab415c6
+    for (i = 1; i < PyTuple_MAXSAVESIZE; i++) {
ab415c6
+        PyOS_snprintf(buf, sizeof(buf),
ab415c6
+                      "free %d-sized PyTupleObject", i);
ab415c6
+        _PyDebugAllocatorStats(out,
ab415c6
+                               buf,
ab415c6
+                               numfree[i], _PyObject_VAR_SIZE(&PyTuple_Type, i));
ab415c6
+    }
ab415c6
+#endif
ab415c6
+}
ab415c6
 
ab415c6
 PyObject *
ab415c6
 PyTuple_New(register Py_ssize_t size)
ab415c6
diff -up Python-3.2.2/Objects/unicodeobject.c.add-debug-malloc-stats Python-3.2.2/Objects/unicodeobject.c
ab415c6
--- Python-3.2.2/Objects/unicodeobject.c.add-debug-malloc-stats	2011-09-03 12:16:47.000000000 -0400
ab415c6
+++ Python-3.2.2/Objects/unicodeobject.c	2011-09-16 18:57:24.990825060 -0400
ab415c6
@@ -10063,6 +10063,12 @@ _PyUnicode_Fini(void)
ab415c6
     (void)PyUnicode_ClearFreeList();
ab415c6
 }
ab415c6
 
ab415c6
+void _PyUnicode_DebugMallocStats(FILE *out)
ab415c6
+{
ab415c6
+    _PyDebugAllocatorStats(out, "free PyUnicodeObject", numfree,
ab415c6
+                           sizeof(PyUnicodeObject));
ab415c6
+}
ab415c6
+
ab415c6
 void
ab415c6
 PyUnicode_InternInPlace(PyObject **p)
ab415c6
 {
ab415c6
diff -up Python-3.2.2/Python/pythonrun.c.add-debug-malloc-stats Python-3.2.2/Python/pythonrun.c
ab415c6
--- Python-3.2.2/Python/pythonrun.c.add-debug-malloc-stats	2011-09-16 19:24:44.747809422 -0400
ab415c6
+++ Python-3.2.2/Python/pythonrun.c	2011-09-16 19:25:00.024809277 -0400
ab415c6
@@ -547,7 +547,7 @@ Py_Finalize(void)
ab415c6
 #endif /* Py_TRACE_REFS */
ab415c6
 #ifdef PYMALLOC_DEBUG
ab415c6
     if (Py_GETENV("PYTHONMALLOCSTATS"))
ab415c6
-        _PyObject_DebugMallocStats();
ab415c6
+        _PyObject_DebugMallocStats(stderr);
ab415c6
 #endif
ab415c6
 
ab415c6
     call_ll_exitfuncs();
ab415c6
diff -up Python-3.2.2/Python/sysmodule.c.add-debug-malloc-stats Python-3.2.2/Python/sysmodule.c
ab415c6
--- Python-3.2.2/Python/sysmodule.c.add-debug-malloc-stats	2011-09-03 12:16:49.000000000 -0400
ab415c6
+++ Python-3.2.2/Python/sysmodule.c	2011-09-16 19:18:45.806812845 -0400
ab415c6
@@ -994,6 +994,25 @@ a 11-tuple where the entries in the tupl
ab415c6
 extern "C" {
ab415c6
 #endif
ab415c6
 
ab415c6
+static PyObject *
ab415c6
+sys_debugmallocstats(PyObject *self, PyObject *args)
ab415c6
+{
ab415c6
+    _PyObject_DebugMallocStats(stderr);
ab415c6
+    fputc('\n', stderr);
ab415c6
+    _PyObject_DebugTypeStats(stderr);
ab415c6
+
ab415c6
+    Py_RETURN_NONE;
ab415c6
+}
ab415c6
+PyDoc_STRVAR(debugmallocstats_doc,
ab415c6
+"_debugmallocstats([file])\n\
ab415c6
+\n\
ab415c6
+Print summary info to stderr about the state of\n\
ab415c6
+pymalloc's structures.\n\
ab415c6
+\n\
ab415c6
+In Py_DEBUG mode, also perform some expensive internal consistency\n\
ab415c6
+checks.\n\
ab415c6
+");
ab415c6
+
ab415c6
 #ifdef Py_TRACE_REFS
ab415c6
 /* Defined in objects.c because it uses static globals if that file */
ab415c6
 extern PyObject *_Py_GetObjects(PyObject *, PyObject *);
ab415c6
@@ -1090,6 +1109,8 @@ static PyMethodDef sys_methods[] = {
ab415c6
     {"settrace",        sys_settrace, METH_O, settrace_doc},
ab415c6
     {"gettrace",        sys_gettrace, METH_NOARGS, gettrace_doc},
ab415c6
     {"call_tracing", sys_call_tracing, METH_VARARGS, call_tracing_doc},
ab415c6
+    {"_debugmallocstats", sys_debugmallocstats, METH_VARARGS,
ab415c6
+     debugmallocstats_doc},
ab415c6
     {NULL,              NULL}           /* sentinel */
ab415c6
 };
ab415c6