| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -103,6 +103,7 @@ _PyObject_CallNoArgsTstate(PyThreadState *tstate, PyObject *func) { | |||
| 103 | 103 | // Private static inline function variant of public PyObject_CallNoArgs() | |
| 104 | 104 | static inline PyObject * | |
| 105 | 105 | _PyObject_CallNoArgs(PyObject *func) { | |
| 106 | + EVAL_CALL_STAT_INC_IF_FUNCTION(EVAL_CALL_API, func); | ||
| 106 | 107 | PyThreadState *tstate = _PyThreadState_GET(); | |
| 107 | 108 | return _PyObject_VectorcallTstate(tstate, func, NULL, 0, NULL); | |
| 108 | 109 | } | |
@@ -111,6 +112,7 @@ _PyObject_CallNoArgs(PyObject *func) { | |||
| 111 | 112 | static inline PyObject * | |
| 112 | 113 | _PyObject_FastCallTstate(PyThreadState *tstate, PyObject *func, PyObject *const *args, Py_ssize_t nargs) | |
| 113 | 114 | { | |
| 115 | + EVAL_CALL_STAT_INC_IF_FUNCTION(EVAL_CALL_API, func); | ||
| 114 | 116 | return _PyObject_VectorcallTstate(tstate, func, args, (size_t)nargs, NULL); | |
| 115 | 117 | } | |
| 116 | 118 | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -68,6 +68,7 @@ extern PyObject* _PyEval_BuiltinsFromGlobals( | |||
| 68 | 68 | static inline PyObject* | |
| 69 | 69 | _PyEval_EvalFrame(PyThreadState *tstate, struct _PyInterpreterFrame *frame, int throwflag) | |
| 70 | 70 | { | |
| 71 | + EVAL_CALL_STAT_INC(EVAL_CALL_TOTAL); | ||
| 71 | 72 | if (tstate->interp->eval_frame == NULL) { | |
| 72 | 73 | return _PyEval_EvalFrameDefault(tstate, frame, throwflag); | |
| 73 | 74 | } | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -265,6 +265,9 @@ extern int _PyStaticCode_InternStrings(PyCodeObject *co); | |||
| 265 | 265 | #define OBJECT_STAT_INC(name) _py_stats.object_stats.name++ | |
| 266 | 266 | #define OBJECT_STAT_INC_COND(name, cond) \ | |
| 267 | 267 | do { if (cond) _py_stats.object_stats.name++; } while (0) | |
| 268 | + #define EVAL_CALL_STAT_INC(name) _py_stats.call_stats.eval_calls[name]++ | ||
| 269 | + #define EVAL_CALL_STAT_INC_IF_FUNCTION(name, callable) \ | ||
| 270 | + do { if (PyFunction_Check(callable)) _py_stats.call_stats.eval_calls[name]++; } while (0) | ||
| 268 | 271 | ||
| 269 | 272 | // Used by the _opcode extension which is built as a shared library | |
| 270 | 273 | PyAPI_FUNC(PyObject*) _Py_GetSpecializationStats(void); | |
@@ -276,6 +279,8 @@ PyAPI_FUNC(PyObject*) _Py_GetSpecializationStats(void); | |||
| 276 | 279 | #define CALL_STAT_INC(name) ((void)0) | |
| 277 | 280 | #define OBJECT_STAT_INC(name) ((void)0) | |
| 278 | 281 | #define OBJECT_STAT_INC_COND(name, cond) ((void)0) | |
| 282 | + #define EVAL_CALL_STAT_INC(name) ((void)0) | ||
| 283 | + #define EVAL_CALL_STAT_INC_IF_FUNCTION(name, callable) ((void)0) | ||
| 279 | 284 | #endif // !Py_STATS | |
| 280 | 285 | ||
| 281 | 286 | // Cache values are only valid in memory, so use native endianness. | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -10,6 +10,20 @@ extern "C" { | |||
| 10 | 10 | ||
| 11 | 11 | #define SPECIALIZATION_FAILURE_KINDS 32 | |
| 12 | 12 | ||
| 13 | + /* Stats for determining who is calling PyEval_EvalFrame */ | ||
| 14 | + #define EVAL_CALL_TOTAL 0 | ||
| 15 | + #define EVAL_CALL_VECTOR 1 | ||
| 16 | + #define EVAL_CALL_GENERATOR 2 | ||
| 17 | + #define EVAL_CALL_LEGACY 3 | ||
| 18 | + #define EVAL_CALL_FUNCTION_VECTORCALL 4 | ||
| 19 | + #define EVAL_CALL_BUILD_CLASS 5 | ||
| 20 | + #define EVAL_CALL_SLOT 6 | ||
| 21 | + #define EVAL_CALL_FUNCTION_EX 7 | ||
| 22 | + #define EVAL_CALL_API 8 | ||
| 23 | + #define EVAL_CALL_METHOD 9 | ||
| 24 | + | ||
| 25 | + #define EVAL_CALL_KINDS 10 | ||
| 26 | + | ||
| 13 | 27 | typedef struct _specialization_stats { | |
| 14 | 28 | uint64_t success; | |
| 15 | 29 | uint64_t failure; | |
@@ -31,6 +45,7 @@ typedef struct _call_stats { | |||
| 31 | 45 | uint64_t pyeval_calls; | |
| 32 | 46 | uint64_t frames_pushed; | |
| 33 | 47 | uint64_t frame_objects_created; | |
| 48 | + uint64_t eval_calls[EVAL_CALL_KINDS]; | ||
| 34 | 49 | } CallStats; | |
| 35 | 50 | ||
| 36 | 51 | typedef struct _object_stats { | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -384,7 +384,7 @@ call_soon(PyObject *loop, PyObject *func, PyObject *arg, PyObject *ctx) | |||
| 384 | 384 | nargs++; | |
| 385 | 385 | } | |
| 386 | 386 | stack[nargs] = (PyObject *)ctx; | |
| 387 | - | ||
| 387 | + EVAL_CALL_STAT_INC_IF_FUNCTION(EVAL_CALL_API, callable); | ||
| 388 | 388 | handle = PyObject_Vectorcall(callable, stack, nargs, context_kwname); | |
| 389 | 389 | Py_DECREF(callable); | |
| 390 | 390 | } | |
@@ -2950,6 +2950,7 @@ task_step_impl(TaskObj *task, PyObject *exc) | |||
| 2950 | 2950 | PyObject *stack[2]; | |
| 2951 | 2951 | stack[0] = wrapper; | |
| 2952 | 2952 | stack[1] = (PyObject *)task->task_context; | |
| 2953 | + EVAL_CALL_STAT_INC_IF_FUNCTION(EVAL_CALL_API, add_cb); | ||
| 2953 | 2954 | tmp = PyObject_Vectorcall(add_cb, stack, 1, context_kwname); | |
| 2954 | 2955 | Py_DECREF(add_cb); | |
| 2955 | 2956 | Py_DECREF(wrapper); | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -109,7 +109,9 @@ _Py_CheckSlotResult(PyObject *obj, const char *slot_name, int success) | |||
| 109 | 109 | PyObject * | |
| 110 | 110 | PyObject_CallNoArgs(PyObject *func) | |
| 111 | 111 | { | |
| 112 | - return _PyObject_CallNoArgs(func); | ||
| 112 | + EVAL_CALL_STAT_INC_IF_FUNCTION(EVAL_CALL_API, func); | ||
| 113 | + PyThreadState *tstate = _PyThreadState_GET(); | ||
| 114 | + return _PyObject_VectorcallTstate(tstate, func, NULL, 0, NULL); | ||
| 113 | 115 | } | |
| 114 | 116 | ||
| 115 | 117 | ||
@@ -322,7 +324,7 @@ _PyObject_Call(PyThreadState *tstate, PyObject *callable, | |||
| 322 | 324 | assert(!_PyErr_Occurred(tstate)); | |
| 323 | 325 | assert(PyTuple_Check(args)); | |
| 324 | 326 | assert(kwargs == NULL || PyDict_Check(kwargs)); | |
| 325 | - | ||
| 327 | + EVAL_CALL_STAT_INC_IF_FUNCTION(EVAL_CALL_API, callable); | ||
| 326 | 328 | vectorcallfunc vector_func = _PyVectorcall_Function(callable); | |
| 327 | 329 | if (vector_func != NULL) { | |
| 328 | 330 | return _PyVectorcall_Call(tstate, vector_func, callable, args, kwargs); | |
@@ -367,6 +369,7 @@ PyCFunction_Call(PyObject *callable, PyObject *args, PyObject *kwargs) | |||
| 367 | 369 | PyObject * | |
| 368 | 370 | PyObject_CallOneArg(PyObject *func, PyObject *arg) | |
| 369 | 371 | { | |
| 372 | + EVAL_CALL_STAT_INC_IF_FUNCTION(EVAL_CALL_API, func); | ||
| 370 | 373 | assert(arg != NULL); | |
| 371 | 374 | PyObject *_args[2]; | |
| 372 | 375 | PyObject **args = _args + 1; // For PY_VECTORCALL_ARGUMENTS_OFFSET | |
@@ -389,6 +392,7 @@ _PyFunction_Vectorcall(PyObject *func, PyObject* const* stack, | |||
| 389 | 392 | assert(nargs >= 0); | |
| 390 | 393 | PyThreadState *tstate = _PyThreadState_GET(); | |
| 391 | 394 | assert(nargs == 0 || stack != NULL); | |
| 395 | + EVAL_CALL_STAT_INC(EVAL_CALL_FUNCTION_VECTORCALL); | ||
| 392 | 396 | if (((PyCodeObject *)f->func_code)->co_flags & CO_OPTIMIZED) { | |
| 393 | 397 | return _PyEval_Vector(tstate, f, NULL, stack, nargs, kwnames); | |
| 394 | 398 | } | |
@@ -520,7 +524,7 @@ _PyObject_CallFunctionVa(PyThreadState *tstate, PyObject *callable, | |||
| 520 | 524 | if (stack == NULL) { | |
| 521 | 525 | return NULL; | |
| 522 | 526 | } | |
| 523 | - | ||
| 527 | + EVAL_CALL_STAT_INC_IF_FUNCTION(EVAL_CALL_API, callable); | ||
| 524 | 528 | if (nargs == 1 && PyTuple_Check(stack[0])) { | |
| 525 | 529 | /* Special cases for backward compatibility: | |
| 526 | 530 | - PyObject_CallFunction(func, "O", tuple) calls func(*tuple) | |
@@ -815,6 +819,11 @@ object_vacall(PyThreadState *tstate, PyObject *base, | |||
| 815 | 819 | stack[i] = va_arg(vargs, PyObject *); | |
| 816 | 820 | } | |
| 817 | 821 | ||
| 822 | + #ifdef Py_STATS | ||
| 823 | + if (PyFunction_Check(callable)) { | ||
| 824 | + EVAL_CALL_STAT_INC(EVAL_CALL_API); | ||
| 825 | + } | ||
| 826 | + #endif | ||
| 818 | 827 | /* Call the function */ | |
| 819 | 828 | result = _PyObject_VectorcallTstate(tstate, callable, stack, nargs, NULL); | |
| 820 | 829 | ||
@@ -852,6 +861,7 @@ PyObject_VectorcallMethod(PyObject *name, PyObject *const *args, | |||
| 852 | 861 | args++; | |
| 853 | 862 | nargsf--; | |
| 854 | 863 | } | |
| 864 | + EVAL_CALL_STAT_INC_IF_FUNCTION(EVAL_CALL_METHOD, callable); | ||
| 855 | 865 | PyObject *result = _PyObject_VectorcallTstate(tstate, callable, | |
| 856 | 866 | args, nargsf, kwnames); | |
| 857 | 867 | Py_DECREF(callable); | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -1677,6 +1677,7 @@ property_descr_set(PyObject *self, PyObject *obj, PyObject *value) | |||
| 1677 | 1677 | res = PyObject_CallOneArg(func, obj); | |
| 1678 | 1678 | } | |
| 1679 | 1679 | else { | |
| 1680 | + EVAL_CALL_STAT_INC_IF_FUNCTION(EVAL_CALL_API, func); | ||
| 1680 | 1681 | PyObject *args[] = { obj, value }; | |
| 1681 | 1682 | res = PyObject_Vectorcall(func, args, 2, NULL); | |
| 1682 | 1683 | } | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -13,6 +13,7 @@ | |||
| 13 | 13 | #include "pycore_pystate.h" // _PyThreadState_GET() | |
| 14 | 14 | #include "structmember.h" // PyMemberDef | |
| 15 | 15 | #include "opcode.h" // SEND | |
| 16 | + #include "pystats.h" | ||
| 16 | 17 | ||
| 17 | 18 | static PyObject *gen_close(PyGenObject *, PyObject *); | |
| 18 | 19 | static PyObject *async_gen_asend_new(PyAsyncGenObject *, PyObject *); | |
@@ -218,6 +219,7 @@ gen_send_ex2(PyGenObject *gen, PyObject *arg, PyObject **presult, | |||
| 218 | 219 | } | |
| 219 | 220 | ||
| 220 | 221 | gen->gi_frame_state = FRAME_EXECUTING; | |
| 222 | + EVAL_CALL_STAT_INC(EVAL_CALL_GENERATOR); | ||
| 221 | 223 | result = _PyEval_EvalFrame(tstate, frame, exc); | |
| 222 | 224 | if (gen->gi_frame_state == FRAME_EXECUTING) { | |
| 223 | 225 | gen->gi_frame_state = FRAME_COMPLETED; | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -1653,6 +1653,7 @@ vectorcall_unbound(PyThreadState *tstate, int unbound, PyObject *func, | |||
| 1653 | 1653 | args++; | |
| 1654 | 1654 | nargsf = nargsf - 1 + PY_VECTORCALL_ARGUMENTS_OFFSET; | |
| 1655 | 1655 | } | |
| 1656 | + EVAL_CALL_STAT_INC_IF_FUNCTION(EVAL_CALL_SLOT, func); | ||
| 1656 | 1657 | return _PyObject_VectorcallTstate(tstate, func, args, nargsf, NULL); | |
| 1657 | 1658 | } | |
| 1658 | 1659 | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -198,6 +198,7 @@ builtin___build_class__(PyObject *self, PyObject *const *args, Py_ssize_t nargs, | |||
| 198 | 198 | goto error; | |
| 199 | 199 | } | |
| 200 | 200 | PyThreadState *tstate = _PyThreadState_GET(); | |
| 201 | + EVAL_CALL_STAT_INC(EVAL_CALL_BUILD_CLASS); | ||
| 201 | 202 | cell = _PyEval_Vector(tstate, (PyFunctionObject *)func, ns, NULL, 0, NULL); | |
| 202 | 203 | if (cell != NULL) { | |
| 203 | 204 | if (bases != orig_bases) { | |
| Back | FazBrowse Home | New Git URL |
0 commit comments