Skip to content

Commit aa300f2

Browse files
committed
pythongh-108308: Remove _PyDict_GetItemStringWithError() function
Remove the internal _PyDict_GetItemStringWithError() function. It can now be replaced with the new public PyDict_ContainsString() and PyDict_GetItemStringRef() functions. getargs.c now uses a strong reference for current_arg. find_keyword() returns a strong reference.
1 parent a35d48d commit aa300f2

File tree

5 files changed

+36
-44
lines changed

5 files changed

+36
-44
lines changed

Include/internal/pycore_dict.h

-1
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@ extern "C" {
1313

1414
// Unsafe flavor of PyDict_GetItemWithError(): no error checking
1515
extern PyObject* _PyDict_GetItemWithError(PyObject *dp, PyObject *key);
16-
extern PyObject* _PyDict_GetItemStringWithError(PyObject *, const char *);
1716

1817
extern int _PyDict_Contains_KnownHash(PyObject *, PyObject *, Py_hash_t);
1918

Objects/dictobject.c

-13
Original file line numberDiff line numberDiff line change
@@ -1829,19 +1829,6 @@ _PyDict_GetItemIdWithError(PyObject *dp, _Py_Identifier *key)
18291829
return _PyDict_GetItem_KnownHash(dp, kv, hash); // borrowed reference
18301830
}
18311831

1832-
PyObject *
1833-
_PyDict_GetItemStringWithError(PyObject *v, const char *key)
1834-
{
1835-
PyObject *kv, *rv;
1836-
kv = PyUnicode_FromString(key);
1837-
if (kv == NULL) {
1838-
return NULL;
1839-
}
1840-
rv = PyDict_GetItemWithError(v, kv);
1841-
Py_DECREF(kv);
1842-
return rv; // borrowed reference
1843-
}
1844-
18451832
/* Fast version of global value lookup (LOAD_GLOBAL).
18461833
* Lookup in globals, then builtins.
18471834
*

Python/getargs.c

+30-28
Original file line numberDiff line numberDiff line change
@@ -1491,7 +1491,6 @@ vgetargskeywords(PyObject *args, PyObject *kwargs, const char *format,
14911491
int i, pos, len;
14921492
int skip = 0;
14931493
Py_ssize_t nargs, nkwargs;
1494-
PyObject *current_arg;
14951494
freelistentry_t static_entries[STATIC_FREELIST_ENTRIES];
14961495
freelist_t freelist;
14971496

@@ -1621,17 +1620,17 @@ vgetargskeywords(PyObject *args, PyObject *kwargs, const char *format,
16211620
return cleanreturn(0, &freelist);
16221621
}
16231622
if (!skip) {
1623+
PyObject *current_arg;
16241624
if (i < nargs) {
1625-
current_arg = PyTuple_GET_ITEM(args, i);
1625+
current_arg = Py_NewRef(PyTuple_GET_ITEM(args, i));
16261626
}
16271627
else if (nkwargs && i >= pos) {
1628-
current_arg = _PyDict_GetItemStringWithError(kwargs, kwlist[i]);
1628+
if (PyDict_GetItemStringRef(kwargs, kwlist[i], &current_arg) < 0) {
1629+
return cleanreturn(0, &freelist);
1630+
}
16291631
if (current_arg) {
16301632
--nkwargs;
16311633
}
1632-
else if (PyErr_Occurred()) {
1633-
return cleanreturn(0, &freelist);
1634-
}
16351634
}
16361635
else {
16371636
current_arg = NULL;
@@ -1640,6 +1639,7 @@ vgetargskeywords(PyObject *args, PyObject *kwargs, const char *format,
16401639
if (current_arg) {
16411640
msg = convertitem(current_arg, &format, p_va, flags,
16421641
levels, msgbuf, sizeof(msgbuf), &freelist);
1642+
Py_DECREF(current_arg);
16431643
if (msg) {
16441644
seterror(i+1, msg, levels, fname, custom_msg);
16451645
return cleanreturn(0, &freelist);
@@ -1710,8 +1710,12 @@ vgetargskeywords(PyObject *args, PyObject *kwargs, const char *format,
17101710
Py_ssize_t j;
17111711
/* make sure there are no arguments given by name and position */
17121712
for (i = pos; i < nargs; i++) {
1713-
current_arg = _PyDict_GetItemStringWithError(kwargs, kwlist[i]);
1713+
PyObject *current_arg;
1714+
if (PyDict_GetItemStringRef(kwargs, kwlist[i], &current_arg) < 0) {
1715+
return cleanreturn(0, &freelist);
1716+
}
17141717
if (current_arg) {
1718+
Py_DECREF(current_arg);
17151719
/* arg present in tuple and in dict */
17161720
PyErr_Format(PyExc_TypeError,
17171721
"argument for %.200s%s given by name ('%s') "
@@ -1721,9 +1725,6 @@ vgetargskeywords(PyObject *args, PyObject *kwargs, const char *format,
17211725
kwlist[i], i+1);
17221726
return cleanreturn(0, &freelist);
17231727
}
1724-
else if (PyErr_Occurred()) {
1725-
return cleanreturn(0, &freelist);
1726-
}
17271728
}
17281729
/* make sure there are no extraneous keyword arguments */
17291730
j = 0;
@@ -1985,15 +1986,15 @@ find_keyword(PyObject *kwnames, PyObject *const *kwstack, PyObject *key)
19851986
/* kwname == key will normally find a match in since keyword keys
19861987
should be interned strings; if not retry below in a new loop. */
19871988
if (kwname == key) {
1988-
return kwstack[i];
1989+
return Py_NewRef(kwstack[i]);
19891990
}
19901991
}
19911992

19921993
for (i = 0; i < nkwargs; i++) {
19931994
PyObject *kwname = PyTuple_GET_ITEM(kwnames, i);
19941995
assert(PyUnicode_Check(kwname));
19951996
if (_PyUnicode_EQ(kwname, key)) {
1996-
return kwstack[i];
1997+
return Py_NewRef(kwstack[i]);
19971998
}
19981999
}
19992000
return NULL;
@@ -2013,7 +2014,6 @@ vgetargskeywordsfast_impl(PyObject *const *args, Py_ssize_t nargs,
20132014
PyObject *keyword;
20142015
int i, pos, len;
20152016
Py_ssize_t nkwargs;
2016-
PyObject *current_arg;
20172017
freelistentry_t static_entries[STATIC_FREELIST_ENTRIES];
20182018
freelist_t freelist;
20192019
PyObject *const *kwstack = NULL;
@@ -2108,14 +2108,14 @@ vgetargskeywordsfast_impl(PyObject *const *args, Py_ssize_t nargs,
21082108
}
21092109
assert(!IS_END_OF_FORMAT(*format));
21102110

2111+
PyObject *current_arg;
21112112
if (i < nargs) {
2112-
current_arg = args[i];
2113+
current_arg = Py_NewRef(args[i]);
21132114
}
21142115
else if (nkwargs && i >= pos) {
21152116
keyword = PyTuple_GET_ITEM(kwtuple, i - pos);
21162117
if (kwargs != NULL) {
2117-
current_arg = PyDict_GetItemWithError(kwargs, keyword);
2118-
if (!current_arg && PyErr_Occurred()) {
2118+
if (PyDict_GetItemRef(kwargs, keyword, &current_arg) < 0) {
21192119
return cleanreturn(0, &freelist);
21202120
}
21212121
}
@@ -2133,6 +2133,7 @@ vgetargskeywordsfast_impl(PyObject *const *args, Py_ssize_t nargs,
21332133
if (current_arg) {
21342134
msg = convertitem(current_arg, &format, p_va, flags,
21352135
levels, msgbuf, sizeof(msgbuf), &freelist);
2136+
Py_DECREF(current_arg);
21362137
if (msg) {
21372138
seterror(i+1, msg, levels, parser->fname, parser->custom_msg);
21382139
return cleanreturn(0, &freelist);
@@ -2183,17 +2184,18 @@ vgetargskeywordsfast_impl(PyObject *const *args, Py_ssize_t nargs,
21832184
if (nkwargs > 0) {
21842185
/* make sure there are no arguments given by name and position */
21852186
for (i = pos; i < nargs; i++) {
2187+
PyObject *current_arg;
21862188
keyword = PyTuple_GET_ITEM(kwtuple, i - pos);
21872189
if (kwargs != NULL) {
2188-
current_arg = PyDict_GetItemWithError(kwargs, keyword);
2189-
if (!current_arg && PyErr_Occurred()) {
2190+
if (PyDict_GetItemRef(kwargs, keyword, &current_arg) < 0) {
21902191
return cleanreturn(0, &freelist);
21912192
}
21922193
}
21932194
else {
21942195
current_arg = find_keyword(kwnames, kwstack, keyword);
21952196
}
21962197
if (current_arg) {
2198+
Py_DECREF(current_arg);
21972199
/* arg present in tuple and in dict */
21982200
PyErr_Format(PyExc_TypeError,
21992201
"argument for %.200s%s given by name ('%U') "
@@ -2248,7 +2250,6 @@ _PyArg_UnpackKeywords(PyObject *const *args, Py_ssize_t nargs,
22482250
int i, posonly, minposonly, maxargs;
22492251
int reqlimit = minkw ? maxpos + minkw : minpos;
22502252
Py_ssize_t nkwargs;
2251-
PyObject *current_arg;
22522253
PyObject * const *kwstack = NULL;
22532254

22542255
assert(kwargs == NULL || PyDict_Check(kwargs));
@@ -2343,11 +2344,11 @@ _PyArg_UnpackKeywords(PyObject *const *args, Py_ssize_t nargs,
23432344

23442345
/* copy keyword args using kwtuple to drive process */
23452346
for (i = Py_MAX((int)nargs, posonly); i < maxargs; i++) {
2347+
PyObject *current_arg;
23462348
if (nkwargs) {
23472349
keyword = PyTuple_GET_ITEM(kwtuple, i - posonly);
23482350
if (kwargs != NULL) {
2349-
current_arg = PyDict_GetItemWithError(kwargs, keyword);
2350-
if (!current_arg && PyErr_Occurred()) {
2351+
if (PyDict_GetItemRef(kwargs, keyword, &current_arg) < 0) {
23512352
return NULL;
23522353
}
23532354
}
@@ -2365,6 +2366,7 @@ _PyArg_UnpackKeywords(PyObject *const *args, Py_ssize_t nargs,
23652366
buf[i] = current_arg;
23662367

23672368
if (current_arg) {
2369+
Py_DECREF(current_arg);
23682370
--nkwargs;
23692371
}
23702372
else if (i < minpos || (maxpos <= i && i < reqlimit)) {
@@ -2382,17 +2384,18 @@ _PyArg_UnpackKeywords(PyObject *const *args, Py_ssize_t nargs,
23822384
if (nkwargs > 0) {
23832385
/* make sure there are no arguments given by name and position */
23842386
for (i = posonly; i < nargs; i++) {
2387+
PyObject *current_arg;
23852388
keyword = PyTuple_GET_ITEM(kwtuple, i - posonly);
23862389
if (kwargs != NULL) {
2387-
current_arg = PyDict_GetItemWithError(kwargs, keyword);
2388-
if (!current_arg && PyErr_Occurred()) {
2390+
if (PyDict_GetItemRef(kwargs, keyword, &current_arg) < 0) {
23892391
return NULL;
23902392
}
23912393
}
23922394
else {
23932395
current_arg = find_keyword(kwnames, kwstack, keyword);
23942396
}
23952397
if (current_arg) {
2398+
Py_DECREF(current_arg);
23962399
/* arg present in tuple and in dict */
23972400
PyErr_Format(PyExc_TypeError,
23982401
"argument for %.200s%s given by name ('%U') "
@@ -2424,7 +2427,6 @@ _PyArg_UnpackKeywordsWithVararg(PyObject *const *args, Py_ssize_t nargs,
24242427
int i, posonly, minposonly, maxargs;
24252428
int reqlimit = minkw ? maxpos + minkw : minpos;
24262429
Py_ssize_t nkwargs;
2427-
PyObject *current_arg;
24282430
PyObject * const *kwstack = NULL;
24292431

24302432
assert(kwargs == NULL || PyDict_Check(kwargs));
@@ -2497,13 +2499,12 @@ _PyArg_UnpackKeywordsWithVararg(PyObject *const *args, Py_ssize_t nargs,
24972499
}
24982500

24992501
/* copy keyword args using kwtuple to drive process */
2500-
for (i = Py_MAX((int)nargs, posonly) -
2501-
Py_SAFE_DOWNCAST(varargssize, Py_ssize_t, int); i < maxargs; i++) {
2502+
for (i = Py_MAX((int)nargs, posonly) - Py_SAFE_DOWNCAST(varargssize, Py_ssize_t, int); i < maxargs; i++) {
2503+
PyObject *current_arg;
25022504
if (nkwargs) {
25032505
keyword = PyTuple_GET_ITEM(kwtuple, i - posonly);
25042506
if (kwargs != NULL) {
2505-
current_arg = PyDict_GetItemWithError(kwargs, keyword);
2506-
if (!current_arg && PyErr_Occurred()) {
2507+
if (PyDict_GetItemRef(kwargs, keyword, &current_arg) < 0) {
25072508
goto exit;
25082509
}
25092510
}
@@ -2536,6 +2537,7 @@ _PyArg_UnpackKeywordsWithVararg(PyObject *const *args, Py_ssize_t nargs,
25362537
}
25372538

25382539
if (current_arg) {
2540+
Py_DECREF(current_arg);
25392541
--nkwargs;
25402542
}
25412543
else if (i < minpos || (maxpos <= i && i < reqlimit)) {

Python/pythonrun.c

-1
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@
1515
#include "pycore_ast.h" // PyAST_mod2obj
1616
#include "pycore_ceval.h" // _Py_EnterRecursiveCall
1717
#include "pycore_compile.h" // _PyAST_Compile()
18-
#include "pycore_dict.h" // _PyDict_GetItemStringWithError()
1918
#include "pycore_interp.h" // PyInterpreterState.importlib
2019
#include "pycore_object.h" // _PyDebug_PrintTotalRefs()
2120
#include "pycore_parser.h" // _PyParser_ASTFromString()

Python/sysmodule.c

+6-1
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,12 @@ _PySys_GetObject(PyInterpreterState *interp, const char *name)
8787
if (sysdict == NULL) {
8888
return NULL;
8989
}
90-
return _PyDict_GetItemStringWithError(sysdict, name);
90+
PyObject *value;
91+
if (PyDict_GetItemStringRef(sysdict, name, &value) != 1) {
92+
return NULL;
93+
}
94+
Py_DECREF(value); // return a borrowed reference
95+
return value;
9196
}
9297

9398
PyObject *

0 commit comments

Comments
 (0)