Skip to content
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
5 changes: 4 additions & 1 deletion Include/internal/pycore_tupleobject.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,10 @@ extern "C" {

#include "tupleobject.h"

#define _PyTuple_ITEMS(op) (_PyTuple_CAST(op)->ob_item)
static inline PyObject** _PyTuple_ITEMS(PyTupleObject *op)
{
return op->ob_item;
}

#ifdef __cplusplus
}
Expand Down
2 changes: 1 addition & 1 deletion Include/tupleobject.h
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ PyAPI_FUNC(void) _PyTuple_MaybeUntrack(PyObject *);
/* Macro, trading safety for speed */
#ifndef Py_LIMITED_API
/* Cast argument to PyTupleObject* type. */
#define _PyTuple_CAST(op) ((PyTupleObject *)(op))
#define _PyTuple_CAST(op) (assert(PyTuple_Check(op)), (PyTupleObject *)(op))

#define PyTuple_GET_ITEM(op, i) (_PyTuple_CAST(op)->ob_item[i])
#define PyTuple_GET_SIZE(op) (assert(PyTuple_Check(op)), Py_SIZE(op))
Expand Down
12 changes: 7 additions & 5 deletions Modules/_functoolsmodule.c
Original file line number Diff line number Diff line change
Expand Up @@ -134,15 +134,16 @@ partial_fastcall(partialobject *pto, PyObject **args, Py_ssize_t nargs,
PyObject *ret;
PyObject **stack, **stack_buf = NULL;
Py_ssize_t nargs2, pto_nargs;
PyTupleObject *pto_args_tuple = _PyTuple_CAST(pto->args);

pto_nargs = PyTuple_GET_SIZE(pto->args);
pto_nargs = PyTuple_GET_SIZE(pto_args_tuple);
nargs2 = pto_nargs + nargs;

if (pto_nargs == 0) {
stack = args;
}
else if (nargs == 0) {
stack = _PyTuple_ITEMS(pto->args);
stack = _PyTuple_ITEMS(pto_args_tuple);
}
else {
if (nargs2 <= (Py_ssize_t)Py_ARRAY_LENGTH(small_stack)) {
Expand All @@ -159,7 +160,7 @@ partial_fastcall(partialobject *pto, PyObject **args, Py_ssize_t nargs,

/* use borrowed references */
memcpy(stack,
_PyTuple_ITEMS(pto->args),
_PyTuple_ITEMS(pto_args_tuple),
pto_nargs * sizeof(PyObject*));
memcpy(&stack[pto_nargs],
args,
Expand Down Expand Up @@ -221,9 +222,10 @@ partial_call(partialobject *pto, PyObject *args, PyObject *kwargs)


if (pto->use_fastcall) {
PyTupleObject *args_tuple = _PyTuple_CAST(args);
res = partial_fastcall(pto,
_PyTuple_ITEMS(args),
PyTuple_GET_SIZE(args),
_PyTuple_ITEMS(args_tuple),
PyTuple_GET_SIZE(args_tuple),
kwargs2);
}
else {
Expand Down
97 changes: 61 additions & 36 deletions Objects/call.c
Original file line number Diff line number Diff line change
Expand Up @@ -225,9 +225,10 @@ PyObject_Call(PyObject *callable, PyObject *args, PyObject *kwargs)
assert(kwargs == NULL || PyDict_Check(kwargs));

if (PyFunction_Check(callable)) {
PyTupleObject *args_tuple = (PyTupleObject *)args;
return _PyFunction_FastCallDict(callable,
_PyTuple_ITEMS(args),
PyTuple_GET_SIZE(args),
_PyTuple_ITEMS(args_tuple),
PyTuple_GET_SIZE(args_tuple),
kwargs);
}
else if (PyCFunction_Check(callable)) {
Expand Down Expand Up @@ -305,8 +306,8 @@ _PyFunction_FastCallDict(PyObject *func, PyObject *const *args, Py_ssize_t nargs
PyObject *globals = PyFunction_GET_GLOBALS(func);
PyObject *argdefs = PyFunction_GET_DEFAULTS(func);
PyObject *kwdefs, *closure, *name, *qualname;
PyObject *kwtuple, **k;
PyObject **d;
PyTupleObject *kwtuple;
PyObject **k, **d;
Py_ssize_t nd, nk;
PyObject *result;

Expand All @@ -327,9 +328,10 @@ _PyFunction_FastCallDict(PyObject *func, PyObject *const *args, Py_ssize_t nargs
&& co->co_argcount == PyTuple_GET_SIZE(argdefs)) {
/* function called with no arguments, but all parameters have
a default value: use default values as arguments .*/
args = _PyTuple_ITEMS(argdefs);
return function_code_fastcall(co, args, PyTuple_GET_SIZE(argdefs),
globals);
PyTupleObject *argdefs_tuple = _PyTuple_CAST(argdefs);
args = _PyTuple_ITEMS(argdefs_tuple);
nargs = PyTuple_GET_SIZE(argdefs_tuple);
return function_code_fastcall(co, args, nargs, globals);
}
}

Expand All @@ -339,7 +341,7 @@ _PyFunction_FastCallDict(PyObject *func, PyObject *const *args, Py_ssize_t nargs

/* bpo-29318, bpo-27840: Caller and callee functions must not share
the dictionary: kwargs must be copied. */
kwtuple = PyTuple_New(2 * nk);
kwtuple = (PyTupleObject *)PyTuple_New(2 * nk);
if (kwtuple == NULL) {
return NULL;
}
Expand Down Expand Up @@ -367,8 +369,9 @@ _PyFunction_FastCallDict(PyObject *func, PyObject *const *args, Py_ssize_t nargs
qualname = ((PyFunctionObject *)func) -> func_qualname;

if (argdefs != NULL) {
d = _PyTuple_ITEMS(argdefs);
nd = PyTuple_GET_SIZE(argdefs);
PyTupleObject *argdefs_tuple = _PyTuple_CAST(argdefs);
d = _PyTuple_ITEMS(argdefs_tuple);
nd = PyTuple_GET_SIZE(argdefs_tuple);
}
else {
d = NULL;
Expand All @@ -388,21 +391,29 @@ PyObject *
_PyFunction_FastCallKeywords(PyObject *func, PyObject *const *stack,
Py_ssize_t nargs, PyObject *kwnames)
{
PyCodeObject *co = (PyCodeObject *)PyFunction_GET_CODE(func);
PyObject *globals = PyFunction_GET_GLOBALS(func);
PyObject *argdefs = PyFunction_GET_DEFAULTS(func);
PyObject *kwdefs, *closure, *name, *qualname;
PyObject **d;
Py_ssize_t nkwargs = (kwnames == NULL) ? 0 : PyTuple_GET_SIZE(kwnames);
Py_ssize_t nd;

assert(PyFunction_Check(func));
assert(nargs >= 0);
assert(kwnames == NULL || PyTuple_CheckExact(kwnames));

PyTupleObject *kwnames_tuple;
Py_ssize_t nkwargs;
if (kwnames) {
kwnames_tuple = _PyTuple_CAST(kwnames);
nkwargs = PyTuple_GET_SIZE(kwnames_tuple);
}
else {
kwnames_tuple = NULL;
nkwargs = 0;
}

assert((nargs == 0 && nkwargs == 0) || stack != NULL);
/* kwnames must only contains str strings, no subclass, and all keys must
be unique */

assert(PyFunction_Check(func));
PyCodeObject *co = (PyCodeObject *)PyFunction_GET_CODE(func);
PyObject *globals = PyFunction_GET_GLOBALS(func);
PyObject *argdefs = PyFunction_GET_DEFAULTS(func);

if (co->co_kwonlyargcount == 0 && nkwargs == 0 &&
(co->co_flags & ~PyCF_MASK) == (CO_OPTIMIZED | CO_NEWLOCALS | CO_NOFREE))
{
Expand All @@ -411,32 +422,42 @@ _PyFunction_FastCallKeywords(PyObject *func, PyObject *const *stack,
}
else if (nargs == 0 && argdefs != NULL
&& co->co_argcount == PyTuple_GET_SIZE(argdefs)) {
PyTupleObject *argdefs_tuple = _PyTuple_CAST(argdefs);
/* function called with no arguments, but all parameters have
a default value: use default values as arguments .*/
stack = _PyTuple_ITEMS(argdefs);
return function_code_fastcall(co, stack, PyTuple_GET_SIZE(argdefs),
globals);
stack = _PyTuple_ITEMS(argdefs_tuple);
nargs = PyTuple_GET_SIZE(argdefs_tuple);
return function_code_fastcall(co, stack, nargs, globals);
}
}

kwdefs = PyFunction_GET_KW_DEFAULTS(func);
closure = PyFunction_GET_CLOSURE(func);
name = ((PyFunctionObject *)func) -> func_name;
qualname = ((PyFunctionObject *)func) -> func_qualname;
PyObject *kwdefs = PyFunction_GET_KW_DEFAULTS(func);
PyObject *closure = PyFunction_GET_CLOSURE(func);
PyObject *name = ((PyFunctionObject *)func) -> func_name;
PyObject *qualname = ((PyFunctionObject *)func) -> func_qualname;

PyObject **d;
Py_ssize_t nd;
if (argdefs != NULL) {
d = _PyTuple_ITEMS(argdefs);
nd = PyTuple_GET_SIZE(argdefs);
PyTupleObject *argdefs_tuple = _PyTuple_CAST(argdefs);
d = _PyTuple_ITEMS(argdefs_tuple);
nd = PyTuple_GET_SIZE(argdefs_tuple);
}
else {
d = NULL;
nd = 0;
}

PyObject **kwnames_array;
if (nkwargs) {
kwnames_array = _PyTuple_ITEMS(_PyTuple_CAST(kwnames_tuple));
}
else {
kwnames_array = NULL;
}
return _PyEval_EvalCodeWithName((PyObject*)co, globals, (PyObject *)NULL,
stack, nargs,
nkwargs ? _PyTuple_ITEMS(kwnames) : NULL,
stack + nargs,
nkwargs, 1,
kwnames_array, stack + nargs, nkwargs, 1,
d, (int)nd, kwdefs,
closure, name, qualname);
}
Expand Down Expand Up @@ -779,6 +800,9 @@ cfunction_call_varargs(PyObject *func, PyObject *args, PyObject *kwargs)
PyObject *
PyCFunction_Call(PyObject *func, PyObject *args, PyObject *kwargs)
{
assert(PyTuple_Check(args));
PyTupleObject *args_tuple = (PyTupleObject *)args;

/* first try METH_VARARGS to pass directly args tuple unchanged.
_PyMethodDef_RawFastCallDict() creates a new temporary tuple
for METH_VARARGS. */
Expand All @@ -787,8 +811,8 @@ PyCFunction_Call(PyObject *func, PyObject *args, PyObject *kwargs)
}
else {
return _PyCFunction_FastCallDict(func,
_PyTuple_ITEMS(args),
PyTuple_GET_SIZE(args),
_PyTuple_ITEMS(args_tuple),
PyTuple_GET_SIZE(args_tuple),
kwargs);
}
}
Expand Down Expand Up @@ -884,8 +908,9 @@ _PyObject_Call_Prepend(PyObject *callable,
PyObject *result;

assert(PyTuple_Check(args));
PyTupleObject *args_tuple = (PyTupleObject *)args;

argcount = PyTuple_GET_SIZE(args);
argcount = PyTuple_GET_SIZE(args_tuple);
if (argcount + 1 <= (Py_ssize_t)Py_ARRAY_LENGTH(small_stack)) {
stack = small_stack;
}
Expand All @@ -900,7 +925,7 @@ _PyObject_Call_Prepend(PyObject *callable,
/* use borrowed references */
stack[0] = obj;
memcpy(&stack[1],
_PyTuple_ITEMS(args),
_PyTuple_ITEMS(args_tuple),
argcount * sizeof(PyObject *));

result = _PyObject_FastCallDict(callable,
Expand Down Expand Up @@ -950,7 +975,7 @@ _PyObject_CallFunctionVa(PyObject *callable, const char *format,
- PyObject_CallFunction(func, "O", tuple) calls func(*tuple)
- PyObject_CallFunction(func, "(OOO)", arg1, arg2, arg3) calls
func(*(arg1, arg2, arg3)): func(arg1, arg2, arg3) */
PyObject *args = stack[0];
PyTupleObject *args = _PyTuple_CAST(stack[0]);
result = _PyObject_FastCall(callable,
_PyTuple_ITEMS(args),
PyTuple_GET_SIZE(args));
Expand Down
10 changes: 5 additions & 5 deletions Objects/codeobject.c
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ all_name_chars(PyObject *o)
}

static void
intern_strings(PyObject *tuple)
intern_strings(PyTupleObject *tuple)
{
Py_ssize_t i;

Expand Down Expand Up @@ -126,10 +126,10 @@ PyCode_New(int argcount, int kwonlyargcount,
if (PyUnicode_READY(filename) < 0)
return NULL;

intern_strings(names);
intern_strings(varnames);
intern_strings(freevars);
intern_strings(cellvars);
intern_strings(_PyTuple_CAST(names));
intern_strings(_PyTuple_CAST(varnames));
intern_strings(_PyTuple_CAST(freevars));
intern_strings(_PyTuple_CAST(cellvars));
intern_string_constants(consts);

/* Check for any inner or outer closure references */
Expand Down
16 changes: 10 additions & 6 deletions Objects/descrobject.c
Original file line number Diff line number Diff line change
Expand Up @@ -226,7 +226,8 @@ methoddescr_call(PyMethodDescrObject *descr, PyObject *args, PyObject *kwargs)

/* Make sure that the first argument is acceptable as 'self' */
assert(PyTuple_Check(args));
nargs = PyTuple_GET_SIZE(args);
PyTupleObject *args_tuple = _PyTuple_CAST(args);
nargs = PyTuple_GET_SIZE(args_tuple);
if (nargs < 1) {
PyErr_Format(PyExc_TypeError,
"descriptor '%V' of '%.100s' "
Expand All @@ -235,7 +236,7 @@ methoddescr_call(PyMethodDescrObject *descr, PyObject *args, PyObject *kwargs)
PyDescr_TYPE(descr)->tp_name);
return NULL;
}
self = PyTuple_GET_ITEM(args, 0);
self = PyTuple_GET_ITEM(args_tuple, 0);
if (!_PyObject_RealIsSubclass((PyObject *)Py_TYPE(self),
(PyObject *)PyDescr_TYPE(descr))) {
PyErr_Format(PyExc_TypeError,
Expand All @@ -249,7 +250,8 @@ methoddescr_call(PyMethodDescrObject *descr, PyObject *args, PyObject *kwargs)
}

result = _PyMethodDef_RawFastCallDict(descr->d_method, self,
&_PyTuple_ITEMS(args)[1], nargs - 1,
&_PyTuple_ITEMS(args_tuple)[1],
nargs - 1,
kwargs);
result = _Py_CheckFunctionResult((PyObject *)descr, result, NULL);
return result;
Expand Down Expand Up @@ -302,7 +304,8 @@ classmethoddescr_call(PyMethodDescrObject *descr, PyObject *args,

/* Make sure that the first argument is acceptable as 'self' */
assert(PyTuple_Check(args));
argc = PyTuple_GET_SIZE(args);
PyTupleObject *args_tuple = _PyTuple_CAST(args);
argc = PyTuple_GET_SIZE(args_tuple);
if (argc < 1) {
PyErr_Format(PyExc_TypeError,
"descriptor '%V' of '%.100s' "
Expand All @@ -311,7 +314,7 @@ classmethoddescr_call(PyMethodDescrObject *descr, PyObject *args,
PyDescr_TYPE(descr)->tp_name);
return NULL;
}
self = PyTuple_GET_ITEM(args, 0);
self = PyTuple_GET_ITEM(args_tuple, 0);
if (!PyType_Check(self)) {
PyErr_Format(PyExc_TypeError,
"descriptor '%V' requires a type "
Expand All @@ -333,7 +336,8 @@ classmethoddescr_call(PyMethodDescrObject *descr, PyObject *args,
}

result = _PyMethodDef_RawFastCallDict(descr->d_method, self,
&_PyTuple_ITEMS(args)[1], argc - 1,
&_PyTuple_ITEMS(args_tuple)[1],
argc - 1,
kwds);
result = _Py_CheckFunctionResult((PyObject *)descr, result, NULL);
return result;
Expand Down
8 changes: 3 additions & 5 deletions Objects/funcobject.c
Original file line number Diff line number Diff line change
Expand Up @@ -580,11 +580,9 @@ func_traverse(PyFunctionObject *f, visitproc visit, void *arg)
static PyObject *
function_call(PyObject *func, PyObject *args, PyObject *kwargs)
{
PyObject **stack;
Py_ssize_t nargs;

stack = _PyTuple_ITEMS(args);
nargs = PyTuple_GET_SIZE(args);
PyTupleObject *args_tuple = _PyTuple_CAST(args);
PyObject **stack = _PyTuple_ITEMS(args_tuple);
Py_ssize_t nargs = PyTuple_GET_SIZE(args_tuple);
return _PyFunction_FastCallDict(func, stack, nargs, kwargs);
}

Expand Down
9 changes: 5 additions & 4 deletions Python/ceval.c
Original file line number Diff line number Diff line change
Expand Up @@ -4648,7 +4648,8 @@ do_call_core(PyObject *func, PyObject *callargs, PyObject *kwdict)
}
else if (Py_TYPE(func) == &PyMethodDescr_Type) {
PyThreadState *tstate = _PyThreadState_GET();
Py_ssize_t nargs = PyTuple_GET_SIZE(callargs);
PyTupleObject *callargs_tuple = _PyTuple_CAST(callargs);
Py_ssize_t nargs = PyTuple_GET_SIZE(callargs_tuple);
if (nargs > 0 && tstate->use_tracing) {
/* We need to create a temporary bound method as argument
for profiling.
Expand All @@ -4657,15 +4658,15 @@ do_call_core(PyObject *func, PyObject *callargs, PyObject *kwdict)
"self". In any case, the call itself would raise
TypeError (foo needs an argument), so we just skip
profiling. */
PyObject *self = PyTuple_GET_ITEM(callargs, 0);
PyObject *self = PyTuple_GET_ITEM(callargs_tuple, 0);
func = Py_TYPE(func)->tp_descr_get(func, self, (PyObject*)Py_TYPE(self));
if (func == NULL) {
return NULL;
}

PyObject **args = &_PyTuple_ITEMS(callargs_tuple)[1];
C_TRACE(result, _PyCFunction_FastCallDict(func,
&_PyTuple_ITEMS(callargs)[1],
nargs - 1,
args, nargs - 1,
kwdict));
Py_DECREF(func);
return result;
Expand Down
Loading