@@ -1763,7 +1763,91 @@ SimpleExtendsException(PyExc_Exception, ReferenceError,
17631763/*
17641764 * MemoryError extends Exception
17651765 */
1766- SimpleExtendsException (PyExc_Exception , MemoryError , "Out of memory." );
1766+
1767+ #define MEMERRORS_SAVE 16
1768+ static PyBaseExceptionObject * memerrors_freelist = NULL ;
1769+ static int memerrors_numfree = 0 ;
1770+
1771+ static PyObject *
1772+ MemoryError_new (PyTypeObject * type , PyObject * args , PyObject * kwds )
1773+ {
1774+ PyBaseExceptionObject * self ;
1775+
1776+ if (type != (PyTypeObject * ) PyExc_MemoryError )
1777+ return BaseException_new (type , args , kwds );
1778+ if (memerrors_freelist == NULL )
1779+ return BaseException_new (type , args , kwds );
1780+ /* Fetch object from freelist and revive it */
1781+ self = memerrors_freelist ;
1782+ self -> args = PyTuple_New (0 );
1783+ /* This shouldn't happen since the empty tuple is persistent */
1784+ if (self -> args == NULL )
1785+ return NULL ;
1786+ memerrors_freelist = (PyBaseExceptionObject * ) self -> dict ;
1787+ memerrors_numfree -- ;
1788+ self -> dict = NULL ;
1789+ _Py_NewReference ((PyObject * )self );
1790+ _PyObject_GC_TRACK (self );
1791+ return (PyObject * )self ;
1792+ }
1793+
1794+ static void
1795+ MemoryError_dealloc (PyBaseExceptionObject * self )
1796+ {
1797+ _PyObject_GC_UNTRACK (self );
1798+ BaseException_clear (self );
1799+ if (memerrors_numfree >= MEMERRORS_SAVE )
1800+ Py_TYPE (self )-> tp_free ((PyObject * )self );
1801+ else {
1802+ self -> dict = (PyObject * ) memerrors_freelist ;
1803+ memerrors_freelist = self ;
1804+ memerrors_numfree ++ ;
1805+ }
1806+ }
1807+
1808+ static void
1809+ preallocate_memerrors (void )
1810+ {
1811+ /* We create enough MemoryErrors and then decref them, which will fill
1812+ up the freelist. */
1813+ int i ;
1814+ PyObject * errors [MEMERRORS_SAVE ];
1815+ for (i = 0 ; i < MEMERRORS_SAVE ; i ++ ) {
1816+ errors [i ] = MemoryError_new ((PyTypeObject * ) PyExc_MemoryError ,
1817+ NULL , NULL );
1818+ if (!errors [i ])
1819+ Py_FatalError ("Could not preallocate MemoryError object" );
1820+ }
1821+ for (i = 0 ; i < MEMERRORS_SAVE ; i ++ ) {
1822+ Py_DECREF (errors [i ]);
1823+ }
1824+ }
1825+
1826+ static void
1827+ free_preallocated_memerrors (void )
1828+ {
1829+ while (memerrors_freelist != NULL ) {
1830+ PyObject * self = (PyObject * ) memerrors_freelist ;
1831+ memerrors_freelist = (PyBaseExceptionObject * ) memerrors_freelist -> dict ;
1832+ Py_TYPE (self )-> tp_free ((PyObject * )self );
1833+ }
1834+ }
1835+
1836+
1837+ static PyTypeObject _PyExc_MemoryError = {
1838+ PyVarObject_HEAD_INIT (NULL , 0 )
1839+ "MemoryError" ,
1840+ sizeof (PyBaseExceptionObject ),
1841+ 0 , (destructor )MemoryError_dealloc , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
1842+ 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
1843+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC ,
1844+ PyDoc_STR ("Out of memory." ), (traverseproc )BaseException_traverse ,
1845+ (inquiry )BaseException_clear , 0 , 0 , 0 , 0 , 0 , 0 , 0 , & _PyExc_Exception ,
1846+ 0 , 0 , 0 , offsetof(PyBaseExceptionObject , dict ),
1847+ (initproc )BaseException_init , 0 , MemoryError_new
1848+ };
1849+ PyObject * PyExc_MemoryError = (PyObject * ) & _PyExc_MemoryError ;
1850+
17671851
17681852/*
17691853 * BufferError extends Exception
@@ -1847,11 +1931,6 @@ SimpleExtendsException(PyExc_Warning, BytesWarning,
18471931
18481932
18491933
1850- /* Pre-computed MemoryError instance. Best to create this as early as
1851- * possible and not wait until a MemoryError is actually raised!
1852- */
1853- PyObject * PyExc_MemoryErrorInst = NULL ;
1854-
18551934/* Pre-computed RuntimeError instance for when recursion depth is reached.
18561935 Meant to be used when normalizing the exception for exceeding the recursion
18571936 depth will cause its own infinite recursion.
@@ -1988,9 +2067,7 @@ _PyExc_Init(void)
19882067 POST_INIT (UnicodeWarning )
19892068 POST_INIT (BytesWarning )
19902069
1991- PyExc_MemoryErrorInst = BaseException_new (& _PyExc_MemoryError , NULL , NULL );
1992- if (!PyExc_MemoryErrorInst )
1993- Py_FatalError ("Cannot pre-allocate MemoryError instance" );
2070+ preallocate_memerrors ();
19942071
19952072 PyExc_RecursionErrorInst = BaseException_new (& _PyExc_RuntimeError , NULL , NULL );
19962073 if (!PyExc_RecursionErrorInst )
@@ -2021,6 +2098,6 @@ _PyExc_Init(void)
20212098void
20222099_PyExc_Fini (void )
20232100{
2024- Py_XDECREF ( PyExc_MemoryErrorInst );
2025- PyExc_MemoryErrorInst = NULL ;
2101+ Py_CLEAR ( PyExc_RecursionErrorInst );
2102+ free_preallocated_memerrors () ;
20262103}
0 commit comments