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