Revert "Backport METH_FASTCALL from Python 3.7 (#328)"

This reverts commit cf73bbd678.
This commit is contained in:
Justine Tunney 2022-05-12 06:49:54 -07:00
parent e7611a8476
commit 2ea1dc405c
102 changed files with 3299 additions and 2894 deletions

View file

@ -239,7 +239,8 @@ _Py_IDENTIFIER(stderr);
/* AC: cannot convert yet, waiting for *args support */
static PyObject *
builtin___build_class__(PyObject *self, PyObject **args, Py_ssize_t nargs, PyObject *kwnames)
builtin___build_class__(PyObject *self, PyObject **args, Py_ssize_t nargs,
PyObject *kwnames)
{
PyObject *func, *name, *bases, *mkw, *meta, *winner, *prep, *ns;
PyObject *cls = NULL, *cell = NULL;
@ -973,12 +974,14 @@ finally:
/* AC: cannot convert yet, as needs PEP 457 group support in inspect */
static PyObject *
builtin_dir(PyObject *self, PyObject **args, Py_ssize_t nargs)
builtin_dir(PyObject *self, PyObject **args, Py_ssize_t nargs, PyObject *kwnames)
{
PyObject *arg = NULL;
if (!_PyArg_UnpackStack(args, nargs, "dir", 0, 1, &arg))
return NULL;
if (!_PyArg_NoStackKeywords("dir", kwnames))
return NULL;
return PyObject_Dir(arg);
}
@ -1189,7 +1192,8 @@ builtin_exec_impl(PyObject *module, PyObject *source, PyObject *globals,
/* AC: cannot convert yet, as needs PEP 457 group support in inspect */
static PyObject *
builtin_getattr(PyObject *self, PyObject **args, Py_ssize_t nargs)
builtin_getattr(PyObject *self, PyObject **args, Py_ssize_t nargs,
PyObject *kwnames)
{
PyObject *v, *result, *dflt = NULL;
PyObject *name;
@ -1197,6 +1201,10 @@ builtin_getattr(PyObject *self, PyObject **args, Py_ssize_t nargs)
if (!_PyArg_UnpackStack(args, nargs, "getattr", 2, 3, &v, &name, &dflt))
return NULL;
if (!_PyArg_NoStackKeywords("getattr", kwnames)) {
return NULL;
}
if (!PyUnicode_Check(name)) {
PyErr_SetString(PyExc_TypeError,
"getattr(): attribute name must be string");
@ -1494,7 +1502,8 @@ PyTypeObject PyMap_Type = {
/* AC: cannot convert yet, as needs PEP 457 group support in inspect */
static PyObject *
builtin_next(PyObject *self, PyObject **args, Py_ssize_t nargs)
builtin_next(PyObject *self, PyObject **args, Py_ssize_t nargs,
PyObject *kwnames)
{
PyObject *it, *res;
PyObject *def = NULL;
@ -1502,6 +1511,10 @@ builtin_next(PyObject *self, PyObject **args, Py_ssize_t nargs)
if (!_PyArg_UnpackStack(args, nargs, "next", 1, 2, &it, &def))
return NULL;
if (!_PyArg_NoStackKeywords("next", kwnames)) {
return NULL;
}
if (!PyIter_Check(it)) {
PyErr_Format(PyExc_TypeError,
"'%.200s' object is not an iterator",
@ -1630,12 +1643,14 @@ builtin_hex(PyObject *module, PyObject *number)
/* AC: cannot convert yet, as needs PEP 457 group support in inspect */
static PyObject *
builtin_iter(PyObject *self, PyObject **args, Py_ssize_t nargs)
builtin_iter(PyObject *self, PyObject **args, Py_ssize_t nargs, PyObject *kwnames)
{
PyObject *v, *w = NULL;
if (!_PyArg_UnpackStack(args, nargs, "iter", 1, 2, &v, &w))
return NULL;
if(!_PyArg_NoStackKeywords("iter", kwnames))
return NULL;
if (w == NULL)
return PyObject_GetIter(v);
if (!PyCallable_Check(v)) {
@ -2318,7 +2333,7 @@ PyDoc_STRVAR(builtin_sorted__doc__,
"reverse flag can be set to request the result in descending order.");
#define BUILTIN_SORTED_METHODDEF \
{"sorted", (PyCFunction)builtin_sorted, METH_FASTCALL | METH_KEYWORDS, builtin_sorted__doc__},
{"sorted", (PyCFunction)builtin_sorted, METH_FASTCALL, builtin_sorted__doc__},
static PyObject *
builtin_sorted(PyObject *self, PyObject **args, Py_ssize_t nargs, PyObject *kwnames)
@ -2357,13 +2372,15 @@ builtin_sorted(PyObject *self, PyObject **args, Py_ssize_t nargs, PyObject *kwna
/* AC: cannot convert yet, as needs PEP 457 group support in inspect */
static PyObject *
builtin_vars(PyObject *self, PyObject **args, Py_ssize_t nargs)
builtin_vars(PyObject *self, PyObject **args, Py_ssize_t nargs, PyObject *kwnames)
{
PyObject *v = NULL;
PyObject *d;
if (!_PyArg_UnpackStack(args, nargs, "vars", 0, 1, &v))
return NULL;
if(!_PyArg_NoStackKeywords("vars", kwnames))
return NULL;
if (v == NULL) {
d = PyEval_GetLocals();
if (d == NULL)
@ -2817,8 +2834,8 @@ PyTypeObject PyZip_Type = {
static PyMethodDef builtin_methods[] = {
{"__build_class__", (PyCFunction)builtin___build_class__,
METH_FASTCALL | METH_KEYWORDS, build_class_doc},
{"__import__", (PyCFunction)builtin___import__, METH_FASTCALL | METH_KEYWORDS, import_doc},
METH_FASTCALL, build_class_doc},
{"__import__", (PyCFunction)builtin___import__, METH_FASTCALL, import_doc},
BUILTIN_ABS_METHODDEF
BUILTIN_ALL_METHODDEF
BUILTIN_ANY_METHODDEF
@ -2851,7 +2868,7 @@ static PyMethodDef builtin_methods[] = {
BUILTIN_OCT_METHODDEF
BUILTIN_ORD_METHODDEF
BUILTIN_POW_METHODDEF
{"print", (PyCFunction)builtin_print, METH_FASTCALL | METH_KEYWORDS, print_doc},
{"print", (PyCFunction)builtin_print, METH_FASTCALL, print_doc},
BUILTIN_REPR_METHODDEF
{"round", (PyCFunction)builtin_round, METH_VARARGS | METH_KEYWORDS, round_doc},
BUILTIN_SETATTR_METHODDEF

View file

@ -13,7 +13,6 @@
#include "third_party/python/Include/ceval.h"
#include "third_party/python/Include/classobject.h"
#include "third_party/python/Include/code.h"
#include "third_party/python/Include/descrobject.h"
#include "third_party/python/Include/dictobject.h"
#include "third_party/python/Include/eval.h"
#include "third_party/python/Include/frameobject.h"
@ -22,7 +21,6 @@
#include "third_party/python/Include/import.h"
#include "third_party/python/Include/longobject.h"
#include "third_party/python/Include/object.h"
#include "third_party/python/Include/objimpl.h"
#include "third_party/python/Include/opcode.h"
#include "third_party/python/Include/pydtrace.h"
#include "third_party/python/Include/pyerrors.h"
@ -52,7 +50,6 @@
#define CHECKEXC 1 /* Double-check exception checking */
#endif
extern int _PyObject_GetMethod(PyObject *, PyObject *, PyObject **);
typedef PyObject *(*callproc)(PyObject *, PyObject *, PyObject *);
#ifdef LLTRACE
@ -63,6 +60,7 @@ static int prtrace(PyObject *, const char *);
static PyObject *call_function(PyObject ***, Py_ssize_t, PyObject *);
static PyObject *cmp_outcome(int, PyObject *, PyObject *);
static PyObject *do_call_core(PyObject *, PyObject *, PyObject *);
static PyObject *fast_function(PyObject *, PyObject **, Py_ssize_t, PyObject *);
static PyObject *import_from(PyObject *, PyObject *);
static PyObject *import_name(PyFrameObject *, PyObject *, PyObject *, PyObject *);
static PyObject *special_lookup(PyObject *, _Py_Identifier *);
@ -732,7 +730,7 @@ PyObject *
return tstate->interp->eval_frame(f, throwflag);
}
PyObject * _Py_HOT_FUNCTION
PyObject *
_PyEval_EvalFrameDefault(PyFrameObject *f, int throwflag)
{
#ifdef DXPAIRS
@ -3314,92 +3312,6 @@ _PyEval_EvalFrameDefault(PyFrameObject *f, int throwflag)
DISPATCH();
}
TARGET(LOAD_METHOD) {
/* Designed to work in tamdem with CALL_METHOD. */
PyObject *name = GETITEM(names, oparg);
PyObject *obj = TOP();
PyObject *meth = NULL;
int meth_found = _PyObject_GetMethod(obj, name, &meth);
if (meth == NULL) {
/* Most likely attribute wasn't found. */
goto error;
}
if (meth_found) {
/* We can bypass temporary bound method object.
meth is unbound method and obj is self.
meth | self | arg1 | ... | argN
*/
SET_TOP(meth);
PUSH(obj); // self
}
else {
/* meth is not an unbound method (but a regular attr, or
something was returned by a descriptor protocol). Set
the second element of the stack to NULL, to signal
CALL_METHOD that it's not a method call.
NULL | meth | arg1 | ... | argN
*/
SET_TOP(NULL);
Py_DECREF(obj);
PUSH(meth);
}
DISPATCH();
}
TARGET(CALL_METHOD) {
/* Designed to work in tamdem with LOAD_METHOD. */
PyObject **sp, *res, *meth;
sp = stack_pointer;
meth = PEEK(oparg + 2);
if (meth == NULL) {
/* `meth` is NULL when LOAD_METHOD thinks that it's not
a method call.
Stack layout:
... | NULL | callable | arg1 | ... | argN
^- TOP()
^- (-oparg)
^- (-oparg-1)
^- (-oparg-2)
`callable` will be POPed by call_function.
NULL will will be POPed manually later.
*/
res = call_function(&sp, oparg, NULL);
stack_pointer = sp;
(void)POP(); /* POP the NULL. */
}
else {
/* This is a method call. Stack layout:
... | method | self | arg1 | ... | argN
^- TOP()
^- (-oparg)
^- (-oparg-1)
^- (-oparg-2)
`self` and `method` will be POPed by call_function.
We'll be passing `oparg + 1` to call_function, to
make it accept the `self` as a first argument.
*/
res = call_function(&sp, oparg + 1, NULL);
stack_pointer = sp;
}
PUSH(res);
if (res == NULL)
goto error;
DISPATCH();
}
PREDICTED(CALL_FUNCTION);
TARGET(CALL_FUNCTION) {
PyObject **sp, *res;
@ -3964,7 +3876,7 @@ too_many_positional(PyCodeObject *co, Py_ssize_t given, Py_ssize_t defcount,
/* This is gonna seem *real weird*, but if you put some other code between
PyEval_EvalFrame() and _PyEval_EvalFrameDefault() you will need to adjust
the test in the if statements in Misc/gdbinit (pystack and pystackv). */
PyObject *
static PyObject *
_PyEval_EvalCodeWithName(PyObject *_co, PyObject *globals, PyObject *locals,
PyObject **args, Py_ssize_t argcount,
PyObject **kwnames, PyObject **kwargs,
@ -3990,7 +3902,7 @@ _PyEval_EvalCodeWithName(PyObject *_co, PyObject *globals, PyObject *locals,
/* Create the frame */
tstate = PyThreadState_GET();
assert(tstate != NULL);
f = _PyFrame_New_NoTrack(tstate, co, globals, locals);
f = PyFrame_New(tstate, co, globals, locals);
if (f == NULL) {
return NULL;
}
@ -4212,15 +4124,9 @@ fail: /* Jump here from prelude on failure */
so recursion_depth must be boosted for the duration.
*/
assert(tstate != NULL);
if (Py_REFCNT(f) > 1) {
Py_DECREF(f);
_PyObject_GC_TRACK(f);
}
else {
++tstate->recursion_depth;
Py_DECREF(f);
--tstate->recursion_depth;
}
++tstate->recursion_depth;
Py_DECREF(f);
--tstate->recursion_depth;
return retval;
}
@ -4756,6 +4662,35 @@ PyEval_MergeCompilerFlags(PyCompilerFlags *cf)
}
/* External interface to call any callable object.
The arg must be a tuple or NULL. The kw must be a dict or NULL. */
PyObject *
PyEval_CallObjectWithKeywords(PyObject *func, PyObject *args, PyObject *kwargs)
{
#ifdef Py_DEBUG
/* PyEval_CallObjectWithKeywords() must not be called with an exception
set. It raises a new exception if parameters are invalid or if
PyTuple_New() fails, and so the original exception is lost. */
assert(!PyErr_Occurred());
#endif
if (args != NULL && !PyTuple_Check(args)) {
PyErr_SetString(PyExc_TypeError,
"argument list must be a tuple");
return NULL;
}
if (kwargs != NULL && !PyDict_Check(kwargs)) {
PyErr_SetString(PyExc_TypeError,
"keyword list must be a dictionary");
return NULL;
}
if (args == NULL) {
return _PyObject_FastCallDict(func, NULL, 0, kwargs);
}
else {
return PyObject_Call(func, args, kwargs);
}
}
const char *
PyEval_GetFuncName(PyObject *func)
{
@ -4813,7 +4748,7 @@ if (tstate->use_tracing && tstate->c_profilefunc) { \
x = call; \
}
forceinline PyObject * _Py_HOT_FUNCTION
static PyObject *
call_function(PyObject ***pp_stack, Py_ssize_t oparg, PyObject *kwnames)
{
PyObject **pfunc = (*pp_stack) - oparg - 1;
@ -4821,41 +4756,16 @@ call_function(PyObject ***pp_stack, Py_ssize_t oparg, PyObject *kwnames)
PyObject *x, *w;
Py_ssize_t nkwargs = (kwnames == NULL) ? 0 : PyTuple_GET_SIZE(kwnames);
Py_ssize_t nargs = oparg - nkwargs;
PyObject **stack = (*pp_stack) - nargs - nkwargs;
PyObject **stack;
/* Always dispatch PyCFunction first, because these are
presumed to be the most frequent callable object.
*/
if (PyCFunction_Check(func)) {
PyThreadState *tstate = PyThreadState_GET();
PCALL(PCALL_CFUNCTION);
stack = (*pp_stack) - nargs - nkwargs;
C_TRACE(x, _PyCFunction_FastCallKeywords(func, stack, nargs, kwnames));
}
else if (Py_TYPE(func) == &PyMethodDescr_Type) {
PyThreadState *tstate = PyThreadState_GET();
if (nargs > 0 && tstate->use_tracing) {
/* We need to create a temporary bound method as argument
for profiling.
If nargs == 0, then this cannot work because we have no
"self". In any case, the call itself would raise
TypeError (foo needs an argument), so we just skip
profiling. */
PyObject *self = stack[0];
func = Py_TYPE(func)->tp_descr_get(func, self, (PyObject*)Py_TYPE(self));
if (func != NULL) {
C_TRACE(x, _PyCFunction_FastCallKeywords(func,
stack+1, nargs-1,
kwnames));
Py_DECREF(func);
}
else {
x = NULL;
}
}
else {
x = _PyMethodDescr_FastCallKeywords(func, stack, nargs, kwnames);
}
}
else {
if (PyMethod_Check(func) && PyMethod_GET_SELF(func) != NULL) {
/* optimize access to bound methods */
@ -4867,13 +4777,13 @@ call_function(PyObject ***pp_stack, Py_ssize_t oparg, PyObject *kwnames)
Py_INCREF(func);
Py_SETREF(*pfunc, self);
nargs++;
stack--;
}
else {
Py_INCREF(func);
}
stack = (*pp_stack) - nargs - nkwargs;
if (PyFunction_Check(func)) {
x = _PyFunction_FastCallKeywords(func, stack, nargs, kwnames);
x = fast_function(func, stack, nargs, kwnames);
}
else {
x = _PyObject_FastCallKeywords(func, stack, nargs, kwnames);
@ -4881,7 +4791,10 @@ call_function(PyObject ***pp_stack, Py_ssize_t oparg, PyObject *kwnames)
Py_DECREF(func);
}
assert((x != NULL) ^ (PyErr_Occurred() != NULL));
/* Clear the stack of the function object. */
/* Clear the stack of the function object. Also removes
the arguments in case they weren't consumed already
(fast_function() and err_args() leave them on the stack).
*/
while ((*pp_stack) > pfunc) {
w = EXT_POP(*pp_stack);
Py_DECREF(w);
@ -4890,6 +4803,183 @@ call_function(PyObject ***pp_stack, Py_ssize_t oparg, PyObject *kwnames)
return x;
}
/* The fast_function() function optimize calls for which no argument
tuple is necessary; the objects are passed directly from the stack.
For the simplest case -- a function that takes only positional
arguments and is called with only positional arguments -- it
inlines the most primitive frame setup code from
PyEval_EvalCodeEx(), which vastly reduces the checks that must be
done before evaluating the frame.
*/
static PyObject*
_PyFunction_FastCall(PyCodeObject *co, PyObject **args, Py_ssize_t nargs,
PyObject *globals)
{
PyFrameObject *f;
PyThreadState *tstate = PyThreadState_GET();
PyObject **fastlocals;
Py_ssize_t i;
PyObject *result;
PCALL(PCALL_FASTER_FUNCTION);
assert(globals != NULL);
/* XXX Perhaps we should create a specialized
PyFrame_New() that doesn't take locals, but does
take builtins without sanity checking them.
*/
assert(tstate != NULL);
f = PyFrame_New(tstate, co, globals, NULL);
if (f == NULL) {
return NULL;
}
fastlocals = f->f_localsplus;
for (i = 0; i < nargs; i++) {
Py_INCREF(*args);
fastlocals[i] = *args++;
}
result = PyEval_EvalFrameEx(f,0);
++tstate->recursion_depth;
Py_DECREF(f);
--tstate->recursion_depth;
return result;
}
static PyObject *
fast_function(PyObject *func, PyObject **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));
assert((nargs == 0 && nkwargs == 0) || stack != NULL);
/* kwnames must only contains str strings, no subclass, and all keys must
be unique */
PCALL(PCALL_FUNCTION);
PCALL(PCALL_FAST_FUNCTION);
if (co->co_kwonlyargcount == 0 && nkwargs == 0 &&
co->co_flags == (CO_OPTIMIZED | CO_NEWLOCALS | CO_NOFREE))
{
if (argdefs == NULL && co->co_argcount == nargs) {
return _PyFunction_FastCall(co, stack, nargs, globals);
}
else if (nargs == 0 && argdefs != NULL
&& co->co_argcount == Py_SIZE(argdefs)) {
/* function called with no arguments, but all parameters have
a default value: use default values as arguments .*/
stack = &PyTuple_GET_ITEM(argdefs, 0);
return _PyFunction_FastCall(co, stack, Py_SIZE(argdefs), globals);
}
}
kwdefs = PyFunction_GET_KW_DEFAULTS(func);
closure = PyFunction_GET_CLOSURE(func);
name = ((PyFunctionObject *)func) -> func_name;
qualname = ((PyFunctionObject *)func) -> func_qualname;
if (argdefs != NULL) {
d = &PyTuple_GET_ITEM(argdefs, 0);
nd = Py_SIZE(argdefs);
}
else {
d = NULL;
nd = 0;
}
return _PyEval_EvalCodeWithName((PyObject*)co, globals, (PyObject *)NULL,
stack, nargs,
nkwargs ? &PyTuple_GET_ITEM(kwnames, 0) : NULL,
stack + nargs,
nkwargs, 1,
d, (int)nd, kwdefs,
closure, name, qualname);
}
PyObject *
_PyFunction_FastCallKeywords(PyObject *func, PyObject **stack,
Py_ssize_t nargs, PyObject *kwnames)
{
return fast_function(func, stack, nargs, kwnames);
}
PyObject *
_PyFunction_FastCallDict(PyObject *func, PyObject **args, Py_ssize_t nargs,
PyObject *kwargs)
{
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 *kwtuple, **k;
PyObject **d;
Py_ssize_t nd, nk;
PyObject *result;
assert(func != NULL);
assert(nargs >= 0);
assert(nargs == 0 || args != NULL);
assert(kwargs == NULL || PyDict_Check(kwargs));
PCALL(PCALL_FUNCTION);
PCALL(PCALL_FAST_FUNCTION);
if (co->co_kwonlyargcount == 0 &&
(kwargs == NULL || PyDict_Size(kwargs) == 0) &&
co->co_flags == (CO_OPTIMIZED | CO_NEWLOCALS | CO_NOFREE))
{
/* Fast paths */
if (argdefs == NULL && co->co_argcount == nargs) {
return _PyFunction_FastCall(co, args, nargs, globals);
}
else if (nargs == 0 && argdefs != NULL
&& co->co_argcount == Py_SIZE(argdefs)) {
/* function called with no arguments, but all parameters have
a default value: use default values as arguments .*/
args = &PyTuple_GET_ITEM(argdefs, 0);
return _PyFunction_FastCall(co, args, Py_SIZE(argdefs), globals);
}
}
if (kwargs != NULL) {
Py_ssize_t pos, i;
nk = PyDict_Size(kwargs);
kwtuple = PyTuple_New(2 * nk);
if (kwtuple == NULL) {
return NULL;
}
k = &PyTuple_GET_ITEM(kwtuple, 0);
pos = i = 0;
while (PyDict_Next(kwargs, &pos, &k[i], &k[i+1])) {
Py_INCREF(k[i]);
Py_INCREF(k[i+1]);
i += 2;
}
nk = i / 2;
}
else {
kwtuple = NULL;
k = NULL;
nk = 0;
}
kwdefs = PyFunction_GET_KW_DEFAULTS(func);
closure = PyFunction_GET_CLOSURE(func);
name = ((PyFunctionObject *)func) -> func_name;
qualname = ((PyFunctionObject *)func) -> func_qualname;
if (argdefs != NULL) {
d = &PyTuple_GET_ITEM(argdefs, 0);
nd = Py_SIZE(argdefs);
}
else {
d = NULL;
nd = 0;
}
result = _PyEval_EvalCodeWithName((PyObject*)co, globals, (PyObject *)NULL,
args, nargs,
k, k != NULL ? k + 1 : NULL, nk, 2,
d, nd, kwdefs,
closure, name, qualname);
Py_XDECREF(kwtuple);
return result;
}
static PyObject *
do_call_core(PyObject *func, PyObject *callargs, PyObject *kwdict)
{

View file

@ -89,7 +89,7 @@ static PyObject *
builtin_format_impl(PyObject *module, PyObject *value, PyObject *format_spec);
static PyObject *
builtin_format(PyObject *module, PyObject **args, Py_ssize_t nargs)
builtin_format(PyObject *module, PyObject **args, Py_ssize_t nargs, PyObject *kwnames)
{
PyObject *return_value = NULL;
PyObject *value;
@ -99,6 +99,10 @@ builtin_format(PyObject *module, PyObject **args, Py_ssize_t nargs)
&value, &format_spec)) {
goto exit;
}
if (!_PyArg_NoStackKeywords("format", kwnames)) {
goto exit;
}
return_value = builtin_format_impl(module, value, format_spec);
exit:
@ -151,7 +155,7 @@ PyDoc_STRVAR(builtin_compile__doc__,
"in addition to any features explicitly specified.");
#define BUILTIN_COMPILE_METHODDEF \
{"compile", (PyCFunction)builtin_compile, METH_FASTCALL|METH_KEYWORDS, builtin_compile__doc__},
{"compile", (PyCFunction)builtin_compile, METH_FASTCALL, builtin_compile__doc__},
static PyObject *
builtin_compile_impl(PyObject *module, PyObject *source, PyObject *filename,
@ -194,7 +198,7 @@ static PyObject *
builtin_divmod_impl(PyObject *module, PyObject *x, PyObject *y);
static PyObject *
builtin_divmod(PyObject *module, PyObject **args, Py_ssize_t nargs)
builtin_divmod(PyObject *module, PyObject **args, Py_ssize_t nargs, PyObject *kwnames)
{
PyObject *return_value = NULL;
PyObject *x;
@ -205,6 +209,10 @@ builtin_divmod(PyObject *module, PyObject **args, Py_ssize_t nargs)
&x, &y)) {
goto exit;
}
if (!_PyArg_NoStackKeywords("divmod", kwnames)) {
goto exit;
}
return_value = builtin_divmod_impl(module, x, y);
exit:
@ -231,7 +239,7 @@ builtin_eval_impl(PyObject *module, PyObject *source, PyObject *globals,
PyObject *locals);
static PyObject *
builtin_eval(PyObject *module, PyObject **args, Py_ssize_t nargs)
builtin_eval(PyObject *module, PyObject **args, Py_ssize_t nargs, PyObject *kwnames)
{
PyObject *return_value = NULL;
PyObject *source;
@ -243,6 +251,10 @@ builtin_eval(PyObject *module, PyObject **args, Py_ssize_t nargs)
&source, &globals, &locals)) {
goto exit;
}
if (!_PyArg_NoStackKeywords("eval", kwnames)) {
goto exit;
}
return_value = builtin_eval_impl(module, source, globals, locals);
exit:
@ -269,7 +281,7 @@ builtin_exec_impl(PyObject *module, PyObject *source, PyObject *globals,
PyObject *locals);
static PyObject *
builtin_exec(PyObject *module, PyObject **args, Py_ssize_t nargs)
builtin_exec(PyObject *module, PyObject **args, Py_ssize_t nargs, PyObject *kwnames)
{
PyObject *return_value = NULL;
PyObject *source;
@ -281,6 +293,10 @@ builtin_exec(PyObject *module, PyObject **args, Py_ssize_t nargs)
&source, &globals, &locals)) {
goto exit;
}
if (!_PyArg_NoStackKeywords("exec", kwnames)) {
goto exit;
}
return_value = builtin_exec_impl(module, source, globals, locals);
exit:
@ -323,7 +339,7 @@ static PyObject *
builtin_hasattr_impl(PyObject *module, PyObject *obj, PyObject *name);
static PyObject *
builtin_hasattr(PyObject *module, PyObject **args, Py_ssize_t nargs)
builtin_hasattr(PyObject *module, PyObject **args, Py_ssize_t nargs, PyObject *kwnames)
{
PyObject *return_value = NULL;
PyObject *obj;
@ -334,6 +350,10 @@ builtin_hasattr(PyObject *module, PyObject **args, Py_ssize_t nargs)
&obj, &name)) {
goto exit;
}
if (!_PyArg_NoStackKeywords("hasattr", kwnames)) {
goto exit;
}
return_value = builtin_hasattr_impl(module, obj, name);
exit:
@ -368,7 +388,7 @@ builtin_setattr_impl(PyObject *module, PyObject *obj, PyObject *name,
PyObject *value);
static PyObject *
builtin_setattr(PyObject *module, PyObject **args, Py_ssize_t nargs)
builtin_setattr(PyObject *module, PyObject **args, Py_ssize_t nargs, PyObject *kwnames)
{
PyObject *return_value = NULL;
PyObject *obj;
@ -380,6 +400,10 @@ builtin_setattr(PyObject *module, PyObject **args, Py_ssize_t nargs)
&obj, &name, &value)) {
goto exit;
}
if (!_PyArg_NoStackKeywords("setattr", kwnames)) {
goto exit;
}
return_value = builtin_setattr_impl(module, obj, name, value);
exit:
@ -401,7 +425,7 @@ static PyObject *
builtin_delattr_impl(PyObject *module, PyObject *obj, PyObject *name);
static PyObject *
builtin_delattr(PyObject *module, PyObject **args, Py_ssize_t nargs)
builtin_delattr(PyObject *module, PyObject **args, Py_ssize_t nargs, PyObject *kwnames)
{
PyObject *return_value = NULL;
PyObject *obj;
@ -412,6 +436,10 @@ builtin_delattr(PyObject *module, PyObject **args, Py_ssize_t nargs)
&obj, &name)) {
goto exit;
}
if (!_PyArg_NoStackKeywords("delattr", kwnames)) {
goto exit;
}
return_value = builtin_delattr_impl(module, obj, name);
exit:
@ -510,7 +538,7 @@ static PyObject *
builtin_pow_impl(PyObject *module, PyObject *x, PyObject *y, PyObject *z);
static PyObject *
builtin_pow(PyObject *module, PyObject **args, Py_ssize_t nargs)
builtin_pow(PyObject *module, PyObject **args, Py_ssize_t nargs, PyObject *kwnames)
{
PyObject *return_value = NULL;
PyObject *x;
@ -522,6 +550,10 @@ builtin_pow(PyObject *module, PyObject **args, Py_ssize_t nargs)
&x, &y, &z)) {
goto exit;
}
if (!_PyArg_NoStackKeywords("pow", kwnames)) {
goto exit;
}
return_value = builtin_pow_impl(module, x, y, z);
exit:
@ -547,7 +579,7 @@ static PyObject *
builtin_input_impl(PyObject *module, PyObject *prompt);
static PyObject *
builtin_input(PyObject *module, PyObject **args, Py_ssize_t nargs)
builtin_input(PyObject *module, PyObject **args, Py_ssize_t nargs, PyObject *kwnames)
{
PyObject *return_value = NULL;
PyObject *prompt = NULL;
@ -557,6 +589,10 @@ builtin_input(PyObject *module, PyObject **args, Py_ssize_t nargs)
&prompt)) {
goto exit;
}
if (!_PyArg_NoStackKeywords("input", kwnames)) {
goto exit;
}
return_value = builtin_input_impl(module, prompt);
exit:
@ -591,7 +627,7 @@ static PyObject *
builtin_sum_impl(PyObject *module, PyObject *iterable, PyObject *start);
static PyObject *
builtin_sum(PyObject *module, PyObject **args, Py_ssize_t nargs)
builtin_sum(PyObject *module, PyObject **args, Py_ssize_t nargs, PyObject *kwnames)
{
PyObject *return_value = NULL;
PyObject *iterable;
@ -602,6 +638,10 @@ builtin_sum(PyObject *module, PyObject **args, Py_ssize_t nargs)
&iterable, &start)) {
goto exit;
}
if (!_PyArg_NoStackKeywords("sum", kwnames)) {
goto exit;
}
return_value = builtin_sum_impl(module, iterable, start);
exit:
@ -626,7 +666,7 @@ builtin_isinstance_impl(PyObject *module, PyObject *obj,
PyObject *class_or_tuple);
static PyObject *
builtin_isinstance(PyObject *module, PyObject **args, Py_ssize_t nargs)
builtin_isinstance(PyObject *module, PyObject **args, Py_ssize_t nargs, PyObject *kwnames)
{
PyObject *return_value = NULL;
PyObject *obj;
@ -637,6 +677,10 @@ builtin_isinstance(PyObject *module, PyObject **args, Py_ssize_t nargs)
&obj, &class_or_tuple)) {
goto exit;
}
if (!_PyArg_NoStackKeywords("isinstance", kwnames)) {
goto exit;
}
return_value = builtin_isinstance_impl(module, obj, class_or_tuple);
exit:
@ -661,7 +705,7 @@ builtin_issubclass_impl(PyObject *module, PyObject *cls,
PyObject *class_or_tuple);
static PyObject *
builtin_issubclass(PyObject *module, PyObject **args, Py_ssize_t nargs)
builtin_issubclass(PyObject *module, PyObject **args, Py_ssize_t nargs, PyObject *kwnames)
{
PyObject *return_value = NULL;
PyObject *cls;
@ -672,9 +716,13 @@ builtin_issubclass(PyObject *module, PyObject **args, Py_ssize_t nargs)
&cls, &class_or_tuple)) {
goto exit;
}
if (!_PyArg_NoStackKeywords("issubclass", kwnames)) {
goto exit;
}
return_value = builtin_issubclass_impl(module, cls, class_or_tuple);
exit:
return return_value;
}
/*[clinic end generated code: output=09752daa8cdd6ec7 input=a9049054013a1b77]*/
/*[clinic end generated code: output=17fedd2dec148677 input=a9049054013a1b77]*/

View file

@ -83,7 +83,7 @@ _imp__fix_co_filename_impl(PyObject *module, PyCodeObject *code,
PyObject *path);
static PyObject *
_imp__fix_co_filename(PyObject *module, PyObject **args, Py_ssize_t nargs)
_imp__fix_co_filename(PyObject *module, PyObject **args, Py_ssize_t nargs, PyObject *kwnames)
{
PyObject *return_value = NULL;
PyCodeObject *code;
@ -93,6 +93,10 @@ _imp__fix_co_filename(PyObject *module, PyObject **args, Py_ssize_t nargs)
&PyCode_Type, &code, &path)) {
goto exit;
}
if (!_PyArg_NoStackKeywords("_fix_co_filename", kwnames)) {
goto exit;
}
return_value = _imp__fix_co_filename_impl(module, code, path);
exit:
@ -276,7 +280,7 @@ static PyObject *
_imp_create_dynamic_impl(PyObject *module, PyObject *spec, PyObject *file);
static PyObject *
_imp_create_dynamic(PyObject *module, PyObject **args, Py_ssize_t nargs)
_imp_create_dynamic(PyObject *module, PyObject **args, Py_ssize_t nargs, PyObject *kwnames)
{
PyObject *return_value = NULL;
PyObject *spec;
@ -287,6 +291,10 @@ _imp_create_dynamic(PyObject *module, PyObject **args, Py_ssize_t nargs)
&spec, &file)) {
goto exit;
}
if (!_PyArg_NoStackKeywords("create_dynamic", kwnames)) {
goto exit;
}
return_value = _imp_create_dynamic_impl(module, spec, file);
exit:
@ -362,4 +370,4 @@ exit:
#ifndef _IMP_EXEC_DYNAMIC_METHODDEF
#define _IMP_EXEC_DYNAMIC_METHODDEF
#endif /* !defined(_IMP_EXEC_DYNAMIC_METHODDEF) */
/*[clinic end generated code: output=d068dd493e513604 input=a9049054013a1b77]*/
/*[clinic end generated code: output=c1d0e65d04114958 input=a9049054013a1b77]*/

View file

@ -1058,8 +1058,6 @@ PyCompile_OpcodeStackEffect(int opcode, int oparg)
return -oparg;
case CALL_FUNCTION:
return -oparg;
case CALL_METHOD:
return -oparg-1;
case CALL_FUNCTION_KW:
return -oparg-1;
case CALL_FUNCTION_EX:
@ -1098,8 +1096,6 @@ PyCompile_OpcodeStackEffect(int opcode, int oparg)
/* If there's a fmt_spec on the stack, we go from 2->1,
else 1->1. */
return (oparg & FVS_MASK) == FVS_HAVE_SPEC ? -1 : 0;
case LOAD_METHOD:
return 1;
default:
return PY_INVALID_STACK_EFFECT;
}
@ -3419,44 +3415,9 @@ compiler_compare(struct compiler *c, expr_ty e)
return 1;
}
// Return 1 if the method call was optimized, -1 if not, and 0 on error.
static int
maybe_optimize_method_call(struct compiler *c, expr_ty e)
{
Py_ssize_t argsl, i;
expr_ty meth = e->v.Call.func;
asdl_seq *args = e->v.Call.args;
/* Check that the call node is an attribute access, and that
the call doesn't have keyword parameters. */
if (meth->kind != Attribute_kind || meth->v.Attribute.ctx != Load ||
asdl_seq_LEN(e->v.Call.keywords))
return -1;
/* Check that there are no *varargs types of arguments. */
argsl = asdl_seq_LEN(args);
for (i = 0; i < argsl; i++) {
expr_ty elt = asdl_seq_GET(args, i);
if (elt->kind == Starred_kind) {
return -1;
}
}
/* Alright, we can optimize the code. */
VISIT(c, expr, meth->v.Attribute.value);
ADDOP_NAME(c, LOAD_METHOD, meth->v.Attribute.attr, names);
VISIT_SEQ(c, expr, e->v.Call.args);
ADDOP_I(c, CALL_METHOD, asdl_seq_LEN(e->v.Call.args));
return 1;
}
static int
compiler_call(struct compiler *c, expr_ty e)
{
int ret = maybe_optimize_method_call(c, e);
if (ret >= 0) {
return ret;
}
VISIT(c, expr, e->v.Call.func);
return compiler_call_helper(c, 0,
e->v.Call.args,

View file

@ -153,7 +153,7 @@ PyErr_SetString(PyObject *exception, const char *string)
Py_XDECREF(value);
}
PyObject * _Py_HOT_FUNCTION
PyObject *
PyErr_Occurred(void)
{
PyThreadState *tstate = _PyThreadState_UncheckedGet();

View file

@ -1688,7 +1688,7 @@ PyMarshal_WriteObjectToString(PyObject *x, int version)
/* And an interface for Python programs... */
static PyObject *
marshal_dump(PyObject *self, PyObject **args, Py_ssize_t nargs)
marshal_dump(PyObject *self, PyObject **args, Py_ssize_t nargs, PyObject *kwnames)
{
/* XXX Quick hack -- need to do this differently */
PyObject *x;
@ -1700,6 +1700,8 @@ marshal_dump(PyObject *self, PyObject **args, Py_ssize_t nargs)
if (!_PyArg_ParseStack(args, nargs, "OO|i:dump", &x, &f, &version))
return NULL;
if (!_PyArg_NoStackKeywords("dump", kwnames))
return NULL;
s = PyMarshal_WriteObjectToString(x, version);
if (s == NULL)
@ -1776,12 +1778,14 @@ dump(), load() will substitute None for the unmarshallable type.");
static PyObject *
marshal_dumps(PyObject *self, PyObject **args, Py_ssize_t nargs)
marshal_dumps(PyObject *self, PyObject **args, Py_ssize_t nargs, PyObject *kwnames)
{
PyObject *x;
int version = Py_MARSHAL_VERSION;
if (!_PyArg_ParseStack(args, nargs, "O|i:dumps", &x, &version))
return NULL;
if(!_PyArg_NoStackKeywords("dumps", kwnames))
return NULL;
return PyMarshal_WriteObjectToString(x, version);
}
@ -1796,7 +1800,7 @@ The version argument indicates the data format that dumps should use.");
static PyObject *
marshal_loads(PyObject *self, PyObject **args, Py_ssize_t nargs)
marshal_loads(PyObject *self, PyObject **args, Py_ssize_t nargs, PyObject *kwnames)
{
RFILE rf;
Py_buffer p;
@ -1805,6 +1809,8 @@ marshal_loads(PyObject *self, PyObject **args, Py_ssize_t nargs)
PyObject* result;
if (!_PyArg_ParseStack(args, nargs, "y*:loads", &p))
return NULL;
if(!_PyArg_NoStackKeywords("loads", kwnames))
return NULL;
s = p.buf;
n = p.len;
rf.fp = NULL;

View file

@ -600,6 +600,58 @@ va_build_stack(PyObject **small_stack, Py_ssize_t small_stack_len,
return stack;
}
PyObject *
PyEval_CallFunction(PyObject *callable, const char *format, ...)
{
va_list vargs;
PyObject *args;
PyObject *res;
va_start(vargs, format);
args = Py_VaBuildValue(format, vargs);
va_end(vargs);
if (args == NULL)
return NULL;
res = PyEval_CallObject(callable, args);
Py_DECREF(args);
return res;
}
PyObject *
PyEval_CallMethod(PyObject *obj, const char *name, const char *format, ...)
{
va_list vargs;
PyObject *meth;
PyObject *args;
PyObject *res;
meth = PyObject_GetAttrString(obj, name);
if (meth == NULL)
return NULL;
va_start(vargs, format);
args = Py_VaBuildValue(format, vargs);
va_end(vargs);
if (args == NULL) {
Py_DECREF(meth);
return NULL;
}
res = PyEval_CallObject(meth, args);
Py_DECREF(meth);
Py_DECREF(args);
return res;
}
int
PyModule_AddObject(PyObject *m, const char *name, PyObject *o)
{

View file

@ -167,8 +167,8 @@ static void *const opcode_targets[256] = {
&&TARGET_BUILD_STRING,
&&TARGET_BUILD_TUPLE_UNPACK_WITH_CALL,
&&_unknown_opcode,
&&TARGET_LOAD_METHOD,
&&TARGET_CALL_METHOD,
&&_unknown_opcode,
&&_unknown_opcode,
&&_unknown_opcode,
&&_unknown_opcode,
&&_unknown_opcode,