#include "Python.h"
#include "pycore_brc.h"
#include "pycore_call.h"
#include "pycore_ceval.h"
#include "pycore_context.h"
#include "pycore_critical_section.h"
#include "pycore_descrobject.h"
#include "pycore_dict.h"
#include "pycore_floatobject.h"
#include "pycore_freelist.h"
#include "pycore_initconfig.h"
#include "pycore_instruction_sequence.h"
#include "pycore_hashtable.h"
#include "pycore_memoryobject.h"
#include "pycore_namespace.h"
#include "pycore_object.h"
#include "pycore_object_state.h"
#include "pycore_long.h"
#include "pycore_optimizer.h"
#include "pycore_pyerrors.h"
#include "pycore_pymem.h"
#include "pycore_pystate.h"
#include "pycore_symtable.h"
#include "pycore_typeobject.h"
#include "pycore_typevarobject.h"
#include "pycore_unionobject.h"
#ifdef Py_LIMITED_API
# error "Py_LIMITED_API macro must not be defined"
#endif
extern void _PyMem_DumpTraceback(int fd, const void *ptr);
int
_PyObject_CheckConsistency(PyObject *op, int check_content)
{ … }
#ifdef Py_REF_DEBUG
Py_ssize_t _Py_RefTotal;
static inline Py_ssize_t
get_legacy_reftotal(void)
{
return _Py_RefTotal;
}
#endif
#ifdef Py_REF_DEBUG
#define REFTOTAL …
static inline void
reftotal_add(PyThreadState *tstate, Py_ssize_t n)
{
#ifdef Py_GIL_DISABLED
_PyThreadStateImpl *tstate_impl = (_PyThreadStateImpl *)tstate;
Py_ssize_t reftotal = tstate_impl->reftotal + n;
_Py_atomic_store_ssize_relaxed(&tstate_impl->reftotal, reftotal);
#else
REFTOTAL(tstate->interp) += n;
#endif
}
static inline Py_ssize_t get_global_reftotal(_PyRuntimeState *);
static Py_ssize_t last_final_reftotal = 0;
void
_Py_FinalizeRefTotal(_PyRuntimeState *runtime)
{
last_final_reftotal = get_global_reftotal(runtime);
runtime->object_state.interpreter_leaks = 0;
}
void
_PyInterpreterState_FinalizeRefTotal(PyInterpreterState *interp)
{
interp->runtime->object_state.interpreter_leaks += REFTOTAL(interp);
REFTOTAL(interp) = 0;
}
static inline Py_ssize_t
get_reftotal(PyInterpreterState *interp)
{
Py_ssize_t total = REFTOTAL(interp);
#ifdef Py_GIL_DISABLED
_Py_FOR_EACH_TSTATE_UNLOCKED(interp, p) {
_PyThreadStateImpl *tstate_impl = (_PyThreadStateImpl *)p;
total += _Py_atomic_load_ssize_relaxed(&tstate_impl->reftotal);
}
#endif
return total;
}
static inline Py_ssize_t
get_global_reftotal(_PyRuntimeState *runtime)
{
Py_ssize_t total = 0;
HEAD_LOCK(&_PyRuntime);
PyInterpreterState *interp = PyInterpreterState_Head();
for (; interp != NULL; interp = PyInterpreterState_Next(interp)) {
total += get_reftotal(interp);
}
HEAD_UNLOCK(&_PyRuntime);
total += get_legacy_reftotal();
total += last_final_reftotal;
total += runtime->object_state.interpreter_leaks;
return total;
}
#undef REFTOTAL
void
_PyDebug_PrintTotalRefs(void) {
_PyRuntimeState *runtime = &_PyRuntime;
fprintf(stderr,
"[%zd refs, %zd blocks]\n",
get_global_reftotal(runtime), _Py_GetGlobalAllocatedBlocks());
}
#endif
#ifdef Py_TRACE_REFS
#define REFCHAIN …
#define REFCHAIN_VALUE …
static inline int
has_own_refchain(PyInterpreterState *interp)
{
if (interp->feature_flags & Py_RTFLAGS_USE_MAIN_OBMALLOC) {
return (_Py_IsMainInterpreter(interp)
|| _PyInterpreterState_Main() == NULL);
}
return 1;
}
static int
refchain_init(PyInterpreterState *interp)
{
if (!has_own_refchain(interp)) {
REFCHAIN(interp) = REFCHAIN(_PyInterpreterState_Main());
return 0;
}
_Py_hashtable_allocator_t alloc = {
.malloc = PyMem_RawMalloc,
.free = PyMem_RawFree,
};
REFCHAIN(interp) = _Py_hashtable_new_full(
_Py_hashtable_hash_ptr, _Py_hashtable_compare_direct,
NULL, NULL, &alloc);
if (REFCHAIN(interp) == NULL) {
return -1;
}
return 0;
}
static void
refchain_fini(PyInterpreterState *interp)
{
if (has_own_refchain(interp) && REFCHAIN(interp) != NULL) {
_Py_hashtable_destroy(REFCHAIN(interp));
}
REFCHAIN(interp) = NULL;
}
bool
_PyRefchain_IsTraced(PyInterpreterState *interp, PyObject *obj)
{
return (_Py_hashtable_get(REFCHAIN(interp), obj) == REFCHAIN_VALUE);
}
static void
_PyRefchain_Trace(PyInterpreterState *interp, PyObject *obj)
{
if (_Py_hashtable_set(REFCHAIN(interp), obj, REFCHAIN_VALUE) < 0) {
Py_FatalError("_Py_hashtable_set() memory allocation failed");
}
}
static void
_PyRefchain_Remove(PyInterpreterState *interp, PyObject *obj)
{
void *value = _Py_hashtable_steal(REFCHAIN(interp), obj);
#ifndef NDEBUG
assert(value == REFCHAIN_VALUE);
#else
(void)value;
#endif
}
void
_Py_AddToAllObjects(PyObject *op)
{
PyInterpreterState *interp = _PyInterpreterState_GET();
if (!_PyRefchain_IsTraced(interp, op)) {
_PyRefchain_Trace(interp, op);
}
}
#endif
#ifdef Py_REF_DEBUG
void
_Py_NegativeRefcount(const char *filename, int lineno, PyObject *op)
{
_PyObject_AssertFailed(op, NULL, "object has negative ref count",
filename, lineno, __func__);
}
void
_Py_INCREF_IncRefTotal(void)
{
reftotal_add(_PyThreadState_GET(), 1);
}
void
_Py_DECREF_DecRefTotal(void)
{
reftotal_add(_PyThreadState_GET(), -1);
}
void
_Py_IncRefTotal(PyThreadState *tstate)
{
reftotal_add(tstate, 1);
}
void
_Py_DecRefTotal(PyThreadState *tstate)
{
reftotal_add(tstate, -1);
}
void
_Py_AddRefTotal(PyThreadState *tstate, Py_ssize_t n)
{
reftotal_add(tstate, n);
}
Py_ssize_t
_Py_GetGlobalRefTotal(void)
{
return get_global_reftotal(&_PyRuntime);
}
Py_ssize_t
_Py_GetLegacyRefTotal(void)
{
return get_legacy_reftotal();
}
Py_ssize_t
_PyInterpreterState_GetRefTotal(PyInterpreterState *interp)
{
HEAD_LOCK(&_PyRuntime);
Py_ssize_t total = get_reftotal(interp);
HEAD_UNLOCK(&_PyRuntime);
return total;
}
#endif
void
Py_IncRef(PyObject *o)
{ … }
void
Py_DecRef(PyObject *o)
{ … }
void
_Py_IncRef(PyObject *o)
{ … }
void
_Py_DecRef(PyObject *o)
{ … }
#ifdef Py_GIL_DISABLED
# ifdef Py_REF_DEBUG
static int
is_dead(PyObject *o)
{
# if SIZEOF_SIZE_T == 8
return (uintptr_t)o->ob_type == 0xDDDDDDDDDDDDDDDD;
# else
return (uintptr_t)o->ob_type == 0xDDDDDDDD;
# endif
}
# endif
void
_Py_DecRefSharedDebug(PyObject *o, const char *filename, int lineno)
{
int should_queue;
Py_ssize_t new_shared;
Py_ssize_t shared = _Py_atomic_load_ssize_relaxed(&o->ob_ref_shared);
do {
should_queue = (shared == 0 || shared == _Py_REF_MAYBE_WEAKREF);
if (should_queue) {
new_shared = _Py_REF_QUEUED;
}
else {
new_shared = shared - (1 << _Py_REF_SHARED_SHIFT);
}
#ifdef Py_REF_DEBUG
if ((new_shared < 0 && _Py_REF_IS_MERGED(new_shared)) ||
(should_queue && is_dead(o)))
{
_Py_NegativeRefcount(filename, lineno, o);
}
#endif
} while (!_Py_atomic_compare_exchange_ssize(&o->ob_ref_shared,
&shared, new_shared));
if (should_queue) {
#ifdef Py_REF_DEBUG
_Py_IncRefTotal(_PyThreadState_GET());
#endif
_Py_brc_queue_object(o);
}
else if (new_shared == _Py_REF_MERGED) {
_Py_Dealloc(o);
}
}
void
_Py_DecRefShared(PyObject *o)
{
_Py_DecRefSharedDebug(o, NULL, 0);
}
void
_Py_MergeZeroLocalRefcount(PyObject *op)
{
assert(op->ob_ref_local == 0);
Py_ssize_t shared = _Py_atomic_load_ssize_acquire(&op->ob_ref_shared);
if (shared == 0) {
_Py_Dealloc(op);
return;
}
_Py_atomic_store_uintptr_relaxed(&op->ob_tid, 0);
Py_ssize_t new_shared;
do {
new_shared = (shared & ~_Py_REF_SHARED_FLAG_MASK) | _Py_REF_MERGED;
} while (!_Py_atomic_compare_exchange_ssize(&op->ob_ref_shared,
&shared, new_shared));
if (new_shared == _Py_REF_MERGED) {
_Py_Dealloc(op);
}
}
Py_ssize_t
_Py_ExplicitMergeRefcount(PyObject *op, Py_ssize_t extra)
{
assert(!_Py_IsImmortal(op));
#ifdef Py_REF_DEBUG
_Py_AddRefTotal(_PyThreadState_GET(), extra);
#endif
Py_ssize_t local = (Py_ssize_t)op->ob_ref_local;
_Py_atomic_store_uint32_relaxed(&op->ob_ref_local, 0);
_Py_atomic_store_uintptr_relaxed(&op->ob_tid, 0);
Py_ssize_t refcnt;
Py_ssize_t new_shared;
Py_ssize_t shared = _Py_atomic_load_ssize_relaxed(&op->ob_ref_shared);
do {
refcnt = Py_ARITHMETIC_RIGHT_SHIFT(Py_ssize_t, shared, _Py_REF_SHARED_SHIFT);
refcnt += local;
refcnt += extra;
new_shared = _Py_REF_SHARED(refcnt, _Py_REF_MERGED);
} while (!_Py_atomic_compare_exchange_ssize(&op->ob_ref_shared,
&shared, new_shared));
return refcnt;
}
#endif
PyObject *
PyObject_Init(PyObject *op, PyTypeObject *tp)
{ … }
PyVarObject *
PyObject_InitVar(PyVarObject *op, PyTypeObject *tp, Py_ssize_t size)
{ … }
PyObject *
_PyObject_New(PyTypeObject *tp)
{ … }
PyVarObject *
_PyObject_NewVar(PyTypeObject *tp, Py_ssize_t nitems)
{ … }
void
PyObject_CallFinalizer(PyObject *self)
{ … }
int
PyObject_CallFinalizerFromDealloc(PyObject *self)
{ … }
int
PyObject_Print(PyObject *op, FILE *fp, int flags)
{ … }
void
_Py_BreakPoint(void)
{ … }
int
_PyObject_IsFreed(PyObject *op)
{ … }
void
_PyObject_Dump(PyObject* op)
{ … }
PyObject *
PyObject_Repr(PyObject *v)
{ … }
PyObject *
PyObject_Str(PyObject *v)
{ … }
PyObject *
PyObject_ASCII(PyObject *v)
{ … }
PyObject *
PyObject_Bytes(PyObject *v)
{ … }
static void
clear_freelist(struct _Py_freelist *freelist, int is_finalization,
freefunc dofree)
{ … }
static void
free_object(void *obj)
{ … }
void
_PyObject_ClearFreeLists(struct _Py_freelists *freelists, int is_finalization)
{ … }
PyObject *
_PyObject_FunctionStr(PyObject *x)
{ … }
int _Py_SwappedOp[] = …;
static const char * const opstrings[] = …;
static PyObject *
do_richcompare(PyThreadState *tstate, PyObject *v, PyObject *w, int op)
{ … }
PyObject *
PyObject_RichCompare(PyObject *v, PyObject *w, int op)
{ … }
int
PyObject_RichCompareBool(PyObject *v, PyObject *w, int op)
{ … }
Py_hash_t
PyObject_HashNotImplemented(PyObject *v)
{ … }
Py_hash_t
PyObject_Hash(PyObject *v)
{ … }
PyObject *
PyObject_GetAttrString(PyObject *v, const char *name)
{ … }
int
PyObject_HasAttrStringWithError(PyObject *obj, const char *name)
{ … }
int
PyObject_HasAttrString(PyObject *obj, const char *name)
{ … }
int
PyObject_SetAttrString(PyObject *v, const char *name, PyObject *w)
{ … }
int
PyObject_DelAttrString(PyObject *v, const char *name)
{ … }
int
_PyObject_IsAbstract(PyObject *obj)
{ … }
PyObject *
_PyObject_GetAttrId(PyObject *v, _Py_Identifier *name)
{ … }
int
_PyObject_SetAttributeErrorContext(PyObject* v, PyObject* name)
{ … }
PyObject *
PyObject_GetAttr(PyObject *v, PyObject *name)
{ … }
int
PyObject_GetOptionalAttr(PyObject *v, PyObject *name, PyObject **result)
{ … }
int
PyObject_GetOptionalAttrString(PyObject *obj, const char *name, PyObject **result)
{ … }
int
PyObject_HasAttrWithError(PyObject *obj, PyObject *name)
{ … }
int
PyObject_HasAttr(PyObject *obj, PyObject *name)
{ … }
int
PyObject_SetAttr(PyObject *v, PyObject *name, PyObject *value)
{ … }
int
PyObject_DelAttr(PyObject *v, PyObject *name)
{ … }
PyObject **
_PyObject_ComputedDictPointer(PyObject *obj)
{ … }
PyObject **
_PyObject_GetDictPtr(PyObject *obj)
{ … }
PyObject *
PyObject_SelfIter(PyObject *obj)
{ … }
PyObject *
_PyObject_NextNotImplemented(PyObject *self)
{ … }
int
_PyObject_GetMethod(PyObject *obj, PyObject *name, PyObject **method)
{ … }
PyObject *
_PyObject_GenericGetAttrWithDict(PyObject *obj, PyObject *name,
PyObject *dict, int suppress)
{ … }
PyObject *
PyObject_GenericGetAttr(PyObject *obj, PyObject *name)
{ … }
int
_PyObject_GenericSetAttrWithDict(PyObject *obj, PyObject *name,
PyObject *value, PyObject *dict)
{ … }
int
PyObject_GenericSetAttr(PyObject *obj, PyObject *name, PyObject *value)
{ … }
int
PyObject_GenericSetDict(PyObject *obj, PyObject *value, void *context)
{ … }
int
PyObject_IsTrue(PyObject *v)
{ … }
int
PyObject_Not(PyObject *v)
{ … }
int
PyCallable_Check(PyObject *x)
{ … }
static PyObject *
_dir_locals(void)
{ … }
static PyObject *
_dir_object(PyObject *obj)
{ … }
PyObject *
PyObject_Dir(PyObject *obj)
{ … }
static PyObject *
none_repr(PyObject *op)
{ … }
static void
none_dealloc(PyObject* none)
{ … }
static PyObject *
none_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
{ … }
static int
none_bool(PyObject *v)
{ … }
static Py_hash_t none_hash(PyObject *v)
{ … }
static PyNumberMethods none_as_number = …;
PyDoc_STRVAR(none_doc,
"NoneType()\n"
"--\n\n"
"The type of the None singleton.");
PyTypeObject _PyNone_Type = …;
PyObject _Py_NoneStruct = …;
static PyObject *
NotImplemented_repr(PyObject *op)
{ … }
static PyObject *
NotImplemented_reduce(PyObject *op, PyObject *Py_UNUSED(ignored))
{ … }
static PyMethodDef notimplemented_methods[] = …;
static PyObject *
notimplemented_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
{ … }
static void
notimplemented_dealloc(PyObject *notimplemented)
{ … }
static int
notimplemented_bool(PyObject *v)
{ … }
static PyNumberMethods notimplemented_as_number = …;
PyDoc_STRVAR(notimplemented_doc,
"NotImplementedType()\n"
"--\n\n"
"The type of the NotImplemented singleton.");
PyTypeObject _PyNotImplemented_Type = …;
PyObject _Py_NotImplementedStruct = …;
PyStatus
_PyObject_InitState(PyInterpreterState *interp)
{ … }
void
_PyObject_FiniState(PyInterpreterState *interp)
{ … }
extern PyTypeObject _PyAnextAwaitable_Type;
extern PyTypeObject _PyLegacyEventHandler_Type;
extern PyTypeObject _PyLineIterator;
extern PyTypeObject _PyMemoryIter_Type;
extern PyTypeObject _PyPositionsIterator;
extern PyTypeObject _Py_GenericAliasIterType;
static PyTypeObject* static_types[] = …;
PyStatus
_PyTypes_InitTypes(PyInterpreterState *interp)
{ … }
void
_PyTypes_FiniTypes(PyInterpreterState *interp)
{ … }
static inline void
new_reference(PyObject *op)
{ … }
void
_Py_NewReference(PyObject *op)
{ … }
void
_Py_NewReferenceNoTotal(PyObject *op)
{ … }
void
_Py_SetImmortalUntracked(PyObject *op)
{ … }
void
_Py_SetImmortal(PyObject *op)
{ … }
void
_PyObject_SetDeferredRefcount(PyObject *op)
{ … }
int
PyUnstable_Object_EnableDeferredRefcount(PyObject *op)
{ … }
void
_Py_ResurrectReference(PyObject *op)
{ … }
#ifdef Py_TRACE_REFS
void
_Py_ForgetReference(PyObject *op)
{
if (Py_REFCNT(op) < 0) {
_PyObject_ASSERT_FAILED_MSG(op, "negative refcnt");
}
PyInterpreterState *interp = _PyInterpreterState_GET();
#ifdef SLOW_UNREF_CHECK
if (!_PyRefchain_Get(interp, op)) {
_PyObject_ASSERT_FAILED_MSG(op,
"object not found in the objects list");
}
#endif
_PyRefchain_Remove(interp, op);
}
static int
_Py_PrintReference(_Py_hashtable_t *ht,
const void *key, const void *value,
void *user_data)
{
PyObject *op = (PyObject*)key;
FILE *fp = (FILE *)user_data;
fprintf(fp, "%p [%zd] ", (void *)op, Py_REFCNT(op));
if (PyObject_Print(op, fp, 0) != 0) {
PyErr_Clear();
}
putc('\n', fp);
return 0;
}
void
_Py_PrintReferences(PyInterpreterState *interp, FILE *fp)
{
if (interp == NULL) {
interp = _PyInterpreterState_Main();
}
fprintf(fp, "Remaining objects:\n");
_Py_hashtable_foreach(REFCHAIN(interp), _Py_PrintReference, fp);
}
static int
_Py_PrintReferenceAddress(_Py_hashtable_t *ht,
const void *key, const void *value,
void *user_data)
{
PyObject *op = (PyObject*)key;
FILE *fp = (FILE *)user_data;
fprintf(fp, "%p [%zd] %s\n",
(void *)op, Py_REFCNT(op), Py_TYPE(op)->tp_name);
return 0;
}
void
_Py_PrintReferenceAddresses(PyInterpreterState *interp, FILE *fp)
{
fprintf(fp, "Remaining object addresses:\n");
_Py_hashtable_foreach(REFCHAIN(interp), _Py_PrintReferenceAddress, fp);
}
typedef struct {
PyObject *self;
PyObject *args;
PyObject *list;
PyObject *type;
Py_ssize_t limit;
} _Py_GetObjectsData;
enum {
_PY_GETOBJECTS_IGNORE = 0,
_PY_GETOBJECTS_ERROR = 1,
_PY_GETOBJECTS_STOP = 2,
};
static int
_Py_GetObject(_Py_hashtable_t *ht,
const void *key, const void *value,
void *user_data)
{
PyObject *op = (PyObject *)key;
_Py_GetObjectsData *data = user_data;
if (data->limit > 0) {
if (PyList_GET_SIZE(data->list) >= data->limit) {
return _PY_GETOBJECTS_STOP;
}
}
if (op == data->self) {
return _PY_GETOBJECTS_IGNORE;
}
if (op == data->args) {
return _PY_GETOBJECTS_IGNORE;
}
if (op == data->list) {
return _PY_GETOBJECTS_IGNORE;
}
if (data->type != NULL) {
if (op == data->type) {
return _PY_GETOBJECTS_IGNORE;
}
if (!Py_IS_TYPE(op, (PyTypeObject *)data->type)) {
return _PY_GETOBJECTS_IGNORE;
}
}
if (PyList_Append(data->list, op) < 0) {
return _PY_GETOBJECTS_ERROR;
}
return 0;
}
PyObject *
_Py_GetObjects(PyObject *self, PyObject *args)
{
Py_ssize_t limit;
PyObject *type = NULL;
if (!PyArg_ParseTuple(args, "n|O", &limit, &type)) {
return NULL;
}
PyObject *list = PyList_New(0);
if (list == NULL) {
return NULL;
}
_Py_GetObjectsData data = {
.self = self,
.args = args,
.list = list,
.type = type,
.limit = limit,
};
PyInterpreterState *interp = _PyInterpreterState_GET();
int res = _Py_hashtable_foreach(REFCHAIN(interp), _Py_GetObject, &data);
if (res == _PY_GETOBJECTS_ERROR) {
Py_DECREF(list);
return NULL;
}
return list;
}
#undef REFCHAIN
#undef REFCHAIN_VALUE
#endif
Py_ssize_t (*_Py_abstract_hack)(PyObject *) = …;
void
_PyObject_DebugTypeStats(FILE *out)
{ … }
int
Py_ReprEnter(PyObject *obj)
{ … }
void
Py_ReprLeave(PyObject *obj)
{ … }
void
_PyTrash_thread_deposit_object(PyThreadState *tstate, PyObject *op)
{ … }
void
_PyTrash_thread_destroy_chain(PyThreadState *tstate)
{ … }
void _Py_NO_RETURN
_PyObject_AssertFailed(PyObject *obj, const char *expr, const char *msg,
const char *file, int line, const char *function)
{ … }
void
_Py_Dealloc(PyObject *op)
{ … }
PyObject **
PyObject_GET_WEAKREFS_LISTPTR(PyObject *op)
{ … }
#undef Py_NewRef
#undef Py_XNewRef
PyObject*
Py_NewRef(PyObject *obj)
{ … }
PyObject*
Py_XNewRef(PyObject *obj)
{ … }
#undef Py_Is
#undef Py_IsNone
#undef Py_IsTrue
#undef Py_IsFalse
int Py_Is(PyObject *x, PyObject *y)
{ … }
int Py_IsNone(PyObject *x)
{ … }
int Py_IsTrue(PyObject *x)
{ … }
int Py_IsFalse(PyObject *x)
{ … }
void
_Py_SetRefcnt(PyObject *ob, Py_ssize_t refcnt)
{ … }
int PyRefTracer_SetTracer(PyRefTracer tracer, void *data) { … }
PyRefTracer PyRefTracer_GetTracer(void** data) { … }
static PyObject* constants[] = …;
void
_Py_GetConstant_Init(void)
{ … }
PyObject*
Py_GetConstant(unsigned int constant_id)
{ … }
PyObject*
Py_GetConstantBorrowed(unsigned int constant_id)
{ … }
#undef Py_TYPE
PyTypeObject*
Py_TYPE(PyObject *ob)
{ … }
#undef Py_REFCNT
Py_ssize_t
Py_REFCNT(PyObject *ob)
{ … }