#endif
};
+void _PyFloat_ExactDealloc(PyObject *op);
+
PyAPI_FUNC(void) _PyFloat_DebugMallocStats(FILE* out);
#include "pycore_pystate.h" // _PyInterpreterState_GET()
#include "pycore_runtime.h" // _PyRuntime
-
#define _PyObject_IMMORTAL_INIT(type) \
{ \
.ob_refcnt = 999999999, \
.ob_size = size, \
}
+PyAPI_FUNC(void) _Py_NO_RETURN _Py_FatalRefcountErrorFunc(
+ const char *func,
+ const char *message);
+
+#define _Py_FatalRefcountError(message) _Py_FatalRefcountErrorFunc(__func__, message)
+
+static inline void
+_Py_DECREF_SPECIALIZED(PyObject *op, const destructor destruct)
+{
+#ifdef Py_REF_DEBUG
+ _Py_RefTotal--;
+#endif
+ if (--op->ob_refcnt != 0) {
+ assert(op->ob_refcnt > 0);
+ }
+ else {
+#ifdef Py_TRACE_REFS
+ _Py_ForgetReference(op);
+#endif
+ destruct(op);
+ }
+}
+
+static inline void
+_Py_DECREF_NO_DEALLOC(PyObject *op)
+{
+#ifdef Py_REF_DEBUG
+ _Py_RefTotal--;
+#endif
+ op->ob_refcnt--;
+#ifdef Py_DEBUG
+ if (op->ob_refcnt <= 0) {
+ _Py_FatalRefcountError("Expected a positive remaining refcount");
+ }
+#endif
+}
PyAPI_FUNC(int) _PyType_CheckConsistency(PyTypeObject *type);
PyAPI_FUNC(int) _PyDict_CheckConsistency(PyObject *mp, int check_content);
PyAPI_FUNC(Py_ssize_t) _Py_UTF8_Edit_Cost(PyObject *str_a, PyObject *str_b,
Py_ssize_t max_cost);
-PyAPI_FUNC(void) _Py_NO_RETURN _Py_FatalRefcountErrorFunc(
- const char *func,
- const char *message);
-
-#define _Py_FatalRefcountError(message) _Py_FatalRefcountErrorFunc(__func__, message)
-
-
#ifdef __cplusplus
}
#endif
#include "pycore_fileutils.h" // _Py_error_handler
+void _PyUnicode_ExactDealloc(PyObject *op);
/* runtime lifecycle */
--- /dev/null
+Add type-specialized versions of the ``Py_DECREF()``, and use them for ``float``, ``int``, ``str``, ``bool``, and ``None`` to avoid pointer-chasing at runtime where types are known at C compile time.
/* Boolean type, a subtype of int */
#include "Python.h"
+#include "pycore_object.h" // _Py_FatalRefcountError()
#include "pycore_runtime.h" // _Py_ID()
-#include "pycore_pyerrors.h" // _Py_FatalRefcountError()
/* We define bool_repr to return "False" or "True" */
return result;
}
-static void
-float_dealloc(PyFloatObject *op)
+void
+_PyFloat_ExactDealloc(PyObject *obj)
{
+ assert(PyFloat_CheckExact(obj));
+ PyFloatObject *op = (PyFloatObject *)obj;
#if PyFloat_MAXFREELIST > 0
- if (PyFloat_CheckExact(op)) {
- struct _Py_float_state *state = get_float_state();
+ struct _Py_float_state *state = get_float_state();
#ifdef Py_DEBUG
- // float_dealloc() must not be called after _PyFloat_Fini()
- assert(state->numfree != -1);
+ // float_dealloc() must not be called after _PyFloat_Fini()
+ assert(state->numfree != -1);
#endif
- if (state->numfree >= PyFloat_MAXFREELIST) {
- PyObject_Free(op);
- return;
- }
- state->numfree++;
- Py_SET_TYPE(op, (PyTypeObject *)state->free_list);
- state->free_list = op;
+ if (state->numfree >= PyFloat_MAXFREELIST) {
+ PyObject_Free(op);
+ return;
+ }
+ state->numfree++;
+ Py_SET_TYPE(op, (PyTypeObject *)state->free_list);
+ state->free_list = op;
+#else
+ PyObject_Free(op);
+#endif
+}
+
+static void
+float_dealloc(PyObject *op)
+{
+ assert(PyFloat_Check(op));
+#if PyFloat_MAXFREELIST > 0
+ if (PyFloat_CheckExact(op)) {
+ _PyFloat_ExactDealloc(op);
}
else
#endif
{
- Py_TYPE(op)->tp_free((PyObject *)op);
+ Py_TYPE(op)->tp_free(op);
}
}
#define IS_SMALL_INT(ival) (-_PY_NSMALLNEGINTS <= (ival) && (ival) < _PY_NSMALLPOSINTS)
#define IS_SMALL_UINT(ival) ((ival) < _PY_NSMALLPOSINTS)
-static inline int is_medium_int(stwodigits x)
+static inline void
+_Py_DECREF_INT(PyLongObject *op)
+{
+ assert(PyLong_CheckExact(op));
+ _Py_DECREF_SPECIALIZED((PyObject *)op, PyObject_Free);
+}
+
+static inline int
+is_medium_int(stwodigits x)
{
/* Take care that we are comparing unsigned values. */
twodigits x_plus_mask = ((twodigits)x) + PyLong_MASK;
if (v && IS_MEDIUM_VALUE(v)) {
stwodigits ival = medium_value(v);
if (IS_SMALL_INT(ival)) {
- Py_DECREF(v);
+ _Py_DECREF_INT(v);
return (PyLongObject *)get_small_int((sdigit)ival);
}
}
#undef WRITE_DIGITS
#undef WRITE_UNICODE_DIGITS
- Py_DECREF(scratch);
+ _Py_DECREF_INT(scratch);
if (writer) {
writer->pos += strlen;
}
*/
i = Py_SIZE(ret) - shift; /* # digits after shift */
(void)v_isub(ret->ob_digit + shift, i, t2->ob_digit, Py_SIZE(t2));
- Py_DECREF(t2);
+ _Py_DECREF_INT(t2);
(void)v_isub(ret->ob_digit + shift, i, t1->ob_digit, Py_SIZE(t1));
- Py_DECREF(t1);
+ _Py_DECREF_INT(t1);
/* 6. t3 <- (ah+al)(bh+bl), and add into result. */
if ((t1 = x_add(ah, al)) == NULL) goto fail;
- Py_DECREF(ah);
- Py_DECREF(al);
+ _Py_DECREF_INT(ah);
+ _Py_DECREF_INT(al);
ah = al = NULL;
if (a == b) {
Py_DECREF(t1);
goto fail;
}
- Py_DECREF(bh);
- Py_DECREF(bl);
+ _Py_DECREF_INT(bh);
+ _Py_DECREF_INT(bl);
bh = bl = NULL;
t3 = k_mul(t1, t2);
- Py_DECREF(t1);
- Py_DECREF(t2);
+ _Py_DECREF_INT(t1);
+ _Py_DECREF_INT(t2);
if (t3 == NULL) goto fail;
assert(Py_SIZE(t3) >= 0);
* See the (*) comment after this function.
*/
(void)v_iadd(ret->ob_digit + shift, i, t3->ob_digit, Py_SIZE(t3));
- Py_DECREF(t3);
+ _Py_DECREF_INT(t3);
return long_normalize(ret);
/* Add into result. */
(void)v_iadd(ret->ob_digit + nbdone, Py_SIZE(ret) - nbdone,
product->ob_digit, Py_SIZE(product));
- Py_DECREF(product);
+ _Py_DECREF_INT(product);
bsize -= nbtouse;
nbdone += nbtouse;
}
- Py_DECREF(bslice);
+ _Py_DECREF_INT(bslice);
return long_normalize(ret);
fail:
0, /* tp_init */
0, /* tp_alloc */
long_new, /* tp_new */
- PyObject_Del, /* tp_free */
+ PyObject_Free, /* tp_free */
};
static PyTypeObject Int_InfoType;
#include "pycore_floatobject.h" // _PyFloat_DebugMallocStats()
#include "pycore_initconfig.h" // _PyStatus_EXCEPTION()
#include "pycore_namespace.h" // _PyNamespace_Type
-#include "pycore_object.h" // _PyType_CheckConsistency()
+#include "pycore_object.h" // _PyType_CheckConsistency(), _Py_FatalRefcountError()
#include "pycore_pyerrors.h" // _PyErr_Occurred()
#include "pycore_pymem.h" // _PyMem_IsPtrFreed()
#include "pycore_pystate.h" // _PyThreadState_GET()
#include "pycore_abstract.h" // _PyIndex_Check()
#include "pycore_gc.h" // _PyObject_GC_IS_TRACKED()
#include "pycore_initconfig.h" // _PyStatus_OK()
-#include "pycore_object.h" // _PyObject_GC_TRACK()
-#include "pycore_pyerrors.h" // _Py_FatalRefcountError()
+#include "pycore_object.h" // _PyObject_GC_TRACK(), _Py_FatalRefcountError()
/*[clinic input]
class tuple "PyTupleObject *" "&PyTuple_Type"
#include "pycore_initconfig.h" // _PyStatus_OK()
#include "pycore_interp.h" // PyInterpreterState.fs_codec
#include "pycore_long.h" // _PyLong_FormatWriter()
-#include "pycore_object.h" // _PyObject_GC_TRACK()
+#include "pycore_object.h" // _PyObject_GC_TRACK(), _Py_FatalRefcountError()
#include "pycore_pathconfig.h" // _Py_DumpPathConfig()
-#include "pycore_pyerrors.h" // _Py_FatalRefcountError()
#include "pycore_pylifecycle.h" // _Py_SetFileSystemEncoding()
#include "pycore_pystate.h" // _PyInterpreterState_GET()
#include "pycore_ucnhash.h" // _PyUnicode_Name_CAPI
return NULL;
}
+void
+_PyUnicode_ExactDealloc(PyObject *op)
+{
+ assert(PyUnicode_CheckExact(op));
+ unicode_dealloc(op);
+}
+
PyDoc_STRVAR(unicode_doc,
"str(object='') -> str\n\
str(bytes_or_buffer[, encoding[, errors]]) -> str\n\
}
if (PyFloat_CheckExact(item)) {
f_result += PyFloat_AS_DOUBLE(item);
- Py_DECREF(item);
+ _Py_DECREF_SPECIALIZED(item, _PyFloat_ExactDealloc);
continue;
}
if (PyLong_Check(item)) {
STAT_INC(BINARY_OP, hit);
PyObject *prod = _PyLong_Multiply((PyLongObject *)left, (PyLongObject *)right);
SET_SECOND(prod);
- Py_DECREF(right);
- Py_DECREF(left);
+ _Py_DECREF_SPECIALIZED(right, PyObject_Free);
+ _Py_DECREF_SPECIALIZED(left, PyObject_Free);
STACK_SHRINK(1);
if (prod == NULL) {
goto error;
((PyFloatObject *)right)->ob_fval;
PyObject *prod = PyFloat_FromDouble(dprod);
SET_SECOND(prod);
- Py_DECREF(right);
- Py_DECREF(left);
+ _Py_DECREF_SPECIALIZED(right, _PyFloat_ExactDealloc);
+ _Py_DECREF_SPECIALIZED(left, _PyFloat_ExactDealloc);
STACK_SHRINK(1);
if (prod == NULL) {
goto error;
STAT_INC(BINARY_OP, hit);
PyObject *sub = _PyLong_Subtract((PyLongObject *)left, (PyLongObject *)right);
SET_SECOND(sub);
- Py_DECREF(right);
- Py_DECREF(left);
+ _Py_DECREF_SPECIALIZED(right, PyObject_Free);
+ _Py_DECREF_SPECIALIZED(left, PyObject_Free);
STACK_SHRINK(1);
if (sub == NULL) {
goto error;
double dsub = ((PyFloatObject *)left)->ob_fval - ((PyFloatObject *)right)->ob_fval;
PyObject *sub = PyFloat_FromDouble(dsub);
SET_SECOND(sub);
- Py_DECREF(right);
- Py_DECREF(left);
+ _Py_DECREF_SPECIALIZED(right, _PyFloat_ExactDealloc);
+ _Py_DECREF_SPECIALIZED(left, _PyFloat_ExactDealloc);
STACK_SHRINK(1);
if (sub == NULL) {
goto error;
PyObject *res = PyUnicode_Concat(left, right);
STACK_SHRINK(1);
SET_TOP(res);
- Py_DECREF(left);
- Py_DECREF(right);
+ _Py_DECREF_SPECIALIZED(left, _PyUnicode_ExactDealloc);
+ _Py_DECREF_SPECIALIZED(right, _PyUnicode_ExactDealloc);
if (TOP() == NULL) {
goto error;
}
* that the string is safe to mutate.
*/
assert(Py_REFCNT(left) >= 2);
- Py_DECREF(left); // XXX never need to dealloc
+ _Py_DECREF_NO_DEALLOC(left);
STACK_SHRINK(2);
PyUnicode_Append(target_local, right);
- Py_DECREF(right);
+ _Py_DECREF_SPECIALIZED(right, _PyUnicode_ExactDealloc);
if (*target_local == NULL) {
goto error;
}
((PyFloatObject *)right)->ob_fval;
PyObject *sum = PyFloat_FromDouble(dsum);
SET_SECOND(sum);
- Py_DECREF(right);
- Py_DECREF(left);
+ _Py_DECREF_SPECIALIZED(right, _PyFloat_ExactDealloc);
+ _Py_DECREF_SPECIALIZED(left, _PyFloat_ExactDealloc);
STACK_SHRINK(1);
if (sum == NULL) {
goto error;
STAT_INC(BINARY_OP, hit);
PyObject *sum = _PyLong_Add((PyLongObject *)left, (PyLongObject *)right);
SET_SECOND(sum);
- Py_DECREF(right);
- Py_DECREF(left);
+ _Py_DECREF_SPECIALIZED(right, PyObject_Free);
+ _Py_DECREF_SPECIALIZED(left, PyObject_Free);
STACK_SHRINK(1);
if (sum == NULL) {
goto error;
assert(res != NULL);
Py_INCREF(res);
STACK_SHRINK(1);
- Py_DECREF(sub);
+ _Py_DECREF_SPECIALIZED(sub, PyObject_Free);
SET_TOP(res);
Py_DECREF(list);
JUMPBY(INLINE_CACHE_ENTRIES_BINARY_SUBSCR);
assert(res != NULL);
Py_INCREF(res);
STACK_SHRINK(1);
- Py_DECREF(sub);
+ _Py_DECREF_SPECIALIZED(sub, PyObject_Free);
SET_TOP(res);
Py_DECREF(tuple);
JUMPBY(INLINE_CACHE_ENTRIES_BINARY_SUBSCR);
STACK_SHRINK(3);
assert(old_value != NULL);
Py_DECREF(old_value);
- Py_DECREF(sub);
+ _Py_DECREF_SPECIALIZED(sub, PyObject_Free);
Py_DECREF(list);
JUMPBY(INLINE_CACHE_ENTRIES_STORE_SUBSCR);
NOTRACE_DISPATCH();
JUMPBY(INLINE_CACHE_ENTRIES_COMPARE_OP);
NEXTOPARG();
STACK_SHRINK(2);
- Py_DECREF(left);
- Py_DECREF(right);
+ _Py_DECREF_SPECIALIZED(left, _PyFloat_ExactDealloc);
+ _Py_DECREF_SPECIALIZED(right, _PyFloat_ExactDealloc);
assert(opcode == POP_JUMP_FORWARD_IF_FALSE ||
opcode == POP_JUMP_BACKWARD_IF_FALSE ||
opcode == POP_JUMP_FORWARD_IF_TRUE ||
JUMPBY(INLINE_CACHE_ENTRIES_COMPARE_OP);
NEXTOPARG();
STACK_SHRINK(2);
- Py_DECREF(left);
- Py_DECREF(right);
+ _Py_DECREF_SPECIALIZED(left, PyObject_Free);
+ _Py_DECREF_SPECIALIZED(right, PyObject_Free);
assert(opcode == POP_JUMP_FORWARD_IF_FALSE ||
opcode == POP_JUMP_BACKWARD_IF_FALSE ||
opcode == POP_JUMP_FORWARD_IF_TRUE ||
opcode == POP_JUMP_FORWARD_IF_TRUE ||
opcode == POP_JUMP_BACKWARD_IF_TRUE);
STACK_SHRINK(2);
- Py_DECREF(left);
- Py_DECREF(right);
+ _Py_DECREF_SPECIALIZED(left, _PyUnicode_ExactDealloc);
+ _Py_DECREF_SPECIALIZED(right, _PyUnicode_ExactDealloc);
assert(res == 0 || res == 1);
int sign = 1 - res;
int jump = (9 << (sign + 1)) & when_to_jump_mask;
PREDICTED(POP_JUMP_BACKWARD_IF_FALSE);
PyObject *cond = POP();
if (Py_IsTrue(cond)) {
- Py_DECREF(cond);
+ _Py_DECREF_NO_DEALLOC(cond);
DISPATCH();
}
if (Py_IsFalse(cond)) {
- Py_DECREF(cond);
+ _Py_DECREF_NO_DEALLOC(cond);
JUMPBY(-oparg);
CHECK_EVAL_BREAKER();
DISPATCH();
PREDICTED(POP_JUMP_FORWARD_IF_FALSE);
PyObject *cond = POP();
if (Py_IsTrue(cond)) {
- Py_DECREF(cond);
+ _Py_DECREF_NO_DEALLOC(cond);
}
else if (Py_IsFalse(cond)) {
- Py_DECREF(cond);
+ _Py_DECREF_NO_DEALLOC(cond);
JUMPBY(oparg);
}
else {
TARGET(POP_JUMP_BACKWARD_IF_TRUE) {
PyObject *cond = POP();
if (Py_IsFalse(cond)) {
- Py_DECREF(cond);
+ _Py_DECREF_NO_DEALLOC(cond);
DISPATCH();
}
if (Py_IsTrue(cond)) {
- Py_DECREF(cond);
+ _Py_DECREF_NO_DEALLOC(cond);
JUMPBY(-oparg);
CHECK_EVAL_BREAKER();
DISPATCH();
TARGET(POP_JUMP_FORWARD_IF_TRUE) {
PyObject *cond = POP();
if (Py_IsFalse(cond)) {
- Py_DECREF(cond);
+ _Py_DECREF_NO_DEALLOC(cond);
}
else if (Py_IsTrue(cond)) {
- Py_DECREF(cond);
+ _Py_DECREF_NO_DEALLOC(cond);
JUMPBY(oparg);
}
else {
CHECK_EVAL_BREAKER();
DISPATCH();
}
- Py_DECREF(value);
+ _Py_DECREF_NO_DEALLOC(value);
DISPATCH();
}
TARGET(POP_JUMP_BACKWARD_IF_NONE) {
PyObject *value = POP();
if (Py_IsNone(value)) {
- Py_DECREF(value);
+ _Py_DECREF_NO_DEALLOC(value);
JUMPBY(-oparg);
CHECK_EVAL_BREAKER();
- DISPATCH();
}
- Py_DECREF(value);
+ else {
+ Py_DECREF(value);
+ }
DISPATCH();
}
TARGET(POP_JUMP_FORWARD_IF_NONE) {
PyObject *value = POP();
if (Py_IsNone(value)) {
+ _Py_DECREF_NO_DEALLOC(value);
JUMPBY(oparg);
}
- Py_DECREF(value);
+ else {
+ Py_DECREF(value);
+ }
DISPATCH();
}
int err;
if (Py_IsTrue(cond)) {
STACK_SHRINK(1);
- Py_DECREF(cond);
+ _Py_DECREF_NO_DEALLOC(cond);
DISPATCH();
}
if (Py_IsFalse(cond)) {
int err;
if (Py_IsFalse(cond)) {
STACK_SHRINK(1);
- Py_DECREF(cond);
+ _Py_DECREF_NO_DEALLOC(cond);
DISPATCH();
}
if (Py_IsTrue(cond)) {