Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
C
cpython
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
cpython
Commits
b1263d5a
Commit
b1263d5a
authored
Jun 28, 2019
by
Jeroen Demeyer
Committed by
Inada Naoki
Jun 28, 2019
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
bpo-37337: Add _PyObject_VectorcallMethod() (GH-14228)
parent
b4bee030
Changes
7
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
105 additions
and
33 deletions
+105
-33
Doc/c-api/object.rst
Doc/c-api/object.rst
+22
-0
Include/cpython/abstract.h
Include/cpython/abstract.h
+16
-0
Misc/NEWS.d/next/C API/2019-06-19-12-06-31.bpo-37337.gXIGyU.rst
...EWS.d/next/C API/2019-06-19-12-06-31.bpo-37337.gXIGyU.rst
+1
-0
Modules/_abc.c
Modules/_abc.c
+13
-6
Objects/call.c
Objects/call.c
+32
-0
Objects/descrobject.c
Objects/descrobject.c
+14
-7
Python/sysmodule.c
Python/sysmodule.c
+7
-20
No files found.
Doc/c-api/object.rst
View file @
b1263d5a
...
...
@@ -395,6 +395,9 @@ Object Protocol
argument 1 (not 0) in the allocated vector.
The callee must restore the value of ``args[-1]`` before returning.
For :c:func:`_PyObject_VectorcallMethod`, this flag means instead that
``args[0]`` may be changed.
Whenever they can do so cheaply (without additional allocation), callers
are encouraged to use :const:`PY_VECTORCALL_ARGUMENTS_OFFSET`.
Doing so will allow callables such as bound methods to make their onward
...
...
@@ -430,6 +433,25 @@ Object Protocol
.. versionadded:: 3.8
.. c:function:: PyObject* _PyObject_VectorcallMethod(PyObject *name, PyObject *const *args, size_t nargsf, PyObject *kwnames)
Call a method using the vectorcall calling convention. The name of the method
is given as Python string *name*. The object whose method is called is
*args[0]* and the *args* array starting at *args[1]* represents the arguments
of the call. There must be at least one positional argument.
*nargsf* is the number of positional arguments including *args[0]*,
plus :const:`PY_VECTORCALL_ARGUMENTS_OFFSET` if the value of ``args[0]`` may
temporarily be changed. Keyword arguments can be passed just like in
:c:func:`_PyObject_Vectorcall`.
If the object has the :const:`Py_TPFLAGS_METHOD_DESCRIPTOR` feature,
this will actually call the unbound method object with the full
*args* vector as arguments.
Return the result of the call on success, or raise an exception and return
*NULL* on failure.
.. versionadded:: 3.9
.. c:function:: Py_hash_t PyObject_Hash(PyObject *o)
...
...
Include/cpython/abstract.h
View file @
b1263d5a
...
...
@@ -158,6 +158,10 @@ PyAPI_FUNC(PyObject *) _PyObject_Call_Prepend(
PyObject
*
args
,
PyObject
*
kwargs
);
PyAPI_FUNC
(
PyObject
*
)
_PyObject_VectorcallMethod
(
PyObject
*
name
,
PyObject
*
const
*
args
,
size_t
nargsf
,
PyObject
*
kwnames
);
/* Like PyObject_CallMethod(), but expect a _Py_Identifier*
as the method name. */
PyAPI_FUNC
(
PyObject
*
)
_PyObject_CallMethodId
(
PyObject
*
obj
,
...
...
@@ -174,6 +178,18 @@ PyAPI_FUNC(PyObject *) _PyObject_CallMethodIdObjArgs(
struct
_Py_Identifier
*
name
,
...);
static
inline
PyObject
*
_PyObject_VectorcallMethodId
(
_Py_Identifier
*
name
,
PyObject
*
const
*
args
,
size_t
nargsf
,
PyObject
*
kwnames
)
{
PyObject
*
oname
=
_PyUnicode_FromId
(
name
);
/* borrowed */
if
(
!
oname
)
{
return
NULL
;
}
return
_PyObject_VectorcallMethod
(
oname
,
args
,
nargsf
,
kwnames
);
}
PyAPI_FUNC
(
int
)
_PyObject_HasLen
(
PyObject
*
o
);
/* Guess the size of object 'o' using len(o) or o.__length_hint__().
...
...
Misc/NEWS.d/next/C API/2019-06-19-12-06-31.bpo-37337.gXIGyU.rst
0 → 100644
View file @
b1263d5a
Add :c:func:`_PyObject_VectorcallMethod` for fast calling of methods.
Modules/_abc.c
View file @
b1263d5a
...
...
@@ -480,6 +480,7 @@ _abc__abc_instancecheck_impl(PyObject *module, PyObject *self,
/*[clinic end generated code: output=b8b5148f63b6b56f input=a4f4525679261084]*/
{
PyObject
*
subtype
,
*
result
=
NULL
,
*
subclass
=
NULL
;
PyObject
*
margs
[
2
];
_abc_data
*
impl
=
_get_impl
(
self
);
if
(
impl
==
NULL
)
{
return
NULL
;
...
...
@@ -514,12 +515,16 @@ _abc__abc_instancecheck_impl(PyObject *module, PyObject *self,
}
}
/* Fall back to the subclass check. */
result
=
_PyObject_CallMethodIdObjArgs
(
self
,
&
PyId___subclasscheck__
,
subclass
,
NULL
);
margs
[
0
]
=
self
;
margs
[
1
]
=
subclass
;
result
=
_PyObject_VectorcallMethodId
(
&
PyId___subclasscheck__
,
margs
,
2
|
PY_VECTORCALL_ARGUMENTS_OFFSET
,
NULL
);
goto
end
;
}
result
=
_PyObject_CallMethodIdObjArgs
(
self
,
&
PyId___subclasscheck__
,
subclass
,
NULL
);
margs
[
0
]
=
self
;
margs
[
1
]
=
subclass
;
result
=
_PyObject_VectorcallMethodId
(
&
PyId___subclasscheck__
,
margs
,
2
|
PY_VECTORCALL_ARGUMENTS_OFFSET
,
NULL
);
if
(
result
==
NULL
)
{
goto
end
;
}
...
...
@@ -531,8 +536,10 @@ _abc__abc_instancecheck_impl(PyObject *module, PyObject *self,
break
;
case
0
:
Py_DECREF
(
result
);
result
=
_PyObject_CallMethodIdObjArgs
(
self
,
&
PyId___subclasscheck__
,
subtype
,
NULL
);
margs
[
0
]
=
self
;
margs
[
1
]
=
subtype
;
result
=
_PyObject_VectorcallMethodId
(
&
PyId___subclasscheck__
,
margs
,
2
|
PY_VECTORCALL_ARGUMENTS_OFFSET
,
NULL
);
break
;
case
1
:
// Nothing to do.
break
;
...
...
Objects/call.c
View file @
b1263d5a
...
...
@@ -1077,6 +1077,38 @@ object_vacall(PyObject *base, PyObject *callable, va_list vargs)
}
PyObject
*
_PyObject_VectorcallMethod
(
PyObject
*
name
,
PyObject
*
const
*
args
,
size_t
nargsf
,
PyObject
*
kwnames
)
{
assert
(
name
!=
NULL
);
assert
(
args
!=
NULL
);
assert
(
PyVectorcall_NARGS
(
nargsf
)
>=
1
);
PyObject
*
callable
=
NULL
;
/* Use args[0] as "self" argument */
int
unbound
=
_PyObject_GetMethod
(
args
[
0
],
name
,
&
callable
);
if
(
callable
==
NULL
)
{
return
NULL
;
}
if
(
unbound
)
{
/* We must remove PY_VECTORCALL_ARGUMENTS_OFFSET since
* that would be interpreted as allowing to change args[-1] */
nargsf
&=
~
PY_VECTORCALL_ARGUMENTS_OFFSET
;
}
else
{
/* Skip "self". We can keep PY_VECTORCALL_ARGUMENTS_OFFSET since
* args[-1] in the onward call is args[0] here. */
args
++
;
nargsf
--
;
}
PyObject
*
result
=
_PyObject_Vectorcall
(
callable
,
args
,
nargsf
,
kwnames
);
Py_DECREF
(
callable
);
return
result
;
}
PyObject
*
PyObject_CallMethodObjArgs
(
PyObject
*
obj
,
PyObject
*
name
,
...)
{
...
...
Objects/descrobject.c
View file @
b1263d5a
...
...
@@ -851,15 +851,22 @@ static PySequenceMethods mappingproxy_as_sequence = {
};
static
PyObject
*
mappingproxy_get
(
mappingproxyobject
*
pp
,
PyObject
*
args
)
mappingproxy_get
(
mappingproxyobject
*
pp
,
PyObject
*
const
*
args
,
Py_ssize_t
n
args
)
{
PyObject
*
key
,
*
def
=
Py_None
;
_Py_IDENTIFIER
(
get
);
/* newargs: mapping, key, default=None */
PyObject
*
newargs
[
3
];
newargs
[
0
]
=
pp
->
mapping
;
newargs
[
2
]
=
Py_None
;
if
(
!
PyArg_UnpackTuple
(
args
,
"get"
,
1
,
2
,
&
key
,
&
def
))
if
(
!
_PyArg_UnpackStack
(
args
,
nargs
,
"get"
,
1
,
2
,
&
newargs
[
1
],
&
newargs
[
2
]))
{
return
NULL
;
return
_PyObject_CallMethodIdObjArgs
(
pp
->
mapping
,
&
PyId_get
,
key
,
def
,
NULL
);
}
_Py_IDENTIFIER
(
get
);
return
_PyObject_VectorcallMethodId
(
&
PyId_get
,
newargs
,
3
|
PY_VECTORCALL_ARGUMENTS_OFFSET
,
NULL
);
}
static
PyObject
*
...
...
@@ -894,7 +901,7 @@ mappingproxy_copy(mappingproxyobject *pp, PyObject *Py_UNUSED(ignored))
to the underlying mapping */
static
PyMethodDef
mappingproxy_methods
[]
=
{
{
"get"
,
(
PyCFunction
)
mappingproxy_get
,
METH_
VARARGS
,
{
"get"
,
(
PyCFunction
)
mappingproxy_get
,
METH_
FASTCALL
,
PyDoc_STR
(
"D.get(k[,d]) -> D[k] if k in D, else d."
" d defaults to None."
)},
{
"keys"
,
(
PyCFunction
)
mappingproxy_keys
,
METH_NOARGS
,
...
...
Python/sysmodule.c
View file @
b1263d5a
...
...
@@ -3110,30 +3110,17 @@ PySys_SetArgv(int argc, wchar_t **argv)
static
int
sys_pyfile_write_unicode
(
PyObject
*
unicode
,
PyObject
*
file
)
{
PyObject
*
writer
=
NULL
,
*
result
=
NULL
;
int
err
;
if
(
file
==
NULL
)
return
-
1
;
writer
=
_PyObject_GetAttrId
(
file
,
&
PyId_write
);
if
(
writer
==
NULL
)
goto
error
;
result
=
PyObject_CallFunctionObjArgs
(
writer
,
unicode
,
NULL
);
assert
(
unicode
!=
NULL
);
PyObject
*
margs
[
2
]
=
{
file
,
unicode
};
PyObject
*
result
=
_PyObject_VectorcallMethodId
(
&
PyId_write
,
margs
,
2
|
PY_VECTORCALL_ARGUMENTS_OFFSET
,
NULL
);
if
(
result
==
NULL
)
{
goto
error
;
}
else
{
err
=
0
;
goto
finally
;
return
-
1
;
}
error:
err
=
-
1
;
finally:
Py_XDECREF
(
writer
);
Py_XDECREF
(
result
);
return
err
;
Py_DECREF
(
result
);
return
0
;
}
static
int
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment