Skip to content

Commit d27df40

Browse files
committed
Use PyTupleWriter in multiple functions
1 parent 8e7025f commit d27df40

3 files changed

Lines changed: 99 additions & 150 deletions

File tree

Modules/_tkinter.c

Lines changed: 22 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -3080,60 +3080,33 @@ Tkapp_Dealloc(PyObject *op)
30803080

30813081
/**** Tkinter Module ****/
30823082

3083-
typedef struct {
3084-
PyObject* tuple;
3085-
Py_ssize_t size; /* current size */
3086-
Py_ssize_t maxsize; /* allocated size */
3087-
} FlattenContext;
3088-
30893083
static int
3090-
_bump(FlattenContext* context, Py_ssize_t size)
3091-
{
3092-
/* expand tuple to hold (at least) size new items.
3093-
return true if successful, false if an exception was raised */
3094-
3095-
Py_ssize_t maxsize = context->maxsize * 2; /* never overflows */
3096-
3097-
if (maxsize < context->size + size)
3098-
maxsize = context->size + size; /* never overflows */
3099-
3100-
context->maxsize = maxsize;
3101-
3102-
return _PyTuple_Resize(&context->tuple, maxsize) >= 0;
3103-
}
3104-
3105-
static int
3106-
_flatten1(FlattenContext* context, PyObject* item, int depth)
3084+
_flatten1(PyTupleWriter *writer, PyObject *item, int depth)
31073085
{
31083086
/* add tuple or list to argument tuple (recursively) */
31093087

3110-
Py_ssize_t i, size;
3111-
31123088
if (depth > 1000) {
31133089
PyErr_SetString(PyExc_ValueError,
31143090
"nesting too deep in _flatten");
31153091
return 0;
3116-
} else if (PyTuple_Check(item) || PyList_Check(item)) {
3117-
size = PySequence_Fast_GET_SIZE(item);
3118-
/* preallocate (assume no nesting) */
3119-
if (context->size + size > context->maxsize &&
3120-
!_bump(context, size))
3121-
return 0;
3092+
}
3093+
3094+
if (PyTuple_Check(item) || PyList_Check(item)) {
3095+
Py_ssize_t size = PySequence_Fast_GET_SIZE(item);
31223096
/* copy items to output tuple */
3123-
for (i = 0; i < size; i++) {
3097+
for (Py_ssize_t i = 0; i < size; i++) {
31243098
PyObject *o = PySequence_Fast_GET_ITEM(item, i);
31253099
if (PyList_Check(o) || PyTuple_Check(o)) {
3126-
if (!_flatten1(context, o, depth + 1))
3100+
if (!_flatten1(writer, o, depth + 1))
31273101
return 0;
31283102
} else if (o != Py_None) {
3129-
if (context->size + 1 > context->maxsize &&
3130-
!_bump(context, 1))
3103+
if (PyTupleWriter_Add(writer, o) < 0) {
31313104
return 0;
3132-
PyTuple_SET_ITEM(context->tuple,
3133-
context->size++, Py_NewRef(o));
3105+
}
31343106
}
31353107
}
3136-
} else {
3108+
}
3109+
else {
31373110
PyErr_SetString(PyExc_TypeError, "argument must be sequence");
31383111
return 0;
31393112
}
@@ -3152,29 +3125,25 @@ static PyObject *
31523125
_tkinter__flatten(PyObject *module, PyObject *item)
31533126
/*[clinic end generated code: output=cad02a3f97f29862 input=6b9c12260aa1157f]*/
31543127
{
3155-
FlattenContext context;
3156-
3157-
context.maxsize = PySequence_Size(item);
3158-
if (context.maxsize < 0)
3128+
Py_ssize_t maxsize = PySequence_Size(item);
3129+
if (maxsize < 0) {
31593130
return NULL;
3160-
if (context.maxsize == 0)
3131+
}
3132+
if (maxsize == 0) {
31613133
return PyTuple_New(0);
3134+
}
31623135

3163-
context.tuple = PyTuple_New(context.maxsize);
3164-
if (!context.tuple)
3165-
return NULL;
3166-
3167-
context.size = 0;
3168-
3169-
if (!_flatten1(&context, item, 0)) {
3170-
Py_XDECREF(context.tuple);
3136+
PyTupleWriter *writer = PyTupleWriter_Create(maxsize);
3137+
if (writer == NULL) {
31713138
return NULL;
31723139
}
31733140

3174-
if (_PyTuple_Resize(&context.tuple, context.size))
3141+
if (!_flatten1(writer, item, 0)) {
3142+
PyTupleWriter_Discard(writer);
31753143
return NULL;
3144+
}
31763145

3177-
return context.tuple;
3146+
return PyTupleWriter_Finish(writer);
31783147
}
31793148

31803149
/*[clinic input]

Objects/genericaliasobject.c

Lines changed: 64 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
#include "pycore_ceval.h" // _PyEval_GetBuiltin()
55
#include "pycore_modsupport.h" // _PyArg_NoKeywords()
66
#include "pycore_object.h"
7+
#include "pycore_tuple.h" // _PyTuple_ITEMS()
78
#include "pycore_typevarobject.h" // _Py_typing_type_repr
89
#include "pycore_unicodeobject.h" // _PyUnicode_EqualToASCIIString()
910
#include "pycore_unionobject.h" // _Py_union_type_or, _PyGenericAlias_Check
@@ -161,22 +162,6 @@ tuple_add(PyObject *self, Py_ssize_t len, PyObject *item)
161162
return 0;
162163
}
163164

164-
static Py_ssize_t
165-
tuple_extend(PyObject **dst, Py_ssize_t dstindex,
166-
PyObject **src, Py_ssize_t count)
167-
{
168-
assert(count >= 0);
169-
if (_PyTuple_Resize(dst, PyTuple_GET_SIZE(*dst) + count - 1) != 0) {
170-
return -1;
171-
}
172-
assert(dstindex + count <= PyTuple_GET_SIZE(*dst));
173-
for (Py_ssize_t i = 0; i < count; ++i) {
174-
PyObject *item = src[i];
175-
PyTuple_SET_ITEM(*dst, dstindex + i, Py_NewRef(item));
176-
}
177-
return dstindex + count;
178-
}
179-
180165
PyObject *
181166
_Py_make_parameters(PyObject *args)
182167
{
@@ -274,43 +259,54 @@ subs_tvars(PyObject *obj, PyObject *params,
274259
if (PyObject_GetOptionalAttr(obj, &_Py_ID(__parameters__), &subparams) < 0) {
275260
return NULL;
276261
}
262+
277263
if (subparams && PyTuple_Check(subparams) && PyTuple_GET_SIZE(subparams)) {
278264
Py_ssize_t nparams = PyTuple_GET_SIZE(params);
279265
Py_ssize_t nsubargs = PyTuple_GET_SIZE(subparams);
280-
PyObject *subargs = PyTuple_New(nsubargs);
281-
if (subargs == NULL) {
282-
Py_DECREF(subparams);
283-
return NULL;
266+
PyTupleWriter *writer = PyTupleWriter_Create(nsubargs);
267+
if (writer == NULL) {
268+
goto error;
284269
}
285-
Py_ssize_t j = 0;
286270
for (Py_ssize_t i = 0; i < nsubargs; ++i) {
287271
PyObject *arg = PyTuple_GET_ITEM(subparams, i);
288272
Py_ssize_t iparam = tuple_index(params, nparams, arg);
289273
if (iparam >= 0) {
290274
PyObject *param = PyTuple_GET_ITEM(params, iparam);
291275
arg = argitems[iparam];
292276
if (Py_TYPE(param)->tp_iter && PyTuple_Check(arg)) { // TypeVarTuple
293-
j = tuple_extend(&subargs, j,
294-
&PyTuple_GET_ITEM(arg, 0),
295-
PyTuple_GET_SIZE(arg));
296-
if (j < 0) {
297-
return NULL;
277+
if (PyTupleWriter_AddArray(writer,
278+
_PyTuple_ITEMS(arg),
279+
PyTuple_GET_SIZE(arg)) < 0) {
280+
goto error;
298281
}
299282
continue;
300283
}
301284
}
302-
PyTuple_SET_ITEM(subargs, j, Py_NewRef(arg));
303-
j++;
285+
if (PyTupleWriter_Add(writer, arg) < 0) {
286+
goto error;
287+
}
304288
}
305-
assert(j == PyTuple_GET_SIZE(subargs));
306289

307-
obj = PyObject_GetItem(obj, subargs);
290+
PyObject *subargs = PyTupleWriter_Finish(writer);
291+
if (subargs != NULL) {
292+
obj = PyObject_GetItem(obj, subargs);
293+
Py_DECREF(subargs);
294+
}
295+
else {
296+
obj = NULL;
297+
}
298+
goto done;
308299

309-
Py_DECREF(subargs);
300+
error:
301+
PyTupleWriter_Discard(writer);
302+
Py_DECREF(subparams);
303+
return NULL;
310304
}
311305
else {
312306
Py_INCREF(obj);
313307
}
308+
309+
done:
314310
Py_XDECREF(subparams);
315311
return obj;
316312
}
@@ -454,60 +450,50 @@ _Py_subs_parameters(PyObject *self, PyObject *args, PyObject *parameters, PyObje
454450
}
455451
}
456452
Py_ssize_t nargs = PyTuple_GET_SIZE(args);
457-
PyObject *newargs = PyTuple_New(nargs);
453+
PyTupleWriter *newargs = PyTupleWriter_Create(nargs);
458454
if (newargs == NULL) {
459-
Py_DECREF(item);
460-
Py_XDECREF(tuple_args);
461-
return NULL;
455+
goto error;
462456
}
463-
for (Py_ssize_t iarg = 0, jarg = 0; iarg < nargs; iarg++) {
457+
458+
for (Py_ssize_t iarg = 0; iarg < nargs; iarg++) {
464459
PyObject *arg = PyTuple_GET_ITEM(args, iarg);
465460
if (PyType_Check(arg)) {
466-
PyTuple_SET_ITEM(newargs, jarg, Py_NewRef(arg));
467-
jarg++;
461+
if (PyTupleWriter_Add(newargs, arg) < 0) {
462+
goto error;
463+
}
468464
continue;
469465
}
466+
470467
// Recursively substitute params in lists/tuples.
471468
if (PyTuple_Check(arg) || PyList_Check(arg)) {
472469
PyObject *subargs = _Py_subs_parameters(self, arg, parameters, item);
473470
if (subargs == NULL) {
474-
Py_DECREF(newargs);
475-
Py_DECREF(item);
476-
Py_XDECREF(tuple_args);
477-
return NULL;
471+
goto error;
478472
}
479473
if (PyTuple_Check(arg)) {
480-
PyTuple_SET_ITEM(newargs, jarg, subargs);
474+
if (PyTupleWriter_AddSteal(newargs, subargs) < 0) {
475+
goto error;
476+
}
481477
}
482478
else {
483479
// _Py_subs_parameters returns a tuple. If the original arg was a list,
484480
// convert subargs to a list as well.
485481
PyObject *subargs_list = PySequence_List(subargs);
486482
Py_DECREF(subargs);
487-
if (subargs_list == NULL) {
488-
Py_DECREF(newargs);
489-
Py_DECREF(item);
490-
Py_XDECREF(tuple_args);
491-
return NULL;
483+
if (PyTupleWriter_AddSteal(newargs, subargs_list) < 0) {
484+
goto error;
492485
}
493-
PyTuple_SET_ITEM(newargs, jarg, subargs_list);
494486
}
495-
jarg++;
496487
continue;
497488
}
489+
498490
int unpack = _is_unpacked_typevartuple(arg);
499491
if (unpack < 0) {
500-
Py_DECREF(newargs);
501-
Py_DECREF(item);
502-
Py_XDECREF(tuple_args);
503-
return NULL;
492+
goto error;
504493
}
505494
PyObject *subst;
506495
if (PyObject_GetOptionalAttr(arg, &_Py_ID(__typing_subst__), &subst) < 0) {
507-
Py_DECREF(newargs);
508-
Py_DECREF(item);
509-
Py_XDECREF(tuple_args);
510-
return NULL;
496+
goto error;
511497
}
512498
if (subst) {
513499
Py_ssize_t iparam = tuple_index(parameters, nparams, arg);
@@ -518,43 +504,42 @@ _Py_subs_parameters(PyObject *self, PyObject *args, PyObject *parameters, PyObje
518504
else {
519505
arg = subs_tvars(arg, parameters, argitems, nitems);
520506
}
521-
if (arg == NULL) {
522-
Py_DECREF(newargs);
523-
Py_DECREF(item);
524-
Py_XDECREF(tuple_args);
525-
return NULL;
526-
}
527507
if (unpack) {
508+
if (arg == NULL) {
509+
goto error;
510+
}
528511
if (!PyTuple_Check(arg)) {
529-
Py_DECREF(newargs);
530-
Py_DECREF(item);
531-
Py_XDECREF(tuple_args);
532512
PyObject *original = PyTuple_GET_ITEM(args, iarg);
533513
PyErr_Format(PyExc_TypeError,
534514
"expected __typing_subst__ of %T objects to return a tuple, not %T",
535515
original, arg);
536516
Py_DECREF(arg);
537-
return NULL;
517+
goto error;
538518
}
539-
jarg = tuple_extend(&newargs, jarg,
540-
&PyTuple_GET_ITEM(arg, 0), PyTuple_GET_SIZE(arg));
541-
Py_DECREF(arg);
542-
if (jarg < 0) {
543-
Py_DECREF(item);
544-
Py_XDECREF(tuple_args);
545-
assert(newargs == NULL);
546-
return NULL;
519+
if (PyTupleWriter_AddArray(newargs,
520+
_PyTuple_ITEMS(arg),
521+
PyTuple_GET_SIZE(arg)) < 0) {
522+
Py_DECREF(arg);
523+
goto error;
547524
}
525+
Py_DECREF(arg);
548526
}
549527
else {
550-
PyTuple_SET_ITEM(newargs, jarg, arg);
551-
jarg++;
528+
if (PyTupleWriter_AddSteal(newargs, arg) < 0) {
529+
goto error;
530+
}
552531
}
553532
}
554533

555534
Py_DECREF(item);
556535
Py_XDECREF(tuple_args);
557-
return newargs;
536+
return PyTupleWriter_Finish(newargs);
537+
538+
error:
539+
PyTupleWriter_Discard(newargs);
540+
Py_DECREF(item);
541+
Py_XDECREF(tuple_args);
542+
return NULL;
558543
}
559544

560545
PyDoc_STRVAR(genericalias__doc__,

0 commit comments

Comments
 (0)