From afbd9fa902c36e9bdf6a4aaf3802a47e581a6e66 Mon Sep 17 00:00:00 2001
From: penguin-wwy <940375606@qq.com>
Date: Mon, 18 Apr 2022 22:51:19 +0800
Subject: [PATCH 1/9] Add long object free list
---
 Include/internal/pycore_gc.h         |  1 +
 Include/internal/pycore_interp.h     |  2 ++
 Include/internal/pycore_long.h       |  1 +
 Include/internal/pycore_longobject.h | 29 ++++++++++++++++++++++++++++
 Makefile.pre.in                      |  1 +
 Modules/gcmodule.c                   |  1 +
 Objects/longobject.c                 | 26 +++++++++++++++++++++++++
 Python/pylifecycle.c                 |  1 +
 8 files changed, 62 insertions(+)
 create mode 100644 Include/internal/pycore_longobject.h
diff --git a/Include/internal/pycore_gc.h b/Include/internal/pycore_gc.h
index 16c1893639f354..6c7495a05d8583 100644
--- a/Include/internal/pycore_gc.h
+++ b/Include/internal/pycore_gc.h
@@ -172,6 +172,7 @@ extern Py_ssize_t _PyGC_CollectNoFail(PyThreadState *tstate);
 // Functions to clear types free lists
 extern void _PyTuple_ClearFreeList(PyInterpreterState *interp);
 extern void _PyFloat_ClearFreeList(PyInterpreterState *interp);
+extern void _PyLong_ClearFreeList(PyInterpreterState *interp);
 extern void _PyList_ClearFreeList(PyInterpreterState *interp);
 extern void _PyDict_ClearFreeList(PyInterpreterState *interp);
 extern void _PyAsyncGen_ClearFreeLists(PyInterpreterState *interp);
diff --git a/Include/internal/pycore_interp.h b/Include/internal/pycore_interp.h
index d55627908a28f8..403bd1d9cc5eb2 100644
--- a/Include/internal/pycore_interp.h
+++ b/Include/internal/pycore_interp.h
@@ -21,6 +21,7 @@ extern "C" {
 #include "pycore_gil.h"           // struct _gil_runtime_state
 #include "pycore_gc.h"            // struct _gc_runtime_state
 #include "pycore_list.h"          // struct _Py_list_state
+#include "pycore_longobject.h"    // struct _Py_long_state
 #include "pycore_tuple.h"         // struct _Py_tuple_state
 #include "pycore_typeobject.h"    // struct type_cache
 #include "pycore_unicodeobject.h" // struct _Py_unicode_state
@@ -164,6 +165,7 @@ struct _is {
 
     struct _Py_unicode_state unicode;
     struct _Py_float_state float_state;
+    struct _Py_long_state long_state;
     /* Using a cache is very effective since typically only a single slice is
        created and then deleted again. */
     PySliceObject *slice_cache;
diff --git a/Include/internal/pycore_long.h b/Include/internal/pycore_long.h
index a33762402491b7..c1c53fc8635f21 100644
--- a/Include/internal/pycore_long.h
+++ b/Include/internal/pycore_long.h
@@ -16,6 +16,7 @@ extern "C" {
 
 extern PyStatus _PyLong_InitTypes(PyInterpreterState *);
 extern void _PyLong_FiniTypes(PyInterpreterState *interp);
+extern void _PyLong_Fini(PyInterpreterState *);
 
 
 /* other API */
diff --git a/Include/internal/pycore_longobject.h b/Include/internal/pycore_longobject.h
new file mode 100644
index 00000000000000..ec21771792631b
--- /dev/null
+++ b/Include/internal/pycore_longobject.h
@@ -0,0 +1,29 @@
+#ifndef Py_INTERNAL_LONGOBJECT_H
+#define Py_INTERNAL_LONGOBJECT_H
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef WITH_FREELISTS
+// without freelists
+#  define PyLong_MAXFREELIST 0
+#endif
+
+#ifndef PyLong_MAXFREELIST
+#  define PyLong_MAXFREELIST   100
+#endif
+
+struct _Py_long_state {
+#if PyLong_MAXFREELIST > 0
+    /* Special free list
+       free_list is a singly-linked list of available PyLongObjects,
+       linked via abuse of their ob_type members. */
+    int numfree;
+    PyLongObject *free_list;
+#endif
+};
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* !Py_INTERNAL_LONGOBJECT_H */
diff --git a/Makefile.pre.in b/Makefile.pre.in
index f6c8c72bbc2c3c..6cffb0449c5ad2 100644
--- a/Makefile.pre.in
+++ b/Makefile.pre.in
@@ -1602,6 +1602,7 @@ PYTHON_HEADERS= \
 		$(srcdir)/Include/internal/pycore_interpreteridobject.h \
 		$(srcdir)/Include/internal/pycore_list.h \
 		$(srcdir)/Include/internal/pycore_long.h \
+		$(srcdir)/Include/internal/pycore_longobject.h \
 		$(srcdir)/Include/internal/pycore_moduleobject.h \
 		$(srcdir)/Include/internal/pycore_namespace.h \
 		$(srcdir)/Include/internal/pycore_object.h \
diff --git a/Modules/gcmodule.c b/Modules/gcmodule.c
index 802c3eadccfb0c..b73dd273c10a46 100644
--- a/Modules/gcmodule.c
+++ b/Modules/gcmodule.c
@@ -1036,6 +1036,7 @@ clear_freelists(PyInterpreterState *interp)
 {
     _PyTuple_ClearFreeList(interp);
     _PyFloat_ClearFreeList(interp);
+    _PyLong_ClearFreeList(interp);
     _PyList_ClearFreeList(interp);
     _PyDict_ClearFreeList(interp);
     _PyAsyncGen_ClearFreeLists(interp);
diff --git a/Objects/longobject.c b/Objects/longobject.c
index cc4aef31d743cc..1b42b706dbb606 100644
--- a/Objects/longobject.c
+++ b/Objects/longobject.c
@@ -6070,3 +6070,29 @@ _PyLong_FiniTypes(PyInterpreterState *interp)
 
     _PyStructSequence_FiniType(&Int_InfoType);
 }
+
+void
+_PyLong_ClearFreeList(PyInterpreterState *interp)
+{
+#if PyLong_MAXFREELIST > 0
+    struct _Py_long_state *state = &interp->long_state;
+    PyLongObject *num = state->free_list;
+    while (num != NULL) {
+        PyLongObject *next = (PyLongObject *) Py_TYPE(num);
+        PyObject_Free(num);
+        num = next;
+    }
+    state->free_list = NULL;
+    state->numfree = 0;
+#endif
+}
+
+void
+_PyLong_Fini(PyInterpreterState *interp)
+{
+    _PyLong_ClearFreeList(interp);
+#if defined(Py_DEBUG) && PyLong_MAXFREELIST > 0
+    struct _Py_long_state *state = &interp->long_state;
+    state->numfree = -1;
+#endif
+}
diff --git a/Python/pylifecycle.c b/Python/pylifecycle.c
index 273f6d62b2a204..1728ea2ea9d30a 100644
--- a/Python/pylifecycle.c
+++ b/Python/pylifecycle.c
@@ -1692,6 +1692,7 @@ finalize_interp_types(PyInterpreterState *interp)
 
     _PyUnicode_Fini(interp);
     _PyFloat_Fini(interp);
+    _PyLong_Fini(interp);
 }
 
 
From 8875ca99bfd52389c3cdd101a5c3f45061caf6b2 Mon Sep 17 00:00:00 2001
From: penguin-wwy <940375606@qq.com>
Date: Tue, 19 Apr 2022 23:13:22 +0800
Subject: [PATCH 2/9] Add long dealloc method
---
 Objects/longobject.c | 60 +++++++++++++++++++++++++++++++++++++++-----
 1 file changed, 54 insertions(+), 6 deletions(-)
diff --git a/Objects/longobject.c b/Objects/longobject.c
index 1b42b706dbb606..434d8409be7f87 100644
--- a/Objects/longobject.c
+++ b/Objects/longobject.c
@@ -124,6 +124,15 @@ long_normalize(PyLongObject *v)
     return v;
 }
 
+#if PyLong_MAXFREELIST > 0
+static struct _Py_long_state *
+get_long_state(void)
+{
+    PyInterpreterState *interp = _PyInterpreterState_GET();
+    return &interp->long_state;
+}
+#endif
+
 /* Allocate a new int object with size digits.
    Return NULL and set exception if we run out of memory. */
 
@@ -188,11 +197,26 @@ _PyLong_FromMedium(sdigit x)
 {
     assert(!IS_SMALL_INT(x));
     assert(is_medium_int(x));
-    /* We could use a freelist here */
-    PyLongObject *v = PyObject_Malloc(sizeof(PyLongObject));
-    if (v == NULL) {
-        PyErr_NoMemory();
-        return NULL;
+    PyLongObject *v;
+#if PyLong_MAXFREELIST > 0
+    struct _Py_long_state *state = get_long_state();
+    v = state->free_list;
+    if (v != NULL) {
+#ifdef Py_DEBUG
+        assert(state->numfree != -1);
+#endif
+        state->free_list = (PyLongObject *) Py_TYPE(v);
+        state->numfree--;
+    }
+    else
+#endif
+    {
+        /* We could use a freelist here */
+        v = PyObject_Malloc(sizeof(PyLongObject));
+        if (v == NULL) {
+            PyErr_NoMemory();
+            return NULL;
+        }
     }
     Py_ssize_t sign = x < 0 ? -1: 1;
     digit abs_x = x < 0 ? -x : x;
@@ -3040,6 +3064,30 @@ PyLong_AsDouble(PyObject *v)
 
 /* Methods */
 
+static void
+float_dealloc(PyLongObject *op)
+{
+#if PyLong_MAXFREELIST > 0
+    if (PyLong_CheckExact(op) && IS_MEDIUM_VALUE(op)) {
+        struct _Py_long_state *state = get_long_state();
+#ifdef Py_DEBUG
+        assert(state->numfree != -1);
+#endif
+        if (state->numfree >= PyLong_MAXFREELIST) {
+            PyObject_Del(op);
+            return;
+        }
+        state->numfree++;
+        Py_SET_TYPE(op, (PyTypeObject *)state->free_list);
+        state->free_list = op;
+    }
+    else
+#endif
+    {
+        Py_TYPE(op)->tp_free((PyObject *)op);
+    }
+}
+
 /* if a < b, return a negative number
    if a == b, return 0
    if a > b, return a positive number */
@@ -5957,7 +6005,7 @@ PyTypeObject PyLong_Type = {
     "int",                                      /* tp_name */
     offsetof(PyLongObject, ob_digit),           /* tp_basicsize */
     sizeof(digit),                              /* tp_itemsize */
-    0,                                          /* tp_dealloc */
+    (destructor)float_dealloc,                  /* tp_dealloc */
     0,                                          /* tp_vectorcall_offset */
     0,                                          /* tp_getattr */
     0,                                          /* tp_setattr */
From 6b2eefebb36ce6515aa24425a5b777c578482c58 Mon Sep 17 00:00:00 2001
From: penguin-wwy <940375606@qq.com>
Date: Sun, 24 Apr 2022 20:12:08 +0800
Subject: [PATCH 3/9] Free list for long object new
---
 Objects/longobject.c | 29 ++++++++++++++++++++++++-----
 1 file changed, 24 insertions(+), 5 deletions(-)
diff --git a/Objects/longobject.c b/Objects/longobject.c
index 7f756198f3bb8d..c978ec8d1a3eae 100644
--- a/Objects/longobject.c
+++ b/Objects/longobject.c
@@ -164,11 +164,30 @@ _PyLong_New(Py_ssize_t size)
        sizeof(PyVarObject) instead of the offsetof, but this risks being
        incorrect in the presence of padding between the PyVarObject header
        and the digits. */
-    result = PyObject_Malloc(offsetof(PyLongObject, ob_digit) +
-                             ndigits*sizeof(digit));
-    if (!result) {
-        PyErr_NoMemory();
-        return NULL;
+#if PyLong_MAXFREELIST > 0
+    if (ndigits + 1 < 3) {
+        struct _Py_long_state *state = get_long_state();
+        result = state->free_list;
+        if (result != NULL) {
+#ifdef Py_DEBUG
+            assert(state->numfree != -1);
+#endif
+            state->free_list = (PyLongObject *) Py_TYPE(result);
+            state->numfree--;
+        }
+    } else {
+        result = NULL;
+    }
+
+    if (result == NULL)
+#endif
+    {
+        result = PyObject_Malloc(offsetof(PyLongObject, ob_digit) +
+                                 ndigits * sizeof(digit));
+        if (!result) {
+            PyErr_NoMemory();
+            return NULL;
+        }
     }
     _PyObject_InitVar((PyVarObject*)result, &PyLong_Type, size);
     return result;
From 0e922e002be19765d25c4e4e27d1a7df353feab2 Mon Sep 17 00:00:00 2001
From: penguin-wwy <940375606@qq.com>
Date: Sun, 24 Apr 2022 20:30:54 +0800
Subject: [PATCH 4/9] Fix pcbuild script
---
 PCbuild/pythoncore.vcxproj         | 1 +
 PCbuild/pythoncore.vcxproj.filters | 3 +++
 2 files changed, 4 insertions(+)
diff --git a/PCbuild/pythoncore.vcxproj b/PCbuild/pythoncore.vcxproj
index 78bbec1e104e48..bb70367fb8054c 100644
--- a/PCbuild/pythoncore.vcxproj
+++ b/PCbuild/pythoncore.vcxproj
@@ -226,6 +226,7 @@
     
     
     
+    
     
     
     
diff --git a/PCbuild/pythoncore.vcxproj.filters b/PCbuild/pythoncore.vcxproj.filters
index 0a9d5454ba957a..55320c319a90f3 100644
--- a/PCbuild/pythoncore.vcxproj.filters
+++ b/PCbuild/pythoncore.vcxproj.filters
@@ -582,6 +582,9 @@
     
       Include\internal
     
+    
+      Include\internal
+    
     
       Include\internal
     
From 33821f27b267297d08336f66002fa0961443b458 Mon Sep 17 00:00:00 2001
From: penguin-wwy <940375606@qq.com>
Date: Sun, 24 Apr 2022 20:45:33 +0800
Subject: [PATCH 5/9] Fix long dealloc
---
 Objects/longobject.c | 8 +++++---
 1 file changed, 5 insertions(+), 3 deletions(-)
diff --git a/Objects/longobject.c b/Objects/longobject.c
index c978ec8d1a3eae..5e0bd31bda237f 100644
--- a/Objects/longobject.c
+++ b/Objects/longobject.c
@@ -36,11 +36,13 @@ medium_value(PyLongObject *x)
 #define IS_SMALL_INT(ival) (-_PY_NSMALLNEGINTS <= (ival) && (ival) < _PY_NSMALLPOSINTS)
 #define IS_SMALL_UINT(ival) ((ival) < _PY_NSMALLPOSINTS)
 
+static void long_dealloc(PyLongObject *op);
+
 static inline void
 _Py_DECREF_INT(PyLongObject *op)
 {
     assert(PyLong_CheckExact(op));
-    _Py_DECREF_SPECIALIZED((PyObject *)op, (destructor)PyObject_Free);
+    _Py_DECREF_SPECIALIZED((PyObject *)op, (destructor)long_dealloc);
 }
 
 static inline int
@@ -3095,7 +3097,7 @@ PyLong_AsDouble(PyObject *v)
 /* Methods */
 
 static void
-float_dealloc(PyLongObject *op)
+long_dealloc(PyLongObject *op)
 {
 #if PyLong_MAXFREELIST > 0
     if (PyLong_CheckExact(op) && IS_MEDIUM_VALUE(op)) {
@@ -6035,7 +6037,7 @@ PyTypeObject PyLong_Type = {
     "int",                                      /* tp_name */
     offsetof(PyLongObject, ob_digit),           /* tp_basicsize */
     sizeof(digit),                              /* tp_itemsize */
-    (destructor)float_dealloc,                  /* tp_dealloc */
+    (destructor)long_dealloc,                   /* tp_dealloc */
     0,                                          /* tp_vectorcall_offset */
     0,                                          /* tp_getattr */
     0,                                          /* tp_setattr */
From e89e3f5fe0948f775081e6011ae731e838e61b6c Mon Sep 17 00:00:00 2001
From: penguin-wwy <940375606@qq.com>
Date: Mon, 25 Apr 2022 11:37:39 +0800
Subject: [PATCH 6/9] Add long exact dealloc
---
 Include/internal/pycore_long.h |  1 +
 Objects/longobject.c           | 47 ++++++++++++++++++++++------------
 Python/ceval.c                 | 22 ++++++++--------
 3 files changed, 43 insertions(+), 27 deletions(-)
diff --git a/Include/internal/pycore_long.h b/Include/internal/pycore_long.h
index c1c53fc8635f21..4fc24c2bc4acc7 100644
--- a/Include/internal/pycore_long.h
+++ b/Include/internal/pycore_long.h
@@ -47,6 +47,7 @@ static inline PyObject* _PyLong_FromUnsignedChar(unsigned char i)
 PyObject *_PyLong_Add(PyLongObject *left, PyLongObject *right);
 PyObject *_PyLong_Multiply(PyLongObject *left, PyLongObject *right);
 PyObject *_PyLong_Subtract(PyLongObject *left, PyLongObject *right);
+void _PyLong_ExactDealloc(PyObject *obj);
 
 /* Used by Python/mystrtoul.c, _PyBytes_FromHex(),
    _PyBytes_DecodeEscape(), etc. */
diff --git a/Objects/longobject.c b/Objects/longobject.c
index 5e0bd31bda237f..c09662bccf192b 100644
--- a/Objects/longobject.c
+++ b/Objects/longobject.c
@@ -36,13 +36,11 @@ medium_value(PyLongObject *x)
 #define IS_SMALL_INT(ival) (-_PY_NSMALLNEGINTS <= (ival) && (ival) < _PY_NSMALLPOSINTS)
 #define IS_SMALL_UINT(ival) ((ival) < _PY_NSMALLPOSINTS)
 
-static void long_dealloc(PyLongObject *op);
-
 static inline void
 _Py_DECREF_INT(PyLongObject *op)
 {
     assert(PyLong_CheckExact(op));
-    _Py_DECREF_SPECIALIZED((PyObject *)op, (destructor)long_dealloc);
+    _Py_DECREF_SPECIALIZED((PyObject *)op, (destructor) _PyLong_ExactDealloc);
 }
 
 static inline int
@@ -3096,27 +3094,44 @@ PyLong_AsDouble(PyObject *v)
 
 /* Methods */
 
-static void
-long_dealloc(PyLongObject *op)
+void
+_PyLong_ExactDealloc(PyObject *obj)
 {
+    assert(PyLong_CheckExact(obj));
+    PyLongObject *op = (PyLongObject *)obj;
 #if PyLong_MAXFREELIST > 0
-    if (PyLong_CheckExact(op) && IS_MEDIUM_VALUE(op)) {
-        struct _Py_long_state *state = get_long_state();
+    if (!IS_MEDIUM_VALUE(op)) {
+        PyObject_Del(op);
+        return;
+    }
+    struct _Py_long_state *state = get_long_state();
 #ifdef Py_DEBUG
-        assert(state->numfree != -1);
+    assert(state->numfree != -1);
 #endif
-        if (state->numfree >= PyLong_MAXFREELIST) {
-            PyObject_Del(op);
-            return;
-        }
-        state->numfree++;
-        Py_SET_TYPE(op, (PyTypeObject *)state->free_list);
-        state->free_list = op;
+    if (state->numfree >= PyLong_MAXFREELIST)  {
+        PyObject_Del(op);
+        return;
+    }
+    state->numfree++;
+    Py_SET_TYPE(op, (PyTypeObject *)state->free_list);
+    state->free_list = op;
+#else
+    PyObject_Del(op);
+#endif
+}
+
+static void
+long_dealloc(PyObject *op)
+{
+    assert(PyLong_Check(op));
+#if PyLong_MAXFREELIST > 0
+    if (PyLong_CheckExact(op)) {
+        _PyLong_ExactDealloc(op);
     }
     else
 #endif
     {
-        Py_TYPE(op)->tp_free((PyObject *)op);
+        Py_TYPE(op)->tp_free(op);
     }
 }
 
diff --git a/Python/ceval.c b/Python/ceval.c
index a80583f5abd12c..6d842eaa0766d0 100644
--- a/Python/ceval.c
+++ b/Python/ceval.c
@@ -1979,8 +1979,8 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int
             STAT_INC(BINARY_OP, hit);
             PyObject *prod = _PyLong_Multiply((PyLongObject *)left, (PyLongObject *)right);
             SET_SECOND(prod);
-            _Py_DECREF_SPECIALIZED(right, (destructor)PyObject_Free);
-            _Py_DECREF_SPECIALIZED(left, (destructor)PyObject_Free);
+            _Py_DECREF_SPECIALIZED(right, (destructor)_PyLong_ExactDealloc);
+            _Py_DECREF_SPECIALIZED(left, (destructor)_PyLong_ExactDealloc);
             STACK_SHRINK(1);
             if (prod == NULL) {
                 goto error;
@@ -2019,8 +2019,8 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int
             STAT_INC(BINARY_OP, hit);
             PyObject *sub = _PyLong_Subtract((PyLongObject *)left, (PyLongObject *)right);
             SET_SECOND(sub);
-            _Py_DECREF_SPECIALIZED(right, (destructor)PyObject_Free);
-            _Py_DECREF_SPECIALIZED(left, (destructor)PyObject_Free);
+            _Py_DECREF_SPECIALIZED(right, (destructor)_PyLong_ExactDealloc);
+            _Py_DECREF_SPECIALIZED(left, (destructor)_PyLong_ExactDealloc);
             STACK_SHRINK(1);
             if (sub == NULL) {
                 goto error;
@@ -2134,8 +2134,8 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int
             STAT_INC(BINARY_OP, hit);
             PyObject *sum = _PyLong_Add((PyLongObject *)left, (PyLongObject *)right);
             SET_SECOND(sum);
-            _Py_DECREF_SPECIALIZED(right, (destructor)PyObject_Free);
-            _Py_DECREF_SPECIALIZED(left, (destructor)PyObject_Free);
+            _Py_DECREF_SPECIALIZED(right, (destructor)_PyLong_ExactDealloc);
+            _Py_DECREF_SPECIALIZED(left, (destructor)_PyLong_ExactDealloc);
             STACK_SHRINK(1);
             if (sum == NULL) {
                 goto error;
@@ -2194,7 +2194,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int
             assert(res != NULL);
             Py_INCREF(res);
             STACK_SHRINK(1);
-            _Py_DECREF_SPECIALIZED(sub, (destructor)PyObject_Free);
+            _Py_DECREF_SPECIALIZED(sub, (destructor)_PyLong_ExactDealloc);
             SET_TOP(res);
             Py_DECREF(list);
             JUMPBY(INLINE_CACHE_ENTRIES_BINARY_SUBSCR);
@@ -2219,7 +2219,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int
             assert(res != NULL);
             Py_INCREF(res);
             STACK_SHRINK(1);
-            _Py_DECREF_SPECIALIZED(sub, (destructor)PyObject_Free);
+            _Py_DECREF_SPECIALIZED(sub, (destructor)_PyLong_ExactDealloc);
             SET_TOP(res);
             Py_DECREF(tuple);
             JUMPBY(INLINE_CACHE_ENTRIES_BINARY_SUBSCR);
@@ -2361,7 +2361,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int
             STACK_SHRINK(3);
             assert(old_value != NULL);
             Py_DECREF(old_value);
-            _Py_DECREF_SPECIALIZED(sub, (destructor)PyObject_Free);
+            _Py_DECREF_SPECIALIZED(sub, (destructor)_PyLong_ExactDealloc);
             Py_DECREF(list);
             JUMPBY(INLINE_CACHE_ENTRIES_STORE_SUBSCR);
             NOTRACE_DISPATCH();
@@ -3797,8 +3797,8 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int
             JUMPBY(INLINE_CACHE_ENTRIES_COMPARE_OP);
             NEXTOPARG();
             STACK_SHRINK(2);
-            _Py_DECREF_SPECIALIZED(left, (destructor)PyObject_Free);
-            _Py_DECREF_SPECIALIZED(right, (destructor)PyObject_Free);
+            _Py_DECREF_SPECIALIZED(left, (destructor) _PyLong_ExactDealloc);
+            _Py_DECREF_SPECIALIZED(right, (destructor)_PyLong_ExactDealloc);
             assert(opcode == POP_JUMP_FORWARD_IF_FALSE ||
                    opcode == POP_JUMP_BACKWARD_IF_FALSE ||
                    opcode == POP_JUMP_FORWARD_IF_TRUE ||
From b83c5295eda1984601c592b1b273b07f54e7f1ac Mon Sep 17 00:00:00 2001
From: penguin-wwy <940375606@qq.com>
Date: Thu, 5 May 2022 14:23:35 +0800
Subject: [PATCH 7/9] Fix minor
---
 Objects/longobject.c | 7 +++----
 1 file changed, 3 insertions(+), 4 deletions(-)
diff --git a/Objects/longobject.c b/Objects/longobject.c
index e4fa98df435649..636b0809089cff 100644
--- a/Objects/longobject.c
+++ b/Objects/longobject.c
@@ -133,7 +133,7 @@ long_normalize(PyLongObject *v)
 }
 
 #if PyLong_MAXFREELIST > 0
-static struct _Py_long_state *
+static inline struct _Py_long_state *
 get_long_state(void)
 {
     PyInterpreterState *interp = _PyInterpreterState_GET();
@@ -238,7 +238,6 @@ _PyLong_FromMedium(sdigit x)
     else
 #endif
     {
-        /* We could use a freelist here */
         v = PyObject_Malloc(sizeof(PyLongObject));
         if (v == NULL) {
             PyErr_NoMemory();
@@ -3101,7 +3100,7 @@ _PyLong_ExactDealloc(PyObject *obj)
     PyLongObject *op = (PyLongObject *)obj;
 #if PyLong_MAXFREELIST > 0
     if (!IS_MEDIUM_VALUE(op)) {
-        PyObject_Del(op);
+        PyObject_FREE(op);
         return;
     }
     struct _Py_long_state *state = get_long_state();
@@ -3109,7 +3108,7 @@ _PyLong_ExactDealloc(PyObject *obj)
     assert(state->numfree != -1);
 #endif
     if (state->numfree >= PyLong_MAXFREELIST)  {
-        PyObject_Del(op);
+        PyObject_FREE(op);
         return;
     }
     state->numfree++;
From d81766015c8706d88fc8d0a25d39a8ef2107e49e Mon Sep 17 00:00:00 2001
From: penguin-wwy <940375606@qq.com>
Date: Mon, 28 Nov 2022 11:31:34 +0800
Subject: [PATCH 8/9] Dealloc long object in cases
---
 Python/bytecodes.c         |  22 +-
 Python/ceval.c             | 488 ++++++++++++++++++-------------------
 Python/generated_cases.c.h |  22 +-
 3 files changed, 266 insertions(+), 266 deletions(-)
diff --git a/Python/bytecodes.c b/Python/bytecodes.c
index a1f910da8ed54a..811089b276b86f 100644
--- a/Python/bytecodes.c
+++ b/Python/bytecodes.c
@@ -211,8 +211,8 @@ dummy_func(
             DEOPT_IF(!PyLong_CheckExact(right), BINARY_OP);
             STAT_INC(BINARY_OP, hit);
             prod = _PyLong_Multiply((PyLongObject *)left, (PyLongObject *)right);
-            _Py_DECREF_SPECIALIZED(right, (destructor)PyObject_Free);
-            _Py_DECREF_SPECIALIZED(left, (destructor)PyObject_Free);
+            _Py_DECREF_SPECIALIZED(right, (destructor)_PyLong_ExactDealloc);
+            _Py_DECREF_SPECIALIZED(left, (destructor)_PyLong_ExactDealloc);
             ERROR_IF(prod == NULL, error);
         }
 
@@ -235,8 +235,8 @@ dummy_func(
             DEOPT_IF(!PyLong_CheckExact(right), BINARY_OP);
             STAT_INC(BINARY_OP, hit);
             sub = _PyLong_Subtract((PyLongObject *)left, (PyLongObject *)right);
-            _Py_DECREF_SPECIALIZED(right, (destructor)PyObject_Free);
-            _Py_DECREF_SPECIALIZED(left, (destructor)PyObject_Free);
+            _Py_DECREF_SPECIALIZED(right, (destructor)_PyLong_ExactDealloc);
+            _Py_DECREF_SPECIALIZED(left, (destructor)_PyLong_ExactDealloc);
             ERROR_IF(sub == NULL, error);
         }
 
@@ -318,8 +318,8 @@ dummy_func(
             DEOPT_IF(Py_TYPE(right) != Py_TYPE(left), BINARY_OP);
             STAT_INC(BINARY_OP, hit);
             sum = _PyLong_Add((PyLongObject *)left, (PyLongObject *)right);
-            _Py_DECREF_SPECIALIZED(right, (destructor)PyObject_Free);
-            _Py_DECREF_SPECIALIZED(left, (destructor)PyObject_Free);
+            _Py_DECREF_SPECIALIZED(right, (destructor)_PyLong_ExactDealloc);
+            _Py_DECREF_SPECIALIZED(left, (destructor)_PyLong_ExactDealloc);
             ERROR_IF(sum == NULL, error);
         }
 
@@ -392,7 +392,7 @@ dummy_func(
             res = PyList_GET_ITEM(list, index);
             assert(res != NULL);
             Py_INCREF(res);
-            _Py_DECREF_SPECIALIZED(sub, (destructor)PyObject_Free);
+            _Py_DECREF_SPECIALIZED(sub, (destructor)_PyLong_ExactDealloc);
             Py_DECREF(list);
         }
 
@@ -411,7 +411,7 @@ dummy_func(
             res = PyTuple_GET_ITEM(tuple, index);
             assert(res != NULL);
             Py_INCREF(res);
-            _Py_DECREF_SPECIALIZED(sub, (destructor)PyObject_Free);
+            _Py_DECREF_SPECIALIZED(sub, (destructor)_PyLong_ExactDealloc);
             Py_DECREF(tuple);
         }
 
@@ -518,7 +518,7 @@ dummy_func(
             STACK_SHRINK(3);
             assert(old_value != NULL);
             Py_DECREF(old_value);
-            _Py_DECREF_SPECIALIZED(sub, (destructor)PyObject_Free);
+            _Py_DECREF_SPECIALIZED(sub, (destructor)_PyLong_ExactDealloc);
             Py_DECREF(list);
             JUMPBY(INLINE_CACHE_ENTRIES_STORE_SUBSCR);
         }
@@ -2129,8 +2129,8 @@ dummy_func(
             JUMPBY(INLINE_CACHE_ENTRIES_COMPARE_OP);
             NEXTOPARG();
             STACK_SHRINK(2);
-            _Py_DECREF_SPECIALIZED(left, (destructor)PyObject_Free);
-            _Py_DECREF_SPECIALIZED(right, (destructor)PyObject_Free);
+            _Py_DECREF_SPECIALIZED(left, (destructor)_PyLong_ExactDealloc);
+            _Py_DECREF_SPECIALIZED(right, (destructor)_PyLong_ExactDealloc);
             assert(opcode == POP_JUMP_IF_FALSE || opcode == POP_JUMP_IF_TRUE);
             int jump = (1 << (sign + 1)) & when_to_jump_mask;
             if (!jump) {
diff --git a/Python/ceval.c b/Python/ceval.c
index 641ab3c30053f6..80bfa21ad0b6f0 100644
--- a/Python/ceval.c
+++ b/Python/ceval.c
@@ -38,7 +38,7 @@
 #include 
 
 #ifdef Py_DEBUG
-/* For debugging the interpreter: */
+   /* For debugging the interpreter: */
 #  define LLTRACE  1      /* Low-level trace feature */
 #endif
 
@@ -103,11 +103,11 @@
 
 /* Forward declarations */
 static PyObject *trace_call_function(
-        PyThreadState *tstate, PyObject *callable, PyObject **stack,
-        Py_ssize_t oparg, PyObject *kwnames);
+    PyThreadState *tstate, PyObject *callable, PyObject **stack,
+    Py_ssize_t oparg, PyObject *kwnames);
 static PyObject * do_call_core(
-        PyThreadState *tstate, PyObject *func,
-        PyObject *callargs, PyObject *kwdict, int use_tracing);
+    PyThreadState *tstate, PyObject *func,
+    PyObject *callargs, PyObject *kwdict, int use_tracing);
 
 #ifdef LLTRACE
 static void
@@ -158,7 +158,7 @@ lltrace_resume_frame(_PyInterpreterFrame *frame)
     if (frame->owner == FRAME_OWNED_BY_CSTACK ||
         fobj == NULL ||
         !PyFunction_Check(fobj)
-            ) {
+    ) {
         printf("\nResuming frame.");
         return;
     }
@@ -288,8 +288,8 @@ _Py_CheckRecursiveCall(PyThreadState *tstate, const char *where)
         if (tstate->c_recursion_remaining <= 0) {
             tstate->recursion_headroom++;
             _PyErr_Format(tstate, PyExc_RecursionError,
-                          "maximum recursion depth exceeded%s",
-                          where);
+                        "maximum recursion depth exceeded%s",
+                        where);
             tstate->recursion_headroom--;
             ++tstate->c_recursion_remaining;
             return -1;
@@ -300,32 +300,32 @@ _Py_CheckRecursiveCall(PyThreadState *tstate, const char *where)
 
 
 static const binaryfunc binary_ops[] = {
-        [NB_ADD] = PyNumber_Add,
-        [NB_AND] = PyNumber_And,
-        [NB_FLOOR_DIVIDE] = PyNumber_FloorDivide,
-        [NB_LSHIFT] = PyNumber_Lshift,
-        [NB_MATRIX_MULTIPLY] = PyNumber_MatrixMultiply,
-        [NB_MULTIPLY] = PyNumber_Multiply,
-        [NB_REMAINDER] = PyNumber_Remainder,
-        [NB_OR] = PyNumber_Or,
-        [NB_POWER] = _PyNumber_PowerNoMod,
-        [NB_RSHIFT] = PyNumber_Rshift,
-        [NB_SUBTRACT] = PyNumber_Subtract,
-        [NB_TRUE_DIVIDE] = PyNumber_TrueDivide,
-        [NB_XOR] = PyNumber_Xor,
-        [NB_INPLACE_ADD] = PyNumber_InPlaceAdd,
-        [NB_INPLACE_AND] = PyNumber_InPlaceAnd,
-        [NB_INPLACE_FLOOR_DIVIDE] = PyNumber_InPlaceFloorDivide,
-        [NB_INPLACE_LSHIFT] = PyNumber_InPlaceLshift,
-        [NB_INPLACE_MATRIX_MULTIPLY] = PyNumber_InPlaceMatrixMultiply,
-        [NB_INPLACE_MULTIPLY] = PyNumber_InPlaceMultiply,
-        [NB_INPLACE_REMAINDER] = PyNumber_InPlaceRemainder,
-        [NB_INPLACE_OR] = PyNumber_InPlaceOr,
-        [NB_INPLACE_POWER] = _PyNumber_InPlacePowerNoMod,
-        [NB_INPLACE_RSHIFT] = PyNumber_InPlaceRshift,
-        [NB_INPLACE_SUBTRACT] = PyNumber_InPlaceSubtract,
-        [NB_INPLACE_TRUE_DIVIDE] = PyNumber_InPlaceTrueDivide,
-        [NB_INPLACE_XOR] = PyNumber_InPlaceXor,
+    [NB_ADD] = PyNumber_Add,
+    [NB_AND] = PyNumber_And,
+    [NB_FLOOR_DIVIDE] = PyNumber_FloorDivide,
+    [NB_LSHIFT] = PyNumber_Lshift,
+    [NB_MATRIX_MULTIPLY] = PyNumber_MatrixMultiply,
+    [NB_MULTIPLY] = PyNumber_Multiply,
+    [NB_REMAINDER] = PyNumber_Remainder,
+    [NB_OR] = PyNumber_Or,
+    [NB_POWER] = _PyNumber_PowerNoMod,
+    [NB_RSHIFT] = PyNumber_Rshift,
+    [NB_SUBTRACT] = PyNumber_Subtract,
+    [NB_TRUE_DIVIDE] = PyNumber_TrueDivide,
+    [NB_XOR] = PyNumber_Xor,
+    [NB_INPLACE_ADD] = PyNumber_InPlaceAdd,
+    [NB_INPLACE_AND] = PyNumber_InPlaceAnd,
+    [NB_INPLACE_FLOOR_DIVIDE] = PyNumber_InPlaceFloorDivide,
+    [NB_INPLACE_LSHIFT] = PyNumber_InPlaceLshift,
+    [NB_INPLACE_MATRIX_MULTIPLY] = PyNumber_InPlaceMatrixMultiply,
+    [NB_INPLACE_MULTIPLY] = PyNumber_InPlaceMultiply,
+    [NB_INPLACE_REMAINDER] = PyNumber_InPlaceRemainder,
+    [NB_INPLACE_OR] = PyNumber_InPlaceOr,
+    [NB_INPLACE_POWER] = _PyNumber_InPlacePowerNoMod,
+    [NB_INPLACE_RSHIFT] = PyNumber_InPlaceRshift,
+    [NB_INPLACE_SUBTRACT] = PyNumber_InPlaceSubtract,
+    [NB_INPLACE_TRUE_DIVIDE] = PyNumber_InPlaceTrueDivide,
+    [NB_INPLACE_XOR] = PyNumber_InPlaceXor,
 };
 
 
@@ -487,7 +487,7 @@ match_class(PyThreadState *tstate, PyObject *subject, PyObject *type,
             // soon as they redefine it.
             match_args = PyTuple_New(0);
             match_self = PyType_HasFeature((PyTypeObject*)type,
-                                           _Py_TPFLAGS_MATCH_SELF);
+                                            _Py_TPFLAGS_MATCH_SELF);
         }
         else {
             goto fail;
@@ -551,8 +551,8 @@ match_class(PyThreadState *tstate, PyObject *subject, PyObject *type,
 
 static int do_raise(PyThreadState *tstate, PyObject *exc, PyObject *cause);
 static int exception_group_match(
-        PyObject* exc_value, PyObject *match_type,
-        PyObject **match, PyObject **rest);
+    PyObject* exc_value, PyObject *match_type,
+    PyObject **match, PyObject **rest);
 
 static int unpack_iterable(PyThreadState *, PyObject *, int, int, PyObject **);
 
@@ -568,14 +568,14 @@ PyEval_EvalCode(PyObject *co, PyObject *globals, PyObject *locals)
         return NULL;
     }
     PyFrameConstructor desc = {
-            .fc_globals = globals,
-            .fc_builtins = builtins,
-            .fc_name = ((PyCodeObject *)co)->co_name,
-            .fc_qualname = ((PyCodeObject *)co)->co_name,
-            .fc_code = co,
-            .fc_defaults = NULL,
-            .fc_kwdefaults = NULL,
-            .fc_closure = NULL
+        .fc_globals = globals,
+        .fc_builtins = builtins,
+        .fc_name = ((PyCodeObject *)co)->co_name,
+        .fc_qualname = ((PyCodeObject *)co)->co_name,
+        .fc_code = co,
+        .fc_defaults = NULL,
+        .fc_kwdefaults = NULL,
+        .fc_closure = NULL
     };
     PyFunctionObject *func = _PyFunction_FromConstructor(&desc);
     if (func == NULL) {
@@ -654,11 +654,11 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)
 #endif
 
 #ifdef HAVE_COMPUTED_GOTOS
-#ifndef USE_COMPUTED_GOTOS
-#define USE_COMPUTED_GOTOS 1
-#endif
+    #ifndef USE_COMPUTED_GOTOS
+    #define USE_COMPUTED_GOTOS 1
+    #endif
 #else
-#if defined(USE_COMPUTED_GOTOS) && USE_COMPUTED_GOTOS
+    #if defined(USE_COMPUTED_GOTOS) && USE_COMPUTED_GOTOS
     #error "Computed gotos are not supported on this compiler."
     #endif
     #undef USE_COMPUTED_GOTOS
@@ -970,9 +970,9 @@ trace_function_entry(PyThreadState *tstate, _PyInterpreterFrame *frame)
             The global trace function is also called
             whenever an exception is detected. */
         if (call_trace_protected(tstate->c_tracefunc,
-                                 tstate->c_traceobj,
-                                 tstate, frame,
-                                 PyTrace_CALL, Py_None)) {
+                                    tstate->c_traceobj,
+                                    tstate, frame,
+                                    PyTrace_CALL, Py_None)) {
             /* Trace function raised an error */
             return -1;
         }
@@ -981,9 +981,9 @@ trace_function_entry(PyThreadState *tstate, _PyInterpreterFrame *frame)
         /* Similar for c_profilefunc, except it needn't
             return itself and isn't called for "line" events */
         if (call_trace_protected(tstate->c_profilefunc,
-                                 tstate->c_profileobj,
-                                 tstate, frame,
-                                 PyTrace_CALL, Py_None)) {
+                                    tstate->c_profileobj,
+                                    tstate, frame,
+                                    PyTrace_CALL, Py_None)) {
             /* Profile function raised an error */
             return -1;
         }
@@ -996,13 +996,13 @@ trace_function_exit(PyThreadState *tstate, _PyInterpreterFrame *frame, PyObject
 {
     if (tstate->c_tracefunc) {
         if (call_trace_protected(tstate->c_tracefunc, tstate->c_traceobj,
-                                 tstate, frame, PyTrace_RETURN, retval)) {
+                                    tstate, frame, PyTrace_RETURN, retval)) {
             return -1;
         }
     }
     if (tstate->c_profilefunc) {
         if (call_trace_protected(tstate->c_profilefunc, tstate->c_profileobj,
-                                 tstate, frame, PyTrace_RETURN, retval)) {
+                                    tstate, frame, PyTrace_RETURN, retval)) {
             return -1;
         }
     }
@@ -1019,7 +1019,7 @@ pop_frame(PyThreadState *tstate, _PyInterpreterFrame *frame)
 
 
 int _Py_CheckRecursiveCallPy(
-        PyThreadState *tstate)
+    PyThreadState *tstate)
 {
     if (tstate->recursion_headroom) {
         if (tstate->py_recursion_remaining < -50) {
@@ -1031,7 +1031,7 @@ int _Py_CheckRecursiveCallPy(
         if (tstate->py_recursion_remaining <= 0) {
             tstate->recursion_headroom++;
             _PyErr_Format(tstate, PyExc_RecursionError,
-                          "maximum recursion depth exceeded");
+                        "maximum recursion depth exceeded");
             tstate->recursion_headroom--;
             return -1;
         }
@@ -1041,7 +1041,7 @@ int _Py_CheckRecursiveCallPy(
 
 static inline int _Py_EnterRecursivePy(PyThreadState *tstate) {
     return (tstate->py_recursion_remaining-- <= 0) &&
-           _Py_CheckRecursiveCallPy(tstate);
+        _Py_CheckRecursiveCallPy(tstate);
 }
 
 
@@ -1115,7 +1115,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int
 #endif
     entry_frame.f_code = tstate->interp->interpreter_trampoline;
     entry_frame.prev_instr =
-            _PyCode_CODE(tstate->interp->interpreter_trampoline);
+        _PyCode_CODE(tstate->interp->interpreter_trampoline);
     entry_frame.stacktop = 0;
     entry_frame.owner = FRAME_OWNED_BY_CSTACK;
     entry_frame.yield_offset = 0;
@@ -1174,7 +1174,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int
     }
 
 resume_frame:
-SET_LOCALS_FROM_FRAME();
+    SET_LOCALS_FROM_FRAME();
 
 #ifdef LLTRACE
     {
@@ -1213,9 +1213,9 @@ SET_LOCALS_FROM_FRAME();
     DISPATCH();
 
     {
-        /* Start instructions */
+    /* Start instructions */
 #if !USE_COMPUTED_GOTOS
-        dispatch_opcode:
+    dispatch_opcode:
         switch (opcode)
 #endif
         {
@@ -1223,94 +1223,94 @@ SET_LOCALS_FROM_FRAME();
 #include "generated_cases.c.h"
 
 #if USE_COMPUTED_GOTOS
-TARGET_DO_TRACING:
+        TARGET_DO_TRACING:
 #else
-            case DO_TRACING:
+        case DO_TRACING:
 #endif
-            {
-                assert(cframe.use_tracing);
-                assert(tstate->tracing == 0);
-                if (INSTR_OFFSET() >= frame->f_code->_co_firsttraceable) {
-                    int instr_prev = _PyInterpreterFrame_LASTI(frame);
-                    frame->prev_instr = next_instr;
-                    NEXTOPARG();
-                    // No _PyOpcode_Deopt here, since RESUME has no optimized forms:
-                    if (opcode == RESUME) {
-                        if (oparg < 2) {
-                            CHECK_EVAL_BREAKER();
-                        }
-                        /* Call tracing */
-                        TRACE_FUNCTION_ENTRY();
-                        DTRACE_FUNCTION_ENTRY();
-                    }
-                    else {
-                        /* line-by-line tracing support */
-                        if (PyDTrace_LINE_ENABLED()) {
-                            maybe_dtrace_line(frame, &tstate->trace_info, instr_prev);
-                        }
-
-                        if (cframe.use_tracing &&
-                            tstate->c_tracefunc != NULL && !tstate->tracing) {
-                            int err;
-                            /* see maybe_call_line_trace()
-                            for expository comments */
-                            _PyFrame_SetStackPointer(frame, stack_pointer);
-
-                            err = maybe_call_line_trace(tstate->c_tracefunc,
-                                                        tstate->c_traceobj,
-                                                        tstate, frame, instr_prev);
-                            // Reload possibly changed frame fields:
-                            stack_pointer = _PyFrame_GetStackPointer(frame);
-                            frame->stacktop = -1;
-                            // next_instr is only reloaded if tracing *does not* raise.
-                            // This is consistent with the behavior of older Python
-                            // versions. If a trace function sets a new f_lineno and
-                            // *then* raises, we use the *old* location when searching
-                            // for an exception handler, displaying the traceback, and
-                            // so on:
-                            if (err) {
-                                // next_instr wasn't incremented at the start of this
-                                // instruction. Increment it before handling the error,
-                                // so that it looks the same as a "normal" instruction:
-                                next_instr++;
-                                goto error;
-                            }
-                            // Reload next_instr. Don't increment it, though, since
-                            // we're going to re-dispatch to the "true" instruction now:
-                            next_instr = frame->prev_instr;
-                        }
-                    }
+    {
+        assert(cframe.use_tracing);
+        assert(tstate->tracing == 0);
+        if (INSTR_OFFSET() >= frame->f_code->_co_firsttraceable) {
+            int instr_prev = _PyInterpreterFrame_LASTI(frame);
+            frame->prev_instr = next_instr;
+            NEXTOPARG();
+            // No _PyOpcode_Deopt here, since RESUME has no optimized forms:
+            if (opcode == RESUME) {
+                if (oparg < 2) {
+                    CHECK_EVAL_BREAKER();
                 }
-                NEXTOPARG();
-                PRE_DISPATCH_GOTO();
-                // No _PyOpcode_Deopt here, since EXTENDED_ARG has no optimized forms:
-                while (opcode == EXTENDED_ARG) {
-                    // CPython hasn't ever traced the instruction after an EXTENDED_ARG.
-                    // Inline the EXTENDED_ARG here, so we can avoid branching there:
-                    INSTRUCTION_START(EXTENDED_ARG);
-                    opcode = _Py_OPCODE(*next_instr);
-                    oparg = oparg << 8 | _Py_OPARG(*next_instr);
-                    // Make sure the next instruction isn't a RESUME, since that needs
-                    // to trace properly (and shouldn't have an EXTENDED_ARG, anyways):
-                    assert(opcode != RESUME);
-                    PRE_DISPATCH_GOTO();
+                /* Call tracing */
+                TRACE_FUNCTION_ENTRY();
+                DTRACE_FUNCTION_ENTRY();
+            }
+            else {
+                /* line-by-line tracing support */
+                if (PyDTrace_LINE_ENABLED()) {
+                    maybe_dtrace_line(frame, &tstate->trace_info, instr_prev);
                 }
-                opcode = _PyOpcode_Deopt[opcode];
-                if (_PyOpcode_Caches[opcode]) {
-                    _Py_CODEUNIT *counter = &next_instr[1];
-                    // The instruction is going to decrement the counter, so we need to
-                    // increment it here to make sure it doesn't try to specialize:
-                    if (!ADAPTIVE_COUNTER_IS_MAX(*counter)) {
-                        INCREMENT_ADAPTIVE_COUNTER(*counter);
+
+                if (cframe.use_tracing &&
+                    tstate->c_tracefunc != NULL && !tstate->tracing) {
+                    int err;
+                    /* see maybe_call_line_trace()
+                    for expository comments */
+                    _PyFrame_SetStackPointer(frame, stack_pointer);
+
+                    err = maybe_call_line_trace(tstate->c_tracefunc,
+                                                tstate->c_traceobj,
+                                                tstate, frame, instr_prev);
+                    // Reload possibly changed frame fields:
+                    stack_pointer = _PyFrame_GetStackPointer(frame);
+                    frame->stacktop = -1;
+                    // next_instr is only reloaded if tracing *does not* raise.
+                    // This is consistent with the behavior of older Python
+                    // versions. If a trace function sets a new f_lineno and
+                    // *then* raises, we use the *old* location when searching
+                    // for an exception handler, displaying the traceback, and
+                    // so on:
+                    if (err) {
+                        // next_instr wasn't incremented at the start of this
+                        // instruction. Increment it before handling the error,
+                        // so that it looks the same as a "normal" instruction:
+                        next_instr++;
+                        goto error;
                     }
+                    // Reload next_instr. Don't increment it, though, since
+                    // we're going to re-dispatch to the "true" instruction now:
+                    next_instr = frame->prev_instr;
                 }
-                DISPATCH_GOTO();
             }
+        }
+        NEXTOPARG();
+        PRE_DISPATCH_GOTO();
+        // No _PyOpcode_Deopt here, since EXTENDED_ARG has no optimized forms:
+        while (opcode == EXTENDED_ARG) {
+            // CPython hasn't ever traced the instruction after an EXTENDED_ARG.
+            // Inline the EXTENDED_ARG here, so we can avoid branching there:
+            INSTRUCTION_START(EXTENDED_ARG);
+            opcode = _Py_OPCODE(*next_instr);
+            oparg = oparg << 8 | _Py_OPARG(*next_instr);
+            // Make sure the next instruction isn't a RESUME, since that needs
+            // to trace properly (and shouldn't have an EXTENDED_ARG, anyways):
+            assert(opcode != RESUME);
+            PRE_DISPATCH_GOTO();
+        }
+        opcode = _PyOpcode_Deopt[opcode];
+        if (_PyOpcode_Caches[opcode]) {
+            _Py_CODEUNIT *counter = &next_instr[1];
+            // The instruction is going to decrement the counter, so we need to
+            // increment it here to make sure it doesn't try to specialize:
+            if (!ADAPTIVE_COUNTER_IS_MAX(*counter)) {
+                INCREMENT_ADAPTIVE_COUNTER(*counter);
+            }
+        }
+        DISPATCH_GOTO();
+    }
 
 #if USE_COMPUTED_GOTOS
-_unknown_opcode:
+        _unknown_opcode:
 #else
-            EXTRA_CASES  // From opcode.h, a 'case' for each unused opcode
+        EXTRA_CASES  // From opcode.h, a 'case' for each unused opcode
 #endif
             /* Tell C compilers not to hold the opcode variable in the loop.
                next_instr points the current instruction without TARGET(). */
@@ -1331,20 +1331,20 @@ SET_LOCALS_FROM_FRAME();
 unbound_local_error:
         {
             format_exc_check_arg(tstate, PyExc_UnboundLocalError,
-                                 UNBOUNDLOCAL_ERROR_MSG,
-                                 PyTuple_GetItem(frame->f_code->co_localsplusnames, oparg)
+                UNBOUNDLOCAL_ERROR_MSG,
+                PyTuple_GetItem(frame->f_code->co_localsplusnames, oparg)
             );
             goto error;
         }
 
 pop_4_error:
-        STACK_SHRINK(1);
+    STACK_SHRINK(1);
 pop_3_error:
-        STACK_SHRINK(1);
+    STACK_SHRINK(1);
 pop_2_error:
-        STACK_SHRINK(1);
+    STACK_SHRINK(1);
 pop_1_error:
-        STACK_SHRINK(1);
+    STACK_SHRINK(1);
 error:
         kwnames = NULL;
         /* Double-check exception status. */
@@ -1443,7 +1443,7 @@ SET_LOCALS_FROM_FRAME();
     }
 
 resume_with_error:
-SET_LOCALS_FROM_FRAME();
+    SET_LOCALS_FROM_FRAME();
     goto error;
 
 }
@@ -1465,44 +1465,44 @@ format_missing(PyThreadState *tstate, const char *kind,
     assert(len >= 1);
     /* Deal with the joys of natural language. */
     switch (len) {
-        case 1:
-            name_str = PyList_GET_ITEM(names, 0);
-            Py_INCREF(name_str);
-            break;
-        case 2:
-            name_str = PyUnicode_FromFormat("%U and %U",
-                                            PyList_GET_ITEM(names, len - 2),
-                                            PyList_GET_ITEM(names, len - 1));
-            break;
-        default:
-            tail = PyUnicode_FromFormat(", %U, and %U",
+    case 1:
+        name_str = PyList_GET_ITEM(names, 0);
+        Py_INCREF(name_str);
+        break;
+    case 2:
+        name_str = PyUnicode_FromFormat("%U and %U",
                                         PyList_GET_ITEM(names, len - 2),
                                         PyList_GET_ITEM(names, len - 1));
-            if (tail == NULL)
-                return;
-            /* Chop off the last two objects in the list. This shouldn't actually
-               fail, but we can't be too careful. */
-            err = PyList_SetSlice(names, len - 2, len, NULL);
-            if (err == -1) {
-                Py_DECREF(tail);
-                return;
-            }
-            /* Stitch everything up into a nice comma-separated list. */
-            comma = PyUnicode_FromString(", ");
-            if (comma == NULL) {
-                Py_DECREF(tail);
-                return;
-            }
-            tmp = PyUnicode_Join(comma, names);
-            Py_DECREF(comma);
-            if (tmp == NULL) {
-                Py_DECREF(tail);
-                return;
-            }
-            name_str = PyUnicode_Concat(tmp, tail);
-            Py_DECREF(tmp);
+        break;
+    default:
+        tail = PyUnicode_FromFormat(", %U, and %U",
+                                    PyList_GET_ITEM(names, len - 2),
+                                    PyList_GET_ITEM(names, len - 1));
+        if (tail == NULL)
+            return;
+        /* Chop off the last two objects in the list. This shouldn't actually
+           fail, but we can't be too careful. */
+        err = PyList_SetSlice(names, len - 2, len, NULL);
+        if (err == -1) {
             Py_DECREF(tail);
-            break;
+            return;
+        }
+        /* Stitch everything up into a nice comma-separated list. */
+        comma = PyUnicode_FromString(", ");
+        if (comma == NULL) {
+            Py_DECREF(tail);
+            return;
+        }
+        tmp = PyUnicode_Join(comma, names);
+        Py_DECREF(comma);
+        if (tmp == NULL) {
+            Py_DECREF(tail);
+            return;
+        }
+        name_str = PyUnicode_Concat(tmp, tail);
+        Py_DECREF(tmp);
+        Py_DECREF(tail);
+        break;
     }
     if (name_str == NULL)
         return;
@@ -1745,8 +1745,8 @@ get_exception_handler(PyCodeObject *code, int index, int *level, int *handler, i
 
 static int
 initialize_locals(PyThreadState *tstate, PyFunctionObject *func,
-                  PyObject **localsplus, PyObject *const *args,
-                  Py_ssize_t argcount, PyObject *kwnames)
+    PyObject **localsplus, PyObject *const *args,
+    Py_ssize_t argcount, PyObject *kwnames)
 {
     PyCodeObject *co = (PyCodeObject*)func->func_code;
     const Py_ssize_t total_args = co->co_argcount + co->co_kwonlyargcount;
@@ -1818,8 +1818,8 @@ initialize_locals(PyThreadState *tstate, PyFunctionObject *func,
 
             if (keyword == NULL || !PyUnicode_Check(keyword)) {
                 _PyErr_Format(tstate, PyExc_TypeError,
-                              "%U() keywords must be strings",
-                              func->func_qualname);
+                            "%U() keywords must be strings",
+                          func->func_qualname);
                 goto kw_fail;
             }
 
@@ -1850,15 +1850,15 @@ initialize_locals(PyThreadState *tstate, PyFunctionObject *func,
 
                 if (co->co_posonlyargcount
                     && positional_only_passed_as_keyword(tstate, co,
-                                                         kwcount, kwnames,
-                                                         func->func_qualname))
+                                                        kwcount, kwnames,
+                                                        func->func_qualname))
                 {
                     goto kw_fail;
                 }
 
                 _PyErr_Format(tstate, PyExc_TypeError,
-                              "%U() got an unexpected keyword argument '%S'",
-                              func->func_qualname, keyword);
+                            "%U() got an unexpected keyword argument '%S'",
+                          func->func_qualname, keyword);
                 goto kw_fail;
             }
 
@@ -1868,18 +1868,18 @@ initialize_locals(PyThreadState *tstate, PyFunctionObject *func,
             Py_DECREF(value);
             continue;
 
-kw_fail:
+        kw_fail:
             for (;i < kwcount; i++) {
                 PyObject *value = args[i+argcount];
                 Py_DECREF(value);
             }
             goto fail_post_args;
 
-kw_found:
+        kw_found:
             if (localsplus[j] != NULL) {
                 _PyErr_Format(tstate, PyExc_TypeError,
-                              "%U() got multiple values for argument '%S'",
-                              func->func_qualname, keyword);
+                            "%U() got multiple values for argument '%S'",
+                          func->func_qualname, keyword);
                 goto kw_fail;
             }
             localsplus[j] = value;
@@ -2012,7 +2012,7 @@ clear_thread_frame(PyThreadState *tstate, _PyInterpreterFrame * frame)
     // Make sure that this is, indeed, the top frame. We can't check this in
     // _PyThreadState_PopFrame, since f_code is already cleared at that point:
     assert((PyObject **)frame + frame->f_code->co_framesize ==
-           tstate->datastack_top);
+        tstate->datastack_top);
     tstate->c_recursion_remaining--;
     assert(frame->frame_obj == NULL || frame->frame_obj->f_frame == frame);
     _PyFrame_Clear(frame);
@@ -2068,7 +2068,7 @@ _PyEval_Vector(PyThreadState *tstate, PyFunctionObject *func,
         }
     }
     _PyInterpreterFrame *frame = _PyEvalFramePushAndInit(
-            tstate, func, locals, args, argcount, kwnames);
+        tstate, func, locals, args, argcount, kwnames);
     if (frame == NULL) {
         return NULL;
     }
@@ -2127,14 +2127,14 @@ PyEval_EvalCodeEx(PyObject *_co, PyObject *globals, PyObject *locals,
         PyTuple_SET_ITEM(kwnames, i, Py_NewRef(kws[2*i]));
     }
     PyFrameConstructor constr = {
-            .fc_globals = globals,
-            .fc_builtins = builtins,
-            .fc_name = ((PyCodeObject *)_co)->co_name,
-            .fc_qualname = ((PyCodeObject *)_co)->co_name,
-            .fc_code = _co,
-            .fc_defaults = defaults,
-            .fc_kwdefaults = kwdefs,
-            .fc_closure = closure
+        .fc_globals = globals,
+        .fc_builtins = builtins,
+        .fc_name = ((PyCodeObject *)_co)->co_name,
+        .fc_qualname = ((PyCodeObject *)_co)->co_name,
+        .fc_code = _co,
+        .fc_defaults = defaults,
+        .fc_kwdefaults = kwdefs,
+        .fc_closure = closure
     };
     func = _PyFunction_FromConstructor(&constr);
     if (func == NULL) {
@@ -2193,7 +2193,7 @@ do_raise(PyThreadState *tstate, PyObject *exc, PyObject *cause)
                           "calling %R should have returned an instance of "
                           "BaseException, not %R",
                           type, Py_TYPE(value));
-            goto raise_error;
+             goto raise_error;
         }
     }
     else if (PyExceptionInstance_Check(exc)) {
@@ -2389,8 +2389,8 @@ unpack_iterable(PyThreadState *tstate, PyObject *v,
     ll = PyList_GET_SIZE(l);
     if (ll < argcntafter) {
         _PyErr_Format(tstate, PyExc_ValueError,
-                      "not enough values to unpack (expected at least %d, got %zd)",
-                      argcnt + argcntafter, argcnt + ll);
+            "not enough values to unpack (expected at least %d, got %zd)",
+            argcnt + argcntafter, argcnt + ll);
         goto Error;
     }
 
@@ -2562,10 +2562,10 @@ maybe_call_line_trace(Py_tracefunc func, PyObject *obj,
     if (line != -1 && f->f_trace_lines) {
         /* Trace backward edges (except in 'yield from') or if line number has changed */
         int trace = line != lastline ||
-                    (_PyInterpreterFrame_LASTI(frame) < instr_prev &&
-                     // SEND has no quickened forms, so no need to use _PyOpcode_Deopt
-                     // here:
-                     _Py_OPCODE(*frame->prev_instr) != SEND);
+            (_PyInterpreterFrame_LASTI(frame) < instr_prev &&
+             // SEND has no quickened forms, so no need to use _PyOpcode_Deopt
+             // here:
+             _Py_OPCODE(*frame->prev_instr) != SEND);
         if (trace) {
             result = call_trace(func, obj, tstate, frame, PyTrace_LINE, Py_None);
         }
@@ -2819,7 +2819,7 @@ PyObject *
 PyEval_GetLocals(void)
 {
     PyThreadState *tstate = _PyThreadState_GET();
-    _PyInterpreterFrame *current_frame = tstate->cframe->current_frame;
+     _PyInterpreterFrame *current_frame = tstate->cframe->current_frame;
     if (current_frame == NULL) {
         _PyErr_SetString(tstate, PyExc_SystemError, "frame does not exist");
         return NULL;
@@ -2948,8 +2948,8 @@ trace_call_function(PyThreadState *tstate,
             return NULL;
         }
         C_TRACE(x, PyObject_Vectorcall(func,
-                                       args+1, nargs-1,
-                                       kwnames));
+                                        args+1, nargs-1,
+                                        kwnames));
         Py_DECREF(func);
         return x;
     }
@@ -2962,7 +2962,7 @@ do_call_core(PyThreadState *tstate,
              PyObject *callargs,
              PyObject *kwdict,
              int use_tracing
-)
+            )
 {
     PyObject *result;
     if (PyCFunction_CheckExact(func) || PyCMethod_CheckExact(func)) {
@@ -2986,10 +2986,10 @@ do_call_core(PyThreadState *tstate,
             }
 
             C_TRACE(result, _PyObject_FastCallDictTstate(
-                    tstate, func,
-                    &_PyTuple_ITEMS(callargs)[1],
-                    nargs - 1,
-                    kwdict));
+                                    tstate, func,
+                                    &_PyTuple_ITEMS(callargs)[1],
+                                    nargs - 1,
+                                    kwdict));
             Py_DECREF(func);
             return result;
         }
@@ -3068,11 +3068,11 @@ import_name(PyThreadState *tstate, _PyInterpreterFrame *frame,
             return NULL;
         }
         res = PyImport_ImportModuleLevelObject(
-                name,
-                frame->f_globals,
-                locals == NULL ? Py_None :locals,
-                fromlist,
-                ilevel);
+                        name,
+                        frame->f_globals,
+                        locals == NULL ? Py_None :locals,
+                        fromlist,
+                        ilevel);
         return res;
     }
 
@@ -3120,7 +3120,7 @@ import_from(PyThreadState *tstate, PyObject *v, PyObject *name)
     }
     Py_DECREF(pkgname);
     return x;
-error:
+ error:
     pkgpath = PyModule_GetFilenameObject(v);
     if (pkgname == NULL) {
         pkgname_or_unknown = PyUnicode_FromString("");
@@ -3135,8 +3135,8 @@ import_from(PyThreadState *tstate, PyObject *v, PyObject *name)
     if (pkgpath == NULL || !PyUnicode_Check(pkgpath)) {
         _PyErr_Clear(tstate);
         errmsg = PyUnicode_FromFormat(
-                "cannot import name %R from %R (unknown location)",
-                name, pkgname_or_unknown
+            "cannot import name %R from %R (unknown location)",
+            name, pkgname_or_unknown
         );
         /* NULL checks for errmsg and pkgname done by PyErr_SetImportError. */
         _PyErr_SetImportErrorWithNameFrom(errmsg, pkgname, NULL, name);
@@ -3144,10 +3144,10 @@ import_from(PyThreadState *tstate, PyObject *v, PyObject *name)
     else {
         PyObject *spec = PyObject_GetAttr(v, &_Py_ID(__spec__));
         const char *fmt =
-                _PyModuleSpec_IsInitializing(spec) ?
-                "cannot import name %R from partially initialized module %R "
-                "(most likely due to a circular import) (%S)" :
-                "cannot import name %R from %R (%S)";
+            _PyModuleSpec_IsInitializing(spec) ?
+            "cannot import name %R from partially initialized module %R "
+            "(most likely due to a circular import) (%S)" :
+            "cannot import name %R from %R (%S)";
         Py_XDECREF(spec);
 
         errmsg = PyUnicode_FromFormat(fmt, name, pkgname_or_unknown, pkgpath);
@@ -3177,7 +3177,7 @@ import_all_from(PyThreadState *tstate, PyObject *locals, PyObject *v)
         }
         if (dict == NULL) {
             _PyErr_SetString(tstate, PyExc_ImportError,
-                             "from-import-* object has no __dict__ and no __all__");
+                    "from-import-* object has no __dict__ and no __all__");
             return -1;
         }
         all = PyMapping_Keys(dict);
@@ -3266,7 +3266,7 @@ check_except_type_valid(PyThreadState *tstate, PyObject* right)
             PyObject *exc = PyTuple_GET_ITEM(right, i);
             if (!PyExceptionClass_Check(exc)) {
                 _PyErr_SetString(tstate, PyExc_TypeError,
-                                 CANNOT_CATCH_MSG);
+                    CANNOT_CATCH_MSG);
                 return -1;
             }
         }
@@ -3274,7 +3274,7 @@ check_except_type_valid(PyThreadState *tstate, PyObject* right)
     else {
         if (!PyExceptionClass_Check(right)) {
             _PyErr_SetString(tstate, PyExc_TypeError,
-                             CANNOT_CATCH_MSG);
+                CANNOT_CATCH_MSG);
             return -1;
         }
     }
@@ -3312,8 +3312,8 @@ check_except_star_type_valid(PyThreadState *tstate, PyObject* right)
     }
     if (is_subclass) {
         _PyErr_SetString(tstate, PyExc_TypeError,
-                         CANNOT_EXCEPT_STAR_EG);
-        return -1;
+            CANNOT_EXCEPT_STAR_EG);
+            return -1;
     }
     return 0;
 }
@@ -3352,9 +3352,9 @@ format_kwargs_error(PyThreadState *tstate, PyObject *func, PyObject *kwargs)
         PyObject *funcstr = _PyObject_FunctionStr(func);
         if (funcstr != NULL) {
             _PyErr_Format(
-                    tstate, PyExc_TypeError,
-                    "%U argument after ** must be a mapping, not %.200s",
-                    funcstr, Py_TYPE(kwargs)->tp_name);
+                tstate, PyExc_TypeError,
+                "%U argument after ** must be a mapping, not %.200s",
+                funcstr, Py_TYPE(kwargs)->tp_name);
             Py_DECREF(funcstr);
         }
     }
@@ -3367,9 +3367,9 @@ format_kwargs_error(PyThreadState *tstate, PyObject *func, PyObject *kwargs)
             if (funcstr != NULL) {
                 PyObject *key = PyTuple_GET_ITEM(val, 0);
                 _PyErr_Format(
-                        tstate, PyExc_TypeError,
-                        "%U got multiple values for keyword argument '%S'",
-                        funcstr, key);
+                    tstate, PyExc_TypeError,
+                    "%U got multiple values for keyword argument '%S'",
+                    funcstr, key);
                 Py_DECREF(funcstr);
             }
             Py_XDECREF(exc);
diff --git a/Python/generated_cases.c.h b/Python/generated_cases.c.h
index ae8fdd5e99c3dc..5c3f3a022481b6 100644
--- a/Python/generated_cases.c.h
+++ b/Python/generated_cases.c.h
@@ -134,8 +134,8 @@
             DEOPT_IF(!PyLong_CheckExact(right), BINARY_OP);
             STAT_INC(BINARY_OP, hit);
             prod = _PyLong_Multiply((PyLongObject *)left, (PyLongObject *)right);
-            _Py_DECREF_SPECIALIZED(right, (destructor)PyObject_Free);
-            _Py_DECREF_SPECIALIZED(left, (destructor)PyObject_Free);
+            _Py_DECREF_SPECIALIZED(right, (destructor)_PyLong_ExactDealloc);
+            _Py_DECREF_SPECIALIZED(left, (destructor)_PyLong_ExactDealloc);
             if (prod == NULL) goto pop_2_error;
             STACK_SHRINK(1);
             POKE(1, prod);
@@ -172,8 +172,8 @@
             DEOPT_IF(!PyLong_CheckExact(right), BINARY_OP);
             STAT_INC(BINARY_OP, hit);
             sub = _PyLong_Subtract((PyLongObject *)left, (PyLongObject *)right);
-            _Py_DECREF_SPECIALIZED(right, (destructor)PyObject_Free);
-            _Py_DECREF_SPECIALIZED(left, (destructor)PyObject_Free);
+            _Py_DECREF_SPECIALIZED(right, (destructor)_PyLong_ExactDealloc);
+            _Py_DECREF_SPECIALIZED(left, (destructor)_PyLong_ExactDealloc);
             if (sub == NULL) goto pop_2_error;
             STACK_SHRINK(1);
             POKE(1, sub);
@@ -281,8 +281,8 @@
             DEOPT_IF(Py_TYPE(right) != Py_TYPE(left), BINARY_OP);
             STAT_INC(BINARY_OP, hit);
             sum = _PyLong_Add((PyLongObject *)left, (PyLongObject *)right);
-            _Py_DECREF_SPECIALIZED(right, (destructor)PyObject_Free);
-            _Py_DECREF_SPECIALIZED(left, (destructor)PyObject_Free);
+            _Py_DECREF_SPECIALIZED(right, (destructor)_PyLong_ExactDealloc);
+            _Py_DECREF_SPECIALIZED(left, (destructor)_PyLong_ExactDealloc);
             if (sum == NULL) goto pop_2_error;
             STACK_SHRINK(1);
             POKE(1, sum);
@@ -376,7 +376,7 @@
             res = PyList_GET_ITEM(list, index);
             assert(res != NULL);
             Py_INCREF(res);
-            _Py_DECREF_SPECIALIZED(sub, (destructor)PyObject_Free);
+            _Py_DECREF_SPECIALIZED(sub, (destructor)_PyLong_ExactDealloc);
             Py_DECREF(list);
             STACK_SHRINK(1);
             POKE(1, res);
@@ -402,7 +402,7 @@
             res = PyTuple_GET_ITEM(tuple, index);
             assert(res != NULL);
             Py_INCREF(res);
-            _Py_DECREF_SPECIALIZED(sub, (destructor)PyObject_Free);
+            _Py_DECREF_SPECIALIZED(sub, (destructor)_PyLong_ExactDealloc);
             Py_DECREF(tuple);
             STACK_SHRINK(1);
             POKE(1, res);
@@ -529,7 +529,7 @@
             STACK_SHRINK(3);
             assert(old_value != NULL);
             Py_DECREF(old_value);
-            _Py_DECREF_SPECIALIZED(sub, (destructor)PyObject_Free);
+            _Py_DECREF_SPECIALIZED(sub, (destructor)_PyLong_ExactDealloc);
             Py_DECREF(list);
             JUMPBY(INLINE_CACHE_ENTRIES_STORE_SUBSCR);
             DISPATCH();
@@ -2144,8 +2144,8 @@
             JUMPBY(INLINE_CACHE_ENTRIES_COMPARE_OP);
             NEXTOPARG();
             STACK_SHRINK(2);
-            _Py_DECREF_SPECIALIZED(left, (destructor)PyObject_Free);
-            _Py_DECREF_SPECIALIZED(right, (destructor)PyObject_Free);
+            _Py_DECREF_SPECIALIZED(left, (destructor)_PyLong_ExactDealloc);
+            _Py_DECREF_SPECIALIZED(right, (destructor)_PyLong_ExactDealloc);
             assert(opcode == POP_JUMP_IF_FALSE || opcode == POP_JUMP_IF_TRUE);
             int jump = (1 << (sign + 1)) & when_to_jump_mask;
             if (!jump) {
From d11e121c135f32b1e31c36791cadab7be5c0ee5d Mon Sep 17 00:00:00 2001
From: penguin-wwy <940375606@qq.com>
Date: Mon, 28 Nov 2022 11:45:27 +0800
Subject: [PATCH 9/9] Add misc/news
---
 .../2022-11-28-11-43-47.gh-issue-91912.QsHR-u.rst                | 1 +
 1 file changed, 1 insertion(+)
 create mode 100644 Misc/NEWS.d/next/Core and Builtins/2022-11-28-11-43-47.gh-issue-91912.QsHR-u.rst
diff --git a/Misc/NEWS.d/next/Core and Builtins/2022-11-28-11-43-47.gh-issue-91912.QsHR-u.rst b/Misc/NEWS.d/next/Core and Builtins/2022-11-28-11-43-47.gh-issue-91912.QsHR-u.rst
new file mode 100644
index 00000000000000..40009695310db7
--- /dev/null
+++ b/Misc/NEWS.d/next/Core and Builtins/2022-11-28-11-43-47.gh-issue-91912.QsHR-u.rst	
@@ -0,0 +1 @@
+Add long object free list for medium value