Skip to content

Commit cc557e9

Browse files
committed
macros removed, post-resizing instead
1 parent acd9c56 commit cc557e9

File tree

1 file changed

+56
-71
lines changed

1 file changed

+56
-71
lines changed

Modules/_functoolsmodule.c

Lines changed: 56 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -355,24 +355,6 @@ partial_descr_get(PyObject *self, PyObject *obj, PyObject *type)
355355
return PyMethod_New(self, obj);
356356
}
357357

358-
#define ALLOCATE_STACK(elsize, size, small_stack, stack) \
359-
do { \
360-
if (size <= (Py_ssize_t)Py_ARRAY_LENGTH(small_stack)) { \
361-
stack = small_stack; \
362-
} \
363-
else { \
364-
/* NOTE, size * elsize in theory could overflow */ \
365-
stack = PyMem_Malloc(size * elsize); \
366-
} \
367-
} while (0)
368-
369-
#define DEALLOCATE_STACK(small_stack, stack) \
370-
do { \
371-
if (stack != small_stack) { \
372-
PyMem_Free(stack); \
373-
} \
374-
} while (0)
375-
376358
static PyObject *
377359
partial_vectorcall(PyObject *self, PyObject *const *args,
378360
size_t nargsf, PyObject *kwnames)
@@ -434,17 +416,25 @@ partial_vectorcall(PyObject *self, PyObject *const *args,
434416
Py_ssize_t tot_nkwds = pto_nkwds + nkwds;
435417
Py_ssize_t tot_nargskw = tot_nargs + tot_nkwds;
436418

437-
PyObject **stack, *small_stack[_PY_FASTCALL_SMALL_STACK];
438-
PyObject *tot_kwnames;
439-
440-
/* Initialize stack & copy keywords to stack */
441-
if (!pto_nkwds) {
442-
/* Allocate Stack */
443-
ALLOCATE_STACK(sizeof(PyObject *), tot_nargskw, small_stack, stack);
419+
/* Allocate Stack */
420+
PyObject **tmp_stack, **stack, *small_stack[_PY_FASTCALL_SMALL_STACK];
421+
if (tot_nargskw <= (Py_ssize_t)Py_ARRAY_LENGTH(small_stack)) {
422+
stack = small_stack;
423+
}
424+
else {
425+
/* NOTE, size * elsize could overflow */
426+
stack = PyMem_Malloc(tot_nargskw * sizeof(PyObject *));
444427
if (stack == NULL) {
445428
PyErr_NoMemory();
446429
return NULL;
447430
}
431+
}
432+
433+
PyObject *pto_kw_merged = NULL; // pto_kw with duplicates merged (if any)
434+
PyObject *tot_kwnames;
435+
436+
/* Copy keywords to stack */
437+
if (!pto_nkwds) {
448438
tot_kwnames = kwnames;
449439

450440
if (nkwds) {
@@ -453,74 +443,59 @@ partial_vectorcall(PyObject *self, PyObject *const *args,
453443
}
454444
}
455445
else {
446+
tot_kwnames = PyTuple_New(tot_nkwds);
456447
PyObject *key, *val;
457-
PyObject *pto_kw = NULL; // pto_kw with duplicates merged (if any)
458-
459-
/* Temporary stack for keywords that are not in pto->kw */
460-
PyObject **kwtail, *small_kwtail[_PY_FASTCALL_SMALL_STACK * 2];
461-
ALLOCATE_STACK(sizeof(PyObject *), nkwds * 2, small_kwtail, kwtail);
462-
if (kwtail == NULL) {
463-
PyErr_NoMemory();
464-
return NULL;
465-
}
466448

467449
/* Merge kw to pto_kw or add to tail (if not duplicate) */
468450
Py_ssize_t n_tail = 0;
469451
for (Py_ssize_t i = 0; i < nkwds; ++i) {
470452
key = PyTuple_GET_ITEM(kwnames, i);
471453
val = args[nargs + i];
472454
if (PyDict_Contains(pto->kw, key)) {
473-
if (pto_kw == NULL) {
474-
pto_kw = PyDict_Copy(pto->kw);
475-
if (pto_kw == NULL) {
476-
DEALLOCATE_STACK(small_kwtail, kwtail);
477-
return NULL;
455+
if (pto_kw_merged == NULL) {
456+
pto_kw_merged = PyDict_Copy(pto->kw);
457+
if (pto_kw_merged == NULL) {
458+
goto error_2;
478459
}
479460
}
480-
if (PyDict_SetItem(pto_kw, key, val) < 0) {
481-
DEALLOCATE_STACK(small_kwtail, kwtail);
482-
Py_DECREF(pto_kw);
483-
return NULL;
461+
if (PyDict_SetItem(pto_kw_merged, key, val) < 0) {
462+
goto error_1;
484463
}
485464
}
486465
else {
487-
kwtail[n_tail] = key;
488-
kwtail[n_tail + nkwds] = val;
466+
/* Copy keyword tail to stack */
467+
PyTuple_SET_ITEM(tot_kwnames, pto_nkwds + n_tail, key);
468+
Py_INCREF(key);
469+
stack[tot_nargs + pto_nkwds + n_tail] = val;
489470
n_tail++;
490471
}
491472
}
492473

493-
/* Allocate Stack */
474+
/* Resize Stack and tot_kwnames */
494475
Py_ssize_t n_merges = nkwds - n_tail;
495-
tot_nkwds = pto_nkwds + nkwds - n_merges;
496-
tot_nargskw = tot_nargs + tot_nkwds;
497-
ALLOCATE_STACK(sizeof(PyObject *), tot_nargskw, small_stack, stack);
498-
if (stack == NULL) {
499-
Py_XDECREF(pto_kw);
500-
PyErr_NoMemory();
501-
return NULL;
476+
if (n_merges) {
477+
if (stack != small_stack) {
478+
tmp_stack = PyMem_Realloc(stack, (tot_nargskw - n_merges) * sizeof(PyObject *));
479+
if (tmp_stack == NULL) {
480+
PyErr_NoMemory();
481+
goto error_1;
482+
}
483+
stack = tmp_stack;
484+
}
485+
if (_PyTuple_Resize(&tot_kwnames, (tot_nkwds - n_merges)) != 0) {
486+
goto error_1;
487+
}
502488
}
503-
tot_kwnames = PyTuple_New(tot_nkwds);
504489

505-
/* Copy pto_kw to stack */
490+
/* Copy pto_kw_merged to stack */
506491
Py_ssize_t pos = 0, i = 0;
507-
while (PyDict_Next(n_merges ? pto_kw : pto->kw, &pos, &key, &val)) {
492+
while (PyDict_Next(n_merges ? pto_kw_merged : pto->kw, &pos, &key, &val)) {
508493
PyTuple_SET_ITEM(tot_kwnames, i, key);
509494
Py_INCREF(key);
510495
stack[tot_nargs + i] = val;
511496
i++;
512497
}
513-
Py_XDECREF(pto_kw);
514-
515-
/* Copy kw tail to stack */
516-
for (Py_ssize_t i = 0; i < n_tail; ++i) {
517-
key = kwtail[i];
518-
val = kwtail[i + nkwds];
519-
PyTuple_SET_ITEM(tot_kwnames, pto_nkwds + i, key);
520-
Py_INCREF(key);
521-
stack[tot_nargs + pto_nkwds + i] = val;
522-
}
523-
DEALLOCATE_STACK(small_kwtail, kwtail);
498+
Py_XDECREF(pto_kw_merged);
524499
}
525500

526501
/* Copy Positionals to stack */
@@ -549,15 +524,25 @@ partial_vectorcall(PyObject *self, PyObject *const *args,
549524
/* Call / Maintenance / Return */
550525
PyObject *ret = _PyObject_VectorcallTstate(tstate, pto->fn, stack,
551526
tot_nargs, tot_kwnames);
552-
DEALLOCATE_STACK(small_stack, stack);
527+
if (stack != small_stack) {
528+
PyMem_Free(stack);
529+
}
553530
if (pto_nkwds) {
554531
Py_DECREF(tot_kwnames);
555532
}
556533
return ret;
557-
}
558534

559-
#undef ALLOCATE_STACK
560-
#undef DEALLOCATE_STACK
535+
error_1:
536+
Py_XDECREF(pto_kw_merged);
537+
error_2:
538+
if (stack != small_stack) {
539+
PyMem_Free(stack);
540+
}
541+
if (pto_nkwds) {
542+
Py_DECREF(tot_kwnames);
543+
}
544+
return NULL;
545+
}
561546

562547
/* Set pto->vectorcall depending on the parameters of the partial object */
563548
static void

0 commit comments

Comments
 (0)