https://github.com/python/cpython/commit/622300bdfa6242b0fc909235fcc64f07b3d280d7 commit: 622300bdfa6242b0fc909235fcc64f07b3d280d7 branch: main author: Mark Shannon <m...@hotpy.org> committer: markshannon <m...@hotpy.org> date: 2025-04-29T09:00:14+01:00 summary:
GH-132554: Add stats for GET_ITER (GH-132592) * Add stats for GET_ITER * Look for common iterable types, not iterator types * Add stats for self iter and fix naming in summary files: M Include/internal/pycore_code.h M Python/bytecodes.c M Python/executor_cases.c.h M Python/generated_cases.c.h M Python/specialize.c M Tools/scripts/summarize_stats.py diff --git a/Include/internal/pycore_code.h b/Include/internal/pycore_code.h index ad2e626c1ee893..635d2b24f4bdff 100644 --- a/Include/internal/pycore_code.h +++ b/Include/internal/pycore_code.h @@ -317,6 +317,7 @@ extern void _Py_Specialize_ForIter(_PyStackRef iter, _Py_CODEUNIT *instr, int op extern void _Py_Specialize_Send(_PyStackRef receiver, _Py_CODEUNIT *instr); extern void _Py_Specialize_ToBool(_PyStackRef value, _Py_CODEUNIT *instr); extern void _Py_Specialize_ContainsOp(_PyStackRef value, _Py_CODEUNIT *instr); +extern void _Py_GatherStats_GetIter(_PyStackRef iterable); // Utility functions for reading/writing 32/64-bit values in the inline caches. // Great care should be taken to ensure that these functions remain correct and diff --git a/Python/bytecodes.c b/Python/bytecodes.c index 40fb0d769afcca..4e2dec7c9852ee 100644 --- a/Python/bytecodes.c +++ b/Python/bytecodes.c @@ -3029,6 +3029,9 @@ dummy_func( } inst(GET_ITER, (iterable -- iter)) { + #ifdef Py_STATS + _Py_GatherStats_GetIter(iterable); + #endif /* before: [obj]; after [getiter(obj)] */ PyObject *iter_o = PyObject_GetIter(PyStackRef_AsPyObjectBorrow(iterable)); PyStackRef_CLOSE(iterable); diff --git a/Python/executor_cases.c.h b/Python/executor_cases.c.h index 978662b241a01c..09998090575e31 100644 --- a/Python/executor_cases.c.h +++ b/Python/executor_cases.c.h @@ -4075,6 +4075,11 @@ _PyStackRef iterable; _PyStackRef iter; iterable = stack_pointer[-1]; + #ifdef Py_STATS + _PyFrame_SetStackPointer(frame, stack_pointer); + _Py_GatherStats_GetIter(iterable); + stack_pointer = _PyFrame_GetStackPointer(frame); + #endif _PyFrame_SetStackPointer(frame, stack_pointer); PyObject *iter_o = PyObject_GetIter(PyStackRef_AsPyObjectBorrow(iterable)); stack_pointer = _PyFrame_GetStackPointer(frame); diff --git a/Python/generated_cases.c.h b/Python/generated_cases.c.h index 48a446a0fe5486..fbd1f2349d0c4a 100644 --- a/Python/generated_cases.c.h +++ b/Python/generated_cases.c.h @@ -5995,6 +5995,11 @@ _PyStackRef iterable; _PyStackRef iter; iterable = stack_pointer[-1]; + #ifdef Py_STATS + _PyFrame_SetStackPointer(frame, stack_pointer); + _Py_GatherStats_GetIter(iterable); + stack_pointer = _PyFrame_GetStackPointer(frame); + #endif _PyFrame_SetStackPointer(frame, stack_pointer); PyObject *iter_o = PyObject_GetIter(PyStackRef_AsPyObjectBorrow(iterable)); stack_pointer = _PyFrame_GetStackPointer(frame); diff --git a/Python/specialize.c b/Python/specialize.c index 48cdcbd2a24cab..562e4a19d64a7f 100644 --- a/Python/specialize.c +++ b/Python/specialize.c @@ -146,6 +146,7 @@ print_spec_stats(FILE *out, OpcodeStats *stats) * even though we don't specialize them yet. */ fprintf(out, "opcode[BINARY_SLICE].specializable : 1\n"); fprintf(out, "opcode[STORE_SLICE].specializable : 1\n"); + fprintf(out, "opcode[GET_ITER].specializable : 1\n"); for (int i = 0; i < 256; i++) { if (_PyOpcode_Caches[i]) { /* Ignore jumps as they cannot be specialized */ @@ -668,6 +669,7 @@ _PyCode_Quicken(_Py_CODEUNIT *instructions, Py_ssize_t size, int enable_counters #define SPEC_FAIL_ITER_CALLABLE 28 #define SPEC_FAIL_ITER_ASCII_STRING 29 #define SPEC_FAIL_ITER_ASYNC_GENERATOR_SEND 30 +#define SPEC_FAIL_ITER_SELF 31 // UNPACK_SEQUENCE @@ -3115,6 +3117,53 @@ _Py_Specialize_ContainsOp(_PyStackRef value_st, _Py_CODEUNIT *instr) return; } +#ifdef Py_STATS +void +_Py_GatherStats_GetIter(_PyStackRef iterable) +{ + PyTypeObject *tp = PyStackRef_TYPE(iterable); + int kind = SPEC_FAIL_OTHER; + if (tp == &PyTuple_Type) { + kind = SPEC_FAIL_ITER_TUPLE; + } + else if (tp == &PyList_Type) { + kind = SPEC_FAIL_ITER_LIST; + } + else if (tp == &PyDict_Type) { + kind = SPEC_FAIL_ITER_DICT_KEYS; + } + else if (tp == &PySet_Type) { + kind = SPEC_FAIL_ITER_SET; + } + else if (tp == &PyBytes_Type) { + kind = SPEC_FAIL_ITER_BYTES; + } + else if (tp == &PyEnum_Type) { + kind = SPEC_FAIL_ITER_ENUMERATE; + } + else if (tp == &PyUnicode_Type) { + kind = SPEC_FAIL_ITER_STRING; + } + else if (tp == &PyGen_Type) { + kind = SPEC_FAIL_ITER_GENERATOR; + } + else if (tp == &PyCoro_Type) { + kind = SPEC_FAIL_ITER_COROUTINE; + } + else if (tp == &PyAsyncGen_Type) { + kind = SPEC_FAIL_ITER_ASYNC_GENERATOR; + } + else if (tp == &_PyAsyncGenASend_Type) { + kind = SPEC_FAIL_ITER_ASYNC_GENERATOR_SEND; + } + else if (tp->tp_iter == PyObject_SelfIter) { + kind = SPEC_FAIL_ITER_SELF; + } + SPECIALIZATION_FAIL(GET_ITER, kind); +} +#endif + + /* Code init cleanup. * CALL_ALLOC_AND_ENTER_INIT will set up * the frame to execute the EXIT_INIT_CHECK diff --git a/Tools/scripts/summarize_stats.py b/Tools/scripts/summarize_stats.py index eb54b8dd115c94..68cfad3f92cdc7 100644 --- a/Tools/scripts/summarize_stats.py +++ b/Tools/scripts/summarize_stats.py @@ -288,7 +288,7 @@ def kind_to_text(kind: int, opcode: str): opcode = "SUPER" elif opcode.endswith("ATTR"): opcode = "ATTR" - elif opcode in ("FOR_ITER", "SEND"): + elif opcode in ("FOR_ITER", "GET_ITER", "SEND"): opcode = "ITER" elif opcode.endswith("SUBSCR"): opcode = "SUBSCR" _______________________________________________ Python-checkins mailing list -- python-checkins@python.org To unsubscribe send an email to python-checkins-le...@python.org https://mail.python.org/mailman3/lists/python-checkins.python.org/ Member address: arch...@mail-archive.com