@@ -1777,7 +1777,91 @@ SimpleExtendsException(PyExc_Exception, ReferenceError,
17771777/*
17781778 * MemoryError extends Exception
17791779 */
1780- SimpleExtendsException (PyExc_Exception , MemoryError , "Out of memory." );
1780+
1781+ #define MEMERRORS_SAVE 16
1782+ static PyBaseExceptionObject * memerrors_freelist = NULL ;
1783+ static int memerrors_numfree = 0 ;
1784+
1785+ static PyObject *
1786+ MemoryError_new (PyTypeObject * type , PyObject * args , PyObject * kwds )
1787+ {
1788+ PyBaseExceptionObject * self ;
1789+
1790+ if (type != (PyTypeObject * ) PyExc_MemoryError )
1791+ return BaseException_new (type , args , kwds );
1792+ if (memerrors_freelist == NULL )
1793+ return BaseException_new (type , args , kwds );
1794+ /* Fetch object from freelist and revive it */
1795+ self = memerrors_freelist ;
1796+ self -> args = PyTuple_New (0 );
1797+ /* This shouldn't happen since the empty tuple is persistent */
1798+ if (self -> args == NULL )
1799+ return NULL ;
1800+ memerrors_freelist = (PyBaseExceptionObject * ) self -> dict ;
1801+ memerrors_numfree -- ;
1802+ self -> dict = NULL ;
1803+ _Py_NewReference ((PyObject * )self );
1804+ _PyObject_GC_TRACK (self );
1805+ return (PyObject * )self ;
1806+ }
1807+
1808+ static void
1809+ MemoryError_dealloc (PyBaseExceptionObject * self )
1810+ {
1811+ _PyObject_GC_UNTRACK (self );
1812+ BaseException_clear (self );
1813+ if (memerrors_numfree >= MEMERRORS_SAVE )
1814+ Py_TYPE (self )-> tp_free ((PyObject * )self );
1815+ else {
1816+ self -> dict = (PyObject * ) memerrors_freelist ;
1817+ memerrors_freelist = self ;
1818+ memerrors_numfree ++ ;
1819+ }
1820+ }
1821+
1822+ static void
1823+ preallocate_memerrors (void )
1824+ {
1825+ /* We create enough MemoryErrors and then decref them, which will fill
1826+ up the freelist. */
1827+ int i ;
1828+ PyObject * errors [MEMERRORS_SAVE ];
1829+ for (i = 0 ; i < MEMERRORS_SAVE ; i ++ ) {
1830+ errors [i ] = MemoryError_new ((PyTypeObject * ) PyExc_MemoryError ,
1831+ NULL , NULL );
1832+ if (!errors [i ])
1833+ Py_FatalError ("Could not preallocate MemoryError object" );
1834+ }
1835+ for (i = 0 ; i < MEMERRORS_SAVE ; i ++ ) {
1836+ Py_DECREF (errors [i ]);
1837+ }
1838+ }
1839+
1840+ static void
1841+ free_preallocated_memerrors (void )
1842+ {
1843+ while (memerrors_freelist != NULL ) {
1844+ PyObject * self = (PyObject * ) memerrors_freelist ;
1845+ memerrors_freelist = (PyBaseExceptionObject * ) memerrors_freelist -> dict ;
1846+ Py_TYPE (self )-> tp_free ((PyObject * )self );
1847+ }
1848+ }
1849+
1850+
1851+ static PyTypeObject _PyExc_MemoryError = {
1852+ PyVarObject_HEAD_INIT (NULL , 0 )
1853+ "MemoryError" ,
1854+ sizeof (PyBaseExceptionObject ),
1855+ 0 , (destructor )MemoryError_dealloc , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
1856+ 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
1857+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC ,
1858+ PyDoc_STR ("Out of memory." ), (traverseproc )BaseException_traverse ,
1859+ (inquiry )BaseException_clear , 0 , 0 , 0 , 0 , 0 , 0 , 0 , & _PyExc_Exception ,
1860+ 0 , 0 , 0 , offsetof(PyBaseExceptionObject , dict ),
1861+ (initproc )BaseException_init , 0 , MemoryError_new
1862+ };
1863+ PyObject * PyExc_MemoryError = (PyObject * ) & _PyExc_MemoryError ;
1864+
17811865
17821866/*
17831867 * BufferError extends Exception
@@ -1869,11 +1953,6 @@ SimpleExtendsException(PyExc_Warning, ResourceWarning,
18691953
18701954
18711955
1872- /* Pre-computed MemoryError instance. Best to create this as early as
1873- * possible and not wait until a MemoryError is actually raised!
1874- */
1875- PyObject * PyExc_MemoryErrorInst = NULL ;
1876-
18771956/* Pre-computed RuntimeError instance for when recursion depth is reached.
18781957 Meant to be used when normalizing the exception for exceeding the recursion
18791958 depth will cause its own infinite recursion.
@@ -2012,9 +2091,7 @@ _PyExc_Init(void)
20122091 POST_INIT (BytesWarning )
20132092 POST_INIT (ResourceWarning )
20142093
2015- PyExc_MemoryErrorInst = BaseException_new (& _PyExc_MemoryError , NULL , NULL );
2016- if (!PyExc_MemoryErrorInst )
2017- Py_FatalError ("Cannot pre-allocate MemoryError instance" );
2094+ preallocate_memerrors ();
20182095
20192096 PyExc_RecursionErrorInst = BaseException_new (& _PyExc_RuntimeError , NULL , NULL );
20202097 if (!PyExc_RecursionErrorInst )
@@ -2045,6 +2122,6 @@ _PyExc_Init(void)
20452122void
20462123_PyExc_Fini (void )
20472124{
2048- Py_CLEAR (PyExc_MemoryErrorInst );
20492125 Py_CLEAR (PyExc_RecursionErrorInst );
2126+ free_preallocated_memerrors ();
20502127}
0 commit comments