Skip to content

gh-123660: Internal macros for accessing empty tuple singleton #123661

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 4 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Include/internal/pycore_runtime_init.h
Original file line number Diff line number Diff line change
Expand Up @@ -257,7 +257,7 @@ extern PyTypeObject _PyExc_MemoryError;
}, \
.last_resort_memory_error = { \
_PyObject_HEAD_INIT(&_PyExc_MemoryError), \
.args = (PyObject*)&_Py_SINGLETON(tuple_empty) \
.args = _Py_EMPTY_TUPLE \
}, \
}, \
}, \
Expand Down
1 change: 1 addition & 0 deletions Include/internal/pycore_tuple.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ extern PyStatus _PyTuple_InitGlobalObjects(PyInterpreterState *);

/* other API */

#define _Py_EMPTY_TUPLE ((PyObject *)&_Py_SINGLETON(tuple_empty))
#define _PyTuple_ITEMS(op) _Py_RVALUE(_PyTuple_CAST(op)->ob_item)

extern PyObject *_PyTuple_FromArray(PyObject *const *, Py_ssize_t);
Expand Down
18 changes: 7 additions & 11 deletions Modules/_elementtree.c
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,12 @@
#endif

#include "Python.h"
#include "pycore_import.h" // _PyImport_GetModuleAttrString()
#include "pycore_pyhash.h" // _Py_HashSecret
#include "pycore_import.h" // _PyImport_GetModuleAttrString()
#include "pycore_pyhash.h" // _Py_HashSecret
#include "pycore_runtime.h" // _PyRuntime
#include "pycore_tuple.h" // _Py_EMPTY_TUPLE

#include <stddef.h> // offsetof()
#include <stddef.h> // offsetof()
#include "expat.h"
#include "pyexpat.h"

Expand Down Expand Up @@ -1095,23 +1097,17 @@ element_setstate_from_Python(elementtreestate *st, ElementObject *self,
{
static char *kwlist[] = {PICKLED_TAG, PICKLED_ATTRIB, PICKLED_TEXT,
PICKLED_TAIL, PICKLED_CHILDREN, 0};
PyObject *args;
PyObject *tag, *attrib, *text, *tail, *children;
PyObject *retval;

tag = attrib = text = tail = children = NULL;
args = PyTuple_New(0);
if (!args)
return NULL;

if (PyArg_ParseTupleAndKeywords(args, state, "|$OOOOO", kwlist, &tag,
&attrib, &text, &tail, &children))
if (PyArg_ParseTupleAndKeywords(_Py_EMPTY_TUPLE, state, "|$OOOOO", kwlist,
&tag, &attrib, &text, &tail, &children))
retval = element_setstate_from_attributes(st, self, tag, attrib, text,
tail, children);
else
retval = NULL;

Py_DECREF(args);
return retval;
}

Expand Down
18 changes: 6 additions & 12 deletions Modules/_lzmamodule.c
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,11 @@
#endif

#include "Python.h"
#include "pycore_runtime.h" // _PyRuntime
#include "pycore_tuple.h" // _Py_EMPTY_TUPLE


#include <stdlib.h> // free()
#include <stdlib.h> // free()
#include <string.h>

#include <lzma.h>
Expand Down Expand Up @@ -83,7 +85,6 @@ typedef struct {
PyTypeObject *lzma_compressor_type;
PyTypeObject *lzma_decompressor_type;
PyObject *error;
PyObject *empty_tuple;
} _lzma_state;

static inline _lzma_state*
Expand Down Expand Up @@ -266,7 +267,7 @@ parse_filter_spec_lzma(_lzma_state *state, PyObject *spec)
return NULL;
}

if (!PyArg_ParseTupleAndKeywords(state->empty_tuple, spec,
if (!PyArg_ParseTupleAndKeywords(_Py_EMPTY_TUPLE, spec,
"|OOO&O&O&O&O&O&O&O&", optnames,
&id, &preset_obj,
uint32_converter, &options->dict_size,
Expand Down Expand Up @@ -294,7 +295,7 @@ parse_filter_spec_delta(_lzma_state *state, PyObject *spec)
uint32_t dist = 1;
lzma_options_delta *options;

if (!PyArg_ParseTupleAndKeywords(state->empty_tuple, spec, "|OO&", optnames,
if (!PyArg_ParseTupleAndKeywords(_Py_EMPTY_TUPLE, spec, "|OO&", optnames,
&id, uint32_converter, &dist)) {
PyErr_SetString(PyExc_ValueError,
"Invalid filter specifier for delta filter");
Expand All @@ -318,7 +319,7 @@ parse_filter_spec_bcj(_lzma_state *state, PyObject *spec)
uint32_t start_offset = 0;
lzma_options_bcj *options;

if (!PyArg_ParseTupleAndKeywords(state->empty_tuple, spec, "|OO&", optnames,
if (!PyArg_ParseTupleAndKeywords(_Py_EMPTY_TUPLE, spec, "|OO&", optnames,
&id, uint32_converter, &start_offset)) {
PyErr_SetString(PyExc_ValueError,
"Invalid filter specifier for BCJ filter");
Expand Down Expand Up @@ -1527,11 +1528,6 @@ lzma_exec(PyObject *module)

_lzma_state *state = get_lzma_state(module);

state->empty_tuple = PyTuple_New(0);
if (state->empty_tuple == NULL) {
return -1;
}

ADD_INT_MACRO(module, FORMAT_AUTO);
ADD_INT_MACRO(module, FORMAT_XZ);
ADD_INT_MACRO(module, FORMAT_ALONE);
Expand Down Expand Up @@ -1615,7 +1611,6 @@ lzma_traverse(PyObject *module, visitproc visit, void *arg)
Py_VISIT(state->lzma_compressor_type);
Py_VISIT(state->lzma_decompressor_type);
Py_VISIT(state->error);
Py_VISIT(state->empty_tuple);
return 0;
}

Expand All @@ -1626,7 +1621,6 @@ lzma_clear(PyObject *module)
Py_CLEAR(state->lzma_compressor_type);
Py_CLEAR(state->lzma_decompressor_type);
Py_CLEAR(state->error);
Py_CLEAR(state->empty_tuple);
return 0;
}

Expand Down
7 changes: 1 addition & 6 deletions Modules/itertoolsmodule.c
Original file line number Diff line number Diff line change
Expand Up @@ -1917,15 +1917,10 @@ product_new(PyTypeObject *type, PyObject *args, PyObject *kwds)

if (kwds != NULL) {
char *kwlist[] = {"repeat", 0};
PyObject *tmpargs = PyTuple_New(0);
if (tmpargs == NULL)
return NULL;
if (!PyArg_ParseTupleAndKeywords(tmpargs, kwds, "|n:product",
if (!PyArg_ParseTupleAndKeywords(_Py_EMPTY_TUPLE, kwds, "|n:product",
kwlist, &repeat)) {
Py_DECREF(tmpargs);
return NULL;
}
Py_DECREF(tmpargs);
if (repeat < 0) {
PyErr_SetString(PyExc_ValueError,
"repeat argument cannot be negative");
Expand Down
12 changes: 3 additions & 9 deletions Objects/codeobject.c
Original file line number Diff line number Diff line change
Expand Up @@ -879,17 +879,12 @@ static const uint8_t linetable[2] = {
PyCodeObject *
PyCode_NewEmpty(const char *filename, const char *funcname, int firstlineno)
{
PyObject *nulltuple = NULL;
PyObject *filename_ob = NULL;
PyObject *funcname_ob = NULL;
PyObject *code_ob = NULL;
PyObject *linetable_ob = NULL;
PyCodeObject *result = NULL;

nulltuple = PyTuple_New(0);
if (nulltuple == NULL) {
goto failed;
}
funcname_ob = PyUnicode_FromString(funcname);
if (funcname_ob == NULL) {
goto failed;
Expand All @@ -915,17 +910,16 @@ PyCode_NewEmpty(const char *filename, const char *funcname, int firstlineno)
.code = code_ob,
.firstlineno = firstlineno,
.linetable = linetable_ob,
.consts = nulltuple,
.names = nulltuple,
.localsplusnames = nulltuple,
.consts = _Py_EMPTY_TUPLE,
.names = _Py_EMPTY_TUPLE,
.localsplusnames = _Py_EMPTY_TUPLE,
.localspluskinds = emptystring,
.exceptiontable = emptystring,
.stacksize = 1,
};
result = _PyCode_New(&con);

failed:
Py_XDECREF(nulltuple);
Py_XDECREF(funcname_ob);
Py_XDECREF(filename_ob);
Py_XDECREF(code_ob);
Expand Down
27 changes: 6 additions & 21 deletions Objects/exceptions.c
Original file line number Diff line number Diff line change
Expand Up @@ -1561,7 +1561,6 @@ static int
ImportError_init(PyImportErrorObject *self, PyObject *args, PyObject *kwds)
{
static char *kwlist[] = {"name", "path", "name_from", 0};
PyObject *empty_tuple;
PyObject *msg = NULL;
PyObject *name = NULL;
PyObject *path = NULL;
Expand All @@ -1570,15 +1569,11 @@ ImportError_init(PyImportErrorObject *self, PyObject *args, PyObject *kwds)
if (BaseException_init((PyBaseExceptionObject *)self, args, NULL) == -1)
return -1;

empty_tuple = PyTuple_New(0);
if (!empty_tuple)
return -1;
if (!PyArg_ParseTupleAndKeywords(empty_tuple, kwds, "|$OOO:ImportError", kwlist,
if (!PyArg_ParseTupleAndKeywords(_Py_EMPTY_TUPLE, kwds,
"|$OOO:ImportError", kwlist,
&name, &path, &name_from)) {
Py_DECREF(empty_tuple);
return -1;
}
Py_DECREF(empty_tuple);

Py_XSETREF(self->name, Py_XNewRef(name));
Py_XSETREF(self->path, Py_XNewRef(path));
Expand Down Expand Up @@ -2240,16 +2235,11 @@ NameError_init(PyNameErrorObject *self, PyObject *args, PyObject *kwds)
return -1;
}

PyObject *empty_tuple = PyTuple_New(0);
if (!empty_tuple) {
return -1;
}
if (!PyArg_ParseTupleAndKeywords(empty_tuple, kwds, "|$O:NameError", kwlist,
if (!PyArg_ParseTupleAndKeywords(_Py_EMPTY_TUPLE, kwds,
"|$O:NameError", kwlist,
&name)) {
Py_DECREF(empty_tuple);
return -1;
}
Py_DECREF(empty_tuple);

Py_XSETREF(self->name, Py_XNewRef(name));

Expand Down Expand Up @@ -2314,16 +2304,11 @@ AttributeError_init(PyAttributeErrorObject *self, PyObject *args, PyObject *kwds
return -1;
}

PyObject *empty_tuple = PyTuple_New(0);
if (!empty_tuple) {
return -1;
}
if (!PyArg_ParseTupleAndKeywords(empty_tuple, kwds, "|$OO:AttributeError", kwlist,
if (!PyArg_ParseTupleAndKeywords(_Py_EMPTY_TUPLE, kwds,
"|$OO:AttributeError", kwlist,
&name, &obj)) {
Py_DECREF(empty_tuple);
return -1;
}
Py_DECREF(empty_tuple);

Py_XSETREF(self->name, Py_XNewRef(name));
Py_XSETREF(self->obj, Py_XNewRef(obj));
Expand Down
6 changes: 3 additions & 3 deletions Objects/tupleobject.c
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ tuple_alloc(Py_ssize_t size)
static inline PyObject *
tuple_get_empty(void)
{
return (PyObject *)&_Py_SINGLETON(tuple_empty);
return _Py_EMPTY_TUPLE;
}

PyObject *
Expand Down Expand Up @@ -185,7 +185,7 @@ tupledealloc(PyTupleObject *op)
{
if (Py_SIZE(op) == 0) {
/* The empty tuple is statically allocated. */
if (op == &_Py_SINGLETON(tuple_empty)) {
if (op == (PyTupleObject *)(_Py_EMPTY_TUPLE)) {
#ifdef Py_DEBUG
_Py_FatalRefcountError("deallocating the empty tuple singleton");
#else
Expand Down Expand Up @@ -942,7 +942,7 @@ _PyTuple_Resize(PyObject **pv, Py_ssize_t newsize)
}
if (oldsize == 0) {
#ifdef Py_DEBUG
assert(v == &_Py_SINGLETON(tuple_empty));
assert(v == (PyTupleObject *)(_Py_EMPTY_TUPLE));
#endif
/* The empty tuple is statically allocated so we never
resize it in-place. */
Expand Down
9 changes: 2 additions & 7 deletions Python/bltinmodule.c
Original file line number Diff line number Diff line change
Expand Up @@ -2886,14 +2886,9 @@ zip_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
int strict = 0;

if (kwds) {
PyObject *empty = PyTuple_New(0);
if (empty == NULL) {
return NULL;
}
static char *kwlist[] = {"strict", NULL};
int parsed = PyArg_ParseTupleAndKeywords(
empty, kwds, "|$p:zip", kwlist, &strict);
Py_DECREF(empty);
int parsed = PyArg_ParseTupleAndKeywords(_Py_EMPTY_TUPLE, kwds,
"|$p:zip", kwlist, &strict);
if (!parsed) {
return NULL;
}
Expand Down
2 changes: 1 addition & 1 deletion Python/ceval.c
Original file line number Diff line number Diff line change
Expand Up @@ -1469,7 +1469,7 @@ initialize_locals(PyThreadState *tstate, PyFunctionObject *func,
if (co->co_flags & CO_VARARGS) {
PyObject *u = NULL;
if (argcount == n) {
u = (PyObject *)&_Py_SINGLETON(tuple_empty);
u = _Py_EMPTY_TUPLE;
}
else {
u = _PyTuple_FromStackRefSteal(args + n, argcount - n);
Expand Down
6 changes: 3 additions & 3 deletions Python/specialize.c
Original file line number Diff line number Diff line change
Expand Up @@ -2739,11 +2739,11 @@ static const PyBytesObject no_location = {

const struct _PyCode8 _Py_InitCleanup = {
_PyVarObject_HEAD_INIT(&PyCode_Type, 3),
.co_consts = (PyObject *)&_Py_SINGLETON(tuple_empty),
.co_names = (PyObject *)&_Py_SINGLETON(tuple_empty),
.co_consts = _Py_EMPTY_TUPLE,
.co_names = _Py_EMPTY_TUPLE,
.co_exceptiontable = (PyObject *)&_Py_SINGLETON(bytes_empty),
.co_flags = CO_OPTIMIZED | CO_NO_MONITORING_EVENTS,
.co_localsplusnames = (PyObject *)&_Py_SINGLETON(tuple_empty),
.co_localsplusnames = _Py_EMPTY_TUPLE,
.co_localspluskinds = (PyObject *)&_Py_SINGLETON(bytes_empty),
.co_filename = &_Py_ID(__init__),
.co_name = &_Py_ID(__init__),
Expand Down
Loading