Python 3.7 METH_FASTCALL backport (#406)

This commit is contained in:
Gautham 2022-05-13 17:35:12 +05:30 committed by GitHub
parent fec396037a
commit 83b743cf96
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
103 changed files with 2949 additions and 3356 deletions

View file

@ -2190,727 +2190,6 @@ PyMapping_Values(PyObject *o)
return fast;
}
/* Operations on callable objects */
/* XXX PyCallable_Check() is in object.c */
PyObject *
PyObject_CallObject(PyObject *callable, PyObject *args)
{
return PyEval_CallObjectWithKeywords(callable, args, NULL);
}
PyObject*
(_Py_CheckFunctionResult)(PyObject *callable, PyObject *result, const char *where)
{
int err_occurred = (PyErr_Occurred() != NULL);
assert((callable != NULL) ^ (where != NULL));
if (result == NULL) {
if (!err_occurred) {
if (callable)
PyErr_Format(PyExc_SystemError,
"%R returned NULL without setting an error",
callable);
else
PyErr_Format(PyExc_SystemError,
"%s returned NULL without setting an error",
where);
#ifdef Py_DEBUG
/* Ensure that the bug is caught in debug mode */
Py_FatalError("a function returned NULL without setting an error");
#endif
return NULL;
}
}
else {
if (err_occurred) {
Py_DECREF(result);
if (callable) {
_PyErr_FormatFromCause(PyExc_SystemError,
"%R returned a result with an error set",
callable);
}
else {
_PyErr_FormatFromCause(PyExc_SystemError,
"%s returned a result with an error set",
where);
}
#ifdef Py_DEBUG
/* Ensure that the bug is caught in debug mode */
Py_FatalError("a function returned a result with an error set");
#endif
return NULL;
}
}
return result;
}
PyObject *
PyObject_Call(PyObject *callable, PyObject *args, PyObject *kwargs)
{
ternaryfunc call;
PyObject *result;
/* PyObject_Call() must not be called with an exception set,
because it can clear it (directly or indirectly) and so the
caller loses its exception */
assert(!PyErr_Occurred());
assert(PyTuple_Check(args));
assert(kwargs == NULL || PyDict_Check(kwargs));
if (PyFunction_Check(callable)) {
return _PyFunction_FastCallDict(callable,
&PyTuple_GET_ITEM(args, 0),
PyTuple_GET_SIZE(args),
kwargs);
}
else if (PyCFunction_Check(callable)) {
return PyCFunction_Call(callable, args, kwargs);
}
else {
call = callable->ob_type->tp_call;
if (call == NULL) {
PyErr_Format(PyExc_TypeError, "'%.200s' object is not callable",
callable->ob_type->tp_name);
return NULL;
}
if (Py_EnterRecursiveCall(" while calling a Python object"))
return NULL;
result = (*call)(callable, args, kwargs);
Py_LeaveRecursiveCall();
return _Py_CheckFunctionResult(callable, result, NULL);
}
}
/* Issue #29234: Inlining _PyStack_AsTuple() into callers increases their
stack consumption, Disable inlining to optimize the stack consumption. */
PyObject* dontinline
_PyStack_AsTuple(PyObject **stack, Py_ssize_t nargs)
{
PyObject *args;
Py_ssize_t i;
args = PyTuple_New(nargs);
if (args == NULL) {
return NULL;
}
for (i=0; i < nargs; i++) {
PyObject *item = stack[i];
Py_INCREF(item);
PyTuple_SET_ITEM(args, i, item);
}
return args;
}
PyObject*
_PyStack_AsTupleSlice(PyObject **stack, Py_ssize_t nargs,
Py_ssize_t start, Py_ssize_t end)
{
PyObject *args;
Py_ssize_t i;
assert(0 <= start);
assert(end <= nargs);
assert(start <= end);
args = PyTuple_New(end - start);
if (args == NULL) {
return NULL;
}
for (i=start; i < end; i++) {
PyObject *item = stack[i];
Py_INCREF(item);
PyTuple_SET_ITEM(args, i - start, item);
}
return args;
}
PyObject *
_PyObject_FastCallDict(PyObject *callable, PyObject **args, Py_ssize_t nargs,
PyObject *kwargs)
{
/* _PyObject_FastCallDict() must not be called with an exception set,
because it can clear it (directly or indirectly) and so the
caller loses its exception */
assert(!PyErr_Occurred());
assert(callable != NULL);
assert(nargs >= 0);
assert(nargs == 0 || args != NULL);
assert(kwargs == NULL || PyDict_Check(kwargs));
if (PyFunction_Check(callable)) {
return _PyFunction_FastCallDict(callable, args, nargs, kwargs);
}
else if (PyCFunction_Check(callable)) {
return _PyCFunction_FastCallDict(callable, args, nargs, kwargs);
}
else {
PyObject *argstuple, *result;
ternaryfunc call;
/* Slow-path: build a temporary tuple */
call = callable->ob_type->tp_call;
if (call == NULL) {
PyErr_Format(PyExc_TypeError, "'%.200s' object is not callable",
callable->ob_type->tp_name);
return NULL;
}
argstuple = _PyStack_AsTuple(args, nargs);
if (argstuple == NULL) {
return NULL;
}
if (Py_EnterRecursiveCall(" while calling a Python object")) {
return NULL;
}
result = (*call)(callable, argstuple, kwargs);
Py_LeaveRecursiveCall();
Py_DECREF(argstuple);
result = _Py_CheckFunctionResult(callable, result, NULL);
return result;
}
}
/* Positional arguments are obj followed by args:
call callable(obj, *args, **kwargs) */
PyObject *
_PyObject_FastCall_Prepend(PyObject *callable,
PyObject *obj, PyObject **args, Py_ssize_t nargs)
{
PyObject *small_stack[_PY_FASTCALL_SMALL_STACK];
PyObject **args2;
PyObject *result;
nargs++;
if (nargs <= (Py_ssize_t)Py_ARRAY_LENGTH(small_stack)) {
args2 = small_stack;
}
else {
args2 = PyMem_Malloc(nargs * sizeof(PyObject *));
if (args2 == NULL) {
PyErr_NoMemory();
return NULL;
}
}
/* use borrowed references */
args2[0] = obj;
if (nargs > 1) {
memcpy(&args2[1],
args,
(nargs - 1)* sizeof(PyObject *));
}
result = _PyObject_FastCall(callable, args2, nargs);
if (args2 != small_stack) {
PyMem_Free(args2);
}
return result;
}
/* Call callable(obj, *args, **kwargs). */
PyObject *
_PyObject_Call_Prepend(PyObject *callable,
PyObject *obj, PyObject *args, PyObject *kwargs)
{
PyObject *small_stack[_PY_FASTCALL_SMALL_STACK];
PyObject **stack;
Py_ssize_t argcount;
PyObject *result;
assert(PyTuple_Check(args));
argcount = PyTuple_GET_SIZE(args);
if (argcount + 1 <= (Py_ssize_t)Py_ARRAY_LENGTH(small_stack)) {
stack = small_stack;
}
else {
stack = PyMem_Malloc((argcount + 1) * sizeof(PyObject *));
if (stack == NULL) {
PyErr_NoMemory();
return NULL;
}
}
/* use borrowed references */
stack[0] = obj;
memcpy(&stack[1],
&PyTuple_GET_ITEM(args, 0),
argcount * sizeof(PyObject *));
result = _PyObject_FastCallDict(callable,
stack, argcount + 1,
kwargs);
if (stack != small_stack) {
PyMem_Free(stack);
}
return result;
}
PyObject *
_PyStack_AsDict(PyObject **values, PyObject *kwnames)
{
Py_ssize_t nkwargs;
PyObject *kwdict;
Py_ssize_t i;
assert(kwnames != NULL);
nkwargs = PyTuple_GET_SIZE(kwnames);
kwdict = _PyDict_NewPresized(nkwargs);
if (kwdict == NULL) {
return NULL;
}
for (i = 0; i < nkwargs; i++) {
PyObject *key = PyTuple_GET_ITEM(kwnames, i);
PyObject *value = *values++;
if (PyDict_SetItem(kwdict, key, value)) {
Py_DECREF(kwdict);
return NULL;
}
}
return kwdict;
}
int
_PyStack_UnpackDict(PyObject **args, Py_ssize_t nargs, PyObject *kwargs,
PyObject ***p_stack, PyObject **p_kwnames)
{
PyObject **stack, **kwstack;
Py_ssize_t nkwargs;
Py_ssize_t pos, i;
PyObject *key, *value;
PyObject *kwnames;
assert(nargs >= 0);
assert(kwargs == NULL || PyDict_CheckExact(kwargs));
if (kwargs == NULL || (nkwargs = PyDict_GET_SIZE(kwargs)) == 0) {
*p_stack = args;
*p_kwnames = NULL;
return 0;
}
if ((size_t)nargs > PY_SSIZE_T_MAX / sizeof(stack[0]) - (size_t)nkwargs) {
PyErr_NoMemory();
return -1;
}
stack = PyMem_Malloc((nargs + nkwargs) * sizeof(stack[0]));
if (stack == NULL) {
PyErr_NoMemory();
return -1;
}
kwnames = PyTuple_New(nkwargs);
if (kwnames == NULL) {
PyMem_Free(stack);
return -1;
}
/* Copy position arguments (borrowed references) */
memcpy(stack, args, nargs * sizeof(stack[0]));
kwstack = stack + nargs;
pos = i = 0;
/* This loop doesn't support lookup function mutating the dictionary
to change its size. It's a deliberate choice for speed, this function is
called in the performance critical hot code. */
while (PyDict_Next(kwargs, &pos, &key, &value)) {
Py_INCREF(key);
PyTuple_SET_ITEM(kwnames, i, key);
/* The stack contains borrowed references */
kwstack[i] = value;
i++;
}
*p_stack = stack;
*p_kwnames = kwnames;
return 0;
}
PyObject *
_PyObject_FastCallKeywords(PyObject *callable, PyObject **stack, Py_ssize_t nargs,
PyObject *kwnames)
{
/* _PyObject_FastCallKeywords() must not be called with an exception set,
because it can clear it (directly or indirectly) and so the
caller loses its exception */
assert(!PyErr_Occurred());
assert(nargs >= 0);
assert(kwnames == NULL || PyTuple_CheckExact(kwnames));
/* kwnames must only contains str strings, no subclass, and all keys must
be unique: these checks are implemented in Python/ceval.c and
_PyArg_ParseStackAndKeywords(). */
if (PyFunction_Check(callable)) {
return _PyFunction_FastCallKeywords(callable, stack, nargs, kwnames);
}
if (PyCFunction_Check(callable)) {
return _PyCFunction_FastCallKeywords(callable, stack, nargs, kwnames);
}
else {
/* Slow-path: build a temporary tuple for positional arguments and a
temporary dictionary for keyword arguments (if any) */
ternaryfunc call;
PyObject *argstuple;
PyObject *kwdict, *result;
Py_ssize_t nkwargs;
nkwargs = (kwnames == NULL) ? 0 : PyTuple_GET_SIZE(kwnames);
assert((nargs == 0 && nkwargs == 0) || stack != NULL);
call = callable->ob_type->tp_call;
if (call == NULL) {
PyErr_Format(PyExc_TypeError, "'%.200s' object is not callable",
callable->ob_type->tp_name);
return NULL;
}
argstuple = _PyStack_AsTuple(stack, nargs);
if (argstuple == NULL) {
return NULL;
}
if (nkwargs > 0) {
kwdict = _PyStack_AsDict(stack + nargs, kwnames);
if (kwdict == NULL) {
Py_DECREF(argstuple);
return NULL;
}
}
else {
kwdict = NULL;
}
if (Py_EnterRecursiveCall(" while calling a Python object")) {
return NULL;
}
result = (*call)(callable, argstuple, kwdict);
Py_LeaveRecursiveCall();
Py_DECREF(argstuple);
Py_XDECREF(kwdict);
result = _Py_CheckFunctionResult(callable, result, NULL);
return result;
}
}
static PyObject *
_PyObject_CallFunctionVa(PyObject *callable, const char *format,
va_list va, int is_size_t)
{
PyObject* small_stack[5];
const Py_ssize_t small_stack_len = Py_ARRAY_LENGTH(small_stack);
PyObject **stack;
Py_ssize_t nargs, i;
PyObject *result;
if (callable == NULL) {
return null_error();
}
if (!format || !*format) {
return _PyObject_CallNoArg(callable);
}
if (is_size_t) {
stack = _Py_VaBuildStack_SizeT(small_stack, small_stack_len, format, va, &nargs);
}
else {
stack = _Py_VaBuildStack(small_stack, small_stack_len, format, va, &nargs);
}
if (stack == NULL) {
return NULL;
}
if (nargs == 1 && PyTuple_Check(stack[0])) {
/* Special cases for backward compatibility:
- 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];
result = _PyObject_FastCall(callable,
&PyTuple_GET_ITEM(args, 0),
PyTuple_GET_SIZE(args));
}
else {
result = _PyObject_FastCall(callable, stack, nargs);
}
for (i = 0; i < nargs; ++i) {
Py_DECREF(stack[i]);
}
if (stack != small_stack) {
PyMem_Free(stack);
}
return result;
}
PyObject *
PyObject_CallFunction(PyObject *callable, const char *format, ...)
{
va_list va;
PyObject *result;
va_start(va, format);
result = _PyObject_CallFunctionVa(callable, format, va, 0);
va_end(va);
return result;
}
PyObject *
_PyObject_CallFunction_SizeT(PyObject *callable, const char *format, ...)
{
va_list va;
PyObject *result;
va_start(va, format);
result = _PyObject_CallFunctionVa(callable, format, va, 1);
va_end(va);
return result;
}
static PyObject*
callmethod(PyObject* callable, const char *format, va_list va, int is_size_t)
{
assert(callable != NULL);
if (!PyCallable_Check(callable)) {
type_error("attribute of type '%.200s' is not callable", callable);
return NULL;
}
return _PyObject_CallFunctionVa(callable, format, va, is_size_t);
}
PyObject *
PyObject_CallMethod(PyObject *obj, const char *name, const char *format, ...)
{
va_list va;
PyObject *callable, *retval;
if (obj == NULL || name == NULL) {
return null_error();
}
callable = PyObject_GetAttrString(obj, name);
if (callable == NULL)
return NULL;
va_start(va, format);
retval = callmethod(callable, format, va, 0);
va_end(va);
Py_DECREF(callable);
return retval;
}
PyObject *
_PyObject_CallMethodId(PyObject *obj, _Py_Identifier *name,
const char *format, ...)
{
va_list va;
PyObject *callable, *retval;
if (obj == NULL || name == NULL) {
return null_error();
}
callable = _PyObject_GetAttrId(obj, name);
if (callable == NULL)
return NULL;
va_start(va, format);
retval = callmethod(callable, format, va, 0);
va_end(va);
Py_DECREF(callable);
return retval;
}
PyObject *
_PyObject_CallMethod_SizeT(PyObject *obj, const char *name,
const char *format, ...)
{
va_list va;
PyObject *callable, *retval;
if (obj == NULL || name == NULL) {
return null_error();
}
callable = PyObject_GetAttrString(obj, name);
if (callable == NULL)
return NULL;
va_start(va, format);
retval = callmethod(callable, format, va, 1);
va_end(va);
Py_DECREF(callable);
return retval;
}
PyObject *
_PyObject_CallMethodId_SizeT(PyObject *obj, _Py_Identifier *name,
const char *format, ...)
{
va_list va;
PyObject *callable, *retval;
if (obj == NULL || name == NULL) {
return null_error();
}
callable = _PyObject_GetAttrId(obj, name);
if (callable == NULL) {
return NULL;
}
va_start(va, format);
retval = callmethod(callable, format, va, 1);
va_end(va);
Py_DECREF(callable);
return retval;
}
static PyObject *
object_vacall(PyObject *callable, va_list vargs)
{
PyObject *small_stack[5];
PyObject **stack;
Py_ssize_t nargs;
PyObject *result;
Py_ssize_t i;
va_list countva;
if (callable == NULL) {
return null_error();
}
/* Count the number of arguments */
va_copy(countva, vargs);
nargs = 0;
while (1) {
PyObject *arg = va_arg(countva, PyObject *);
if (arg == NULL) {
break;
}
nargs++;
}
va_end(countva);
/* Copy arguments */
if (nargs <= (Py_ssize_t)Py_ARRAY_LENGTH(small_stack)) {
stack = small_stack;
}
else {
stack = PyMem_Malloc(nargs * sizeof(stack[0]));
if (stack == NULL) {
PyErr_NoMemory();
return NULL;
}
}
for (i = 0; i < nargs; ++i) {
stack[i] = va_arg(vargs, PyObject *);
}
/* Call the function */
result = _PyObject_FastCall(callable, stack, nargs);
if (stack != small_stack) {
PyMem_Free(stack);
}
return result;
}
PyObject *
PyObject_CallMethodObjArgs(PyObject *callable, PyObject *name, ...)
{
va_list vargs;
PyObject *result;
if (callable == NULL || name == NULL) {
return null_error();
}
callable = PyObject_GetAttr(callable, name);
if (callable == NULL) {
return NULL;
}
va_start(vargs, name);
result = object_vacall(callable, vargs);
va_end(vargs);
Py_DECREF(callable);
return result;
}
PyObject *
_PyObject_CallMethodIdObjArgs(PyObject *obj,
struct _Py_Identifier *name, ...)
{
va_list vargs;
PyObject *callable, *result;
if (obj == NULL || name == NULL) {
return null_error();
}
callable = _PyObject_GetAttrId(obj, name);
if (callable == NULL) {
return NULL;
}
va_start(vargs, name);
result = object_vacall(callable, vargs);
va_end(vargs);
Py_DECREF(callable);
return result;
}
PyObject *
PyObject_CallFunctionObjArgs(PyObject *callable, ...)
{
va_list vargs;
PyObject *result;
va_start(vargs, callable);
result = object_vacall(callable, vargs);
va_end(vargs);
return result;
}
/* isinstance(), issubclass() */
/* abstract_get_bases() has logically 4 return states:

1431
third_party/python/Objects/call.c vendored Normal file

File diff suppressed because it is too large Load diff

View file

@ -52,7 +52,7 @@ PyDoc_STRVAR(bytearray_translate__doc__,
"The remaining characters are mapped through the given translation table.");
#define BYTEARRAY_TRANSLATE_METHODDEF \
{"translate", (PyCFunction)bytearray_translate, METH_FASTCALL, bytearray_translate__doc__},
{"translate", (PyCFunction)bytearray_translate, METH_FASTCALL|METH_KEYWORDS, bytearray_translate__doc__},
static PyObject *
bytearray_translate_impl(PyByteArrayObject *self, PyObject *table,
@ -95,7 +95,7 @@ static PyObject *
bytearray_maketrans_impl(Py_buffer *frm, Py_buffer *to);
static PyObject *
bytearray_maketrans(void *null, PyObject **args, Py_ssize_t nargs, PyObject *kwnames)
bytearray_maketrans(void *null, PyObject **args, Py_ssize_t nargs)
{
PyObject *return_value = NULL;
Py_buffer frm = {NULL, NULL};
@ -105,10 +105,6 @@ bytearray_maketrans(void *null, PyObject **args, Py_ssize_t nargs, PyObject *kwn
&frm, &to)) {
goto exit;
}
if (!_PyArg_NoStackKeywords("maketrans", kwnames)) {
goto exit;
}
return_value = bytearray_maketrans_impl(&frm, &to);
exit:
@ -145,7 +141,7 @@ bytearray_replace_impl(PyByteArrayObject *self, Py_buffer *old,
Py_buffer *new, Py_ssize_t count);
static PyObject *
bytearray_replace(PyByteArrayObject *self, PyObject **args, Py_ssize_t nargs, PyObject *kwnames)
bytearray_replace(PyByteArrayObject *self, PyObject **args, Py_ssize_t nargs)
{
PyObject *return_value = NULL;
Py_buffer old = {NULL, NULL};
@ -156,10 +152,6 @@ bytearray_replace(PyByteArrayObject *self, PyObject **args, Py_ssize_t nargs, Py
&old, &new, &count)) {
goto exit;
}
if (!_PyArg_NoStackKeywords("replace", kwnames)) {
goto exit;
}
return_value = bytearray_replace_impl(self, &old, &new, count);
exit:
@ -190,7 +182,7 @@ PyDoc_STRVAR(bytearray_split__doc__,
" -1 (the default value) means no limit.");
#define BYTEARRAY_SPLIT_METHODDEF \
{"split", (PyCFunction)bytearray_split, METH_FASTCALL, bytearray_split__doc__},
{"split", (PyCFunction)bytearray_split, METH_FASTCALL|METH_KEYWORDS, bytearray_split__doc__},
static PyObject *
bytearray_split_impl(PyByteArrayObject *self, PyObject *sep,
@ -265,7 +257,7 @@ PyDoc_STRVAR(bytearray_rsplit__doc__,
"Splitting is done starting at the end of the bytearray and working to the front.");
#define BYTEARRAY_RSPLIT_METHODDEF \
{"rsplit", (PyCFunction)bytearray_rsplit, METH_FASTCALL, bytearray_rsplit__doc__},
{"rsplit", (PyCFunction)bytearray_rsplit, METH_FASTCALL|METH_KEYWORDS, bytearray_rsplit__doc__},
static PyObject *
bytearray_rsplit_impl(PyByteArrayObject *self, PyObject *sep,
@ -326,7 +318,7 @@ static PyObject *
bytearray_insert_impl(PyByteArrayObject *self, Py_ssize_t index, int item);
static PyObject *
bytearray_insert(PyByteArrayObject *self, PyObject **args, Py_ssize_t nargs, PyObject *kwnames)
bytearray_insert(PyByteArrayObject *self, PyObject **args, Py_ssize_t nargs)
{
PyObject *return_value = NULL;
Py_ssize_t index;
@ -336,10 +328,6 @@ bytearray_insert(PyByteArrayObject *self, PyObject **args, Py_ssize_t nargs, PyO
&index, _getbytevalue, &item)) {
goto exit;
}
if (!_PyArg_NoStackKeywords("insert", kwnames)) {
goto exit;
}
return_value = bytearray_insert_impl(self, index, item);
exit:
@ -407,7 +395,7 @@ static PyObject *
bytearray_pop_impl(PyByteArrayObject *self, Py_ssize_t index);
static PyObject *
bytearray_pop(PyByteArrayObject *self, PyObject **args, Py_ssize_t nargs, PyObject *kwnames)
bytearray_pop(PyByteArrayObject *self, PyObject **args, Py_ssize_t nargs)
{
PyObject *return_value = NULL;
Py_ssize_t index = -1;
@ -416,10 +404,6 @@ bytearray_pop(PyByteArrayObject *self, PyObject **args, Py_ssize_t nargs, PyObje
&index)) {
goto exit;
}
if (!_PyArg_NoStackKeywords("pop", kwnames)) {
goto exit;
}
return_value = bytearray_pop_impl(self, index);
exit:
@ -471,7 +455,7 @@ static PyObject *
bytearray_strip_impl(PyByteArrayObject *self, PyObject *bytes);
static PyObject *
bytearray_strip(PyByteArrayObject *self, PyObject **args, Py_ssize_t nargs, PyObject *kwnames)
bytearray_strip(PyByteArrayObject *self, PyObject **args, Py_ssize_t nargs)
{
PyObject *return_value = NULL;
PyObject *bytes = Py_None;
@ -481,10 +465,6 @@ bytearray_strip(PyByteArrayObject *self, PyObject **args, Py_ssize_t nargs, PyOb
&bytes)) {
goto exit;
}
if (!_PyArg_NoStackKeywords("strip", kwnames)) {
goto exit;
}
return_value = bytearray_strip_impl(self, bytes);
exit:
@ -506,7 +486,7 @@ static PyObject *
bytearray_lstrip_impl(PyByteArrayObject *self, PyObject *bytes);
static PyObject *
bytearray_lstrip(PyByteArrayObject *self, PyObject **args, Py_ssize_t nargs, PyObject *kwnames)
bytearray_lstrip(PyByteArrayObject *self, PyObject **args, Py_ssize_t nargs)
{
PyObject *return_value = NULL;
PyObject *bytes = Py_None;
@ -516,10 +496,6 @@ bytearray_lstrip(PyByteArrayObject *self, PyObject **args, Py_ssize_t nargs, PyO
&bytes)) {
goto exit;
}
if (!_PyArg_NoStackKeywords("lstrip", kwnames)) {
goto exit;
}
return_value = bytearray_lstrip_impl(self, bytes);
exit:
@ -541,7 +517,7 @@ static PyObject *
bytearray_rstrip_impl(PyByteArrayObject *self, PyObject *bytes);
static PyObject *
bytearray_rstrip(PyByteArrayObject *self, PyObject **args, Py_ssize_t nargs, PyObject *kwnames)
bytearray_rstrip(PyByteArrayObject *self, PyObject **args, Py_ssize_t nargs)
{
PyObject *return_value = NULL;
PyObject *bytes = Py_None;
@ -551,10 +527,6 @@ bytearray_rstrip(PyByteArrayObject *self, PyObject **args, Py_ssize_t nargs, PyO
&bytes)) {
goto exit;
}
if (!_PyArg_NoStackKeywords("rstrip", kwnames)) {
goto exit;
}
return_value = bytearray_rstrip_impl(self, bytes);
exit:
@ -577,7 +549,7 @@ PyDoc_STRVAR(bytearray_decode__doc__,
" can handle UnicodeDecodeErrors.");
#define BYTEARRAY_DECODE_METHODDEF \
{"decode", (PyCFunction)bytearray_decode, METH_FASTCALL, bytearray_decode__doc__},
{"decode", (PyCFunction)bytearray_decode, METH_FASTCALL|METH_KEYWORDS, bytearray_decode__doc__},
static PyObject *
bytearray_decode_impl(PyByteArrayObject *self, const char *encoding,
@ -625,7 +597,7 @@ PyDoc_STRVAR(bytearray_splitlines__doc__,
"true.");
#define BYTEARRAY_SPLITLINES_METHODDEF \
{"splitlines", (PyCFunction)bytearray_splitlines, METH_FASTCALL, bytearray_splitlines__doc__},
{"splitlines", (PyCFunction)bytearray_splitlines, METH_FASTCALL|METH_KEYWORDS, bytearray_splitlines__doc__},
static PyObject *
bytearray_splitlines_impl(PyByteArrayObject *self, int keepends);
@ -709,7 +681,7 @@ static PyObject *
bytearray_reduce_ex_impl(PyByteArrayObject *self, int proto);
static PyObject *
bytearray_reduce_ex(PyByteArrayObject *self, PyObject **args, Py_ssize_t nargs, PyObject *kwnames)
bytearray_reduce_ex(PyByteArrayObject *self, PyObject **args, Py_ssize_t nargs)
{
PyObject *return_value = NULL;
int proto = 0;
@ -718,10 +690,6 @@ bytearray_reduce_ex(PyByteArrayObject *self, PyObject **args, Py_ssize_t nargs,
&proto)) {
goto exit;
}
if (!_PyArg_NoStackKeywords("__reduce_ex__", kwnames)) {
goto exit;
}
return_value = bytearray_reduce_ex_impl(self, proto);
exit:
@ -745,4 +713,4 @@ bytearray_sizeof(PyByteArrayObject *self, PyObject *Py_UNUSED(ignored))
{
return bytearray_sizeof_impl(self);
}
/*[clinic end generated code: output=c1b1b83b0e19df74 input=a9049054013a1b77]*/
/*[clinic end generated code: output=c2804d009182328c input=a9049054013a1b77]*/

View file

@ -18,7 +18,7 @@ PyDoc_STRVAR(bytes_split__doc__,
" -1 (the default value) means no limit.");
#define BYTES_SPLIT_METHODDEF \
{"split", (PyCFunction)bytes_split, METH_FASTCALL, bytes_split__doc__},
{"split", (PyCFunction)bytes_split, METH_FASTCALL|METH_KEYWORDS, bytes_split__doc__},
static PyObject *
bytes_split_impl(PyBytesObject *self, PyObject *sep, Py_ssize_t maxsplit);
@ -137,7 +137,7 @@ PyDoc_STRVAR(bytes_rsplit__doc__,
"Splitting is done starting at the end of the bytes and working to the front.");
#define BYTES_RSPLIT_METHODDEF \
{"rsplit", (PyCFunction)bytes_rsplit, METH_FASTCALL, bytes_rsplit__doc__},
{"rsplit", (PyCFunction)bytes_rsplit, METH_FASTCALL|METH_KEYWORDS, bytes_rsplit__doc__},
static PyObject *
bytes_rsplit_impl(PyBytesObject *self, PyObject *sep, Py_ssize_t maxsplit);
@ -191,7 +191,7 @@ static PyObject *
bytes_strip_impl(PyBytesObject *self, PyObject *bytes);
static PyObject *
bytes_strip(PyBytesObject *self, PyObject **args, Py_ssize_t nargs, PyObject *kwnames)
bytes_strip(PyBytesObject *self, PyObject **args, Py_ssize_t nargs)
{
PyObject *return_value = NULL;
PyObject *bytes = Py_None;
@ -201,10 +201,6 @@ bytes_strip(PyBytesObject *self, PyObject **args, Py_ssize_t nargs, PyObject *kw
&bytes)) {
goto exit;
}
if (!_PyArg_NoStackKeywords("strip", kwnames)) {
goto exit;
}
return_value = bytes_strip_impl(self, bytes);
exit:
@ -226,7 +222,7 @@ static PyObject *
bytes_lstrip_impl(PyBytesObject *self, PyObject *bytes);
static PyObject *
bytes_lstrip(PyBytesObject *self, PyObject **args, Py_ssize_t nargs, PyObject *kwnames)
bytes_lstrip(PyBytesObject *self, PyObject **args, Py_ssize_t nargs)
{
PyObject *return_value = NULL;
PyObject *bytes = Py_None;
@ -236,10 +232,6 @@ bytes_lstrip(PyBytesObject *self, PyObject **args, Py_ssize_t nargs, PyObject *k
&bytes)) {
goto exit;
}
if (!_PyArg_NoStackKeywords("lstrip", kwnames)) {
goto exit;
}
return_value = bytes_lstrip_impl(self, bytes);
exit:
@ -261,7 +253,7 @@ static PyObject *
bytes_rstrip_impl(PyBytesObject *self, PyObject *bytes);
static PyObject *
bytes_rstrip(PyBytesObject *self, PyObject **args, Py_ssize_t nargs, PyObject *kwnames)
bytes_rstrip(PyBytesObject *self, PyObject **args, Py_ssize_t nargs)
{
PyObject *return_value = NULL;
PyObject *bytes = Py_None;
@ -271,10 +263,6 @@ bytes_rstrip(PyBytesObject *self, PyObject **args, Py_ssize_t nargs, PyObject *k
&bytes)) {
goto exit;
}
if (!_PyArg_NoStackKeywords("rstrip", kwnames)) {
goto exit;
}
return_value = bytes_rstrip_impl(self, bytes);
exit:
@ -294,7 +282,7 @@ PyDoc_STRVAR(bytes_translate__doc__,
"The remaining characters are mapped through the given translation table.");
#define BYTES_TRANSLATE_METHODDEF \
{"translate", (PyCFunction)bytes_translate, METH_FASTCALL, bytes_translate__doc__},
{"translate", (PyCFunction)bytes_translate, METH_FASTCALL|METH_KEYWORDS, bytes_translate__doc__},
static PyObject *
bytes_translate_impl(PyBytesObject *self, PyObject *table,
@ -337,7 +325,7 @@ static PyObject *
bytes_maketrans_impl(Py_buffer *frm, Py_buffer *to);
static PyObject *
bytes_maketrans(void *null, PyObject **args, Py_ssize_t nargs, PyObject *kwnames)
bytes_maketrans(void *null, PyObject **args, Py_ssize_t nargs)
{
PyObject *return_value = NULL;
Py_buffer frm = {NULL, NULL};
@ -347,10 +335,6 @@ bytes_maketrans(void *null, PyObject **args, Py_ssize_t nargs, PyObject *kwnames
&frm, &to)) {
goto exit;
}
if (!_PyArg_NoStackKeywords("maketrans", kwnames)) {
goto exit;
}
return_value = bytes_maketrans_impl(&frm, &to);
exit:
@ -387,7 +371,7 @@ bytes_replace_impl(PyBytesObject *self, Py_buffer *old, Py_buffer *new,
Py_ssize_t count);
static PyObject *
bytes_replace(PyBytesObject *self, PyObject **args, Py_ssize_t nargs, PyObject *kwnames)
bytes_replace(PyBytesObject *self, PyObject **args, Py_ssize_t nargs)
{
PyObject *return_value = NULL;
Py_buffer old = {NULL, NULL};
@ -398,10 +382,6 @@ bytes_replace(PyBytesObject *self, PyObject **args, Py_ssize_t nargs, PyObject *
&old, &new, &count)) {
goto exit;
}
if (!_PyArg_NoStackKeywords("replace", kwnames)) {
goto exit;
}
return_value = bytes_replace_impl(self, &old, &new, count);
exit:
@ -433,7 +413,7 @@ PyDoc_STRVAR(bytes_decode__doc__,
" can handle UnicodeDecodeErrors.");
#define BYTES_DECODE_METHODDEF \
{"decode", (PyCFunction)bytes_decode, METH_FASTCALL, bytes_decode__doc__},
{"decode", (PyCFunction)bytes_decode, METH_FASTCALL|METH_KEYWORDS, bytes_decode__doc__},
static PyObject *
bytes_decode_impl(PyBytesObject *self, const char *encoding,
@ -468,7 +448,7 @@ PyDoc_STRVAR(bytes_splitlines__doc__,
"true.");
#define BYTES_SPLITLINES_METHODDEF \
{"splitlines", (PyCFunction)bytes_splitlines, METH_FASTCALL, bytes_splitlines__doc__},
{"splitlines", (PyCFunction)bytes_splitlines, METH_FASTCALL|METH_KEYWORDS, bytes_splitlines__doc__},
static PyObject *
bytes_splitlines_impl(PyBytesObject *self, int keepends);
@ -520,4 +500,4 @@ bytes_fromhex(PyTypeObject *type, PyObject *arg)
exit:
return return_value;
}
/*[clinic end generated code: output=debf785947e0eec2 input=a9049054013a1b77]*/
/*[clinic end generated code: output=fc9e02359cc56d36 input=a9049054013a1b77]*/

View file

@ -16,7 +16,7 @@ static PyObject *
dict_fromkeys_impl(PyTypeObject *type, PyObject *iterable, PyObject *value);
static PyObject *
dict_fromkeys(PyTypeObject *type, PyObject **args, Py_ssize_t nargs, PyObject *kwnames)
dict_fromkeys(PyTypeObject *type, PyObject **args, Py_ssize_t nargs)
{
PyObject *return_value = NULL;
PyObject *iterable;
@ -27,10 +27,6 @@ dict_fromkeys(PyTypeObject *type, PyObject **args, Py_ssize_t nargs, PyObject *k
&iterable, &value)) {
goto exit;
}
if (!_PyArg_NoStackKeywords("fromkeys", kwnames)) {
goto exit;
}
return_value = dict_fromkeys_impl(type, iterable, value);
exit:
@ -45,4 +41,4 @@ PyDoc_STRVAR(dict___contains____doc__,
#define DICT___CONTAINS___METHODDEF \
{"__contains__", (PyCFunction)dict___contains__, METH_O|METH_COEXIST, dict___contains____doc__},
/*[clinic end generated code: output=69f3d767ed44e8ec input=a9049054013a1b77]*/
/*[clinic end generated code: output=d6997a57899cf28d input=a9049054013a1b77]*/

View file

@ -1,136 +0,0 @@
/* clang-format off */
/*[clinic input]
preserve
[clinic start generated code]*/
PyDoc_STRVAR(OrderedDict_fromkeys__doc__,
"fromkeys($type, /, iterable, value=None)\n"
"--\n"
"\n"
"New ordered dictionary with keys from S.\n"
"\n"
"If not specified, the value defaults to None.");
#define ORDEREDDICT_FROMKEYS_METHODDEF \
{"fromkeys", (PyCFunction)OrderedDict_fromkeys, METH_FASTCALL|METH_CLASS, OrderedDict_fromkeys__doc__},
static PyObject *
OrderedDict_fromkeys_impl(PyTypeObject *type, PyObject *seq, PyObject *value);
static PyObject *
OrderedDict_fromkeys(PyTypeObject *type, PyObject **args, Py_ssize_t nargs, PyObject *kwnames)
{
PyObject *return_value = NULL;
static const char * const _keywords[] = {"iterable", "value", NULL};
static _PyArg_Parser _parser = {"O|O:fromkeys", _keywords, 0};
PyObject *seq;
PyObject *value = Py_None;
if (!_PyArg_ParseStackAndKeywords(args, nargs, kwnames, &_parser,
&seq, &value)) {
goto exit;
}
return_value = OrderedDict_fromkeys_impl(type, seq, value);
exit:
return return_value;
}
PyDoc_STRVAR(OrderedDict_setdefault__doc__,
"setdefault($self, /, key, default=None)\n"
"--\n"
"\n"
"od.get(k,d), also set od[k]=d if k not in od.");
#define ORDEREDDICT_SETDEFAULT_METHODDEF \
{"setdefault", (PyCFunction)OrderedDict_setdefault, METH_FASTCALL, OrderedDict_setdefault__doc__},
static PyObject *
OrderedDict_setdefault_impl(PyODictObject *self, PyObject *key,
PyObject *failobj);
static PyObject *
OrderedDict_setdefault(PyODictObject *self, PyObject **args, Py_ssize_t nargs, PyObject *kwnames)
{
PyObject *return_value = NULL;
static const char * const _keywords[] = {"key", "default", NULL};
static _PyArg_Parser _parser = {"O|O:setdefault", _keywords, 0};
PyObject *key;
PyObject *failobj = Py_None;
if (!_PyArg_ParseStackAndKeywords(args, nargs, kwnames, &_parser,
&key, &failobj)) {
goto exit;
}
return_value = OrderedDict_setdefault_impl(self, key, failobj);
exit:
return return_value;
}
PyDoc_STRVAR(OrderedDict_popitem__doc__,
"popitem($self, /, last=True)\n"
"--\n"
"\n"
"Return (k, v) and remove a (key, value) pair.\n"
"\n"
"Pairs are returned in LIFO order if last is true or FIFO order if false.");
#define ORDEREDDICT_POPITEM_METHODDEF \
{"popitem", (PyCFunction)OrderedDict_popitem, METH_FASTCALL, OrderedDict_popitem__doc__},
static PyObject *
OrderedDict_popitem_impl(PyODictObject *self, int last);
static PyObject *
OrderedDict_popitem(PyODictObject *self, PyObject **args, Py_ssize_t nargs, PyObject *kwnames)
{
PyObject *return_value = NULL;
static const char * const _keywords[] = {"last", NULL};
static _PyArg_Parser _parser = {"|p:popitem", _keywords, 0};
int last = 1;
if (!_PyArg_ParseStackAndKeywords(args, nargs, kwnames, &_parser,
&last)) {
goto exit;
}
return_value = OrderedDict_popitem_impl(self, last);
exit:
return return_value;
}
PyDoc_STRVAR(OrderedDict_move_to_end__doc__,
"move_to_end($self, /, key, last=True)\n"
"--\n"
"\n"
"\"Move an existing element to the end (or beginning if last==False).\n"
"\n"
" Raises KeyError if the element does not exist.\n"
" When last=True, acts like a fast version of self[key]=self.pop(key).");
#define ORDEREDDICT_MOVE_TO_END_METHODDEF \
{"move_to_end", (PyCFunction)OrderedDict_move_to_end, METH_FASTCALL, OrderedDict_move_to_end__doc__},
static PyObject *
OrderedDict_move_to_end_impl(PyODictObject *self, PyObject *key, int last);
static PyObject *
OrderedDict_move_to_end(PyODictObject *self, PyObject **args, Py_ssize_t nargs, PyObject *kwnames)
{
PyObject *return_value = NULL;
static const char * const _keywords[] = {"key", "last", NULL};
static _PyArg_Parser _parser = {"O|p:move_to_end", _keywords, 0};
PyObject *key;
int last = 1;
if (!_PyArg_ParseStackAndKeywords(args, nargs, kwnames, &_parser,
&key, &last)) {
goto exit;
}
return_value = OrderedDict_move_to_end_impl(self, key, last);
exit:
return return_value;
}
/*[clinic end generated code: output=f2641e1277045b59 input=a9049054013a1b77]*/

View file

@ -24,7 +24,7 @@ static PyObject *
unicode_maketrans_impl(PyObject *x, PyObject *y, PyObject *z);
static PyObject *
unicode_maketrans(void *null, PyObject **args, Py_ssize_t nargs, PyObject *kwnames)
unicode_maketrans(void *null, PyObject **args, Py_ssize_t nargs)
{
PyObject *return_value = NULL;
PyObject *x;
@ -35,13 +35,9 @@ unicode_maketrans(void *null, PyObject **args, Py_ssize_t nargs, PyObject *kwnam
&x, &y, &z)) {
goto exit;
}
if (!_PyArg_NoStackKeywords("maketrans", kwnames)) {
goto exit;
}
return_value = unicode_maketrans_impl(x, y, z);
exit:
return return_value;
}
/*[clinic end generated code: output=af4804dbf21463b5 input=a9049054013a1b77]*/
/*[clinic end generated code: output=d1e48260a99031c2 input=a9049054013a1b77]*/

View file

@ -264,6 +264,44 @@ methoddescr_call(PyMethodDescrObject *descr, PyObject *args, PyObject *kwargs)
return result;
}
// same to methoddescr_call(), but use FASTCALL convention.
PyObject *
_PyMethodDescr_FastCallKeywords(PyObject *descrobj,
PyObject *const *args, Py_ssize_t nargs,
PyObject *kwnames)
{
assert(Py_TYPE(descrobj) == &PyMethodDescr_Type);
PyMethodDescrObject *descr = (PyMethodDescrObject *)descrobj;
PyObject *self, *result;
/* Make sure that the first argument is acceptable as 'self' */
if (nargs < 1) {
PyErr_Format(PyExc_TypeError,
"descriptor '%V' of '%.100s' "
"object needs an argument",
descr_name((PyDescrObject *)descr), "?",
PyDescr_TYPE(descr)->tp_name);
return NULL;
}
self = args[0];
if (!_PyObject_RealIsSubclass((PyObject *)Py_TYPE(self),
(PyObject *)PyDescr_TYPE(descr))) {
PyErr_Format(PyExc_TypeError,
"descriptor '%V' "
"requires a '%.100s' object "
"but received a '%.100s'",
descr_name((PyDescrObject *)descr), "?",
PyDescr_TYPE(descr)->tp_name,
self->ob_type->tp_name);
return NULL;
}
result = _PyMethodDef_RawFastCallKeywords(descr->d_method, self,
args+1, nargs-1, kwnames);
result = _Py_CheckFunctionResult((PyObject *)descr, result, NULL);
return result;
}
static PyObject *
classmethoddescr_call(PyMethodDescrObject *descr, PyObject *args,
PyObject *kwds)

View file

@ -748,7 +748,7 @@ the <dummy> value.
For both, when the key isn't found a DKIX_EMPTY is returned. hashpos returns
where the key index should be inserted.
*/
static Py_ssize_t
static Py_ssize_t _Py_HOT_FUNCTION
lookdict(PyDictObject *mp, PyObject *key,
Py_hash_t hash, PyObject ***value_addr, Py_ssize_t *hashpos)
{
@ -862,7 +862,7 @@ top:
}
/* Specialized version for string-only keys */
static Py_ssize_t
static Py_ssize_t _Py_HOT_FUNCTION
lookdict_unicode(PyDictObject *mp, PyObject *key,
Py_hash_t hash, PyObject ***value_addr, Py_ssize_t *hashpos)
{
@ -936,7 +936,7 @@ lookdict_unicode(PyDictObject *mp, PyObject *key,
/* Faster version of lookdict_unicode when it is known that no <dummy> keys
* will be present. */
static Py_ssize_t
static Py_ssize_t _Py_HOT_FUNCTION
lookdict_unicode_nodummy(PyDictObject *restrict mp, PyObject *restrict key,
Py_hash_t hash, PyObject ***value_addr,
Py_ssize_t *hashpos)
@ -1003,7 +1003,7 @@ lookdict_unicode_nodummy(PyDictObject *restrict mp, PyObject *restrict key,
* Split tables only contain unicode keys and no dummy keys,
* so algorithm is the same as lookdict_unicode_nodummy.
*/
static Py_ssize_t
static Py_ssize_t _Py_HOT_FUNCTION
lookdict_split(PyDictObject *mp, PyObject *key,
Py_hash_t hash, PyObject ***value_addr, Py_ssize_t *hashpos)
{
@ -2911,7 +2911,7 @@ dict___contains__(PyDictObject *self, PyObject *key)
}
static PyObject *
dict_get(PyDictObject *mp, PyObject **args, Py_ssize_t nargs, PyObject *kwnames)
dict_get(PyDictObject *mp, PyObject **args, Py_ssize_t nargs)
{
PyObject *key;
PyObject *failobj = Py_None;
@ -2923,9 +2923,6 @@ dict_get(PyDictObject *mp, PyObject **args, Py_ssize_t nargs, PyObject *kwnames)
if (!_PyArg_UnpackStack(args, nargs, "get", 1, 2, &key, &failobj))
return NULL;
if (!_PyArg_NoStackKeywords("get", kwnames))
return NULL;
if (!PyUnicode_CheckExact(key) ||
(hash = ((PyASCIIObject *) key)->hash) == -1) {
hash = PyObject_Hash(key);
@ -3032,7 +3029,7 @@ PyDict_SetDefault(PyObject *d, PyObject *key, PyObject *defaultobj)
}
static PyObject *
dict_setdefault(PyDictObject *mp, PyObject **args, Py_ssize_t nargs, PyObject *kwnames)
dict_setdefault(PyDictObject *mp, PyObject **args, Py_ssize_t nargs)
{
PyObject *key, *val;
PyObject *defaultobj = Py_None;
@ -3040,9 +3037,6 @@ dict_setdefault(PyDictObject *mp, PyObject **args, Py_ssize_t nargs, PyObject *k
if (!_PyArg_UnpackStack(args, nargs, "setdefault", 1, 2, &key, &defaultobj))
return NULL;
if(!_PyArg_NoStackKeywords("pop", kwnames))
return NULL;
val = PyDict_SetDefault((PyObject *)mp, key, defaultobj);
Py_XINCREF(val);
return val;
@ -3056,16 +3050,13 @@ dict_clear(PyDictObject *mp)
}
static PyObject *
dict_pop(PyDictObject *mp, PyObject **args, Py_ssize_t nargs, PyObject *kwnames)
dict_pop(PyDictObject *mp, PyObject **args, Py_ssize_t nargs)
{
PyObject *key, *deflt = NULL;
if(!_PyArg_UnpackStack(args, nargs, "pop", 1, 2, &key, &deflt))
return NULL;
if(!_PyArg_NoStackKeywords("pop", kwnames))
return NULL;
return _PyDict_Pop((PyObject*)mp, key, deflt);
}

View file

@ -364,7 +364,7 @@ PyFile_NewStdPrinter(int fd)
}
static PyObject *
stdprinter_write(PyStdPrinter_Object *self, PyObject **args, Py_ssize_t nargs, PyObject *kwnames)
stdprinter_write(PyStdPrinter_Object *self, PyObject **args, Py_ssize_t nargs)
{
PyObject *unicode;
PyObject *bytes = NULL;
@ -383,9 +383,6 @@ stdprinter_write(PyStdPrinter_Object *self, PyObject **args, Py_ssize_t nargs, P
if (!_PyArg_UnpackStack(args, nargs, "write", 1, 1, &unicode))
return NULL;
if(!_PyArg_NoStackKeywords("write", kwnames))
return NULL;
/* encode Unicode to UTF-8 */
str = PyUnicode_AsUTF8AndSize(unicode, &n);
if (str == NULL) {

View file

@ -1038,7 +1038,7 @@ double_round(double x, int ndigits) {
/* round a Python float v to the closest multiple of 10**-ndigits */
static PyObject *
float_round(PyObject *v, PyObject **args, Py_ssize_t nargs, PyObject *kwnames)
float_round(PyObject *v, PyObject **args, Py_ssize_t nargs)
{
double x, rounded;
PyObject *o_ndigits = NULL;
@ -1048,9 +1048,6 @@ float_round(PyObject *v, PyObject **args, Py_ssize_t nargs, PyObject *kwnames)
if (!_PyArg_UnpackStack(args, nargs, "__round__", 0, 1, &o_ndigits))
return NULL;
if(!_PyArg_NoStackKeywords("__round__", kwnames))
return NULL;
if (o_ndigits == NULL || o_ndigits == Py_None) {
/* single-argument round or with None ndigits:
* round to nearest integer */
@ -1766,7 +1763,7 @@ float_getzero(PyObject *v, void *closure)
}
static PyObject *
float__format__(PyObject *self, PyObject **args, Py_ssize_t nargs, PyObject *kwnames)
float__format__(PyObject *self, PyObject **args, Py_ssize_t nargs)
{
PyObject *format_spec;
_PyUnicodeWriter writer;
@ -1775,9 +1772,6 @@ float__format__(PyObject *self, PyObject **args, Py_ssize_t nargs, PyObject *kwn
if (!_PyArg_ParseStack(args, nargs, "U:__format__", &format_spec))
return NULL;
if(!_PyArg_NoStackKeywords("__format__", kwnames))
return NULL;
_PyUnicodeWriter_Init(&writer);
ret = _PyFloat_FormatAdvancedWriter(
&writer,

View file

@ -461,13 +461,15 @@ static int numfree;
static PyFrameObject *free_list;
#define PyFrame_MAXFREELIST 200
static void
static void _Py_HOT_FUNCTION
frame_dealloc(PyFrameObject *restrict f)
{
PyObject **p, **valuestack;
PyCodeObject *co;
PyObject_GC_UnTrack(f);
if (_PyObject_GC_IS_TRACKED(f))
_PyObject_GC_UNTRACK(f);
Py_TRASHCAN_SAFE_BEGIN(f)
/* Kill all local variables */
valuestack = f->f_valuestack;
@ -658,9 +660,9 @@ int _PyFrame_Init()
return 1;
}
PyFrameObject *
PyFrame_New(PyThreadState *tstate, PyCodeObject *code, PyObject *globals,
PyObject *locals)
PyFrameObject* _Py_HOT_FUNCTION
_PyFrame_New_NoTrack(PyThreadState *tstate, PyCodeObject *code,
PyObject *globals, PyObject *locals)
{
PyFrameObject *back = tstate->frame;
PyFrameObject *f;
@ -715,7 +717,8 @@ PyFrame_New(PyThreadState *tstate, PyCodeObject *code, PyObject *globals,
extras = code->co_stacksize + code->co_nlocals + ncells +
nfrees;
if (free_list == NULL) {
f = PyObject_GC_NewVar(PyFrameObject, &PyFrame_Type, extras);
f = PyObject_GC_NewVar(PyFrameObject, &PyFrame_Type,
extras);
if (f == NULL) {
Py_DECREF(builtins);
return NULL;
@ -779,7 +782,16 @@ PyFrame_New(PyThreadState *tstate, PyCodeObject *code, PyObject *globals,
f->f_executing = 0;
f->f_gen = NULL;
_PyObject_GC_TRACK(f);
return f;
}
PyFrameObject*
PyFrame_New(PyThreadState *tstate, PyCodeObject *code,
PyObject *globals, PyObject *locals)
{
PyFrameObject *f = _PyFrame_New_NoTrack(tstate, code, globals, locals);
if (f)
_PyObject_GC_TRACK(f);
return f;
}

View file

@ -755,12 +755,11 @@ list_ass_item(PyListObject *a, Py_ssize_t i, PyObject *v)
}
static PyObject *
listinsert(PyListObject *self, PyObject **args, Py_ssize_t nargs, PyObject *kwnames)
listinsert(PyListObject *self, PyObject **args, Py_ssize_t nargs)
{
Py_ssize_t i;
PyObject *v;
if (!_PyArg_ParseStack(args, nargs, "nO:insert", &i, &v)
|| !_PyArg_NoStackKeywords("insert", kwnames))
if (!_PyArg_ParseStack(args, nargs, "nO:insert", &i, &v))
return NULL;
if (ins1(self, i, v) == 0)
Py_RETURN_NONE;
@ -921,14 +920,13 @@ list_inplace_concat(PyListObject *self, PyObject *other)
}
static PyObject *
listpop(PyListObject *self, PyObject **args, Py_ssize_t nargs, PyObject *kwnames)
listpop(PyListObject *self, PyObject **args, Py_ssize_t nargs)
{
Py_ssize_t i = -1;
PyObject *v;
int status;
if (!_PyArg_ParseStack(args, nargs, "|n:pop", &i)
|| !_PyArg_NoStackKeywords("pop", kwnames))
if (!_PyArg_ParseStack(args, nargs, "|n:pop", &i))
return NULL;
if (Py_SIZE(self) == 0) {

View file

@ -4907,7 +4907,7 @@ long_get1(PyLongObject *v, void *context) {
}
static PyObject *
long__format__(PyObject *self, PyObject **args, Py_ssize_t nargs, PyObject *kwnames)
long__format__(PyObject *self, PyObject **args, Py_ssize_t nargs)
{
PyObject *format_spec;
_PyUnicodeWriter writer;
@ -5026,7 +5026,7 @@ _PyLong_DivmodNear(PyObject *a, PyObject *b)
}
static PyObject *
long_round(PyObject *self, PyObject **args, Py_ssize_t nargs, PyObject *kwnames)
long_round(PyObject *self, PyObject **args, Py_ssize_t nargs)
{
PyObject *o_ndigits=NULL, *temp, *result, *ndigits;

View file

@ -90,331 +90,6 @@ PyCFunction_GetFlags(PyObject *op)
return PyCFunction_GET_FLAGS(op);
}
static PyObject *
cfunction_call_varargs(PyObject *func, PyObject *args, PyObject *kwargs)
{
assert(!PyErr_Occurred());
PyCFunction meth = PyCFunction_GET_FUNCTION(func);
PyObject *self = PyCFunction_GET_SELF(func);
PyObject *result;
if (PyCFunction_GET_FLAGS(func) & METH_KEYWORDS) {
if (Py_EnterRecursiveCall(" while calling a Python object")) {
return NULL;
}
result = (*(PyCFunctionWithKeywords)meth)(self, args, kwargs);
Py_LeaveRecursiveCall();
}
else {
if (kwargs != NULL && PyDict_Size(kwargs) != 0) {
PyErr_Format(PyExc_TypeError, "%.200s() takes no keyword arguments",
((PyCFunctionObject*)func)->m_ml->ml_name);
return NULL;
}
if (Py_EnterRecursiveCall(" while calling a Python object")) {
return NULL;
}
result = (*meth)(self, args);
Py_LeaveRecursiveCall();
}
return _Py_CheckFunctionResult(func, result, NULL);
}
PyObject *
PyCFunction_Call(PyObject *func, PyObject *args, PyObject *kwargs)
{
/* first try METH_VARARGS to pass directly args tuple unchanged.
_PyMethodDef_RawFastCallDict() creates a new temporary tuple
for METH_VARARGS. */
if (PyCFunction_GET_FLAGS(func) & METH_VARARGS) {
return cfunction_call_varargs(func, args, kwargs);
}
else {
return _PyCFunction_FastCallDict(func,
&PyTuple_GET_ITEM(args, 0),
PyTuple_GET_SIZE(args),
kwargs);
}
}
PyObject *
_PyMethodDef_RawFastCallDict(PyMethodDef *method, PyObject *self, PyObject **args,
Py_ssize_t nargs, PyObject *kwargs)
{
/* _PyMethodDef_RawFastCallDict() must not be called with an exception set,
because it can clear it (directly or indirectly) and so the
caller loses its exception */
assert(!PyErr_Occurred());
assert(method != NULL);
assert(nargs >= 0);
assert(nargs == 0 || args != NULL);
assert(kwargs == NULL || PyDict_Check(kwargs));
PyCFunction meth = method->ml_meth;
int flags = method->ml_flags & ~(METH_CLASS | METH_STATIC | METH_COEXIST);
PyObject *result = NULL;
if (Py_EnterRecursiveCall(" while calling a Python object")) {
return NULL;
}
switch (flags)
{
case METH_NOARGS:
if (nargs != 0) {
PyErr_Format(PyExc_TypeError,
"%.200s() takes no arguments (%zd given)",
method->ml_name, nargs);
goto exit;
}
if (kwargs != NULL && PyDict_GET_SIZE(kwargs) != 0) {
goto no_keyword_error;
}
result = (*meth) (self, NULL);
break;
case METH_O:
if (nargs != 1) {
PyErr_Format(PyExc_TypeError,
"%.200s() takes exactly one argument (%zd given)",
method->ml_name, nargs);
goto exit;
}
if (kwargs != NULL && PyDict_GET_SIZE(kwargs) != 0) {
goto no_keyword_error;
}
result = (*meth) (self, args[0]);
break;
case METH_VARARGS:
if (!(flags & METH_KEYWORDS)
&& kwargs != NULL && PyDict_GET_SIZE(kwargs) != 0) {
goto no_keyword_error;
}
/* fall through next case */
case METH_VARARGS | METH_KEYWORDS:
{
/* Slow-path: create a temporary tuple for positional arguments */
PyObject *argstuple = _PyStack_AsTuple(args, nargs);
if (argstuple == NULL) {
goto exit;
}
if (flags & METH_KEYWORDS) {
result = (*(PyCFunctionWithKeywords)meth) (self, argstuple, kwargs);
}
else {
result = (*meth) (self, argstuple);
}
Py_DECREF(argstuple);
break;
}
case METH_FASTCALL:
{
PyObject **stack;
PyObject *kwnames;
_PyCFunctionFast fastmeth = (_PyCFunctionFast)meth;
if (_PyStack_UnpackDict(args, nargs, kwargs, &stack, &kwnames) < 0) {
goto exit;
}
result = (*fastmeth) (self, stack, nargs, kwnames);
if (stack != args) {
PyMem_Free(stack);
}
Py_XDECREF(kwnames);
break;
}
default:
PyErr_SetString(PyExc_SystemError,
"Bad call flags in _PyMethodDef_RawFastCallDict. "
"METH_OLDARGS is no longer supported!");
goto exit;
}
goto exit;
no_keyword_error:
PyErr_Format(PyExc_TypeError,
"%.200s() takes no keyword arguments",
method->ml_name, nargs);
exit:
Py_LeaveRecursiveCall();
return result;
}
PyObject *
_PyCFunction_FastCallDict(PyObject *func, PyObject **args, Py_ssize_t nargs,
PyObject *kwargs)
{
PyObject *result;
assert(func != NULL);
assert(PyCFunction_Check(func));
result = _PyMethodDef_RawFastCallDict(((PyCFunctionObject*)func)->m_ml,
PyCFunction_GET_SELF(func),
args, nargs, kwargs);
result = _Py_CheckFunctionResult(func, result, NULL);
return result;
}
PyObject *
_PyMethodDef_RawFastCallKeywords(PyMethodDef *method, PyObject *self, PyObject **args,
Py_ssize_t nargs, PyObject *kwnames)
{
/* _PyMethodDef_RawFastCallKeywords() must not be called with an exception set,
because it can clear it (directly or indirectly) and so the
caller loses its exception */
assert(!PyErr_Occurred());
assert(method != NULL);
assert(nargs >= 0);
assert(kwnames == NULL || PyTuple_CheckExact(kwnames));
/* kwnames must only contains str strings, no subclass, and all keys must
be unique */
PyCFunction meth = method->ml_meth;
int flags = method->ml_flags & ~(METH_CLASS | METH_STATIC | METH_COEXIST);
Py_ssize_t nkwargs = kwnames == NULL ? 0 : PyTuple_Size(kwnames);
PyObject *result = NULL;
if (Py_EnterRecursiveCall(" while calling a Python object")) {
return NULL;
}
switch (flags)
{
case METH_NOARGS:
if (nargs != 0) {
PyErr_Format(PyExc_TypeError,
"%.200s() takes no arguments (%zd given)",
method->ml_name, nargs);
goto exit;
}
if (nkwargs) {
goto no_keyword_error;
}
result = (*meth) (self, NULL);
break;
case METH_O:
if (nargs != 1) {
PyErr_Format(PyExc_TypeError,
"%.200s() takes exactly one argument (%zd given)",
method->ml_name, nargs);
goto exit;
}
if (nkwargs) {
goto no_keyword_error;
}
result = (*meth) (self, args[0]);
break;
case METH_FASTCALL:
/* Fast-path: avoid temporary dict to pass keyword arguments */
result = ((_PyCFunctionFast)meth) (self, args, nargs, kwnames);
break;
case METH_VARARGS:
case METH_VARARGS | METH_KEYWORDS:
{
/* Slow-path: create a temporary tuple for positional arguments
and a temporary dict for keyword arguments */
PyObject *argtuple;
if (!(flags & METH_KEYWORDS) && nkwargs) {
goto no_keyword_error;
}
argtuple = _PyStack_AsTuple(args, nargs);
if (argtuple == NULL) {
goto exit;
}
if (flags & METH_KEYWORDS) {
PyObject *kwdict;
if (nkwargs > 0) {
kwdict = _PyStack_AsDict(args + nargs, kwnames);
if (kwdict == NULL) {
Py_DECREF(argtuple);
goto exit;
}
}
else {
kwdict = NULL;
}
result = (*(PyCFunctionWithKeywords)meth) (self, argtuple, kwdict);
Py_XDECREF(kwdict);
}
else {
result = (*meth) (self, argtuple);
}
Py_DECREF(argtuple);
break;
}
default:
PyErr_SetString(PyExc_SystemError,
"Bad call flags in _PyCFunction_FastCallKeywords. "
"METH_OLDARGS is no longer supported!");
goto exit;
}
goto exit;
no_keyword_error:
PyErr_Format(PyExc_TypeError,
"%.200s() takes no keyword arguments",
method->ml_name);
exit:
Py_LeaveRecursiveCall();
return result;
}
PyObject *
_PyCFunction_FastCallKeywords(PyObject *func, PyObject **args,
Py_ssize_t nargs, PyObject *kwnames)
{
PyObject *result;
assert(func != NULL);
assert(PyCFunction_Check(func));
result = _PyMethodDef_RawFastCallKeywords(((PyCFunctionObject*)func)->m_ml,
PyCFunction_GET_SELF(func),
args, nargs, kwnames);
result = _Py_CheckFunctionResult(func, result, NULL);
return result;
}
/* Methods (the standard built-in methods, that is) */
static void

View file

@ -1091,6 +1091,89 @@ _PyObject_NextNotImplemented(PyObject *self)
return NULL;
}
/* Specialized version of _PyObject_GenericGetAttrWithDict
specifically for the LOAD_METHOD opcode.
Return 1 if a method is found, 0 if it's a regular attribute
from __dict__ or something returned by using a descriptor
protocol.
`method` will point to the resolved attribute or NULL. In the
latter case, an error will be set.
*/
int
_PyObject_GetMethod(PyObject *obj, PyObject *name, PyObject **method)
{
PyTypeObject *tp = Py_TYPE(obj);
PyObject *descr;
descrgetfunc f = NULL;
PyObject **dictptr, *dict;
PyObject *attr;
int meth_found = 0;
assert(*method == NULL);
if (Py_TYPE(obj)->tp_getattro != PyObject_GenericGetAttr
|| !PyUnicode_Check(name)) {
*method = PyObject_GetAttr(obj, name);
return 0;
}
if (tp->tp_dict == NULL && PyType_Ready(tp) < 0)
return 0;
descr = _PyType_Lookup(tp, name);
if (descr != NULL) {
Py_INCREF(descr);
if (PyFunction_Check(descr) ||
(Py_TYPE(descr) == &PyMethodDescr_Type)) {
meth_found = 1;
} else {
f = descr->ob_type->tp_descr_get;
if (f != NULL && PyDescr_IsData(descr)) {
*method = f(descr, obj, (PyObject *)obj->ob_type);
Py_DECREF(descr);
return 0;
}
}
}
dictptr = _PyObject_GetDictPtr(obj);
if (dictptr != NULL && (dict = *dictptr) != NULL) {
Py_INCREF(dict);
attr = PyDict_GetItem(dict, name);
if (attr != NULL) {
Py_INCREF(attr);
*method = attr;
Py_DECREF(dict);
Py_XDECREF(descr);
return 0;
}
Py_DECREF(dict);
}
if (meth_found) {
*method = descr;
return 1;
}
if (f != NULL) {
*method = f(descr, obj, (PyObject *)Py_TYPE(obj));
Py_DECREF(descr);
return 0;
}
if (descr != NULL) {
*method = descr;
return 0;
}
PyErr_Format(PyExc_AttributeError,
"'%.50s' object has no attribute '%U'",
tp->tp_name, name);
return 0;
}
/* Generic GetAttr functions - put these in your tp_[gs]etattro slot */
PyObject *

View file

@ -90,7 +90,7 @@ Linked-List API
As noted, the linked-list implemented here does not have all the bells and
whistles. However, we recognize that the implementation may need to
change to accommodate performance improvements or extra functionality. To
that end, We use a simple API to interact with the linked-list. Here's a
that end, we use a simple API to interact with the linked-list. Here's a
summary of the methods/macros:
Node info:
@ -124,10 +124,6 @@ Others:
* _odict_find_node(od, key)
* _odict_keys_equal(od1, od2)
Used, but specific to the linked-list implementation:
* _odict_free_fast_nodes(od)
And here's a look at how the linked-list relates to the OrderedDict API:
============ === === ==== ==== ==== === ==== ===== ==== ==== === ==== === ===
@ -401,7 +397,6 @@ tp_iter odict_iter
tp_dictoffset (offset)
tp_init odict_init
tp_alloc (repeated)
tp_new odict_new
================= ================
================= ================
@ -467,7 +462,7 @@ Potential Optimizations
- Set node->key to NULL to indicate the node is not-in-use.
- Add _odict_EXISTS()?
- How to maintain consistency across resizes? Existing node pointers
would be invalidate after a resize, which is particularly problematic
would be invalidated after a resize, which is particularly problematic
for the iterators.
* Use a more stream-lined implementation of update() and, likely indirectly,
__init__().
@ -492,14 +487,6 @@ later:
*/
#include "third_party/python/Objects/clinic/odictobject.inc"
/*[clinic input]
class OrderedDict "PyODictObject *" "&PyODict_Type"
[clinic start generated code]*/
/*[clinic end generated code: output=da39a3ee5e6b4b0d input=ca0641cf6143d4af]*/
typedef struct _odictnode _ODictNode;
/* PyODictObject */
@ -547,24 +534,15 @@ struct _odictnode {
#define _odict_FOREACH(od, node) \
for (node = _odict_FIRST(od); node != NULL; node = _odictnode_NEXT(node))
#define _odict_FAST_SIZE(od) ((PyDictObject *)od)->ma_keys->dk_size
static void
_odict_free_fast_nodes(PyODictObject *od) {
if (od->od_fast_nodes) {
PyMem_FREE(od->od_fast_nodes);
}
}
/* Return the index into the hash table, regardless of a valid node. */
static Py_ssize_t
_odict_get_index_raw(PyODictObject *od, PyObject *key, Py_hash_t hash)
{
PyObject **value = NULL;
PyObject **value_addr = NULL;
PyDictKeysObject *keys = ((PyDictObject *)od)->ma_keys;
Py_ssize_t ix;
ix = (keys->dk_lookup)((PyDictObject *)od, key, hash, &value, NULL);
ix = (keys->dk_lookup)((PyDictObject *)od, key, hash, &value_addr, NULL);
if (ix == DKIX_EMPTY) {
return keys->dk_nentries; /* index of new entry */
}
@ -576,7 +554,8 @@ _odict_get_index_raw(PyODictObject *od, PyObject *key, Py_hash_t hash)
/* Replace od->od_fast_nodes with a new table matching the size of dict's. */
static int
_odict_resize(PyODictObject *od) {
_odict_resize(PyODictObject *od)
{
Py_ssize_t size, i;
_ODictNode **fast_nodes, *node;
@ -602,7 +581,7 @@ _odict_resize(PyODictObject *od) {
}
/* Replace the old fast nodes table. */
_odict_free_fast_nodes(od);
PyMem_FREE(od->od_fast_nodes);
od->od_fast_nodes = fast_nodes;
od->od_fast_nodes_size = size;
od->od_resize_sentinel = ((PyDictObject *)od)->ma_keys;
@ -640,6 +619,7 @@ _odict_find_node_hash(PyODictObject *od, PyObject *key, Py_hash_t hash)
index = _odict_get_index(od, key, hash);
if (index < 0)
return NULL;
assert(od->od_fast_nodes != NULL);
return od->od_fast_nodes[index];
}
@ -657,6 +637,7 @@ _odict_find_node(PyODictObject *od, PyObject *key)
index = _odict_get_index(od, key, hash);
if (index < 0)
return NULL;
assert(od->od_fast_nodes != NULL);
return od->od_fast_nodes[index];
}
@ -701,7 +682,8 @@ _odict_add_new_node(PyODictObject *od, PyObject *key, Py_hash_t hash)
Py_DECREF(key);
return -1;
}
else if (od->od_fast_nodes[i] != NULL) {
assert(od->od_fast_nodes != NULL);
if (od->od_fast_nodes[i] != NULL) {
/* We already have a node for the key so there's no need to add one. */
Py_DECREF(key);
return 0;
@ -780,6 +762,7 @@ _odict_clear_node(PyODictObject *od, _ODictNode *node, PyObject *key,
if (i < 0)
return PyErr_Occurred() ? -1 : 0;
assert(od->od_fast_nodes != NULL);
if (node == NULL)
node = od->od_fast_nodes[i];
assert(node == od->od_fast_nodes[i]);
@ -800,8 +783,10 @@ _odict_clear_nodes(PyODictObject *od)
{
_ODictNode *node, *next;
_odict_free_fast_nodes(od);
PyMem_FREE(od->od_fast_nodes);
od->od_fast_nodes = NULL;
od->od_fast_nodes_size = 0;
od->od_resize_sentinel = NULL;
node = _odict_FIRST(od);
_odict_FIRST(od) = NULL;
@ -900,8 +885,7 @@ odict_eq(PyObject *a, PyObject *b)
PyDoc_STRVAR(odict_init__doc__,
"Initialize an ordered dictionary. The signature is the same as\n\
regular dictionaries, but keyword arguments are not recommended because\n\
their insertion order is arbitrary.\n\
regular dictionaries. Keyword argument order is preserved.\n\
\n\
");
@ -937,23 +921,25 @@ PyDoc_STRVAR(odict_setitem__doc__, "od.__setitem__(i, y) <==> od[i]=y");
/* fromkeys() */
/*[clinic input]
@classmethod
OrderedDict.fromkeys
iterable as seq: object
value: object = None
New ordered dictionary with keys from S.
If not specified, the value defaults to None.
[clinic start generated code]*/
PyDoc_STRVAR(odict_fromkeys__doc__,
"OD.fromkeys(S[, v]) -> New ordered dictionary with keys from S.\n\
If not specified, the value defaults to None.\n\
\n\
");
static PyObject *
OrderedDict_fromkeys_impl(PyTypeObject *type, PyObject *seq, PyObject *value)
/*[clinic end generated code: output=c10390d452d78d6d input=33eefc496d5eee7b]*/
odict_fromkeys(PyObject *cls, PyObject *args, PyObject *kwargs)
{
return _PyDict_FromKeys((PyObject *)type, seq, value);
static char *kwlist[] = {"iterable", "value", 0};
PyObject *seq;
PyObject *value = Py_None;
/* both borrowed */
if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|O:fromkeys", kwlist,
&seq, &value)) {
return NULL;
}
return _PyDict_FromKeys(cls, seq, value);
}
/* __sizeof__() */
@ -965,7 +951,7 @@ static PyObject *
odict_sizeof(PyODictObject *od)
{
Py_ssize_t res = _PyDict_SizeOf((PyDictObject *)od);
res += sizeof(_ODictNode *) * _odict_FAST_SIZE(od); /* od_fast_nodes */
res += sizeof(_ODictNode *) * od->od_fast_nodes_size; /* od_fast_nodes */
if (!_odict_EMPTY(od)) {
res += sizeof(_ODictNode) * PyODict_SIZE(od); /* linked-list */
}
@ -1023,32 +1009,32 @@ Done:
return result;
}
/* setdefault(): Skips __missing__() calls. */
/* setdefault() */
PyDoc_STRVAR(odict_setdefault__doc__,
"od.setdefault(k[,d]) -> od.get(k,d), also set od[k]=d if k not in od");
/*[clinic input]
OrderedDict.setdefault
key: object
default as failobj: object = None
od.get(k,d), also set od[k]=d if k not in od.
[clinic start generated code]*/
/* Skips __missing__() calls. */
static PyObject *
OrderedDict_setdefault_impl(PyODictObject *self, PyObject *key,
PyObject *failobj)
/*[clinic end generated code: output=605d0f6f61ccb0a6 input=4ee5006f32f5691b]*/
odict_setdefault(register PyODictObject *od, PyObject *args, PyObject *kwargs)
{
PyObject *result = NULL;
static char *kwlist[] = {"key", "default", 0};
PyObject *key, *result = NULL;
PyObject *failobj = Py_None;
if (PyODict_CheckExact(self)) {
result = PyODict_GetItemWithError(self, key); /* borrowed */
/* both borrowed */
if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|O:setdefault", kwlist,
&key, &failobj)) {
return NULL;
}
if (PyODict_CheckExact(od)) {
result = PyODict_GetItemWithError(od, key); /* borrowed */
if (result == NULL) {
if (PyErr_Occurred())
return NULL;
assert(_odict_find_node(self, key) == NULL);
if (PyODict_SetItem((PyObject *)self, key, failobj) >= 0) {
assert(_odict_find_node(od, key) == NULL);
if (PyODict_SetItem((PyObject *)od, key, failobj) >= 0) {
result = failobj;
Py_INCREF(failobj);
}
@ -1058,14 +1044,14 @@ OrderedDict_setdefault_impl(PyODictObject *self, PyObject *key,
}
}
else {
int exists = PySequence_Contains((PyObject *)self, key);
int exists = PySequence_Contains((PyObject *)od, key);
if (exists < 0) {
return NULL;
}
else if (exists) {
result = PyObject_GetItem((PyObject *)self, key);
result = PyObject_GetItem((PyObject *)od, key);
}
else if (PyObject_SetItem((PyObject *)self, key, failobj) >= 0) {
else if (PyObject_SetItem((PyObject *)od, key, failobj) >= 0) {
result = failobj;
Py_INCREF(failobj);
}
@ -1175,37 +1161,41 @@ _odict_popkey(PyObject *od, PyObject *key, PyObject *failobj)
return _odict_popkey_hash(od, key, failobj, hash);
}
/* popitem() */
/*[clinic input]
OrderedDict.popitem
last: bool = True
Return (k, v) and remove a (key, value) pair.
Pairs are returned in LIFO order if last is true or FIFO order if false.
[clinic start generated code]*/
PyDoc_STRVAR(odict_popitem__doc__,
"popitem($self, /, last=True)\n"
"--\n"
"\n"
"Remove and return a (key, value) pair from the dictionary.\n"
"\n"
"Pairs are returned in LIFO order if last is true or FIFO order if false.");
static PyObject *
OrderedDict_popitem_impl(PyODictObject *self, int last)
/*[clinic end generated code: output=98e7d986690d49eb input=4937da2015939126]*/
odict_popitem(PyObject *od, PyObject *args, PyObject *kwargs)
{
static char *kwlist[] = {"last", 0};
PyObject *key, *value, *item = NULL;
_ODictNode *node;
int last = 1;
/* pull the item */
if (_odict_EMPTY(self)) {
/* borrowed */
if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|p:popitem", kwlist,
&last)) {
return NULL;
}
if (_odict_EMPTY(od)) {
PyErr_SetString(PyExc_KeyError, "dictionary is empty");
return NULL;
}
node = last ? _odict_LAST(self) : _odict_FIRST(self);
node = last ? _odict_LAST(od) : _odict_FIRST(od);
key = _odictnode_KEY(node);
Py_INCREF(key);
value = _odict_popkey_hash((PyObject *)self, key, NULL, _odictnode_HASH(node));
value = _odict_popkey_hash(od, key, NULL, _odictnode_HASH(node));
if (value == NULL)
return NULL;
item = PyTuple_Pack(2, key, value);
@ -1251,12 +1241,10 @@ PyDoc_STRVAR(odict_clear__doc__,
"od.clear() -> None. Remove all items from od.");
static PyObject *
odict_clear(register PyODictObject *od)
odict_clear(register PyODictObject *od, PyObject *Py_UNUSED(ignored))
{
PyDict_Clear((PyObject *)od);
_odict_clear_nodes(od);
if (_odict_resize(od) < 0)
return NULL;
Py_RETURN_NONE;
}
@ -1277,7 +1265,7 @@ odict_copy(register PyODictObject *od)
if (PyODict_CheckExact(od))
od_copy = PyODict_New();
else
od_copy = _PyObject_CallNoArg((PyObject *)Py_TYPE(od));
od_copy = PyObject_CallFunctionObjArgs((PyObject *)Py_TYPE(od), NULL);
if (od_copy == NULL)
return NULL;
@ -1333,34 +1321,36 @@ odict_reversed(PyODictObject *od)
return odictiter_new(od, _odict_ITER_KEYS|_odict_ITER_REVERSED);
}
/* move_to_end() */
/*[clinic input]
OrderedDict.move_to_end
key: object
last: bool = True
"Move an existing element to the end (or beginning if last==False).
Raises KeyError if the element does not exist.
When last=True, acts like a fast version of self[key]=self.pop(key).
[clinic start generated code]*/
PyDoc_STRVAR(odict_move_to_end__doc__,
"Move an existing element to the end (or beginning if last==False).\n\
\n\
Raises KeyError if the element does not exist.\n\
When last=True, acts like a fast version of self[key]=self.pop(key).\n\
\n\
");
static PyObject *
OrderedDict_move_to_end_impl(PyODictObject *self, PyObject *key, int last)
/*[clinic end generated code: output=fafa4c5cc9b92f20 input=3b8283f7d0e15e43]*/
odict_move_to_end(PyODictObject *od, PyObject *args, PyObject *kwargs)
{
static char *kwlist[] = {"key", "last", 0};
PyObject *key;
int last = 1;
_ODictNode *node;
if (_odict_EMPTY(self)) {
if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|p:move_to_end", kwlist,
&key, &last)) {
return NULL;
}
if (_odict_EMPTY(od)) {
PyErr_SetObject(PyExc_KeyError, key);
return NULL;
}
node = last ? _odict_LAST(self) : _odict_FIRST(self);
node = last ? _odict_LAST(od) : _odict_FIRST(od);
if (key != _odictnode_KEY(node)) {
node = _odict_find_node(self, key);
node = _odict_find_node(od, key);
if (node == NULL) {
if (!PyErr_Occurred())
PyErr_SetObject(PyExc_KeyError, key);
@ -1368,16 +1358,16 @@ OrderedDict_move_to_end_impl(PyODictObject *self, PyObject *key, int last)
}
if (last) {
/* Only move if not already the last one. */
if (node != _odict_LAST(self)) {
_odict_remove_node(self, node);
_odict_add_tail(self, node);
if (node != _odict_LAST(od)) {
_odict_remove_node(od, node);
_odict_add_tail(od, node);
}
}
else {
/* Only move if not already the first one. */
if (node != _odict_FIRST(self)) {
_odict_remove_node(self, node);
_odict_add_head(self, node);
if (node != _odict_FIRST(od)) {
_odict_remove_node(od, node);
_odict_add_head(od, node);
}
}
}
@ -1405,17 +1395,20 @@ static PyMethodDef odict_methods[] = {
odict_repr__doc__},
{"__setitem__", (PyCFunction)odict_mp_ass_sub, METH_NOARGS,
odict_setitem__doc__},
ORDEREDDICT_FROMKEYS_METHODDEF
{"fromkeys", (PyCFunction)odict_fromkeys,
METH_VARARGS | METH_KEYWORDS | METH_CLASS, odict_fromkeys__doc__},
/* overridden dict methods */
{"__sizeof__", (PyCFunction)odict_sizeof, METH_NOARGS,
odict_sizeof__doc__},
{"__reduce__", (PyCFunction)odict_reduce, METH_NOARGS,
odict_reduce__doc__},
ORDEREDDICT_SETDEFAULT_METHODDEF
{"setdefault", (PyCFunction)odict_setdefault,
METH_VARARGS | METH_KEYWORDS, odict_setdefault__doc__},
{"pop", (PyCFunction)odict_pop,
METH_VARARGS | METH_KEYWORDS, odict_pop__doc__},
ORDEREDDICT_POPITEM_METHODDEF
{"popitem", (PyCFunction)odict_popitem,
METH_VARARGS | METH_KEYWORDS, odict_popitem__doc__},
{"keys", (PyCFunction)odictkeys_new, METH_NOARGS,
odict_keys__doc__},
{"values", (PyCFunction)odictvalues_new, METH_NOARGS,
@ -1432,7 +1425,8 @@ static PyMethodDef odict_methods[] = {
/* new methods */
{"__reversed__", (PyCFunction)odict_reversed, METH_NOARGS,
odict_reversed__doc__},
ORDEREDDICT_MOVE_TO_END_METHODDEF
{"move_to_end", (PyCFunction)odict_move_to_end,
METH_VARARGS | METH_KEYWORDS, odict_move_to_end__doc__},
{NULL, NULL} /* sentinel */
};
@ -1584,13 +1578,10 @@ odict_traverse(PyODictObject *od, visitproc visit, void *arg)
static int
odict_tp_clear(PyODictObject *od)
{
PyObject *res;
Py_CLEAR(od->od_inst_dict);
Py_CLEAR(od->od_weakreflist);
res = odict_clear(od);
if (res == NULL)
return -1;
Py_DECREF(res);
PyDict_Clear((PyObject *)od);
_odict_clear_nodes(od);
return 0;
}
@ -1665,27 +1656,6 @@ odict_init(PyObject *self, PyObject *args, PyObject *kwds)
}
}
/* tp_new */
static PyObject *
odict_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
{
PyODictObject *od;
od = (PyODictObject *)PyDict_Type.tp_new(type, args, kwds);
if (od == NULL)
return NULL;
/* type constructor fills the memory with zeros (see
PyType_GenericAlloc()), there is no need to set them to zero again */
if (_odict_resize(od) < 0) {
Py_DECREF(od);
return NULL;
}
return (PyObject*)od;
}
/* PyODict_Type */
PyTypeObject PyODict_Type = {
@ -1726,7 +1696,7 @@ PyTypeObject PyODict_Type = {
offsetof(PyODictObject, od_inst_dict), /* tp_dictoffset */
(initproc)odict_init, /* tp_init */
PyType_GenericAlloc, /* tp_alloc */
(newfunc)odict_new, /* tp_new */
0, /* tp_new */
0, /* tp_free */
};
@ -1736,8 +1706,9 @@ PyTypeObject PyODict_Type = {
*/
PyObject *
PyODict_New(void) {
return odict_new(&PyODict_Type, NULL, NULL);
PyODict_New(void)
{
return PyDict_Type.tp_new(&PyODict_Type, NULL, NULL);
}
static int
@ -1935,40 +1906,21 @@ done:
PyDoc_STRVAR(reduce_doc, "Return state information for pickling");
static PyObject *
odictiter_reduce(odictiterobject *di)
odictiter_reduce(odictiterobject *di, PyObject *Py_UNUSED(ignored))
{
PyObject *list, *iter;
list = PyList_New(0);
if (!list)
return NULL;
/* copy the iterator state */
odictiterobject tmp = *di;
Py_XINCREF(tmp.di_odict);
Py_XINCREF(tmp.di_current);
/* iterate the temporary into a list */
for(;;) {
PyObject *element = odictiter_iternext(di);
if (element) {
if (PyList_Append(list, element)) {
Py_DECREF(element);
Py_DECREF(list);
return NULL;
}
Py_DECREF(element);
}
else {
/* done iterating? */
break;
}
}
if (PyErr_Occurred()) {
Py_DECREF(list);
PyObject *list = PySequence_List((PyObject*)&tmp);
Py_XDECREF(tmp.di_odict);
Py_XDECREF(tmp.di_current);
if (list == NULL) {
return NULL;
}
iter = _PyObject_GetBuiltin("iter");
if (iter == NULL) {
Py_DECREF(list);
return NULL;
}
return Py_BuildValue("N(N)", iter, list);
return Py_BuildValue("N(N)", _PyObject_GetBuiltin("iter"), list);
}
static PyMethodDef odictiter_methods[] = {
@ -2438,7 +2390,8 @@ mutablemapping_update(PyObject *self, PyObject *args, PyObject *kwargs)
/* now handle kwargs */
assert(kwargs == NULL || PyDict_Check(kwargs));
if (kwargs != NULL && PyDict_GET_SIZE(kwargs)) {
len = (kwargs != NULL) ? PyDict_Size(kwargs) : 0;
if (len > 0) {
PyObject *items = PyDict_Items(kwargs);
if (items == NULL)
return NULL;

View file

@ -3345,7 +3345,7 @@ static PyMethodDef type_methods[] = {
{"__subclasses__", (PyCFunction)type_subclasses, METH_NOARGS,
PyDoc_STR("__subclasses__() -> list of immediate subclasses")},
{"__prepare__", (PyCFunction)type_prepare,
METH_FASTCALL | METH_CLASS,
METH_FASTCALL | METH_KEYWORDS | METH_CLASS,
PyDoc_STR("__prepare__() -> dict\n"
"used to create the namespace for the class statement")},
{"__instancecheck__", type___instancecheck__, METH_O,