diff --git a/Include/internal/pycore_global_strings.h b/Include/internal/pycore_global_strings.h index 10773d7a6c7e3f..ce3fdbee9d4dbb 100644 --- a/Include/internal/pycore_global_strings.h +++ b/Include/internal/pycore_global_strings.h @@ -797,11 +797,15 @@ struct _Py_global_strings { ? (PyObject*)&_Py_SINGLETON(strings).ascii[(CH)] \ : (PyObject*)&_Py_SINGLETON(strings).latin1[(CH) - 128]) +#define _Py_EMPTY_STRING ((PyObject *)(&_Py_STR(empty))) + +#define _Py_EMPTY_BYTES ((PyObject *)&_Py_SINGLETON(bytes_empty)) + /* _Py_DECLARE_STR() should precede all uses of _Py_STR() in a function. This is true even if the same string has already been declared elsewhere, even in the same file. Mismatched duplicates are detected - by Tools/scripts/generate-global-objects.py. + by Tools/build/generate_global_objects.py. Pairing _Py_DECLARE_STR() with every use of _Py_STR() makes sure the string keeps working even if the declaration is removed somewhere diff --git a/Include/internal/pycore_parser.h b/Include/internal/pycore_parser.h index b16084aaa15515..3104944559580c 100644 --- a/Include/internal/pycore_parser.h +++ b/Include/internal/pycore_parser.h @@ -30,14 +30,13 @@ struct _parser_runtime_state { struct _expr dummy_name; }; -_Py_DECLARE_STR(empty, "") #if defined(Py_DEBUG) && defined(Py_GIL_DISABLED) #define _parser_runtime_state_INIT \ { \ .mutex = {0}, \ .dummy_name = { \ .kind = Name_kind, \ - .v.Name.id = &_Py_STR(empty), \ + .v.Name.id = _Py_EMPTY_STRING, \ .v.Name.ctx = Load, \ .lineno = 1, \ .col_offset = 0, \ @@ -50,7 +49,7 @@ _Py_DECLARE_STR(empty, "") { \ .dummy_name = { \ .kind = Name_kind, \ - .v.Name.id = &_Py_STR(empty), \ + .v.Name.id = _Py_EMPTY_STRING, \ .v.Name.ctx = Load, \ .lineno = 1, \ .col_offset = 0, \ diff --git a/InternalDocs/string_interning.md b/InternalDocs/string_interning.md index 358e2c070cd5fa..75a56ac18fe4b1 100644 --- a/InternalDocs/string_interning.md +++ b/InternalDocs/string_interning.md @@ -26,7 +26,7 @@ They are collected from CPython sources using `make regen-global-objects` (`Tools/build/generate_global_objects.py`), which generates code for declaration, initialization and finalization. -The empty string is one of the singletons: `_Py_STR(empty)`. +The empty string is one of the singletons: `_Py_EMPTY_STRING`. The three sets of singletons (`_Py_LATIN1_CHR`, `_Py_ID`, `_Py_STR`) are disjoint. diff --git a/Modules/_io/bufferedio.c b/Modules/_io/bufferedio.c index bc5fff54a62b6d..9c9f3359cf964b 100644 --- a/Modules/_io/bufferedio.c +++ b/Modules/_io/bufferedio.c @@ -1283,7 +1283,7 @@ _buffered_readline(buffered *self, Py_ssize_t limit) Py_CLEAR(res); goto end; } - Py_XSETREF(res, PyBytes_Join((PyObject *)&_Py_SINGLETON(bytes_empty), chunks)); + Py_XSETREF(res, PyBytes_Join(_Py_EMPTY_BYTES, chunks)); end: LEAVE_BUFFERED(self) @@ -1736,7 +1736,7 @@ _bufferedreader_read_all(buffered *self) goto cleanup; } else { - tmp = PyBytes_Join((PyObject *)&_Py_SINGLETON(bytes_empty), chunks); + tmp = PyBytes_Join(_Py_EMPTY_BYTES, chunks); res = tmp; goto cleanup; } diff --git a/Modules/_io/iobase.c b/Modules/_io/iobase.c index 419e5516b5c11e..78a3bb13ab43e1 100644 --- a/Modules/_io/iobase.c +++ b/Modules/_io/iobase.c @@ -999,7 +999,7 @@ _io__RawIOBase_readall_impl(PyObject *self) return NULL; } } - result = PyBytes_Join((PyObject *)&_Py_SINGLETON(bytes_empty), chunks); + result = PyBytes_Join(_Py_EMPTY_BYTES, chunks); Py_DECREF(chunks); return result; } diff --git a/Modules/_io/textio.c b/Modules/_io/textio.c index 439e26c5271939..73a67d0b8250e2 100644 --- a/Modules/_io/textio.c +++ b/Modules/_io/textio.c @@ -2059,8 +2059,7 @@ _io_TextIOWrapper_read_impl(textio *self, Py_ssize_t n) if (chunks != NULL) { if (result != NULL && PyList_Append(chunks, result) < 0) goto fail; - _Py_DECLARE_STR(empty, ""); - Py_XSETREF(result, PyUnicode_Join(&_Py_STR(empty), chunks)); + Py_XSETREF(result, PyUnicode_Join(_Py_EMPTY_STRING, chunks)); if (result == NULL) goto fail; Py_CLEAR(chunks); @@ -2322,13 +2321,13 @@ _textiowrapper_readline(textio *self, Py_ssize_t limit) goto error; Py_DECREF(line); } - line = PyUnicode_Join(&_Py_STR(empty), chunks); + line = PyUnicode_Join(_Py_EMPTY_STRING, chunks); if (line == NULL) goto error; Py_CLEAR(chunks); } if (line == NULL) { - line = &_Py_STR(empty); + line = _Py_EMPTY_STRING; } return line; diff --git a/Modules/_sre/sre.c b/Modules/_sre/sre.c index 2c86f8869d8e58..e7f79e16a28458 100644 --- a/Modules/_sre/sre.c +++ b/Modules/_sre/sre.c @@ -2914,11 +2914,11 @@ expand_template(TemplateObject *self, MatchObject *match) } if (PyUnicode_Check(self->literal)) { - result = _PyUnicode_JoinArray(&_Py_STR(empty), out, count); + result = _PyUnicode_JoinArray(_Py_EMPTY_STRING, out, count); } else { Py_SET_SIZE(list, count); - result = PyBytes_Join((PyObject *)&_Py_SINGLETON(bytes_empty), list); + result = PyBytes_Join(_Py_EMPTY_BYTES, list); } cleanup: diff --git a/Objects/bytesobject.c b/Objects/bytesobject.c index ba6636808d90e0..37a22064a38aa3 100644 --- a/Objects/bytesobject.c +++ b/Objects/bytesobject.c @@ -39,7 +39,7 @@ Py_LOCAL_INLINE(Py_ssize_t) _PyBytesWriter_GetSize(_PyBytesWriter *writer, #define CHARACTERS _Py_SINGLETON(bytes_characters) #define CHARACTER(ch) \ ((PyBytesObject *)&(CHARACTERS[ch])); -#define EMPTY (&_Py_SINGLETON(bytes_empty)) +#define EMPTY ((PyBytesObject *)_Py_EMPTY_BYTES) // Return a reference to the immortal empty bytes string singleton. diff --git a/Objects/codeobject.c b/Objects/codeobject.c index 6f0b3f8b9a3262..6b84563d75ca4f 100644 --- a/Objects/codeobject.c +++ b/Objects/codeobject.c @@ -907,7 +907,6 @@ PyCode_NewEmpty(const char *filename, const char *funcname, int firstlineno) goto failed; } -#define emptystring (PyObject *)&_Py_SINGLETON(bytes_empty) struct _PyCodeConstructor con = { .filename = filename_ob, .name = funcname_ob, @@ -918,8 +917,8 @@ PyCode_NewEmpty(const char *filename, const char *funcname, int firstlineno) .consts = nulltuple, .names = nulltuple, .localsplusnames = nulltuple, - .localspluskinds = emptystring, - .exceptiontable = emptystring, + .localspluskinds = _Py_EMPTY_BYTES, + .exceptiontable = _Py_EMPTY_BYTES, .stacksize = 1, }; result = _PyCode_New(&con); diff --git a/Objects/funcobject.c b/Objects/funcobject.c index 8df0da800980a9..1f6d07723ef9aa 100644 --- a/Objects/funcobject.c +++ b/Objects/funcobject.c @@ -2,11 +2,12 @@ /* Function object implementation */ #include "Python.h" -#include "pycore_ceval.h" // _PyEval_BuiltinsFromGlobals() -#include "pycore_long.h" // _PyLong_GetOne() -#include "pycore_modsupport.h" // _PyArg_NoKeywords() -#include "pycore_object.h" // _PyObject_GC_UNTRACK() -#include "pycore_pyerrors.h" // _PyErr_Occurred() +#include "pycore_ceval.h" // _PyEval_BuiltinsFromGlobals() +#include "pycore_global_strings.h" // _Py_EMPTY_STRING +#include "pycore_long.h" // _PyLong_GetOne() +#include "pycore_modsupport.h" // _PyArg_NoKeywords() +#include "pycore_object.h" // _PyObject_GC_UNTRACK() +#include "pycore_pyerrors.h" // _PyErr_Occurred() static const char * @@ -1036,8 +1037,8 @@ func_clear(PyFunctionObject *op) // However, name and qualname could be str subclasses, so they // could have reference cycles. The solution is to replace them // with a genuinely immutable string. - Py_SETREF(op->func_name, &_Py_STR(empty)); - Py_SETREF(op->func_qualname, &_Py_STR(empty)); + Py_SETREF(op->func_name, _Py_EMPTY_STRING); + Py_SETREF(op->func_qualname, _Py_EMPTY_STRING); return 0; } diff --git a/Objects/unicodeobject.c b/Objects/unicodeobject.c index fc1fb78b7cab95..d0c7cb49aa5ea7 100644 --- a/Objects/unicodeobject.c +++ b/Objects/unicodeobject.c @@ -214,7 +214,7 @@ static int unicode_is_singleton(PyObject *unicode); static inline PyObject* unicode_get_empty(void) { _Py_DECLARE_STR(empty, ""); - return &_Py_STR(empty); + return _Py_EMPTY_STRING; } /* This dictionary holds per-interpreter interned strings. @@ -340,7 +340,7 @@ init_global_interned_strings(PyInterpreterState *interp) assert(s == LATIN1(i)); } #ifdef Py_DEBUG - assert(_PyUnicode_CheckConsistency(&_Py_STR(empty), 1)); + assert(_PyUnicode_CheckConsistency(_Py_EMPTY_STRING, 1)); for (int i = 0; i < 256; i++) { assert(_PyUnicode_CheckConsistency(LATIN1(i), 1)); @@ -1720,7 +1720,7 @@ unicode_dealloc(PyObject *unicode) static int unicode_is_singleton(PyObject *unicode) { - if (unicode == &_Py_STR(empty)) { + if (unicode == _Py_EMPTY_STRING) { return 1; } diff --git a/Python/bytecodes.c b/Python/bytecodes.c index c4cc8127bafbb4..f288e43977558a 100644 --- a/Python/bytecodes.c +++ b/Python/bytecodes.c @@ -402,7 +402,7 @@ dummy_func( PyObject *value_o = PyStackRef_AsPyObjectBorrow(value); EXIT_IF(!PyUnicode_CheckExact(value_o)); STAT_INC(TO_BOOL, hit); - if (value_o == &_Py_STR(empty)) { + if (value_o == _Py_EMPTY_STRING) { assert(_Py_IsImmortalLoose(value_o)); res = PyStackRef_False; } @@ -1682,7 +1682,7 @@ dummy_func( DECREF_INPUTS(); ERROR_IF(true, error); } - PyObject *str_o = _PyUnicode_JoinArray(&_Py_STR(empty), pieces_o, oparg); + PyObject *str_o = _PyUnicode_JoinArray(_Py_EMPTY_STRING, pieces_o, oparg); STACKREFS_TO_PYOBJECTS_CLEANUP(pieces_o); DECREF_INPUTS(); ERROR_IF(str_o == NULL, error); diff --git a/Python/compile.c b/Python/compile.c index 5c28f0cb200a91..d949ab20caff9b 100644 --- a/Python/compile.c +++ b/Python/compile.c @@ -3040,8 +3040,7 @@ codegen_from_import(struct compiler *c, stmt_ty s) ADDOP_NAME(c, LOC(s), IMPORT_NAME, s->v.ImportFrom.module, names); } else { - _Py_DECLARE_STR(empty, ""); - ADDOP_NAME(c, LOC(s), IMPORT_NAME, &_Py_STR(empty), names); + ADDOP_NAME(c, LOC(s), IMPORT_NAME, _Py_EMPTY_STRING, names); } for (Py_ssize_t i = 0; i < n; i++) { alias_ty alias = (alias_ty)asdl_seq_GET(s->v.ImportFrom.names, i); @@ -4115,8 +4114,7 @@ codegen_joined_str(struct compiler *c, expr_ty e) location loc = LOC(e); Py_ssize_t value_count = asdl_seq_LEN(e->v.JoinedStr.values); if (value_count > STACK_USE_GUIDELINE) { - _Py_DECLARE_STR(empty, ""); - ADDOP_LOAD_CONST_NEW(c, loc, Py_NewRef(&_Py_STR(empty))); + ADDOP_LOAD_CONST_NEW(c, loc, _Py_EMPTY_STRING); ADDOP_NAME(c, loc, LOAD_METHOD, &_Py_ID(join), names); ADDOP_I(c, loc, BUILD_LIST, 0); for (Py_ssize_t i = 0; i < asdl_seq_LEN(e->v.JoinedStr.values); i++) { @@ -4131,8 +4129,7 @@ codegen_joined_str(struct compiler *c, expr_ty e) ADDOP_I(c, loc, BUILD_STRING, value_count); } else if (value_count == 0) { - _Py_DECLARE_STR(empty, ""); - ADDOP_LOAD_CONST_NEW(c, loc, Py_NewRef(&_Py_STR(empty))); + ADDOP_LOAD_CONST_NEW(c, loc, _Py_EMPTY_STRING); } } return SUCCESS; diff --git a/Python/crossinterp.c b/Python/crossinterp.c index 0aca322d987dba..2a8aa57fdb7cc8 100644 --- a/Python/crossinterp.c +++ b/Python/crossinterp.c @@ -418,7 +418,7 @@ _convert_exc_to_TracebackException(PyObject *exc, PyObject **p_tbexc) // We accommodate backports here. #ifndef _Py_EMPTY_STR -# define _Py_EMPTY_STR &_Py_STR(empty) +# define _Py_EMPTY_STR _Py_EMPTY_STRING #endif static const char * diff --git a/Python/executor_cases.c.h b/Python/executor_cases.c.h index d4be7904a50c10..bd9e7502c371b3 100644 --- a/Python/executor_cases.c.h +++ b/Python/executor_cases.c.h @@ -442,7 +442,7 @@ JUMP_TO_JUMP_TARGET(); } STAT_INC(TO_BOOL, hit); - if (value_o == &_Py_STR(empty)) { + if (value_o == _Py_EMPTY_STRING) { assert(_Py_IsImmortalLoose(value_o)); res = PyStackRef_False; } @@ -1876,7 +1876,7 @@ } if (true) JUMP_TO_ERROR(); } - PyObject *str_o = _PyUnicode_JoinArray(&_Py_STR(empty), pieces_o, oparg); + PyObject *str_o = _PyUnicode_JoinArray(_Py_EMPTY_STRING, pieces_o, oparg); STACKREFS_TO_PYOBJECTS_CLEANUP(pieces_o); for (int _i = oparg; --_i >= 0;) { PyStackRef_CLOSE(pieces[_i]); diff --git a/Python/generated_cases.c.h b/Python/generated_cases.c.h index 65dfb990cc2820..91d79a9e755667 100644 --- a/Python/generated_cases.c.h +++ b/Python/generated_cases.c.h @@ -780,7 +780,7 @@ goto error; } } - PyObject *str_o = _PyUnicode_JoinArray(&_Py_STR(empty), pieces_o, oparg); + PyObject *str_o = _PyUnicode_JoinArray(_Py_EMPTY_STRING, pieces_o, oparg); STACKREFS_TO_PYOBJECTS_CLEANUP(pieces_o); for (int _i = oparg; --_i >= 0;) { PyStackRef_CLOSE(pieces[_i]); @@ -7391,7 +7391,7 @@ PyObject *value_o = PyStackRef_AsPyObjectBorrow(value); DEOPT_IF(!PyUnicode_CheckExact(value_o), TO_BOOL); STAT_INC(TO_BOOL, hit); - if (value_o == &_Py_STR(empty)) { + if (value_o == _Py_EMPTY_STRING) { assert(_Py_IsImmortalLoose(value_o)); res = PyStackRef_False; } diff --git a/Python/optimizer_symbols.c b/Python/optimizer_symbols.c index 40cbf95e3d6d39..f8d549c2f469e2 100644 --- a/Python/optimizer_symbols.c +++ b/Python/optimizer_symbols.c @@ -324,7 +324,7 @@ _Py_uop_sym_truthiness(_Py_UopsSymbol *sym) return !_PyLong_IsZero((PyLongObject *)value); } if (tp == &PyUnicode_Type) { - return value != &_Py_STR(empty); + return value != _Py_EMPTY_STRING; } if (tp == &PyBool_Type) { return value == Py_True; diff --git a/Python/specialize.c b/Python/specialize.c index da618952e85978..ae15835ffc5902 100644 --- a/Python/specialize.c +++ b/Python/specialize.c @@ -2741,10 +2741,10 @@ 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_exceptiontable = (PyObject *)&_Py_SINGLETON(bytes_empty), + .co_exceptiontable = _Py_EMPTY_BYTES, .co_flags = CO_OPTIMIZED | CO_NO_MONITORING_EVENTS, .co_localsplusnames = (PyObject *)&_Py_SINGLETON(tuple_empty), - .co_localspluskinds = (PyObject *)&_Py_SINGLETON(bytes_empty), + .co_localspluskinds = _Py_EMPTY_BYTES, .co_filename = &_Py_ID(__init__), .co_name = &_Py_ID(__init__), .co_qualname = &_Py_ID(__init__),