:c:func:`PyEval_SetProfile`, except the tracing function does receive line-number
events.
-.. c:function:: PyObject* PyEval_GetCallStats(PyObject *self)
-
- Return a tuple of function call counts. There are constants defined for the
- positions within the tuple:
-
- +-------------------------------+-------+
- | Name | Value |
- +===============================+=======+
- | :const:`PCALL_ALL` | 0 |
- +-------------------------------+-------+
- | :const:`PCALL_FUNCTION` | 1 |
- +-------------------------------+-------+
- | :const:`PCALL_FAST_FUNCTION` | 2 |
- +-------------------------------+-------+
- | :const:`PCALL_FASTER_FUNCTION`| 3 |
- +-------------------------------+-------+
- | :const:`PCALL_METHOD` | 4 |
- +-------------------------------+-------+
- | :const:`PCALL_BOUND_METHOD` | 5 |
- +-------------------------------+-------+
- | :const:`PCALL_CFUNCTION` | 6 |
- +-------------------------------+-------+
- | :const:`PCALL_TYPE` | 7 |
- +-------------------------------+-------+
- | :const:`PCALL_GENERATOR` | 8 |
- +-------------------------------+-------+
- | :const:`PCALL_OTHER` | 9 |
- +-------------------------------+-------+
- | :const:`PCALL_POP` | 10 |
- +-------------------------------+-------+
-
- :const:`PCALL_FAST_FUNCTION` means no argument tuple needs to be created.
- :const:`PCALL_FASTER_FUNCTION` means that the fast-path frame setup code is used.
-
- If there is a method call where the call can be optimized by changing
- the argument tuple and calling the function directly, it gets recorded
- twice.
-
- This function is only present if Python is compiled with :const:`CALL_PROFILE`
- defined.
.. _advanced-debugging:
#endif
#endif
-/* Function call profile */
-#ifdef CALL_PROFILE
-#define PCALL_NUM 11
-static int pcall[PCALL_NUM];
-
-#define PCALL_ALL 0
-#define PCALL_FUNCTION 1
-#define PCALL_FAST_FUNCTION 2
-#define PCALL_FASTER_FUNCTION 3
-#define PCALL_METHOD 4
-#define PCALL_BOUND_METHOD 5
-#define PCALL_CFUNCTION 6
-#define PCALL_TYPE 7
-#define PCALL_GENERATOR 8
-#define PCALL_OTHER 9
-#define PCALL_POP 10
-
-/* Notes about the statistics
-
- PCALL_FAST stats
-
- FAST_FUNCTION means no argument tuple needs to be created.
- FASTER_FUNCTION means that the fast-path frame setup code is used.
-
- If there is a method call where the call can be optimized by changing
- the argument tuple and calling the function directly, it gets recorded
- twice.
-
- As a result, the relationship among the statistics appears to be
- PCALL_ALL == PCALL_FUNCTION + PCALL_METHOD - PCALL_BOUND_METHOD +
- PCALL_CFUNCTION + PCALL_TYPE + PCALL_GENERATOR + PCALL_OTHER
- PCALL_FUNCTION > PCALL_FAST_FUNCTION > PCALL_FASTER_FUNCTION
- PCALL_METHOD > PCALL_BOUND_METHOD
-*/
-
-#define PCALL(POS) pcall[POS]++
-
-PyObject *
-PyEval_GetCallStats(PyObject *self)
-{
- return Py_BuildValue("iiiiiiiiiii",
- pcall[0], pcall[1], pcall[2], pcall[3],
- pcall[4], pcall[5], pcall[6], pcall[7],
- pcall[8], pcall[9], pcall[10]);
-}
-#else
-#define PCALL(O)
-
-PyObject *
-PyEval_GetCallStats(PyObject *self)
-{
- Py_INCREF(Py_None);
- return Py_None;
-}
-#endif
-
-
#ifdef WITH_THREAD
#define GIL_REQUEST _Py_atomic_load_relaxed(&gil_drop_request)
#else
PREDICTED(CALL_FUNCTION);
TARGET(CALL_FUNCTION) {
PyObject **sp, *res;
- PCALL(PCALL_ALL);
sp = stack_pointer;
res = call_function(&sp, oparg, NULL);
stack_pointer = sp;
names = POP();
assert(PyTuple_CheckExact(names) && PyTuple_GET_SIZE(names) <= oparg);
- PCALL(PCALL_ALL);
sp = stack_pointer;
res = call_function(&sp, oparg, names);
stack_pointer = sp;
TARGET(CALL_FUNCTION_EX) {
PyObject *func, *callargs, *kwargs = NULL, *result;
- PCALL(PCALL_ALL);
if (oparg & 0x01) {
kwargs = POP();
if (!PyDict_CheckExact(kwargs)) {
* when the generator is resumed. */
Py_CLEAR(f->f_back);
- PCALL(PCALL_GENERATOR);
-
/* Create a new generator that owns the ready to run frame
* and return that as the value. */
if (is_coro) {
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));
}
if (PyMethod_Check(func) && PyMethod_GET_SELF(func) != NULL) {
/* optimize access to bound methods */
PyObject *self = PyMethod_GET_SELF(func);
- PCALL(PCALL_METHOD);
- PCALL(PCALL_BOUND_METHOD);
Py_INCREF(self);
func = PyMethod_GET_FUNCTION(func);
Py_INCREF(func);
while ((*pp_stack) > pfunc) {
w = EXT_POP(*pp_stack);
Py_DECREF(w);
- PCALL(PCALL_POP);
}
return x;
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
/* 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))
{
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))
static PyObject *
do_call_core(PyObject *func, PyObject *callargs, PyObject *kwdict)
{
-#ifdef CALL_PROFILE
- /* At this point, we have to look at the type of func to
- update the call stats properly. Do it here so as to avoid
- exposing the call stats machinery outside ceval.c
- */
- if (PyFunction_Check(func))
- PCALL(PCALL_FUNCTION);
- else if (PyMethod_Check(func))
- PCALL(PCALL_METHOD);
- else if (PyType_Check(func))
- PCALL(PCALL_TYPE);
- else if (PyCFunction_Check(func))
- PCALL(PCALL_CFUNCTION);
- else
- PCALL(PCALL_OTHER);
-#endif
-
if (PyCFunction_Check(func)) {
PyObject *result;
PyThreadState *tstate = PyThreadState_GET();
10. Number of stack pops performed by call_function()"
);
+static PyObject *
+sys_callstats(PyObject *self)
+{
+ if (PyErr_WarnEx(PyExc_DeprecationWarning,
+ "sys.callstats() has been deprecated in Python 3.7 "
+ "and will be removed in the future", 1) < 0) {
+ return NULL;
+ }
+
+ Py_RETURN_NONE;
+}
+
+
#ifdef __cplusplus
extern "C" {
#endif
static PyMethodDef sys_methods[] = {
/* Might as well keep this in alphabetic order */
- {"callstats", (PyCFunction)PyEval_GetCallStats, METH_NOARGS,
+ {"callstats", (PyCFunction)sys_callstats, METH_NOARGS,
callstats_doc},
{"_clear_type_cache", sys_clear_type_cache, METH_NOARGS,
sys_clear_type_cache__doc__},