GH-132554: "Virtual" iterators (GH-132555)
* FOR_ITER now pushes either the iterator and NULL or leaves the iterable and pushes tagged zero * NEXT_ITER uses the tagged int as the index into the sequence or, if TOS is NULL, iterates as before.
This commit is contained in:
parent
9300a596d3
commit
f6f4e8a662
@ -353,6 +353,8 @@ PyAPI_FUNC(_PyStackRef) _PyFloat_FromDouble_ConsumeInputs(_PyStackRef left, _PyS
|
|||||||
extern int _PyRunRemoteDebugger(PyThreadState *tstate);
|
extern int _PyRunRemoteDebugger(PyThreadState *tstate);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
_PyStackRef _PyForIter_NextWithIndex(PyObject *seq, _PyStackRef index);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -313,7 +313,7 @@ extern void _Py_Specialize_CompareOp(_PyStackRef lhs, _PyStackRef rhs,
|
|||||||
_Py_CODEUNIT *instr, int oparg);
|
_Py_CODEUNIT *instr, int oparg);
|
||||||
extern void _Py_Specialize_UnpackSequence(_PyStackRef seq, _Py_CODEUNIT *instr,
|
extern void _Py_Specialize_UnpackSequence(_PyStackRef seq, _Py_CODEUNIT *instr,
|
||||||
int oparg);
|
int oparg);
|
||||||
extern void _Py_Specialize_ForIter(_PyStackRef iter, _Py_CODEUNIT *instr, int oparg);
|
extern void _Py_Specialize_ForIter(_PyStackRef iter, _PyStackRef null_or_index, _Py_CODEUNIT *instr, int oparg);
|
||||||
extern void _Py_Specialize_Send(_PyStackRef receiver, _Py_CODEUNIT *instr);
|
extern void _Py_Specialize_Send(_PyStackRef receiver, _Py_CODEUNIT *instr);
|
||||||
extern void _Py_Specialize_ToBool(_PyStackRef value, _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_Specialize_ContainsOp(_PyStackRef value, _Py_CODEUNIT *instr);
|
||||||
|
@ -95,6 +95,7 @@ typedef enum {
|
|||||||
enum _PyCompile_FBlockType {
|
enum _PyCompile_FBlockType {
|
||||||
COMPILE_FBLOCK_WHILE_LOOP,
|
COMPILE_FBLOCK_WHILE_LOOP,
|
||||||
COMPILE_FBLOCK_FOR_LOOP,
|
COMPILE_FBLOCK_FOR_LOOP,
|
||||||
|
COMPILE_FBLOCK_ASYNC_FOR_LOOP,
|
||||||
COMPILE_FBLOCK_TRY_EXCEPT,
|
COMPILE_FBLOCK_TRY_EXCEPT,
|
||||||
COMPILE_FBLOCK_FINALLY_TRY,
|
COMPILE_FBLOCK_FINALLY_TRY,
|
||||||
COMPILE_FBLOCK_FINALLY_END,
|
COMPILE_FBLOCK_FINALLY_END,
|
||||||
|
@ -279,6 +279,8 @@ Known values:
|
|||||||
Python 3.14b1 3624 (Don't optimize LOAD_FAST when local is killed by DELETE_FAST)
|
Python 3.14b1 3624 (Don't optimize LOAD_FAST when local is killed by DELETE_FAST)
|
||||||
Python 3.15a0 3650 (Initial version)
|
Python 3.15a0 3650 (Initial version)
|
||||||
Python 3.15a1 3651 (Simplify LOAD_CONST)
|
Python 3.15a1 3651 (Simplify LOAD_CONST)
|
||||||
|
Python 3.15a1 3652 (Virtual iterators)
|
||||||
|
|
||||||
|
|
||||||
Python 3.16 will start with 3700
|
Python 3.16 will start with 3700
|
||||||
|
|
||||||
@ -291,7 +293,7 @@ PC/launcher.c must also be updated.
|
|||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define PYC_MAGIC_NUMBER 3651
|
#define PYC_MAGIC_NUMBER 3652
|
||||||
/* This is equivalent to converting PYC_MAGIC_NUMBER to 2 bytes
|
/* This is equivalent to converting PYC_MAGIC_NUMBER to 2 bytes
|
||||||
(little-endian) and then appending b'\r\n'. */
|
(little-endian) and then appending b'\r\n'. */
|
||||||
#define PYC_MAGIC_NUMBER_TOKEN \
|
#define PYC_MAGIC_NUMBER_TOKEN \
|
||||||
|
40
Include/internal/pycore_opcode_metadata.h
generated
40
Include/internal/pycore_opcode_metadata.h
generated
@ -205,15 +205,15 @@ int _PyOpcode_num_popped(int opcode, int oparg) {
|
|||||||
case FORMAT_WITH_SPEC:
|
case FORMAT_WITH_SPEC:
|
||||||
return 2;
|
return 2;
|
||||||
case FOR_ITER:
|
case FOR_ITER:
|
||||||
return 1;
|
return 2;
|
||||||
case FOR_ITER_GEN:
|
case FOR_ITER_GEN:
|
||||||
return 1;
|
return 2;
|
||||||
case FOR_ITER_LIST:
|
case FOR_ITER_LIST:
|
||||||
return 1;
|
return 2;
|
||||||
case FOR_ITER_RANGE:
|
case FOR_ITER_RANGE:
|
||||||
return 1;
|
return 2;
|
||||||
case FOR_ITER_TUPLE:
|
case FOR_ITER_TUPLE:
|
||||||
return 1;
|
return 2;
|
||||||
case GET_AITER:
|
case GET_AITER:
|
||||||
return 1;
|
return 1;
|
||||||
case GET_ANEXT:
|
case GET_ANEXT:
|
||||||
@ -239,11 +239,11 @@ int _PyOpcode_num_popped(int opcode, int oparg) {
|
|||||||
case INSTRUMENTED_END_ASYNC_FOR:
|
case INSTRUMENTED_END_ASYNC_FOR:
|
||||||
return 2;
|
return 2;
|
||||||
case INSTRUMENTED_END_FOR:
|
case INSTRUMENTED_END_FOR:
|
||||||
return 2;
|
return 3;
|
||||||
case INSTRUMENTED_END_SEND:
|
case INSTRUMENTED_END_SEND:
|
||||||
return 2;
|
return 2;
|
||||||
case INSTRUMENTED_FOR_ITER:
|
case INSTRUMENTED_FOR_ITER:
|
||||||
return 1;
|
return 2;
|
||||||
case INSTRUMENTED_INSTRUCTION:
|
case INSTRUMENTED_INSTRUCTION:
|
||||||
return 0;
|
return 0;
|
||||||
case INSTRUMENTED_JUMP_BACKWARD:
|
case INSTRUMENTED_JUMP_BACKWARD:
|
||||||
@ -257,7 +257,7 @@ int _PyOpcode_num_popped(int opcode, int oparg) {
|
|||||||
case INSTRUMENTED_NOT_TAKEN:
|
case INSTRUMENTED_NOT_TAKEN:
|
||||||
return 0;
|
return 0;
|
||||||
case INSTRUMENTED_POP_ITER:
|
case INSTRUMENTED_POP_ITER:
|
||||||
return 1;
|
return 2;
|
||||||
case INSTRUMENTED_POP_JUMP_IF_FALSE:
|
case INSTRUMENTED_POP_JUMP_IF_FALSE:
|
||||||
return 1;
|
return 1;
|
||||||
case INSTRUMENTED_POP_JUMP_IF_NONE:
|
case INSTRUMENTED_POP_JUMP_IF_NONE:
|
||||||
@ -395,7 +395,7 @@ int _PyOpcode_num_popped(int opcode, int oparg) {
|
|||||||
case POP_EXCEPT:
|
case POP_EXCEPT:
|
||||||
return 1;
|
return 1;
|
||||||
case POP_ITER:
|
case POP_ITER:
|
||||||
return 1;
|
return 2;
|
||||||
case POP_JUMP_IF_FALSE:
|
case POP_JUMP_IF_FALSE:
|
||||||
return 1;
|
return 1;
|
||||||
case POP_JUMP_IF_NONE:
|
case POP_JUMP_IF_NONE:
|
||||||
@ -688,15 +688,15 @@ int _PyOpcode_num_pushed(int opcode, int oparg) {
|
|||||||
case FORMAT_WITH_SPEC:
|
case FORMAT_WITH_SPEC:
|
||||||
return 1;
|
return 1;
|
||||||
case FOR_ITER:
|
case FOR_ITER:
|
||||||
return 2;
|
return 3;
|
||||||
case FOR_ITER_GEN:
|
case FOR_ITER_GEN:
|
||||||
return 1;
|
return 2;
|
||||||
case FOR_ITER_LIST:
|
case FOR_ITER_LIST:
|
||||||
return 2;
|
return 3;
|
||||||
case FOR_ITER_RANGE:
|
case FOR_ITER_RANGE:
|
||||||
return 2;
|
return 3;
|
||||||
case FOR_ITER_TUPLE:
|
case FOR_ITER_TUPLE:
|
||||||
return 2;
|
return 3;
|
||||||
case GET_AITER:
|
case GET_AITER:
|
||||||
return 1;
|
return 1;
|
||||||
case GET_ANEXT:
|
case GET_ANEXT:
|
||||||
@ -704,7 +704,7 @@ int _PyOpcode_num_pushed(int opcode, int oparg) {
|
|||||||
case GET_AWAITABLE:
|
case GET_AWAITABLE:
|
||||||
return 1;
|
return 1;
|
||||||
case GET_ITER:
|
case GET_ITER:
|
||||||
return 1;
|
return 2;
|
||||||
case GET_LEN:
|
case GET_LEN:
|
||||||
return 2;
|
return 2;
|
||||||
case GET_YIELD_FROM_ITER:
|
case GET_YIELD_FROM_ITER:
|
||||||
@ -722,11 +722,11 @@ int _PyOpcode_num_pushed(int opcode, int oparg) {
|
|||||||
case INSTRUMENTED_END_ASYNC_FOR:
|
case INSTRUMENTED_END_ASYNC_FOR:
|
||||||
return 0;
|
return 0;
|
||||||
case INSTRUMENTED_END_FOR:
|
case INSTRUMENTED_END_FOR:
|
||||||
return 1;
|
return 2;
|
||||||
case INSTRUMENTED_END_SEND:
|
case INSTRUMENTED_END_SEND:
|
||||||
return 1;
|
return 1;
|
||||||
case INSTRUMENTED_FOR_ITER:
|
case INSTRUMENTED_FOR_ITER:
|
||||||
return 2;
|
return 3;
|
||||||
case INSTRUMENTED_INSTRUCTION:
|
case INSTRUMENTED_INSTRUCTION:
|
||||||
return 0;
|
return 0;
|
||||||
case INSTRUMENTED_JUMP_BACKWARD:
|
case INSTRUMENTED_JUMP_BACKWARD:
|
||||||
@ -1157,7 +1157,7 @@ const struct opcode_metadata _PyOpcode_opcode_metadata[267] = {
|
|||||||
[FOR_ITER_GEN] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_DEOPT_FLAG },
|
[FOR_ITER_GEN] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_DEOPT_FLAG },
|
||||||
[FOR_ITER_LIST] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_JUMP_FLAG | HAS_DEOPT_FLAG | HAS_EXIT_FLAG | HAS_ESCAPES_FLAG },
|
[FOR_ITER_LIST] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_JUMP_FLAG | HAS_DEOPT_FLAG | HAS_EXIT_FLAG | HAS_ESCAPES_FLAG },
|
||||||
[FOR_ITER_RANGE] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_JUMP_FLAG | HAS_EXIT_FLAG | HAS_ERROR_FLAG },
|
[FOR_ITER_RANGE] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_JUMP_FLAG | HAS_EXIT_FLAG | HAS_ERROR_FLAG },
|
||||||
[FOR_ITER_TUPLE] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_JUMP_FLAG | HAS_EXIT_FLAG | HAS_ESCAPES_FLAG },
|
[FOR_ITER_TUPLE] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_JUMP_FLAG | HAS_EXIT_FLAG },
|
||||||
[GET_AITER] = { true, INSTR_FMT_IX, HAS_ERROR_FLAG | HAS_ESCAPES_FLAG },
|
[GET_AITER] = { true, INSTR_FMT_IX, HAS_ERROR_FLAG | HAS_ESCAPES_FLAG },
|
||||||
[GET_ANEXT] = { true, INSTR_FMT_IX, HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG },
|
[GET_ANEXT] = { true, INSTR_FMT_IX, HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG },
|
||||||
[GET_AWAITABLE] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG },
|
[GET_AWAITABLE] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG },
|
||||||
@ -1242,7 +1242,7 @@ const struct opcode_metadata _PyOpcode_opcode_metadata[267] = {
|
|||||||
[NOP] = { true, INSTR_FMT_IX, HAS_PURE_FLAG },
|
[NOP] = { true, INSTR_FMT_IX, HAS_PURE_FLAG },
|
||||||
[NOT_TAKEN] = { true, INSTR_FMT_IX, HAS_PURE_FLAG },
|
[NOT_TAKEN] = { true, INSTR_FMT_IX, HAS_PURE_FLAG },
|
||||||
[POP_EXCEPT] = { true, INSTR_FMT_IX, HAS_ESCAPES_FLAG },
|
[POP_EXCEPT] = { true, INSTR_FMT_IX, HAS_ESCAPES_FLAG },
|
||||||
[POP_ITER] = { true, INSTR_FMT_IX, HAS_ESCAPES_FLAG | HAS_PURE_FLAG },
|
[POP_ITER] = { true, INSTR_FMT_IX, HAS_ESCAPES_FLAG },
|
||||||
[POP_JUMP_IF_FALSE] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_JUMP_FLAG },
|
[POP_JUMP_IF_FALSE] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_JUMP_FLAG },
|
||||||
[POP_JUMP_IF_NONE] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_JUMP_FLAG | HAS_ESCAPES_FLAG },
|
[POP_JUMP_IF_NONE] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_JUMP_FLAG | HAS_ESCAPES_FLAG },
|
||||||
[POP_JUMP_IF_NOT_NONE] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_JUMP_FLAG | HAS_ESCAPES_FLAG },
|
[POP_JUMP_IF_NOT_NONE] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_JUMP_FLAG | HAS_ESCAPES_FLAG },
|
||||||
@ -1453,7 +1453,7 @@ _PyOpcode_macro_expansion[256] = {
|
|||||||
[NOP] = { .nuops = 1, .uops = { { _NOP, OPARG_SIMPLE, 0 } } },
|
[NOP] = { .nuops = 1, .uops = { { _NOP, OPARG_SIMPLE, 0 } } },
|
||||||
[NOT_TAKEN] = { .nuops = 1, .uops = { { _NOP, OPARG_SIMPLE, 0 } } },
|
[NOT_TAKEN] = { .nuops = 1, .uops = { { _NOP, OPARG_SIMPLE, 0 } } },
|
||||||
[POP_EXCEPT] = { .nuops = 1, .uops = { { _POP_EXCEPT, OPARG_SIMPLE, 0 } } },
|
[POP_EXCEPT] = { .nuops = 1, .uops = { { _POP_EXCEPT, OPARG_SIMPLE, 0 } } },
|
||||||
[POP_ITER] = { .nuops = 1, .uops = { { _POP_TOP, OPARG_SIMPLE, 0 } } },
|
[POP_ITER] = { .nuops = 1, .uops = { { _POP_ITER, OPARG_SIMPLE, 0 } } },
|
||||||
[POP_JUMP_IF_FALSE] = { .nuops = 1, .uops = { { _POP_JUMP_IF_FALSE, OPARG_REPLACED, 1 } } },
|
[POP_JUMP_IF_FALSE] = { .nuops = 1, .uops = { { _POP_JUMP_IF_FALSE, OPARG_REPLACED, 1 } } },
|
||||||
[POP_JUMP_IF_NONE] = { .nuops = 2, .uops = { { _IS_NONE, OPARG_SIMPLE, 1 }, { _POP_JUMP_IF_TRUE, OPARG_REPLACED, 1 } } },
|
[POP_JUMP_IF_NONE] = { .nuops = 2, .uops = { { _IS_NONE, OPARG_SIMPLE, 1 }, { _POP_JUMP_IF_TRUE, OPARG_REPLACED, 1 } } },
|
||||||
[POP_JUMP_IF_NOT_NONE] = { .nuops = 2, .uops = { { _IS_NONE, OPARG_SIMPLE, 1 }, { _POP_JUMP_IF_FALSE, OPARG_REPLACED, 1 } } },
|
[POP_JUMP_IF_NOT_NONE] = { .nuops = 2, .uops = { { _IS_NONE, OPARG_SIMPLE, 1 }, { _POP_JUMP_IF_FALSE, OPARG_REPLACED, 1 } } },
|
||||||
|
@ -232,6 +232,9 @@ extern intptr_t PyStackRef_UntagInt(_PyStackRef ref);
|
|||||||
|
|
||||||
extern _PyStackRef PyStackRef_TagInt(intptr_t i);
|
extern _PyStackRef PyStackRef_TagInt(intptr_t i);
|
||||||
|
|
||||||
|
/* Increments a tagged int, but does not check for overflow */
|
||||||
|
extern _PyStackRef PyStackRef_IncrementTaggedIntNoOverflow(_PyStackRef ref);
|
||||||
|
|
||||||
extern bool
|
extern bool
|
||||||
PyStackRef_IsNullOrInt(_PyStackRef ref);
|
PyStackRef_IsNullOrInt(_PyStackRef ref);
|
||||||
|
|
||||||
@ -239,11 +242,12 @@ PyStackRef_IsNullOrInt(_PyStackRef ref);
|
|||||||
|
|
||||||
#define Py_INT_TAG 3
|
#define Py_INT_TAG 3
|
||||||
#define Py_TAG_REFCNT 1
|
#define Py_TAG_REFCNT 1
|
||||||
|
#define Py_TAG_BITS 3
|
||||||
|
|
||||||
static inline bool
|
static inline bool
|
||||||
PyStackRef_IsTaggedInt(_PyStackRef i)
|
PyStackRef_IsTaggedInt(_PyStackRef i)
|
||||||
{
|
{
|
||||||
return (i.bits & Py_INT_TAG) == Py_INT_TAG;
|
return (i.bits & Py_TAG_BITS) == Py_INT_TAG;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline _PyStackRef
|
static inline _PyStackRef
|
||||||
@ -262,12 +266,21 @@ PyStackRef_UntagInt(_PyStackRef i)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static inline _PyStackRef
|
||||||
|
PyStackRef_IncrementTaggedIntNoOverflow(_PyStackRef ref)
|
||||||
|
{
|
||||||
|
assert((ref.bits & Py_TAG_BITS) == Py_INT_TAG); // Is tagged int
|
||||||
|
assert((ref.bits & (~Py_TAG_BITS)) != (INT_MAX & (~Py_TAG_BITS))); // Isn't about to overflow
|
||||||
|
return (_PyStackRef){ .bits = ref.bits + 4 };
|
||||||
|
}
|
||||||
|
|
||||||
|
#define PyStackRef_IsDeferredOrTaggedInt(ref) (((ref).bits & Py_TAG_REFCNT) != 0)
|
||||||
|
|
||||||
#ifdef Py_GIL_DISABLED
|
#ifdef Py_GIL_DISABLED
|
||||||
|
|
||||||
#define Py_TAG_DEFERRED Py_TAG_REFCNT
|
#define Py_TAG_DEFERRED Py_TAG_REFCNT
|
||||||
|
|
||||||
#define Py_TAG_PTR ((uintptr_t)0)
|
#define Py_TAG_PTR ((uintptr_t)0)
|
||||||
#define Py_TAG_BITS ((uintptr_t)1)
|
|
||||||
|
|
||||||
|
|
||||||
static const _PyStackRef PyStackRef_NULL = { .bits = Py_TAG_DEFERRED};
|
static const _PyStackRef PyStackRef_NULL = { .bits = Py_TAG_DEFERRED};
|
||||||
@ -379,7 +392,7 @@ PyStackRef_FromPyObjectBorrow(PyObject *obj)
|
|||||||
do { \
|
do { \
|
||||||
_PyStackRef _close_tmp = (REF); \
|
_PyStackRef _close_tmp = (REF); \
|
||||||
assert(!PyStackRef_IsNull(_close_tmp)); \
|
assert(!PyStackRef_IsNull(_close_tmp)); \
|
||||||
if (!PyStackRef_IsDeferred(_close_tmp)) { \
|
if (!PyStackRef_IsDeferredOrTaggedInt(_close_tmp)) { \
|
||||||
Py_DECREF(PyStackRef_AsPyObjectBorrow(_close_tmp)); \
|
Py_DECREF(PyStackRef_AsPyObjectBorrow(_close_tmp)); \
|
||||||
} \
|
} \
|
||||||
} while (0)
|
} while (0)
|
||||||
@ -395,7 +408,7 @@ static inline _PyStackRef
|
|||||||
PyStackRef_DUP(_PyStackRef stackref)
|
PyStackRef_DUP(_PyStackRef stackref)
|
||||||
{
|
{
|
||||||
assert(!PyStackRef_IsNull(stackref));
|
assert(!PyStackRef_IsNull(stackref));
|
||||||
if (PyStackRef_IsDeferred(stackref)) {
|
if (PyStackRef_IsDeferredOrTaggedInt(stackref)) {
|
||||||
return stackref;
|
return stackref;
|
||||||
}
|
}
|
||||||
Py_INCREF(PyStackRef_AsPyObjectBorrow(stackref));
|
Py_INCREF(PyStackRef_AsPyObjectBorrow(stackref));
|
||||||
@ -442,7 +455,6 @@ PyStackRef_AsStrongReference(_PyStackRef stackref)
|
|||||||
/* References to immortal objects always have their tag bit set to Py_TAG_REFCNT
|
/* References to immortal objects always have their tag bit set to Py_TAG_REFCNT
|
||||||
* as they can (must) have their reclamation deferred */
|
* as they can (must) have their reclamation deferred */
|
||||||
|
|
||||||
#define Py_TAG_BITS 3
|
|
||||||
#if _Py_IMMORTAL_FLAGS != Py_TAG_REFCNT
|
#if _Py_IMMORTAL_FLAGS != Py_TAG_REFCNT
|
||||||
# error "_Py_IMMORTAL_FLAGS != Py_TAG_REFCNT"
|
# error "_Py_IMMORTAL_FLAGS != Py_TAG_REFCNT"
|
||||||
#endif
|
#endif
|
||||||
@ -678,7 +690,13 @@ PyStackRef_XCLOSE(_PyStackRef ref)
|
|||||||
|
|
||||||
#endif // !defined(Py_GIL_DISABLED) && defined(Py_STACKREF_DEBUG)
|
#endif // !defined(Py_GIL_DISABLED) && defined(Py_STACKREF_DEBUG)
|
||||||
|
|
||||||
#define PyStackRef_TYPE(stackref) Py_TYPE(PyStackRef_AsPyObjectBorrow(stackref))
|
static inline PyTypeObject *
|
||||||
|
PyStackRef_TYPE(_PyStackRef stackref) {
|
||||||
|
if (PyStackRef_IsTaggedInt(stackref)) {
|
||||||
|
return &PyLong_Type;
|
||||||
|
}
|
||||||
|
return Py_TYPE(PyStackRef_AsPyObjectBorrow(stackref));
|
||||||
|
}
|
||||||
|
|
||||||
// Converts a PyStackRef back to a PyObject *, converting the
|
// Converts a PyStackRef back to a PyObject *, converting the
|
||||||
// stackref to a new reference.
|
// stackref to a new reference.
|
||||||
@ -686,42 +704,30 @@ PyStackRef_XCLOSE(_PyStackRef ref)
|
|||||||
|
|
||||||
// StackRef type checks
|
// StackRef type checks
|
||||||
|
|
||||||
static inline bool
|
#define STACKREF_CHECK_FUNC(T) \
|
||||||
PyStackRef_GenCheck(_PyStackRef stackref)
|
static inline bool \
|
||||||
{
|
PyStackRef_ ## T ## Check(_PyStackRef stackref) { \
|
||||||
return PyGen_Check(PyStackRef_AsPyObjectBorrow(stackref));
|
if (PyStackRef_IsTaggedInt(stackref)) { \
|
||||||
}
|
return false; \
|
||||||
|
} \
|
||||||
|
return Py ## T ## _Check(PyStackRef_AsPyObjectBorrow(stackref)); \
|
||||||
|
}
|
||||||
|
|
||||||
static inline bool
|
STACKREF_CHECK_FUNC(Gen)
|
||||||
PyStackRef_BoolCheck(_PyStackRef stackref)
|
STACKREF_CHECK_FUNC(Bool)
|
||||||
{
|
STACKREF_CHECK_FUNC(ExceptionInstance)
|
||||||
return PyBool_Check(PyStackRef_AsPyObjectBorrow(stackref));
|
STACKREF_CHECK_FUNC(Code)
|
||||||
}
|
STACKREF_CHECK_FUNC(Function)
|
||||||
|
|
||||||
static inline bool
|
static inline bool
|
||||||
PyStackRef_LongCheck(_PyStackRef stackref)
|
PyStackRef_LongCheck(_PyStackRef stackref)
|
||||||
{
|
{
|
||||||
|
if (PyStackRef_IsTaggedInt(stackref)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
return PyLong_Check(PyStackRef_AsPyObjectBorrow(stackref));
|
return PyLong_Check(PyStackRef_AsPyObjectBorrow(stackref));
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline bool
|
|
||||||
PyStackRef_ExceptionInstanceCheck(_PyStackRef stackref)
|
|
||||||
{
|
|
||||||
return PyExceptionInstance_Check(PyStackRef_AsPyObjectBorrow(stackref));
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline bool
|
|
||||||
PyStackRef_CodeCheck(_PyStackRef stackref)
|
|
||||||
{
|
|
||||||
return PyCode_Check(PyStackRef_AsPyObjectBorrow(stackref));
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline bool
|
|
||||||
PyStackRef_FunctionCheck(_PyStackRef stackref)
|
|
||||||
{
|
|
||||||
return PyFunction_Check(PyStackRef_AsPyObjectBorrow(stackref));
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void
|
static inline void
|
||||||
_PyThreadState_PushCStackRef(PyThreadState *tstate, _PyCStackRef *ref)
|
_PyThreadState_PushCStackRef(PyThreadState *tstate, _PyCStackRef *ref)
|
||||||
{
|
{
|
||||||
|
1
Include/internal/pycore_uop_ids.h
generated
1
Include/internal/pycore_uop_ids.h
generated
@ -272,6 +272,7 @@ extern "C" {
|
|||||||
#define _POP_CALL_TWO 489
|
#define _POP_CALL_TWO 489
|
||||||
#define _POP_CALL_TWO_LOAD_CONST_INLINE_BORROW 490
|
#define _POP_CALL_TWO_LOAD_CONST_INLINE_BORROW 490
|
||||||
#define _POP_EXCEPT POP_EXCEPT
|
#define _POP_EXCEPT POP_EXCEPT
|
||||||
|
#define _POP_ITER POP_ITER
|
||||||
#define _POP_JUMP_IF_FALSE 491
|
#define _POP_JUMP_IF_FALSE 491
|
||||||
#define _POP_JUMP_IF_TRUE 492
|
#define _POP_JUMP_IF_TRUE 492
|
||||||
#define _POP_TOP POP_TOP
|
#define _POP_TOP POP_TOP
|
||||||
|
6
Include/internal/pycore_uop_metadata.h
generated
6
Include/internal/pycore_uop_metadata.h
generated
@ -66,6 +66,7 @@ const uint16_t _PyUop_Flags[MAX_UOP_ID+1] = {
|
|||||||
[_POP_TWO] = HAS_ESCAPES_FLAG,
|
[_POP_TWO] = HAS_ESCAPES_FLAG,
|
||||||
[_PUSH_NULL] = HAS_PURE_FLAG,
|
[_PUSH_NULL] = HAS_PURE_FLAG,
|
||||||
[_END_FOR] = HAS_ESCAPES_FLAG | HAS_NO_SAVE_IP_FLAG,
|
[_END_FOR] = HAS_ESCAPES_FLAG | HAS_NO_SAVE_IP_FLAG,
|
||||||
|
[_POP_ITER] = HAS_ESCAPES_FLAG,
|
||||||
[_END_SEND] = HAS_ESCAPES_FLAG | HAS_PURE_FLAG,
|
[_END_SEND] = HAS_ESCAPES_FLAG | HAS_PURE_FLAG,
|
||||||
[_UNARY_NEGATIVE] = HAS_ERROR_FLAG | HAS_ESCAPES_FLAG,
|
[_UNARY_NEGATIVE] = HAS_ERROR_FLAG | HAS_ESCAPES_FLAG,
|
||||||
[_UNARY_NOT] = HAS_PURE_FLAG,
|
[_UNARY_NOT] = HAS_PURE_FLAG,
|
||||||
@ -205,7 +206,7 @@ const uint16_t _PyUop_Flags[MAX_UOP_ID+1] = {
|
|||||||
[_FOR_ITER_TIER_TWO] = HAS_EXIT_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG,
|
[_FOR_ITER_TIER_TWO] = HAS_EXIT_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG,
|
||||||
[_ITER_CHECK_LIST] = HAS_EXIT_FLAG,
|
[_ITER_CHECK_LIST] = HAS_EXIT_FLAG,
|
||||||
[_GUARD_NOT_EXHAUSTED_LIST] = HAS_EXIT_FLAG,
|
[_GUARD_NOT_EXHAUSTED_LIST] = HAS_EXIT_FLAG,
|
||||||
[_ITER_NEXT_LIST_TIER_TWO] = HAS_EXIT_FLAG | HAS_ESCAPES_FLAG,
|
[_ITER_NEXT_LIST_TIER_TWO] = HAS_DEOPT_FLAG | HAS_ESCAPES_FLAG,
|
||||||
[_ITER_CHECK_TUPLE] = HAS_EXIT_FLAG,
|
[_ITER_CHECK_TUPLE] = HAS_EXIT_FLAG,
|
||||||
[_GUARD_NOT_EXHAUSTED_TUPLE] = HAS_EXIT_FLAG,
|
[_GUARD_NOT_EXHAUSTED_TUPLE] = HAS_EXIT_FLAG,
|
||||||
[_ITER_NEXT_TUPLE] = 0,
|
[_ITER_NEXT_TUPLE] = 0,
|
||||||
@ -569,6 +570,7 @@ const char *const _PyOpcode_uop_name[MAX_UOP_ID+1] = {
|
|||||||
[_POP_CALL_TWO] = "_POP_CALL_TWO",
|
[_POP_CALL_TWO] = "_POP_CALL_TWO",
|
||||||
[_POP_CALL_TWO_LOAD_CONST_INLINE_BORROW] = "_POP_CALL_TWO_LOAD_CONST_INLINE_BORROW",
|
[_POP_CALL_TWO_LOAD_CONST_INLINE_BORROW] = "_POP_CALL_TWO_LOAD_CONST_INLINE_BORROW",
|
||||||
[_POP_EXCEPT] = "_POP_EXCEPT",
|
[_POP_EXCEPT] = "_POP_EXCEPT",
|
||||||
|
[_POP_ITER] = "_POP_ITER",
|
||||||
[_POP_TOP] = "_POP_TOP",
|
[_POP_TOP] = "_POP_TOP",
|
||||||
[_POP_TOP_LOAD_CONST_INLINE] = "_POP_TOP_LOAD_CONST_INLINE",
|
[_POP_TOP_LOAD_CONST_INLINE] = "_POP_TOP_LOAD_CONST_INLINE",
|
||||||
[_POP_TOP_LOAD_CONST_INLINE_BORROW] = "_POP_TOP_LOAD_CONST_INLINE_BORROW",
|
[_POP_TOP_LOAD_CONST_INLINE_BORROW] = "_POP_TOP_LOAD_CONST_INLINE_BORROW",
|
||||||
@ -730,6 +732,8 @@ int _PyUop_num_popped(int opcode, int oparg)
|
|||||||
return 0;
|
return 0;
|
||||||
case _END_FOR:
|
case _END_FOR:
|
||||||
return 1;
|
return 1;
|
||||||
|
case _POP_ITER:
|
||||||
|
return 2;
|
||||||
case _END_SEND:
|
case _END_SEND:
|
||||||
return 2;
|
return 2;
|
||||||
case _UNARY_NEGATIVE:
|
case _UNARY_NEGATIVE:
|
||||||
|
@ -851,7 +851,7 @@ Disassembly of <code object <genexpr> at 0x..., file "%s", line %d>:
|
|||||||
%4d RETURN_GENERATOR
|
%4d RETURN_GENERATOR
|
||||||
POP_TOP
|
POP_TOP
|
||||||
L1: RESUME 0
|
L1: RESUME 0
|
||||||
LOAD_FAST_BORROW 0 (.0)
|
LOAD_FAST 0 (.0)
|
||||||
GET_ITER
|
GET_ITER
|
||||||
L2: FOR_ITER 14 (to L3)
|
L2: FOR_ITER 14 (to L3)
|
||||||
STORE_FAST 1 (z)
|
STORE_FAST 1 (z)
|
||||||
@ -1821,7 +1821,7 @@ expected_opinfo_jumpy = [
|
|||||||
make_inst(opname='LOAD_SMALL_INT', arg=10, argval=10, argrepr='', offset=12, start_offset=12, starts_line=False, line_number=3),
|
make_inst(opname='LOAD_SMALL_INT', arg=10, argval=10, argrepr='', offset=12, start_offset=12, starts_line=False, line_number=3),
|
||||||
make_inst(opname='CALL', arg=1, argval=1, argrepr='', offset=14, start_offset=14, starts_line=False, line_number=3, cache_info=[('counter', 1, b'\x00\x00'), ('func_version', 2, b'\x00\x00\x00\x00')]),
|
make_inst(opname='CALL', arg=1, argval=1, argrepr='', offset=14, start_offset=14, starts_line=False, line_number=3, cache_info=[('counter', 1, b'\x00\x00'), ('func_version', 2, b'\x00\x00\x00\x00')]),
|
||||||
make_inst(opname='GET_ITER', arg=None, argval=None, argrepr='', offset=22, start_offset=22, starts_line=False, line_number=3),
|
make_inst(opname='GET_ITER', arg=None, argval=None, argrepr='', offset=22, start_offset=22, starts_line=False, line_number=3),
|
||||||
make_inst(opname='FOR_ITER', arg=32, argval=92, argrepr='to L4', offset=24, start_offset=24, starts_line=False, line_number=3, label=1, cache_info=[('counter', 1, b'\x00\x00')]),
|
make_inst(opname='FOR_ITER', arg=33, argval=94, argrepr='to L4', offset=24, start_offset=24, starts_line=False, line_number=3, label=1, cache_info=[('counter', 1, b'\x00\x00')]),
|
||||||
make_inst(opname='STORE_FAST', arg=0, argval='i', argrepr='i', offset=28, start_offset=28, starts_line=False, line_number=3),
|
make_inst(opname='STORE_FAST', arg=0, argval='i', argrepr='i', offset=28, start_offset=28, starts_line=False, line_number=3),
|
||||||
make_inst(opname='LOAD_GLOBAL', arg=3, argval='print', argrepr='print + NULL', offset=30, start_offset=30, starts_line=True, line_number=4, cache_info=[('counter', 1, b'\x00\x00'), ('index', 1, b'\x00\x00'), ('module_keys_version', 1, b'\x00\x00'), ('builtin_keys_version', 1, b'\x00\x00')]),
|
make_inst(opname='LOAD_GLOBAL', arg=3, argval='print', argrepr='print + NULL', offset=30, start_offset=30, starts_line=True, line_number=4, cache_info=[('counter', 1, b'\x00\x00'), ('index', 1, b'\x00\x00'), ('module_keys_version', 1, b'\x00\x00'), ('builtin_keys_version', 1, b'\x00\x00')]),
|
||||||
make_inst(opname='LOAD_FAST_BORROW', arg=0, argval='i', argrepr='i', offset=40, start_offset=40, starts_line=False, line_number=4),
|
make_inst(opname='LOAD_FAST_BORROW', arg=0, argval='i', argrepr='i', offset=40, start_offset=40, starts_line=False, line_number=4),
|
||||||
@ -1840,110 +1840,111 @@ expected_opinfo_jumpy = [
|
|||||||
make_inst(opname='NOT_TAKEN', arg=None, argval=None, argrepr='', offset=82, start_offset=82, starts_line=False, line_number=7),
|
make_inst(opname='NOT_TAKEN', arg=None, argval=None, argrepr='', offset=82, start_offset=82, starts_line=False, line_number=7),
|
||||||
make_inst(opname='JUMP_BACKWARD', arg=32, argval=24, argrepr='to L1', offset=84, start_offset=84, starts_line=False, line_number=7, cache_info=[('counter', 1, b'\x00\x00')]),
|
make_inst(opname='JUMP_BACKWARD', arg=32, argval=24, argrepr='to L1', offset=84, start_offset=84, starts_line=False, line_number=7, cache_info=[('counter', 1, b'\x00\x00')]),
|
||||||
make_inst(opname='POP_TOP', arg=None, argval=None, argrepr='', offset=88, start_offset=88, starts_line=True, line_number=8, label=3),
|
make_inst(opname='POP_TOP', arg=None, argval=None, argrepr='', offset=88, start_offset=88, starts_line=True, line_number=8, label=3),
|
||||||
make_inst(opname='JUMP_FORWARD', arg=13, argval=118, argrepr='to L5', offset=90, start_offset=90, starts_line=False, line_number=8),
|
make_inst(opname='POP_TOP', arg=None, argval=None, argrepr='', offset=90, start_offset=90, starts_line=False, line_number=8),
|
||||||
make_inst(opname='END_FOR', arg=None, argval=None, argrepr='', offset=92, start_offset=92, starts_line=True, line_number=3, label=4),
|
make_inst(opname='JUMP_FORWARD', arg=13, argval=120, argrepr='to L5', offset=92, start_offset=92, starts_line=False, line_number=8),
|
||||||
make_inst(opname='POP_ITER', arg=None, argval=None, argrepr='', offset=94, start_offset=94, starts_line=False, line_number=3),
|
make_inst(opname='END_FOR', arg=None, argval=None, argrepr='', offset=94, start_offset=94, starts_line=True, line_number=3, label=4),
|
||||||
make_inst(opname='LOAD_GLOBAL', arg=3, argval='print', argrepr='print + NULL', offset=96, start_offset=96, starts_line=True, line_number=10, cache_info=[('counter', 1, b'\x00\x00'), ('index', 1, b'\x00\x00'), ('module_keys_version', 1, b'\x00\x00'), ('builtin_keys_version', 1, b'\x00\x00')]),
|
make_inst(opname='POP_ITER', arg=None, argval=None, argrepr='', offset=96, start_offset=96, starts_line=False, line_number=3),
|
||||||
make_inst(opname='LOAD_CONST', arg=1, argval='I can haz else clause?', argrepr="'I can haz else clause?'", offset=106, start_offset=106, starts_line=False, line_number=10),
|
make_inst(opname='LOAD_GLOBAL', arg=3, argval='print', argrepr='print + NULL', offset=98, start_offset=98, starts_line=True, line_number=10, cache_info=[('counter', 1, b'\x00\x00'), ('index', 1, b'\x00\x00'), ('module_keys_version', 1, b'\x00\x00'), ('builtin_keys_version', 1, b'\x00\x00')]),
|
||||||
make_inst(opname='CALL', arg=1, argval=1, argrepr='', offset=108, start_offset=108, starts_line=False, line_number=10, cache_info=[('counter', 1, b'\x00\x00'), ('func_version', 2, b'\x00\x00\x00\x00')]),
|
make_inst(opname='LOAD_CONST', arg=1, argval='I can haz else clause?', argrepr="'I can haz else clause?'", offset=108, start_offset=108, starts_line=False, line_number=10),
|
||||||
make_inst(opname='POP_TOP', arg=None, argval=None, argrepr='', offset=116, start_offset=116, starts_line=False, line_number=10),
|
make_inst(opname='CALL', arg=1, argval=1, argrepr='', offset=110, start_offset=110, starts_line=False, line_number=10, cache_info=[('counter', 1, b'\x00\x00'), ('func_version', 2, b'\x00\x00\x00\x00')]),
|
||||||
make_inst(opname='LOAD_FAST_CHECK', arg=0, argval='i', argrepr='i', offset=118, start_offset=118, starts_line=True, line_number=11, label=5),
|
make_inst(opname='POP_TOP', arg=None, argval=None, argrepr='', offset=118, start_offset=118, starts_line=False, line_number=10),
|
||||||
make_inst(opname='TO_BOOL', arg=None, argval=None, argrepr='', offset=120, start_offset=120, starts_line=False, line_number=11, cache_info=[('counter', 1, b'\x00\x00'), ('version', 2, b'\x00\x00\x00\x00')]),
|
make_inst(opname='LOAD_FAST_CHECK', arg=0, argval='i', argrepr='i', offset=120, start_offset=120, starts_line=True, line_number=11, label=5),
|
||||||
make_inst(opname='POP_JUMP_IF_FALSE', arg=40, argval=212, argrepr='to L8', offset=128, start_offset=128, starts_line=False, line_number=11, cache_info=[('counter', 1, b'\x00\x00')]),
|
make_inst(opname='TO_BOOL', arg=None, argval=None, argrepr='', offset=122, start_offset=122, starts_line=False, line_number=11, cache_info=[('counter', 1, b'\x00\x00'), ('version', 2, b'\x00\x00\x00\x00')]),
|
||||||
make_inst(opname='NOT_TAKEN', arg=None, argval=None, argrepr='', offset=132, start_offset=132, starts_line=False, line_number=11),
|
make_inst(opname='POP_JUMP_IF_FALSE', arg=40, argval=214, argrepr='to L8', offset=130, start_offset=130, starts_line=False, line_number=11, cache_info=[('counter', 1, b'\x00\x00')]),
|
||||||
make_inst(opname='LOAD_GLOBAL', arg=3, argval='print', argrepr='print + NULL', offset=134, start_offset=134, starts_line=True, line_number=12, cache_info=[('counter', 1, b'\x00\x00'), ('index', 1, b'\x00\x00'), ('module_keys_version', 1, b'\x00\x00'), ('builtin_keys_version', 1, b'\x00\x00')]),
|
make_inst(opname='NOT_TAKEN', arg=None, argval=None, argrepr='', offset=134, start_offset=134, starts_line=False, line_number=11),
|
||||||
make_inst(opname='LOAD_FAST_BORROW', arg=0, argval='i', argrepr='i', offset=144, start_offset=144, starts_line=False, line_number=12),
|
make_inst(opname='LOAD_GLOBAL', arg=3, argval='print', argrepr='print + NULL', offset=136, start_offset=136, starts_line=True, line_number=12, cache_info=[('counter', 1, b'\x00\x00'), ('index', 1, b'\x00\x00'), ('module_keys_version', 1, b'\x00\x00'), ('builtin_keys_version', 1, b'\x00\x00')]),
|
||||||
make_inst(opname='CALL', arg=1, argval=1, argrepr='', offset=146, start_offset=146, starts_line=False, line_number=12, cache_info=[('counter', 1, b'\x00\x00'), ('func_version', 2, b'\x00\x00\x00\x00')]),
|
make_inst(opname='LOAD_FAST_BORROW', arg=0, argval='i', argrepr='i', offset=146, start_offset=146, starts_line=False, line_number=12),
|
||||||
make_inst(opname='POP_TOP', arg=None, argval=None, argrepr='', offset=154, start_offset=154, starts_line=False, line_number=12),
|
make_inst(opname='CALL', arg=1, argval=1, argrepr='', offset=148, start_offset=148, starts_line=False, line_number=12, cache_info=[('counter', 1, b'\x00\x00'), ('func_version', 2, b'\x00\x00\x00\x00')]),
|
||||||
make_inst(opname='LOAD_FAST_BORROW', arg=0, argval='i', argrepr='i', offset=156, start_offset=156, starts_line=True, line_number=13),
|
make_inst(opname='POP_TOP', arg=None, argval=None, argrepr='', offset=156, start_offset=156, starts_line=False, line_number=12),
|
||||||
make_inst(opname='LOAD_SMALL_INT', arg=1, argval=1, argrepr='', offset=158, start_offset=158, starts_line=False, line_number=13),
|
make_inst(opname='LOAD_FAST_BORROW', arg=0, argval='i', argrepr='i', offset=158, start_offset=158, starts_line=True, line_number=13),
|
||||||
make_inst(opname='BINARY_OP', arg=23, argval=23, argrepr='-=', offset=160, start_offset=160, starts_line=False, line_number=13, cache_info=[('counter', 1, b'\x00\x00'), ('descr', 4, b'\x00\x00\x00\x00\x00\x00\x00\x00')]),
|
make_inst(opname='LOAD_SMALL_INT', arg=1, argval=1, argrepr='', offset=160, start_offset=160, starts_line=False, line_number=13),
|
||||||
make_inst(opname='STORE_FAST', arg=0, argval='i', argrepr='i', offset=172, start_offset=172, starts_line=False, line_number=13),
|
make_inst(opname='BINARY_OP', arg=23, argval=23, argrepr='-=', offset=162, start_offset=162, starts_line=False, line_number=13, cache_info=[('counter', 1, b'\x00\x00'), ('descr', 4, b'\x00\x00\x00\x00\x00\x00\x00\x00')]),
|
||||||
make_inst(opname='LOAD_FAST_BORROW', arg=0, argval='i', argrepr='i', offset=174, start_offset=174, starts_line=True, line_number=14),
|
make_inst(opname='STORE_FAST', arg=0, argval='i', argrepr='i', offset=174, start_offset=174, starts_line=False, line_number=13),
|
||||||
make_inst(opname='LOAD_SMALL_INT', arg=6, argval=6, argrepr='', offset=176, start_offset=176, starts_line=False, line_number=14),
|
make_inst(opname='LOAD_FAST_BORROW', arg=0, argval='i', argrepr='i', offset=176, start_offset=176, starts_line=True, line_number=14),
|
||||||
make_inst(opname='COMPARE_OP', arg=148, argval='>', argrepr='bool(>)', offset=178, start_offset=178, starts_line=False, line_number=14, cache_info=[('counter', 1, b'\x00\x00')]),
|
make_inst(opname='LOAD_SMALL_INT', arg=6, argval=6, argrepr='', offset=178, start_offset=178, starts_line=False, line_number=14),
|
||||||
make_inst(opname='POP_JUMP_IF_FALSE', arg=3, argval=192, argrepr='to L6', offset=182, start_offset=182, starts_line=False, line_number=14, cache_info=[('counter', 1, b'\x00\x00')]),
|
make_inst(opname='COMPARE_OP', arg=148, argval='>', argrepr='bool(>)', offset=180, start_offset=180, starts_line=False, line_number=14, cache_info=[('counter', 1, b'\x00\x00')]),
|
||||||
make_inst(opname='NOT_TAKEN', arg=None, argval=None, argrepr='', offset=186, start_offset=186, starts_line=False, line_number=14),
|
make_inst(opname='POP_JUMP_IF_FALSE', arg=3, argval=194, argrepr='to L6', offset=184, start_offset=184, starts_line=False, line_number=14, cache_info=[('counter', 1, b'\x00\x00')]),
|
||||||
make_inst(opname='JUMP_BACKWARD', arg=37, argval=118, argrepr='to L5', offset=188, start_offset=188, starts_line=True, line_number=15, cache_info=[('counter', 1, b'\x00\x00')]),
|
make_inst(opname='NOT_TAKEN', arg=None, argval=None, argrepr='', offset=188, start_offset=188, starts_line=False, line_number=14),
|
||||||
make_inst(opname='LOAD_FAST_BORROW', arg=0, argval='i', argrepr='i', offset=192, start_offset=192, starts_line=True, line_number=16, label=6),
|
make_inst(opname='JUMP_BACKWARD', arg=37, argval=120, argrepr='to L5', offset=190, start_offset=190, starts_line=True, line_number=15, cache_info=[('counter', 1, b'\x00\x00')]),
|
||||||
make_inst(opname='LOAD_SMALL_INT', arg=4, argval=4, argrepr='', offset=194, start_offset=194, starts_line=False, line_number=16),
|
make_inst(opname='LOAD_FAST_BORROW', arg=0, argval='i', argrepr='i', offset=194, start_offset=194, starts_line=True, line_number=16, label=6),
|
||||||
make_inst(opname='COMPARE_OP', arg=18, argval='<', argrepr='bool(<)', offset=196, start_offset=196, starts_line=False, line_number=16, cache_info=[('counter', 1, b'\x00\x00')]),
|
make_inst(opname='LOAD_SMALL_INT', arg=4, argval=4, argrepr='', offset=196, start_offset=196, starts_line=False, line_number=16),
|
||||||
make_inst(opname='POP_JUMP_IF_TRUE', arg=3, argval=210, argrepr='to L7', offset=200, start_offset=200, starts_line=False, line_number=16, cache_info=[('counter', 1, b'\x00\x00')]),
|
make_inst(opname='COMPARE_OP', arg=18, argval='<', argrepr='bool(<)', offset=198, start_offset=198, starts_line=False, line_number=16, cache_info=[('counter', 1, b'\x00\x00')]),
|
||||||
make_inst(opname='NOT_TAKEN', arg=None, argval=None, argrepr='', offset=204, start_offset=204, starts_line=False, line_number=16),
|
make_inst(opname='POP_JUMP_IF_TRUE', arg=3, argval=212, argrepr='to L7', offset=202, start_offset=202, starts_line=False, line_number=16, cache_info=[('counter', 1, b'\x00\x00')]),
|
||||||
make_inst(opname='JUMP_BACKWARD', arg=46, argval=118, argrepr='to L5', offset=206, start_offset=206, starts_line=False, line_number=16, cache_info=[('counter', 1, b'\x00\x00')]),
|
make_inst(opname='NOT_TAKEN', arg=None, argval=None, argrepr='', offset=206, start_offset=206, starts_line=False, line_number=16),
|
||||||
make_inst(opname='JUMP_FORWARD', arg=11, argval=234, argrepr='to L9', offset=210, start_offset=210, starts_line=True, line_number=17, label=7),
|
make_inst(opname='JUMP_BACKWARD', arg=46, argval=120, argrepr='to L5', offset=208, start_offset=208, starts_line=False, line_number=16, cache_info=[('counter', 1, b'\x00\x00')]),
|
||||||
make_inst(opname='LOAD_GLOBAL', arg=3, argval='print', argrepr='print + NULL', offset=212, start_offset=212, starts_line=True, line_number=19, label=8, cache_info=[('counter', 1, b'\x00\x00'), ('index', 1, b'\x00\x00'), ('module_keys_version', 1, b'\x00\x00'), ('builtin_keys_version', 1, b'\x00\x00')]),
|
make_inst(opname='JUMP_FORWARD', arg=11, argval=236, argrepr='to L9', offset=212, start_offset=212, starts_line=True, line_number=17, label=7),
|
||||||
make_inst(opname='LOAD_CONST', arg=2, argval='Who let lolcatz into this test suite?', argrepr="'Who let lolcatz into this test suite?'", offset=222, start_offset=222, starts_line=False, line_number=19),
|
make_inst(opname='LOAD_GLOBAL', arg=3, argval='print', argrepr='print + NULL', offset=214, start_offset=214, starts_line=True, line_number=19, label=8, cache_info=[('counter', 1, b'\x00\x00'), ('index', 1, b'\x00\x00'), ('module_keys_version', 1, b'\x00\x00'), ('builtin_keys_version', 1, b'\x00\x00')]),
|
||||||
make_inst(opname='CALL', arg=1, argval=1, argrepr='', offset=224, start_offset=224, starts_line=False, line_number=19, cache_info=[('counter', 1, b'\x00\x00'), ('func_version', 2, b'\x00\x00\x00\x00')]),
|
make_inst(opname='LOAD_CONST', arg=2, argval='Who let lolcatz into this test suite?', argrepr="'Who let lolcatz into this test suite?'", offset=224, start_offset=224, starts_line=False, line_number=19),
|
||||||
make_inst(opname='POP_TOP', arg=None, argval=None, argrepr='', offset=232, start_offset=232, starts_line=False, line_number=19),
|
make_inst(opname='CALL', arg=1, argval=1, argrepr='', offset=226, start_offset=226, starts_line=False, line_number=19, cache_info=[('counter', 1, b'\x00\x00'), ('func_version', 2, b'\x00\x00\x00\x00')]),
|
||||||
make_inst(opname='NOP', arg=None, argval=None, argrepr='', offset=234, start_offset=234, starts_line=True, line_number=20, label=9),
|
make_inst(opname='POP_TOP', arg=None, argval=None, argrepr='', offset=234, start_offset=234, starts_line=False, line_number=19),
|
||||||
make_inst(opname='LOAD_SMALL_INT', arg=1, argval=1, argrepr='', offset=236, start_offset=236, starts_line=True, line_number=21),
|
make_inst(opname='NOP', arg=None, argval=None, argrepr='', offset=236, start_offset=236, starts_line=True, line_number=20, label=9),
|
||||||
make_inst(opname='LOAD_SMALL_INT', arg=0, argval=0, argrepr='', offset=238, start_offset=238, starts_line=False, line_number=21),
|
make_inst(opname='LOAD_SMALL_INT', arg=1, argval=1, argrepr='', offset=238, start_offset=238, starts_line=True, line_number=21),
|
||||||
make_inst(opname='BINARY_OP', arg=11, argval=11, argrepr='/', offset=240, start_offset=240, starts_line=False, line_number=21, cache_info=[('counter', 1, b'\x00\x00'), ('descr', 4, b'\x00\x00\x00\x00\x00\x00\x00\x00')]),
|
make_inst(opname='LOAD_SMALL_INT', arg=0, argval=0, argrepr='', offset=240, start_offset=240, starts_line=False, line_number=21),
|
||||||
make_inst(opname='POP_TOP', arg=None, argval=None, argrepr='', offset=252, start_offset=252, starts_line=False, line_number=21),
|
make_inst(opname='BINARY_OP', arg=11, argval=11, argrepr='/', offset=242, start_offset=242, starts_line=False, line_number=21, cache_info=[('counter', 1, b'\x00\x00'), ('descr', 4, b'\x00\x00\x00\x00\x00\x00\x00\x00')]),
|
||||||
make_inst(opname='LOAD_FAST_BORROW', arg=0, argval='i', argrepr='i', offset=254, start_offset=254, starts_line=True, line_number=25),
|
make_inst(opname='POP_TOP', arg=None, argval=None, argrepr='', offset=254, start_offset=254, starts_line=False, line_number=21),
|
||||||
make_inst(opname='COPY', arg=1, argval=1, argrepr='', offset=256, start_offset=256, starts_line=False, line_number=25),
|
make_inst(opname='LOAD_FAST_BORROW', arg=0, argval='i', argrepr='i', offset=256, start_offset=256, starts_line=True, line_number=25),
|
||||||
make_inst(opname='LOAD_SPECIAL', arg=1, argval=1, argrepr='__exit__', offset=258, start_offset=258, starts_line=False, line_number=25),
|
make_inst(opname='COPY', arg=1, argval=1, argrepr='', offset=258, start_offset=258, starts_line=False, line_number=25),
|
||||||
make_inst(opname='SWAP', arg=2, argval=2, argrepr='', offset=260, start_offset=260, starts_line=False, line_number=25),
|
make_inst(opname='LOAD_SPECIAL', arg=1, argval=1, argrepr='__exit__', offset=260, start_offset=260, starts_line=False, line_number=25),
|
||||||
make_inst(opname='SWAP', arg=3, argval=3, argrepr='', offset=262, start_offset=262, starts_line=False, line_number=25),
|
make_inst(opname='SWAP', arg=2, argval=2, argrepr='', offset=262, start_offset=262, starts_line=False, line_number=25),
|
||||||
make_inst(opname='LOAD_SPECIAL', arg=0, argval=0, argrepr='__enter__', offset=264, start_offset=264, starts_line=False, line_number=25),
|
make_inst(opname='SWAP', arg=3, argval=3, argrepr='', offset=264, start_offset=264, starts_line=False, line_number=25),
|
||||||
make_inst(opname='CALL', arg=0, argval=0, argrepr='', offset=266, start_offset=266, starts_line=False, line_number=25, cache_info=[('counter', 1, b'\x00\x00'), ('func_version', 2, b'\x00\x00\x00\x00')]),
|
make_inst(opname='LOAD_SPECIAL', arg=0, argval=0, argrepr='__enter__', offset=266, start_offset=266, starts_line=False, line_number=25),
|
||||||
make_inst(opname='STORE_FAST', arg=1, argval='dodgy', argrepr='dodgy', offset=274, start_offset=274, starts_line=False, line_number=25),
|
make_inst(opname='CALL', arg=0, argval=0, argrepr='', offset=268, start_offset=268, starts_line=False, line_number=25, cache_info=[('counter', 1, b'\x00\x00'), ('func_version', 2, b'\x00\x00\x00\x00')]),
|
||||||
make_inst(opname='LOAD_GLOBAL', arg=3, argval='print', argrepr='print + NULL', offset=276, start_offset=276, starts_line=True, line_number=26, cache_info=[('counter', 1, b'\x00\x00'), ('index', 1, b'\x00\x00'), ('module_keys_version', 1, b'\x00\x00'), ('builtin_keys_version', 1, b'\x00\x00')]),
|
make_inst(opname='STORE_FAST', arg=1, argval='dodgy', argrepr='dodgy', offset=276, start_offset=276, starts_line=False, line_number=25),
|
||||||
make_inst(opname='LOAD_CONST', arg=3, argval='Never reach this', argrepr="'Never reach this'", offset=286, start_offset=286, starts_line=False, line_number=26),
|
make_inst(opname='LOAD_GLOBAL', arg=3, argval='print', argrepr='print + NULL', offset=278, start_offset=278, starts_line=True, line_number=26, cache_info=[('counter', 1, b'\x00\x00'), ('index', 1, b'\x00\x00'), ('module_keys_version', 1, b'\x00\x00'), ('builtin_keys_version', 1, b'\x00\x00')]),
|
||||||
make_inst(opname='CALL', arg=1, argval=1, argrepr='', offset=288, start_offset=288, starts_line=False, line_number=26, cache_info=[('counter', 1, b'\x00\x00'), ('func_version', 2, b'\x00\x00\x00\x00')]),
|
make_inst(opname='LOAD_CONST', arg=3, argval='Never reach this', argrepr="'Never reach this'", offset=288, start_offset=288, starts_line=False, line_number=26),
|
||||||
make_inst(opname='POP_TOP', arg=None, argval=None, argrepr='', offset=296, start_offset=296, starts_line=False, line_number=26),
|
make_inst(opname='CALL', arg=1, argval=1, argrepr='', offset=290, start_offset=290, starts_line=False, line_number=26, cache_info=[('counter', 1, b'\x00\x00'), ('func_version', 2, b'\x00\x00\x00\x00')]),
|
||||||
make_inst(opname='LOAD_CONST', arg=4, argval=None, argrepr='None', offset=298, start_offset=298, starts_line=True, line_number=25),
|
make_inst(opname='POP_TOP', arg=None, argval=None, argrepr='', offset=298, start_offset=298, starts_line=False, line_number=26),
|
||||||
make_inst(opname='LOAD_CONST', arg=4, argval=None, argrepr='None', offset=300, start_offset=300, starts_line=False, line_number=25),
|
make_inst(opname='LOAD_CONST', arg=4, argval=None, argrepr='None', offset=300, start_offset=300, starts_line=True, line_number=25),
|
||||||
make_inst(opname='LOAD_CONST', arg=4, argval=None, argrepr='None', offset=302, start_offset=302, starts_line=False, line_number=25),
|
make_inst(opname='LOAD_CONST', arg=4, argval=None, argrepr='None', offset=302, start_offset=302, starts_line=False, line_number=25),
|
||||||
make_inst(opname='CALL', arg=3, argval=3, argrepr='', offset=304, start_offset=304, starts_line=False, line_number=25, cache_info=[('counter', 1, b'\x00\x00'), ('func_version', 2, b'\x00\x00\x00\x00')]),
|
make_inst(opname='LOAD_CONST', arg=4, argval=None, argrepr='None', offset=304, start_offset=304, starts_line=False, line_number=25),
|
||||||
make_inst(opname='POP_TOP', arg=None, argval=None, argrepr='', offset=312, start_offset=312, starts_line=False, line_number=25),
|
make_inst(opname='CALL', arg=3, argval=3, argrepr='', offset=306, start_offset=306, starts_line=False, line_number=25, cache_info=[('counter', 1, b'\x00\x00'), ('func_version', 2, b'\x00\x00\x00\x00')]),
|
||||||
make_inst(opname='LOAD_GLOBAL', arg=3, argval='print', argrepr='print + NULL', offset=314, start_offset=314, starts_line=True, line_number=28, label=10, cache_info=[('counter', 1, b'\x00\x00'), ('index', 1, b'\x00\x00'), ('module_keys_version', 1, b'\x00\x00'), ('builtin_keys_version', 1, b'\x00\x00')]),
|
make_inst(opname='POP_TOP', arg=None, argval=None, argrepr='', offset=314, start_offset=314, starts_line=False, line_number=25),
|
||||||
make_inst(opname='LOAD_CONST', arg=6, argval="OK, now we're done", argrepr='"OK, now we\'re done"', offset=324, start_offset=324, starts_line=False, line_number=28),
|
make_inst(opname='LOAD_GLOBAL', arg=3, argval='print', argrepr='print + NULL', offset=316, start_offset=316, starts_line=True, line_number=28, label=10, cache_info=[('counter', 1, b'\x00\x00'), ('index', 1, b'\x00\x00'), ('module_keys_version', 1, b'\x00\x00'), ('builtin_keys_version', 1, b'\x00\x00')]),
|
||||||
make_inst(opname='CALL', arg=1, argval=1, argrepr='', offset=326, start_offset=326, starts_line=False, line_number=28, cache_info=[('counter', 1, b'\x00\x00'), ('func_version', 2, b'\x00\x00\x00\x00')]),
|
make_inst(opname='LOAD_CONST', arg=6, argval="OK, now we're done", argrepr='"OK, now we\'re done"', offset=326, start_offset=326, starts_line=False, line_number=28),
|
||||||
make_inst(opname='POP_TOP', arg=None, argval=None, argrepr='', offset=334, start_offset=334, starts_line=False, line_number=28),
|
make_inst(opname='CALL', arg=1, argval=1, argrepr='', offset=328, start_offset=328, starts_line=False, line_number=28, cache_info=[('counter', 1, b'\x00\x00'), ('func_version', 2, b'\x00\x00\x00\x00')]),
|
||||||
make_inst(opname='LOAD_CONST', arg=4, argval=None, argrepr='None', offset=336, start_offset=336, starts_line=False, line_number=28),
|
make_inst(opname='POP_TOP', arg=None, argval=None, argrepr='', offset=336, start_offset=336, starts_line=False, line_number=28),
|
||||||
make_inst(opname='RETURN_VALUE', arg=None, argval=None, argrepr='', offset=338, start_offset=338, starts_line=False, line_number=28),
|
make_inst(opname='LOAD_CONST', arg=4, argval=None, argrepr='None', offset=338, start_offset=338, starts_line=False, line_number=28),
|
||||||
make_inst(opname='PUSH_EXC_INFO', arg=None, argval=None, argrepr='', offset=340, start_offset=340, starts_line=True, line_number=25),
|
make_inst(opname='RETURN_VALUE', arg=None, argval=None, argrepr='', offset=340, start_offset=340, starts_line=False, line_number=28),
|
||||||
make_inst(opname='WITH_EXCEPT_START', arg=None, argval=None, argrepr='', offset=342, start_offset=342, starts_line=False, line_number=25),
|
make_inst(opname='PUSH_EXC_INFO', arg=None, argval=None, argrepr='', offset=342, start_offset=342, starts_line=True, line_number=25),
|
||||||
make_inst(opname='TO_BOOL', arg=None, argval=None, argrepr='', offset=344, start_offset=344, starts_line=False, line_number=25, cache_info=[('counter', 1, b'\x00\x00'), ('version', 2, b'\x00\x00\x00\x00')]),
|
make_inst(opname='WITH_EXCEPT_START', arg=None, argval=None, argrepr='', offset=344, start_offset=344, starts_line=False, line_number=25),
|
||||||
make_inst(opname='POP_JUMP_IF_TRUE', arg=2, argval=360, argrepr='to L11', offset=352, start_offset=352, starts_line=False, line_number=25, cache_info=[('counter', 1, b'\x00\x00')]),
|
make_inst(opname='TO_BOOL', arg=None, argval=None, argrepr='', offset=346, start_offset=346, starts_line=False, line_number=25, cache_info=[('counter', 1, b'\x00\x00'), ('version', 2, b'\x00\x00\x00\x00')]),
|
||||||
make_inst(opname='NOT_TAKEN', arg=None, argval=None, argrepr='', offset=356, start_offset=356, starts_line=False, line_number=25),
|
make_inst(opname='POP_JUMP_IF_TRUE', arg=2, argval=362, argrepr='to L11', offset=354, start_offset=354, starts_line=False, line_number=25, cache_info=[('counter', 1, b'\x00\x00')]),
|
||||||
make_inst(opname='RERAISE', arg=2, argval=2, argrepr='', offset=358, start_offset=358, starts_line=False, line_number=25),
|
make_inst(opname='NOT_TAKEN', arg=None, argval=None, argrepr='', offset=358, start_offset=358, starts_line=False, line_number=25),
|
||||||
make_inst(opname='POP_TOP', arg=None, argval=None, argrepr='', offset=360, start_offset=360, starts_line=False, line_number=25, label=11),
|
make_inst(opname='RERAISE', arg=2, argval=2, argrepr='', offset=360, start_offset=360, starts_line=False, line_number=25),
|
||||||
make_inst(opname='POP_EXCEPT', arg=None, argval=None, argrepr='', offset=362, start_offset=362, starts_line=False, line_number=25),
|
make_inst(opname='POP_TOP', arg=None, argval=None, argrepr='', offset=362, start_offset=362, starts_line=False, line_number=25, label=11),
|
||||||
make_inst(opname='POP_TOP', arg=None, argval=None, argrepr='', offset=364, start_offset=364, starts_line=False, line_number=25),
|
make_inst(opname='POP_EXCEPT', arg=None, argval=None, argrepr='', offset=364, start_offset=364, starts_line=False, line_number=25),
|
||||||
make_inst(opname='POP_TOP', arg=None, argval=None, argrepr='', offset=366, start_offset=366, starts_line=False, line_number=25),
|
make_inst(opname='POP_TOP', arg=None, argval=None, argrepr='', offset=366, start_offset=366, starts_line=False, line_number=25),
|
||||||
make_inst(opname='POP_TOP', arg=None, argval=None, argrepr='', offset=368, start_offset=368, starts_line=False, line_number=25),
|
make_inst(opname='POP_TOP', arg=None, argval=None, argrepr='', offset=368, start_offset=368, starts_line=False, line_number=25),
|
||||||
make_inst(opname='JUMP_BACKWARD_NO_INTERRUPT', arg=29, argval=314, argrepr='to L10', offset=370, start_offset=370, starts_line=False, line_number=25),
|
make_inst(opname='POP_TOP', arg=None, argval=None, argrepr='', offset=370, start_offset=370, starts_line=False, line_number=25),
|
||||||
make_inst(opname='COPY', arg=3, argval=3, argrepr='', offset=372, start_offset=372, starts_line=True, line_number=None),
|
make_inst(opname='JUMP_BACKWARD_NO_INTERRUPT', arg=29, argval=316, argrepr='to L10', offset=372, start_offset=372, starts_line=False, line_number=25),
|
||||||
make_inst(opname='POP_EXCEPT', arg=None, argval=None, argrepr='', offset=374, start_offset=374, starts_line=False, line_number=None),
|
make_inst(opname='COPY', arg=3, argval=3, argrepr='', offset=374, start_offset=374, starts_line=True, line_number=None),
|
||||||
make_inst(opname='RERAISE', arg=1, argval=1, argrepr='', offset=376, start_offset=376, starts_line=False, line_number=None),
|
make_inst(opname='POP_EXCEPT', arg=None, argval=None, argrepr='', offset=376, start_offset=376, starts_line=False, line_number=None),
|
||||||
make_inst(opname='PUSH_EXC_INFO', arg=None, argval=None, argrepr='', offset=378, start_offset=378, starts_line=False, line_number=None),
|
make_inst(opname='RERAISE', arg=1, argval=1, argrepr='', offset=378, start_offset=378, starts_line=False, line_number=None),
|
||||||
make_inst(opname='LOAD_GLOBAL', arg=4, argval='ZeroDivisionError', argrepr='ZeroDivisionError', offset=380, start_offset=380, starts_line=True, line_number=22, cache_info=[('counter', 1, b'\x00\x00'), ('index', 1, b'\x00\x00'), ('module_keys_version', 1, b'\x00\x00'), ('builtin_keys_version', 1, b'\x00\x00')]),
|
make_inst(opname='PUSH_EXC_INFO', arg=None, argval=None, argrepr='', offset=380, start_offset=380, starts_line=False, line_number=None),
|
||||||
make_inst(opname='CHECK_EXC_MATCH', arg=None, argval=None, argrepr='', offset=390, start_offset=390, starts_line=False, line_number=22),
|
make_inst(opname='LOAD_GLOBAL', arg=4, argval='ZeroDivisionError', argrepr='ZeroDivisionError', offset=382, start_offset=382, starts_line=True, line_number=22, cache_info=[('counter', 1, b'\x00\x00'), ('index', 1, b'\x00\x00'), ('module_keys_version', 1, b'\x00\x00'), ('builtin_keys_version', 1, b'\x00\x00')]),
|
||||||
make_inst(opname='POP_JUMP_IF_FALSE', arg=15, argval=426, argrepr='to L12', offset=392, start_offset=392, starts_line=False, line_number=22, cache_info=[('counter', 1, b'\x00\x00')]),
|
make_inst(opname='CHECK_EXC_MATCH', arg=None, argval=None, argrepr='', offset=392, start_offset=392, starts_line=False, line_number=22),
|
||||||
make_inst(opname='NOT_TAKEN', arg=None, argval=None, argrepr='', offset=396, start_offset=396, starts_line=False, line_number=22),
|
make_inst(opname='POP_JUMP_IF_FALSE', arg=15, argval=428, argrepr='to L12', offset=394, start_offset=394, starts_line=False, line_number=22, cache_info=[('counter', 1, b'\x00\x00')]),
|
||||||
make_inst(opname='POP_TOP', arg=None, argval=None, argrepr='', offset=398, start_offset=398, starts_line=False, line_number=22),
|
make_inst(opname='NOT_TAKEN', arg=None, argval=None, argrepr='', offset=398, start_offset=398, starts_line=False, line_number=22),
|
||||||
make_inst(opname='LOAD_GLOBAL', arg=3, argval='print', argrepr='print + NULL', offset=400, start_offset=400, starts_line=True, line_number=23, cache_info=[('counter', 1, b'\x00\x00'), ('index', 1, b'\x00\x00'), ('module_keys_version', 1, b'\x00\x00'), ('builtin_keys_version', 1, b'\x00\x00')]),
|
make_inst(opname='POP_TOP', arg=None, argval=None, argrepr='', offset=400, start_offset=400, starts_line=False, line_number=22),
|
||||||
make_inst(opname='LOAD_CONST', arg=5, argval='Here we go, here we go, here we go...', argrepr="'Here we go, here we go, here we go...'", offset=410, start_offset=410, starts_line=False, line_number=23),
|
make_inst(opname='LOAD_GLOBAL', arg=3, argval='print', argrepr='print + NULL', offset=402, start_offset=402, starts_line=True, line_number=23, cache_info=[('counter', 1, b'\x00\x00'), ('index', 1, b'\x00\x00'), ('module_keys_version', 1, b'\x00\x00'), ('builtin_keys_version', 1, b'\x00\x00')]),
|
||||||
make_inst(opname='CALL', arg=1, argval=1, argrepr='', offset=412, start_offset=412, starts_line=False, line_number=23, cache_info=[('counter', 1, b'\x00\x00'), ('func_version', 2, b'\x00\x00\x00\x00')]),
|
make_inst(opname='LOAD_CONST', arg=5, argval='Here we go, here we go, here we go...', argrepr="'Here we go, here we go, here we go...'", offset=412, start_offset=412, starts_line=False, line_number=23),
|
||||||
make_inst(opname='POP_TOP', arg=None, argval=None, argrepr='', offset=420, start_offset=420, starts_line=False, line_number=23),
|
make_inst(opname='CALL', arg=1, argval=1, argrepr='', offset=414, start_offset=414, starts_line=False, line_number=23, cache_info=[('counter', 1, b'\x00\x00'), ('func_version', 2, b'\x00\x00\x00\x00')]),
|
||||||
make_inst(opname='POP_EXCEPT', arg=None, argval=None, argrepr='', offset=422, start_offset=422, starts_line=False, line_number=23),
|
make_inst(opname='POP_TOP', arg=None, argval=None, argrepr='', offset=422, start_offset=422, starts_line=False, line_number=23),
|
||||||
make_inst(opname='JUMP_BACKWARD_NO_INTERRUPT', arg=56, argval=314, argrepr='to L10', offset=424, start_offset=424, starts_line=False, line_number=23),
|
make_inst(opname='POP_EXCEPT', arg=None, argval=None, argrepr='', offset=424, start_offset=424, starts_line=False, line_number=23),
|
||||||
make_inst(opname='RERAISE', arg=0, argval=0, argrepr='', offset=426, start_offset=426, starts_line=True, line_number=22, label=12),
|
make_inst(opname='JUMP_BACKWARD_NO_INTERRUPT', arg=56, argval=316, argrepr='to L10', offset=426, start_offset=426, starts_line=False, line_number=23),
|
||||||
make_inst(opname='COPY', arg=3, argval=3, argrepr='', offset=428, start_offset=428, starts_line=True, line_number=None),
|
make_inst(opname='RERAISE', arg=0, argval=0, argrepr='', offset=428, start_offset=428, starts_line=True, line_number=22, label=12),
|
||||||
make_inst(opname='POP_EXCEPT', arg=None, argval=None, argrepr='', offset=430, start_offset=430, starts_line=False, line_number=None),
|
make_inst(opname='COPY', arg=3, argval=3, argrepr='', offset=430, start_offset=430, starts_line=True, line_number=None),
|
||||||
make_inst(opname='RERAISE', arg=1, argval=1, argrepr='', offset=432, start_offset=432, starts_line=False, line_number=None),
|
make_inst(opname='POP_EXCEPT', arg=None, argval=None, argrepr='', offset=432, start_offset=432, starts_line=False, line_number=None),
|
||||||
make_inst(opname='PUSH_EXC_INFO', arg=None, argval=None, argrepr='', offset=434, start_offset=434, starts_line=False, line_number=None),
|
make_inst(opname='RERAISE', arg=1, argval=1, argrepr='', offset=434, start_offset=434, starts_line=False, line_number=None),
|
||||||
make_inst(opname='LOAD_GLOBAL', arg=3, argval='print', argrepr='print + NULL', offset=436, start_offset=436, starts_line=True, line_number=28, cache_info=[('counter', 1, b'\x00\x00'), ('index', 1, b'\x00\x00'), ('module_keys_version', 1, b'\x00\x00'), ('builtin_keys_version', 1, b'\x00\x00')]),
|
make_inst(opname='PUSH_EXC_INFO', arg=None, argval=None, argrepr='', offset=436, start_offset=436, starts_line=False, line_number=None),
|
||||||
make_inst(opname='LOAD_CONST', arg=6, argval="OK, now we're done", argrepr='"OK, now we\'re done"', offset=446, start_offset=446, starts_line=False, line_number=28),
|
make_inst(opname='LOAD_GLOBAL', arg=3, argval='print', argrepr='print + NULL', offset=438, start_offset=438, starts_line=True, line_number=28, cache_info=[('counter', 1, b'\x00\x00'), ('index', 1, b'\x00\x00'), ('module_keys_version', 1, b'\x00\x00'), ('builtin_keys_version', 1, b'\x00\x00')]),
|
||||||
make_inst(opname='CALL', arg=1, argval=1, argrepr='', offset=448, start_offset=448, starts_line=False, line_number=28, cache_info=[('counter', 1, b'\x00\x00'), ('func_version', 2, b'\x00\x00\x00\x00')]),
|
make_inst(opname='LOAD_CONST', arg=6, argval="OK, now we're done", argrepr='"OK, now we\'re done"', offset=448, start_offset=448, starts_line=False, line_number=28),
|
||||||
make_inst(opname='POP_TOP', arg=None, argval=None, argrepr='', offset=456, start_offset=456, starts_line=False, line_number=28),
|
make_inst(opname='CALL', arg=1, argval=1, argrepr='', offset=450, start_offset=450, starts_line=False, line_number=28, cache_info=[('counter', 1, b'\x00\x00'), ('func_version', 2, b'\x00\x00\x00\x00')]),
|
||||||
make_inst(opname='RERAISE', arg=0, argval=0, argrepr='', offset=458, start_offset=458, starts_line=False, line_number=28),
|
make_inst(opname='POP_TOP', arg=None, argval=None, argrepr='', offset=458, start_offset=458, starts_line=False, line_number=28),
|
||||||
make_inst(opname='COPY', arg=3, argval=3, argrepr='', offset=460, start_offset=460, starts_line=True, line_number=None),
|
make_inst(opname='RERAISE', arg=0, argval=0, argrepr='', offset=460, start_offset=460, starts_line=False, line_number=28),
|
||||||
make_inst(opname='POP_EXCEPT', arg=None, argval=None, argrepr='', offset=462, start_offset=462, starts_line=False, line_number=None),
|
make_inst(opname='COPY', arg=3, argval=3, argrepr='', offset=462, start_offset=462, starts_line=True, line_number=None),
|
||||||
make_inst(opname='RERAISE', arg=1, argval=1, argrepr='', offset=464, start_offset=464, starts_line=False, line_number=None),
|
make_inst(opname='POP_EXCEPT', arg=None, argval=None, argrepr='', offset=464, start_offset=464, starts_line=False, line_number=None),
|
||||||
|
make_inst(opname='RERAISE', arg=1, argval=1, argrepr='', offset=466, start_offset=466, starts_line=False, line_number=None),
|
||||||
]
|
]
|
||||||
|
|
||||||
# One last piece of inspect fodder to check the default line number handling
|
# One last piece of inspect fodder to check the default line number handling
|
||||||
|
@ -365,5 +365,20 @@ class ListTest(list_tests.CommonTest):
|
|||||||
rc, _, _ = assert_python_ok("-c", code)
|
rc, _, _ = assert_python_ok("-c", code)
|
||||||
self.assertEqual(rc, 0)
|
self.assertEqual(rc, 0)
|
||||||
|
|
||||||
|
def test_list_overwrite_local(self):
|
||||||
|
"""Test that overwriting the last reference to the
|
||||||
|
iterable doesn't prematurely free the iterable"""
|
||||||
|
|
||||||
|
def foo(x):
|
||||||
|
self.assertEqual(sys.getrefcount(x), 1)
|
||||||
|
r = 0
|
||||||
|
for i in x:
|
||||||
|
r += i
|
||||||
|
x = None
|
||||||
|
return r
|
||||||
|
|
||||||
|
self.assertEqual(foo(list(range(10))), 45)
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
unittest.main()
|
unittest.main()
|
||||||
|
@ -0,0 +1,4 @@
|
|||||||
|
Change iteration to use "virtual iterators" for sequences. Instead of
|
||||||
|
creating an iterator, a tagged integer representing the next index is pushed
|
||||||
|
to the stack above the iterable. For non-sequence iterators, ``NULL`` is
|
||||||
|
pushed.
|
@ -1386,6 +1386,10 @@ mark_stacks(PyCodeObject *code_obj, int len)
|
|||||||
stacks[j] = next_stack;
|
stacks[j] = next_stack;
|
||||||
break;
|
break;
|
||||||
case GET_ITER:
|
case GET_ITER:
|
||||||
|
next_stack = push_value(pop_value(next_stack), Iterator);
|
||||||
|
next_stack = push_value(next_stack, Iterator);
|
||||||
|
stacks[next_i] = next_stack;
|
||||||
|
break;
|
||||||
case GET_AITER:
|
case GET_AITER:
|
||||||
next_stack = push_value(pop_value(next_stack), Iterator);
|
next_stack = push_value(pop_value(next_stack), Iterator);
|
||||||
stacks[next_i] = next_stack;
|
stacks[next_i] = next_stack;
|
||||||
|
2
Programs/test_frozenmain.h
generated
2
Programs/test_frozenmain.h
generated
@ -1,6 +1,6 @@
|
|||||||
// Auto-generated by Programs/freeze_test_frozenmain.py
|
// Auto-generated by Programs/freeze_test_frozenmain.py
|
||||||
unsigned char M_test_frozenmain[] = {
|
unsigned char M_test_frozenmain[] = {
|
||||||
227,0,0,0,0,0,0,0,0,0,0,0,0,8,0,0,
|
227,0,0,0,0,0,0,0,0,0,0,0,0,9,0,0,
|
||||||
0,0,0,0,0,243,184,0,0,0,128,0,94,0,82,1,
|
0,0,0,0,0,243,184,0,0,0,128,0,94,0,82,1,
|
||||||
73,0,116,0,94,0,82,1,73,1,116,1,93,2,33,0,
|
73,0,116,0,94,0,82,1,73,1,116,1,93,2,33,0,
|
||||||
82,2,52,1,0,0,0,0,0,0,31,0,93,2,33,0,
|
82,2,52,1,0,0,0,0,0,0,31,0,93,2,33,0,
|
||||||
|
@ -341,7 +341,7 @@ dummy_func(
|
|||||||
}
|
}
|
||||||
|
|
||||||
pure inst(POP_TOP, (value --)) {
|
pure inst(POP_TOP, (value --)) {
|
||||||
PyStackRef_CLOSE(value);
|
PyStackRef_XCLOSE(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
tier2 op(_POP_TWO, (nos, tos --)) {
|
tier2 op(_POP_TWO, (nos, tos --)) {
|
||||||
@ -362,9 +362,14 @@ dummy_func(
|
|||||||
PyStackRef_CLOSE(value);
|
PyStackRef_CLOSE(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
macro(POP_ITER) = POP_TOP;
|
|
||||||
|
|
||||||
no_save_ip tier1 inst(INSTRUMENTED_END_FOR, (receiver, value -- receiver)) {
|
inst(POP_ITER, (iter, index_or_null -- )) {
|
||||||
|
(void)index_or_null;
|
||||||
|
DEAD(index_or_null);
|
||||||
|
PyStackRef_CLOSE(iter);
|
||||||
|
}
|
||||||
|
|
||||||
|
no_save_ip tier1 inst(INSTRUMENTED_END_FOR, (receiver, index_or_null, value -- receiver, index_or_null)) {
|
||||||
/* Need to create a fake StopIteration error here,
|
/* Need to create a fake StopIteration error here,
|
||||||
* to conform to PEP 380 */
|
* to conform to PEP 380 */
|
||||||
if (PyStackRef_GenCheck(receiver)) {
|
if (PyStackRef_GenCheck(receiver)) {
|
||||||
@ -376,7 +381,9 @@ dummy_func(
|
|||||||
PyStackRef_CLOSE(value);
|
PyStackRef_CLOSE(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
tier1 inst(INSTRUMENTED_POP_ITER, (iter -- )) {
|
tier1 inst(INSTRUMENTED_POP_ITER, (iter, index_or_null -- )) {
|
||||||
|
(void)index_or_null;
|
||||||
|
DEAD(index_or_null);
|
||||||
INSTRUMENTED_JUMP(prev_instr, this_instr+1, PY_MONITORING_EVENT_BRANCH_RIGHT);
|
INSTRUMENTED_JUMP(prev_instr, this_instr+1, PY_MONITORING_EVENT_BRANCH_RIGHT);
|
||||||
PyStackRef_CLOSE(iter);
|
PyStackRef_CLOSE(iter);
|
||||||
}
|
}
|
||||||
@ -3041,15 +3048,24 @@ dummy_func(
|
|||||||
values_or_none = PyStackRef_FromPyObjectSteal(values_or_none_o);
|
values_or_none = PyStackRef_FromPyObjectSteal(values_or_none_o);
|
||||||
}
|
}
|
||||||
|
|
||||||
inst(GET_ITER, (iterable -- iter)) {
|
inst(GET_ITER, (iterable -- iter, index_or_null)) {
|
||||||
#ifdef Py_STATS
|
#ifdef Py_STATS
|
||||||
_Py_GatherStats_GetIter(iterable);
|
_Py_GatherStats_GetIter(iterable);
|
||||||
#endif
|
#endif
|
||||||
/* before: [obj]; after [getiter(obj)] */
|
/* before: [obj]; after [getiter(obj)] */
|
||||||
PyObject *iter_o = PyObject_GetIter(PyStackRef_AsPyObjectBorrow(iterable));
|
PyTypeObject *tp = PyStackRef_TYPE(iterable);
|
||||||
PyStackRef_CLOSE(iterable);
|
if (tp == &PyTuple_Type || tp == &PyList_Type) {
|
||||||
ERROR_IF(iter_o == NULL);
|
iter = iterable;
|
||||||
iter = PyStackRef_FromPyObjectSteal(iter_o);
|
DEAD(iterable);
|
||||||
|
index_or_null = PyStackRef_TagInt(0);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
PyObject *iter_o = PyObject_GetIter(PyStackRef_AsPyObjectBorrow(iterable));
|
||||||
|
PyStackRef_CLOSE(iterable);
|
||||||
|
ERROR_IF(iter_o == NULL);
|
||||||
|
iter = PyStackRef_FromPyObjectSteal(iter_o);
|
||||||
|
index_or_null = PyStackRef_NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inst(GET_YIELD_FROM_ITER, (iterable -- iter)) {
|
inst(GET_YIELD_FROM_ITER, (iterable -- iter)) {
|
||||||
@ -3096,11 +3112,11 @@ dummy_func(
|
|||||||
FOR_ITER_GEN,
|
FOR_ITER_GEN,
|
||||||
};
|
};
|
||||||
|
|
||||||
specializing op(_SPECIALIZE_FOR_ITER, (counter/1, iter -- iter)) {
|
specializing op(_SPECIALIZE_FOR_ITER, (counter/1, iter, null_or_index -- iter, null_or_index)) {
|
||||||
#if ENABLE_SPECIALIZATION_FT
|
#if ENABLE_SPECIALIZATION_FT
|
||||||
if (ADAPTIVE_COUNTER_TRIGGERS(counter)) {
|
if (ADAPTIVE_COUNTER_TRIGGERS(counter)) {
|
||||||
next_instr = this_instr;
|
next_instr = this_instr;
|
||||||
_Py_Specialize_ForIter(iter, next_instr, oparg);
|
_Py_Specialize_ForIter(iter, null_or_index, next_instr, oparg);
|
||||||
DISPATCH_SAME_OPARG();
|
DISPATCH_SAME_OPARG();
|
||||||
}
|
}
|
||||||
OPCODE_DEFERRED_INC(FOR_ITER);
|
OPCODE_DEFERRED_INC(FOR_ITER);
|
||||||
@ -3108,33 +3124,44 @@ dummy_func(
|
|||||||
#endif /* ENABLE_SPECIALIZATION_FT */
|
#endif /* ENABLE_SPECIALIZATION_FT */
|
||||||
}
|
}
|
||||||
|
|
||||||
replaced op(_FOR_ITER, (iter -- iter, next)) {
|
replaced op(_FOR_ITER, (iter, null_or_index -- iter, null_or_index, next)) {
|
||||||
/* before: [iter]; after: [iter, iter()] *or* [] (and jump over END_FOR.) */
|
/* before: [iter]; after: [iter, iter()] *or* [] (and jump over END_FOR.) */
|
||||||
PyObject *iter_o = PyStackRef_AsPyObjectBorrow(iter);
|
PyObject *iter_o = PyStackRef_AsPyObjectBorrow(iter);
|
||||||
PyObject *next_o = (*Py_TYPE(iter_o)->tp_iternext)(iter_o);
|
if (PyStackRef_IsTaggedInt(null_or_index)) {
|
||||||
if (next_o == NULL) {
|
next = _PyForIter_NextWithIndex(iter_o, null_or_index);
|
||||||
if (_PyErr_Occurred(tstate)) {
|
if (PyStackRef_IsNull(next)) {
|
||||||
int matches = _PyErr_ExceptionMatches(tstate, PyExc_StopIteration);
|
null_or_index = PyStackRef_TagInt(-1);
|
||||||
if (!matches) {
|
JUMPBY(oparg + 1);
|
||||||
ERROR_NO_POP();
|
DISPATCH();
|
||||||
}
|
|
||||||
_PyEval_MonitorRaise(tstate, frame, this_instr);
|
|
||||||
_PyErr_Clear(tstate);
|
|
||||||
}
|
}
|
||||||
/* iterator ended normally */
|
null_or_index = PyStackRef_IncrementTaggedIntNoOverflow(null_or_index);
|
||||||
assert(next_instr[oparg].op.code == END_FOR ||
|
}
|
||||||
next_instr[oparg].op.code == INSTRUMENTED_END_FOR);
|
else {
|
||||||
/* Jump forward oparg, then skip following END_FOR */
|
PyObject *next_o = (*Py_TYPE(iter_o)->tp_iternext)(iter_o);
|
||||||
JUMPBY(oparg + 1);
|
if (next_o == NULL) {
|
||||||
DISPATCH();
|
if (_PyErr_Occurred(tstate)) {
|
||||||
|
int matches = _PyErr_ExceptionMatches(tstate, PyExc_StopIteration);
|
||||||
|
if (!matches) {
|
||||||
|
ERROR_NO_POP();
|
||||||
|
}
|
||||||
|
_PyEval_MonitorRaise(tstate, frame, this_instr);
|
||||||
|
_PyErr_Clear(tstate);
|
||||||
|
}
|
||||||
|
/* iterator ended normally */
|
||||||
|
assert(next_instr[oparg].op.code == END_FOR ||
|
||||||
|
next_instr[oparg].op.code == INSTRUMENTED_END_FOR);
|
||||||
|
/* Jump forward oparg, then skip following END_FOR */
|
||||||
|
JUMPBY(oparg + 1);
|
||||||
|
DISPATCH();
|
||||||
|
}
|
||||||
|
next = PyStackRef_FromPyObjectSteal(next_o);
|
||||||
}
|
}
|
||||||
next = PyStackRef_FromPyObjectSteal(next_o);
|
|
||||||
// Common case: no jump, leave it to the code generator
|
|
||||||
}
|
}
|
||||||
|
|
||||||
op(_FOR_ITER_TIER_TWO, (iter -- iter, next)) {
|
op(_FOR_ITER_TIER_TWO, (iter, null_or_index -- iter, null_or_index, next)) {
|
||||||
/* before: [iter]; after: [iter, iter()] *or* [] (and jump over END_FOR.) */
|
/* before: [iter]; after: [iter, iter()] *or* [] (and jump over END_FOR.) */
|
||||||
PyObject *iter_o = PyStackRef_AsPyObjectBorrow(iter);
|
PyObject *iter_o = PyStackRef_AsPyObjectBorrow(iter);
|
||||||
|
EXIT_IF(!PyStackRef_IsNull(null_or_index));
|
||||||
PyObject *next_o = (*Py_TYPE(iter_o)->tp_iternext)(iter_o);
|
PyObject *next_o = (*Py_TYPE(iter_o)->tp_iternext)(iter_o);
|
||||||
if (next_o == NULL) {
|
if (next_o == NULL) {
|
||||||
if (_PyErr_Occurred(tstate)) {
|
if (_PyErr_Occurred(tstate)) {
|
||||||
@ -3156,63 +3183,63 @@ dummy_func(
|
|||||||
macro(FOR_ITER) = _SPECIALIZE_FOR_ITER + _FOR_ITER;
|
macro(FOR_ITER) = _SPECIALIZE_FOR_ITER + _FOR_ITER;
|
||||||
|
|
||||||
|
|
||||||
inst(INSTRUMENTED_FOR_ITER, (unused/1, iter -- iter, next)) {
|
inst(INSTRUMENTED_FOR_ITER, (unused/1, iter, null_or_index -- iter, null_or_index, next)) {
|
||||||
PyObject *iter_o = PyStackRef_AsPyObjectBorrow(iter);
|
PyObject *iter_o = PyStackRef_AsPyObjectBorrow(iter);
|
||||||
PyObject *next_o = (*Py_TYPE(iter_o)->tp_iternext)(iter_o);
|
if (PyStackRef_IsTaggedInt(null_or_index)) {
|
||||||
if (next_o != NULL) {
|
next = _PyForIter_NextWithIndex(iter_o, null_or_index);
|
||||||
next = PyStackRef_FromPyObjectSteal(next_o);
|
if (PyStackRef_IsNull(next)) {
|
||||||
|
JUMPBY(oparg + 1);
|
||||||
|
DISPATCH();
|
||||||
|
}
|
||||||
INSTRUMENTED_JUMP(this_instr, next_instr, PY_MONITORING_EVENT_BRANCH_LEFT);
|
INSTRUMENTED_JUMP(this_instr, next_instr, PY_MONITORING_EVENT_BRANCH_LEFT);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (_PyErr_Occurred(tstate)) {
|
PyObject *next_o = (*Py_TYPE(iter_o)->tp_iternext)(iter_o);
|
||||||
int matches = _PyErr_ExceptionMatches(tstate, PyExc_StopIteration);
|
if (next_o != NULL) {
|
||||||
if (!matches) {
|
next = PyStackRef_FromPyObjectSteal(next_o);
|
||||||
ERROR_NO_POP();
|
INSTRUMENTED_JUMP(this_instr, next_instr, PY_MONITORING_EVENT_BRANCH_LEFT);
|
||||||
}
|
}
|
||||||
_PyEval_MonitorRaise(tstate, frame, this_instr);
|
else {
|
||||||
_PyErr_Clear(tstate);
|
if (_PyErr_Occurred(tstate)) {
|
||||||
|
int matches = _PyErr_ExceptionMatches(tstate, PyExc_StopIteration);
|
||||||
|
if (!matches) {
|
||||||
|
ERROR_NO_POP();
|
||||||
|
}
|
||||||
|
_PyEval_MonitorRaise(tstate, frame, this_instr);
|
||||||
|
_PyErr_Clear(tstate);
|
||||||
|
}
|
||||||
|
/* iterator ended normally */
|
||||||
|
assert(next_instr[oparg].op.code == END_FOR ||
|
||||||
|
next_instr[oparg].op.code == INSTRUMENTED_END_FOR);
|
||||||
|
/* Skip END_FOR */
|
||||||
|
JUMPBY(oparg + 1);
|
||||||
|
DISPATCH();
|
||||||
}
|
}
|
||||||
/* iterator ended normally */
|
|
||||||
assert(next_instr[oparg].op.code == END_FOR ||
|
|
||||||
next_instr[oparg].op.code == INSTRUMENTED_END_FOR);
|
|
||||||
/* Skip END_FOR */
|
|
||||||
JUMPBY(oparg + 1);
|
|
||||||
DISPATCH();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
op(_ITER_CHECK_LIST, (iter -- iter)) {
|
op(_ITER_CHECK_LIST, (iter, null_or_index -- iter, null_or_index)) {
|
||||||
PyObject *iter_o = PyStackRef_AsPyObjectBorrow(iter);
|
PyObject *iter_o = PyStackRef_AsPyObjectBorrow(iter);
|
||||||
EXIT_IF(Py_TYPE(iter_o) != &PyListIter_Type);
|
EXIT_IF(Py_TYPE(iter_o) != &PyList_Type);
|
||||||
|
assert(PyStackRef_IsTaggedInt(null_or_index));
|
||||||
#ifdef Py_GIL_DISABLED
|
#ifdef Py_GIL_DISABLED
|
||||||
EXIT_IF(!_PyObject_IsUniquelyReferenced(iter_o));
|
EXIT_IF(!_Py_IsOwnedByCurrentThread(iter_o) && !_PyObject_GC_IS_SHARED(iter_o));
|
||||||
_PyListIterObject *it = (_PyListIterObject *)iter_o;
|
|
||||||
EXIT_IF(!_Py_IsOwnedByCurrentThread((PyObject *)it->it_seq) ||
|
|
||||||
!_PyObject_GC_IS_SHARED(it->it_seq));
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
replaced op(_ITER_JUMP_LIST, (iter -- iter)) {
|
replaced op(_ITER_JUMP_LIST, (iter, null_or_index -- iter, null_or_index)) {
|
||||||
PyObject *iter_o = PyStackRef_AsPyObjectBorrow(iter);
|
|
||||||
assert(Py_TYPE(iter_o) == &PyListIter_Type);
|
|
||||||
// For free-threaded Python, the loop exit can happen at any point during
|
|
||||||
// item retrieval, so it doesn't make much sense to check and jump
|
|
||||||
// separately before item retrieval. Any length check we do here can be
|
|
||||||
// invalid by the time we actually try to fetch the item.
|
|
||||||
#ifdef Py_GIL_DISABLED
|
#ifdef Py_GIL_DISABLED
|
||||||
assert(_PyObject_IsUniquelyReferenced(iter_o));
|
// For free-threaded Python, the loop exit can happen at any point during
|
||||||
(void)iter_o;
|
// item retrieval, so it doesn't make much sense to check and jump
|
||||||
|
// separately before item retrieval. Any length check we do here can be
|
||||||
|
// invalid by the time we actually try to fetch the item.
|
||||||
#else
|
#else
|
||||||
_PyListIterObject *it = (_PyListIterObject *)iter_o;
|
PyObject *list_o = PyStackRef_AsPyObjectBorrow(iter);
|
||||||
|
assert(Py_TYPE(list_o) == &PyList_Type);
|
||||||
STAT_INC(FOR_ITER, hit);
|
STAT_INC(FOR_ITER, hit);
|
||||||
PyListObject *seq = it->it_seq;
|
if ((size_t)PyStackRef_UntagInt(null_or_index) >= (size_t)PyList_GET_SIZE(list_o)) {
|
||||||
if (seq == NULL || (size_t)it->it_index >= (size_t)PyList_GET_SIZE(seq)) {
|
null_or_index = PyStackRef_TagInt(-1);
|
||||||
it->it_index = -1;
|
|
||||||
if (seq != NULL) {
|
|
||||||
it->it_seq = NULL;
|
|
||||||
Py_DECREF(seq);
|
|
||||||
}
|
|
||||||
/* Jump forward oparg, then skip following END_FOR instruction */
|
/* Jump forward oparg, then skip following END_FOR instruction */
|
||||||
JUMPBY(oparg + 1);
|
JUMPBY(oparg + 1);
|
||||||
DISPATCH();
|
DISPATCH();
|
||||||
@ -3221,73 +3248,54 @@ dummy_func(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Only used by Tier 2
|
// Only used by Tier 2
|
||||||
op(_GUARD_NOT_EXHAUSTED_LIST, (iter -- iter)) {
|
op(_GUARD_NOT_EXHAUSTED_LIST, (iter, null_or_index -- iter, null_or_index)) {
|
||||||
#ifndef Py_GIL_DISABLED
|
#ifndef Py_GIL_DISABLED
|
||||||
PyObject *iter_o = PyStackRef_AsPyObjectBorrow(iter);
|
PyObject *list_o = PyStackRef_AsPyObjectBorrow(iter);
|
||||||
_PyListIterObject *it = (_PyListIterObject *)iter_o;
|
assert(Py_TYPE(list_o) == &PyList_Type);
|
||||||
assert(Py_TYPE(iter_o) == &PyListIter_Type);
|
EXIT_IF((size_t)PyStackRef_UntagInt(null_or_index) >= (size_t)PyList_GET_SIZE(list_o));
|
||||||
PyListObject *seq = it->it_seq;
|
|
||||||
EXIT_IF(seq == NULL);
|
|
||||||
if ((size_t)it->it_index >= (size_t)PyList_GET_SIZE(seq)) {
|
|
||||||
it->it_index = -1;
|
|
||||||
EXIT_IF(1);
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
replaced op(_ITER_NEXT_LIST, (iter -- iter, next)) {
|
replaced op(_ITER_NEXT_LIST, (iter, null_or_index -- iter, null_or_index, next)) {
|
||||||
PyObject *iter_o = PyStackRef_AsPyObjectBorrow(iter);
|
PyObject *list_o = PyStackRef_AsPyObjectBorrow(iter);
|
||||||
_PyListIterObject *it = (_PyListIterObject *)iter_o;
|
assert(PyList_CheckExact(list_o));
|
||||||
assert(Py_TYPE(iter_o) == &PyListIter_Type);
|
|
||||||
PyListObject *seq = it->it_seq;
|
|
||||||
assert(seq);
|
|
||||||
#ifdef Py_GIL_DISABLED
|
#ifdef Py_GIL_DISABLED
|
||||||
assert(_PyObject_IsUniquelyReferenced(iter_o));
|
assert(_Py_IsOwnedByCurrentThread(list_o) ||
|
||||||
assert(_Py_IsOwnedByCurrentThread((PyObject *)seq) ||
|
_PyObject_GC_IS_SHARED(list_o));
|
||||||
_PyObject_GC_IS_SHARED(seq));
|
|
||||||
STAT_INC(FOR_ITER, hit);
|
STAT_INC(FOR_ITER, hit);
|
||||||
int result = _PyList_GetItemRefNoLock(seq, it->it_index, &next);
|
int result = _PyList_GetItemRefNoLock((PyListObject *)list_o, PyStackRef_UntagInt(null_or_index), &next);
|
||||||
// A negative result means we lost a race with another thread
|
// A negative result means we lost a race with another thread
|
||||||
// and we need to take the slow path.
|
// and we need to take the slow path.
|
||||||
DEOPT_IF(result < 0);
|
DEOPT_IF(result < 0);
|
||||||
if (result == 0) {
|
if (result == 0) {
|
||||||
it->it_index = -1;
|
null_or_index = PyStackRef_TagInt(-1);
|
||||||
/* Jump forward oparg, then skip following END_FOR instruction */
|
/* Jump forward oparg, then skip following END_FOR instruction */
|
||||||
JUMPBY(oparg + 1);
|
JUMPBY(oparg + 1);
|
||||||
DISPATCH();
|
DISPATCH();
|
||||||
}
|
}
|
||||||
it->it_index++;
|
|
||||||
#else
|
#else
|
||||||
assert(it->it_index < PyList_GET_SIZE(seq));
|
next = PyStackRef_FromPyObjectNew(PyList_GET_ITEM(list_o, PyStackRef_UntagInt(null_or_index)));
|
||||||
next = PyStackRef_FromPyObjectNew(PyList_GET_ITEM(seq, it->it_index++));
|
|
||||||
#endif
|
#endif
|
||||||
|
null_or_index = PyStackRef_IncrementTaggedIntNoOverflow(null_or_index);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Only used by Tier 2
|
// Only used by Tier 2
|
||||||
op(_ITER_NEXT_LIST_TIER_TWO, (iter -- iter, next)) {
|
op(_ITER_NEXT_LIST_TIER_TWO, (iter, null_or_index -- iter, null_or_index, next)) {
|
||||||
PyObject *iter_o = PyStackRef_AsPyObjectBorrow(iter);
|
PyObject *list_o = PyStackRef_AsPyObjectBorrow(iter);
|
||||||
_PyListIterObject *it = (_PyListIterObject *)iter_o;
|
assert(PyList_CheckExact(list_o));
|
||||||
assert(Py_TYPE(iter_o) == &PyListIter_Type);
|
|
||||||
PyListObject *seq = it->it_seq;
|
|
||||||
assert(seq);
|
|
||||||
#ifdef Py_GIL_DISABLED
|
#ifdef Py_GIL_DISABLED
|
||||||
assert(_PyObject_IsUniquelyReferenced(iter_o));
|
assert(_Py_IsOwnedByCurrentThread((PyObject *)list_o) ||
|
||||||
assert(_Py_IsOwnedByCurrentThread((PyObject *)seq) ||
|
_PyObject_GC_IS_SHARED(list_o));
|
||||||
_PyObject_GC_IS_SHARED(seq));
|
|
||||||
STAT_INC(FOR_ITER, hit);
|
STAT_INC(FOR_ITER, hit);
|
||||||
int result = _PyList_GetItemRefNoLock(seq, it->it_index, &next);
|
int result = _PyList_GetItemRefNoLock((PyListObject *)list_o, PyStackRef_UntagInt(null_or_index), &next);
|
||||||
// A negative result means we lost a race with another thread
|
// A negative result means we lost a race with another thread
|
||||||
// and we need to take the slow path.
|
// and we need to take the slow path.
|
||||||
EXIT_IF(result < 0);
|
DEOPT_IF(result <= 0);
|
||||||
if (result == 0) {
|
|
||||||
it->it_index = -1;
|
|
||||||
EXIT_IF(1);
|
|
||||||
}
|
|
||||||
it->it_index++;
|
|
||||||
#else
|
#else
|
||||||
assert(it->it_index < PyList_GET_SIZE(seq));
|
assert(PyStackRef_UntagInt(null_or_index) < PyList_GET_SIZE(list_o));
|
||||||
next = PyStackRef_FromPyObjectNew(PyList_GET_ITEM(seq, it->it_index++));
|
next = PyStackRef_FromPyObjectNew(PyList_GET_ITEM(list_o, PyStackRef_UntagInt(null_or_index)));
|
||||||
#endif
|
#endif
|
||||||
|
null_or_index = PyStackRef_IncrementTaggedIntNoOverflow(null_or_index);
|
||||||
}
|
}
|
||||||
|
|
||||||
macro(FOR_ITER_LIST) =
|
macro(FOR_ITER_LIST) =
|
||||||
@ -3296,31 +3304,19 @@ dummy_func(
|
|||||||
_ITER_JUMP_LIST +
|
_ITER_JUMP_LIST +
|
||||||
_ITER_NEXT_LIST;
|
_ITER_NEXT_LIST;
|
||||||
|
|
||||||
op(_ITER_CHECK_TUPLE, (iter -- iter)) {
|
op(_ITER_CHECK_TUPLE, (iter, null_or_index -- iter, null_or_index)) {
|
||||||
PyObject *iter_o = PyStackRef_AsPyObjectBorrow(iter);
|
PyObject *iter_o = PyStackRef_AsPyObjectBorrow(iter);
|
||||||
EXIT_IF(Py_TYPE(iter_o) != &PyTupleIter_Type);
|
EXIT_IF(Py_TYPE(iter_o) != &PyTuple_Type);
|
||||||
#ifdef Py_GIL_DISABLED
|
assert(PyStackRef_IsTaggedInt(null_or_index));
|
||||||
EXIT_IF(!_PyObject_IsUniquelyReferenced(iter_o));
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
replaced op(_ITER_JUMP_TUPLE, (iter -- iter)) {
|
replaced op(_ITER_JUMP_TUPLE, (iter, null_or_index -- iter, null_or_index)) {
|
||||||
PyObject *iter_o = PyStackRef_AsPyObjectBorrow(iter);
|
PyObject *tuple_o = PyStackRef_AsPyObjectBorrow(iter);
|
||||||
(void)iter_o;
|
(void)tuple_o;
|
||||||
assert(Py_TYPE(iter_o) == &PyTupleIter_Type);
|
assert(Py_TYPE(tuple_o) == &PyTuple_Type);
|
||||||
#ifdef Py_GIL_DISABLED
|
|
||||||
assert(_PyObject_IsUniquelyReferenced(iter_o));
|
|
||||||
#endif
|
|
||||||
_PyTupleIterObject *it = (_PyTupleIterObject *)iter_o;
|
|
||||||
STAT_INC(FOR_ITER, hit);
|
STAT_INC(FOR_ITER, hit);
|
||||||
PyTupleObject *seq = it->it_seq;
|
if ((size_t)PyStackRef_UntagInt(null_or_index) >= (size_t)PyTuple_GET_SIZE(tuple_o)) {
|
||||||
if (seq == NULL || (size_t)it->it_index >= (size_t)PyTuple_GET_SIZE(seq)) {
|
null_or_index = PyStackRef_TagInt(-1);
|
||||||
#ifndef Py_GIL_DISABLED
|
|
||||||
if (seq != NULL) {
|
|
||||||
it->it_seq = NULL;
|
|
||||||
Py_DECREF(seq);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
/* Jump forward oparg, then skip following END_FOR instruction */
|
/* Jump forward oparg, then skip following END_FOR instruction */
|
||||||
JUMPBY(oparg + 1);
|
JUMPBY(oparg + 1);
|
||||||
DISPATCH();
|
DISPATCH();
|
||||||
@ -3328,29 +3324,19 @@ dummy_func(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Only used by Tier 2
|
// Only used by Tier 2
|
||||||
op(_GUARD_NOT_EXHAUSTED_TUPLE, (iter -- iter)) {
|
op(_GUARD_NOT_EXHAUSTED_TUPLE, (iter, null_or_index -- iter, null_or_index)) {
|
||||||
PyObject *iter_o = PyStackRef_AsPyObjectBorrow(iter);
|
PyObject *tuple_o = PyStackRef_AsPyObjectBorrow(iter);
|
||||||
_PyTupleIterObject *it = (_PyTupleIterObject *)iter_o;
|
assert(Py_TYPE(tuple_o) == &PyTuple_Type);
|
||||||
assert(Py_TYPE(iter_o) == &PyTupleIter_Type);
|
EXIT_IF((size_t)PyStackRef_UntagInt(null_or_index) >= (size_t)PyTuple_GET_SIZE(tuple_o));
|
||||||
#ifdef Py_GIL_DISABLED
|
|
||||||
assert(_PyObject_IsUniquelyReferenced(iter_o));
|
|
||||||
#endif
|
|
||||||
PyTupleObject *seq = it->it_seq;
|
|
||||||
EXIT_IF(seq == NULL);
|
|
||||||
EXIT_IF(it->it_index >= PyTuple_GET_SIZE(seq));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
op(_ITER_NEXT_TUPLE, (iter -- iter, next)) {
|
op(_ITER_NEXT_TUPLE, (iter, null_or_index -- iter, null_or_index, next)) {
|
||||||
PyObject *iter_o = PyStackRef_AsPyObjectBorrow(iter);
|
PyObject *tuple_o = PyStackRef_AsPyObjectBorrow(iter);
|
||||||
_PyTupleIterObject *it = (_PyTupleIterObject *)iter_o;
|
assert(Py_TYPE(tuple_o) == &PyTuple_Type);
|
||||||
assert(Py_TYPE(iter_o) == &PyTupleIter_Type);
|
uintptr_t i = PyStackRef_UntagInt(null_or_index);
|
||||||
PyTupleObject *seq = it->it_seq;
|
assert((size_t)i < (size_t)PyTuple_GET_SIZE(tuple_o));
|
||||||
#ifdef Py_GIL_DISABLED
|
next = PyStackRef_FromPyObjectNew(PyTuple_GET_ITEM(tuple_o, i));
|
||||||
assert(_PyObject_IsUniquelyReferenced(iter_o));
|
null_or_index = PyStackRef_IncrementTaggedIntNoOverflow(null_or_index);
|
||||||
#endif
|
|
||||||
assert(seq);
|
|
||||||
assert(it->it_index < PyTuple_GET_SIZE(seq));
|
|
||||||
next = PyStackRef_FromPyObjectNew(PyTuple_GET_ITEM(seq, it->it_index++));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
macro(FOR_ITER_TUPLE) =
|
macro(FOR_ITER_TUPLE) =
|
||||||
@ -3359,7 +3345,7 @@ dummy_func(
|
|||||||
_ITER_JUMP_TUPLE +
|
_ITER_JUMP_TUPLE +
|
||||||
_ITER_NEXT_TUPLE;
|
_ITER_NEXT_TUPLE;
|
||||||
|
|
||||||
op(_ITER_CHECK_RANGE, (iter -- iter)) {
|
op(_ITER_CHECK_RANGE, (iter, null_or_index -- iter, null_or_index)) {
|
||||||
_PyRangeIterObject *r = (_PyRangeIterObject *)PyStackRef_AsPyObjectBorrow(iter);
|
_PyRangeIterObject *r = (_PyRangeIterObject *)PyStackRef_AsPyObjectBorrow(iter);
|
||||||
EXIT_IF(Py_TYPE(r) != &PyRangeIter_Type);
|
EXIT_IF(Py_TYPE(r) != &PyRangeIter_Type);
|
||||||
#ifdef Py_GIL_DISABLED
|
#ifdef Py_GIL_DISABLED
|
||||||
@ -3367,7 +3353,7 @@ dummy_func(
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
replaced op(_ITER_JUMP_RANGE, (iter -- iter)) {
|
replaced op(_ITER_JUMP_RANGE, (iter, null_or_index -- iter, null_or_index)) {
|
||||||
_PyRangeIterObject *r = (_PyRangeIterObject *)PyStackRef_AsPyObjectBorrow(iter);
|
_PyRangeIterObject *r = (_PyRangeIterObject *)PyStackRef_AsPyObjectBorrow(iter);
|
||||||
assert(Py_TYPE(r) == &PyRangeIter_Type);
|
assert(Py_TYPE(r) == &PyRangeIter_Type);
|
||||||
#ifdef Py_GIL_DISABLED
|
#ifdef Py_GIL_DISABLED
|
||||||
@ -3382,13 +3368,13 @@ dummy_func(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Only used by Tier 2
|
// Only used by Tier 2
|
||||||
op(_GUARD_NOT_EXHAUSTED_RANGE, (iter -- iter)) {
|
op(_GUARD_NOT_EXHAUSTED_RANGE, (iter, null_or_index -- iter, null_or_index)) {
|
||||||
_PyRangeIterObject *r = (_PyRangeIterObject *)PyStackRef_AsPyObjectBorrow(iter);
|
_PyRangeIterObject *r = (_PyRangeIterObject *)PyStackRef_AsPyObjectBorrow(iter);
|
||||||
assert(Py_TYPE(r) == &PyRangeIter_Type);
|
assert(Py_TYPE(r) == &PyRangeIter_Type);
|
||||||
EXIT_IF(r->len <= 0);
|
EXIT_IF(r->len <= 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
op(_ITER_NEXT_RANGE, (iter -- iter, next)) {
|
op(_ITER_NEXT_RANGE, (iter, null_or_index -- iter, null_or_index, next)) {
|
||||||
_PyRangeIterObject *r = (_PyRangeIterObject *)PyStackRef_AsPyObjectBorrow(iter);
|
_PyRangeIterObject *r = (_PyRangeIterObject *)PyStackRef_AsPyObjectBorrow(iter);
|
||||||
assert(Py_TYPE(r) == &PyRangeIter_Type);
|
assert(Py_TYPE(r) == &PyRangeIter_Type);
|
||||||
#ifdef Py_GIL_DISABLED
|
#ifdef Py_GIL_DISABLED
|
||||||
@ -3409,7 +3395,7 @@ dummy_func(
|
|||||||
_ITER_JUMP_RANGE +
|
_ITER_JUMP_RANGE +
|
||||||
_ITER_NEXT_RANGE;
|
_ITER_NEXT_RANGE;
|
||||||
|
|
||||||
op(_FOR_ITER_GEN_FRAME, (iter -- iter, gen_frame: _PyInterpreterFrame*)) {
|
op(_FOR_ITER_GEN_FRAME, (iter, null -- iter, null, gen_frame: _PyInterpreterFrame*)) {
|
||||||
PyGenObject *gen = (PyGenObject *)PyStackRef_AsPyObjectBorrow(iter);
|
PyGenObject *gen = (PyGenObject *)PyStackRef_AsPyObjectBorrow(iter);
|
||||||
DEOPT_IF(Py_TYPE(gen) != &PyGen_Type);
|
DEOPT_IF(Py_TYPE(gen) != &PyGen_Type);
|
||||||
#ifdef Py_GIL_DISABLED
|
#ifdef Py_GIL_DISABLED
|
||||||
|
@ -3425,6 +3425,26 @@ _PyEval_LoadName(PyThreadState *tstate, _PyInterpreterFrame *frame, PyObject *na
|
|||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_PyStackRef
|
||||||
|
_PyForIter_NextWithIndex(PyObject *seq, _PyStackRef index)
|
||||||
|
{
|
||||||
|
assert(PyStackRef_IsTaggedInt(index));
|
||||||
|
assert(PyTuple_CheckExact(seq) || PyList_CheckExact(seq));
|
||||||
|
intptr_t i = PyStackRef_UntagInt(index);
|
||||||
|
if (PyTuple_CheckExact(seq)) {
|
||||||
|
size_t size = PyTuple_GET_SIZE(seq);
|
||||||
|
if ((size_t)i >= size) {
|
||||||
|
return PyStackRef_NULL;
|
||||||
|
}
|
||||||
|
return PyStackRef_FromPyObjectNew(PyTuple_GET_ITEM(seq, i));
|
||||||
|
}
|
||||||
|
PyObject *item = _PyList_GetItemRef((PyListObject *)seq, i);
|
||||||
|
if (item == NULL) {
|
||||||
|
return PyStackRef_NULL;
|
||||||
|
}
|
||||||
|
return PyStackRef_FromPyObjectSteal(item);
|
||||||
|
}
|
||||||
|
|
||||||
/* Check if a 'cls' provides the given special method. */
|
/* Check if a 'cls' provides the given special method. */
|
||||||
static inline int
|
static inline int
|
||||||
type_has_special_method(PyTypeObject *cls, PyObject *name)
|
type_has_special_method(PyTypeObject *cls, PyObject *name)
|
||||||
|
@ -525,6 +525,15 @@ codegen_unwind_fblock(compiler *c, location *ploc,
|
|||||||
return SUCCESS;
|
return SUCCESS;
|
||||||
|
|
||||||
case COMPILE_FBLOCK_FOR_LOOP:
|
case COMPILE_FBLOCK_FOR_LOOP:
|
||||||
|
/* Pop the iterator */
|
||||||
|
if (preserve_tos) {
|
||||||
|
ADDOP_I(c, *ploc, SWAP, 3);
|
||||||
|
}
|
||||||
|
ADDOP(c, *ploc, POP_TOP);
|
||||||
|
ADDOP(c, *ploc, POP_TOP);
|
||||||
|
return SUCCESS;
|
||||||
|
|
||||||
|
case COMPILE_FBLOCK_ASYNC_FOR_LOOP:
|
||||||
/* Pop the iterator */
|
/* Pop the iterator */
|
||||||
if (preserve_tos) {
|
if (preserve_tos) {
|
||||||
ADDOP_I(c, *ploc, SWAP, 2);
|
ADDOP_I(c, *ploc, SWAP, 2);
|
||||||
@ -629,7 +638,8 @@ codegen_unwind_fblock_stack(compiler *c, location *ploc,
|
|||||||
c, *ploc, "'break', 'continue' and 'return' cannot appear in an except* block");
|
c, *ploc, "'break', 'continue' and 'return' cannot appear in an except* block");
|
||||||
}
|
}
|
||||||
if (loop != NULL && (top->fb_type == COMPILE_FBLOCK_WHILE_LOOP ||
|
if (loop != NULL && (top->fb_type == COMPILE_FBLOCK_WHILE_LOOP ||
|
||||||
top->fb_type == COMPILE_FBLOCK_FOR_LOOP)) {
|
top->fb_type == COMPILE_FBLOCK_FOR_LOOP ||
|
||||||
|
top->fb_type == COMPILE_FBLOCK_ASYNC_FOR_LOOP)) {
|
||||||
*loop = top;
|
*loop = top;
|
||||||
return SUCCESS;
|
return SUCCESS;
|
||||||
}
|
}
|
||||||
@ -2125,7 +2135,7 @@ codegen_async_for(compiler *c, stmt_ty s)
|
|||||||
ADDOP(c, LOC(s->v.AsyncFor.iter), GET_AITER);
|
ADDOP(c, LOC(s->v.AsyncFor.iter), GET_AITER);
|
||||||
|
|
||||||
USE_LABEL(c, start);
|
USE_LABEL(c, start);
|
||||||
RETURN_IF_ERROR(_PyCompile_PushFBlock(c, loc, COMPILE_FBLOCK_FOR_LOOP, start, end, NULL));
|
RETURN_IF_ERROR(_PyCompile_PushFBlock(c, loc, COMPILE_FBLOCK_ASYNC_FOR_LOOP, start, end, NULL));
|
||||||
|
|
||||||
/* SETUP_FINALLY to guard the __anext__ call */
|
/* SETUP_FINALLY to guard the __anext__ call */
|
||||||
ADDOP_JUMP(c, loc, SETUP_FINALLY, except);
|
ADDOP_JUMP(c, loc, SETUP_FINALLY, except);
|
||||||
@ -2142,7 +2152,7 @@ codegen_async_for(compiler *c, stmt_ty s)
|
|||||||
/* Mark jump as artificial */
|
/* Mark jump as artificial */
|
||||||
ADDOP_JUMP(c, NO_LOCATION, JUMP, start);
|
ADDOP_JUMP(c, NO_LOCATION, JUMP, start);
|
||||||
|
|
||||||
_PyCompile_PopFBlock(c, COMPILE_FBLOCK_FOR_LOOP, start);
|
_PyCompile_PopFBlock(c, COMPILE_FBLOCK_ASYNC_FOR_LOOP, start);
|
||||||
|
|
||||||
/* Except block for __anext__ */
|
/* Except block for __anext__ */
|
||||||
USE_LABEL(c, except);
|
USE_LABEL(c, except);
|
||||||
@ -3895,10 +3905,11 @@ maybe_optimize_function_call(compiler *c, expr_ty e, jump_target_label end)
|
|||||||
NEW_JUMP_TARGET_LABEL(c, loop);
|
NEW_JUMP_TARGET_LABEL(c, loop);
|
||||||
NEW_JUMP_TARGET_LABEL(c, cleanup);
|
NEW_JUMP_TARGET_LABEL(c, cleanup);
|
||||||
|
|
||||||
|
ADDOP(c, loc, PUSH_NULL); // Push NULL index for loop
|
||||||
USE_LABEL(c, loop);
|
USE_LABEL(c, loop);
|
||||||
ADDOP_JUMP(c, loc, FOR_ITER, cleanup);
|
ADDOP_JUMP(c, loc, FOR_ITER, cleanup);
|
||||||
if (const_oparg == CONSTANT_BUILTIN_TUPLE) {
|
if (const_oparg == CONSTANT_BUILTIN_TUPLE) {
|
||||||
ADDOP_I(c, loc, LIST_APPEND, 2);
|
ADDOP_I(c, loc, LIST_APPEND, 3);
|
||||||
ADDOP_JUMP(c, loc, JUMP, loop);
|
ADDOP_JUMP(c, loc, JUMP, loop);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@ -4442,13 +4453,12 @@ codegen_sync_comprehension_generator(compiler *c, location loc,
|
|||||||
}
|
}
|
||||||
if (IS_JUMP_TARGET_LABEL(start)) {
|
if (IS_JUMP_TARGET_LABEL(start)) {
|
||||||
VISIT(c, expr, gen->iter);
|
VISIT(c, expr, gen->iter);
|
||||||
ADDOP(c, LOC(gen->iter), GET_ITER);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (IS_JUMP_TARGET_LABEL(start)) {
|
if (IS_JUMP_TARGET_LABEL(start)) {
|
||||||
depth++;
|
depth += 2;
|
||||||
ADDOP(c, LOC(gen->iter), GET_ITER);
|
ADDOP(c, LOC(gen->iter), GET_ITER);
|
||||||
USE_LABEL(c, start);
|
USE_LABEL(c, start);
|
||||||
ADDOP_JUMP(c, LOC(gen->iter), FOR_ITER, anchor);
|
ADDOP_JUMP(c, LOC(gen->iter), FOR_ITER, anchor);
|
||||||
@ -4543,9 +4553,9 @@ codegen_async_comprehension_generator(compiler *c, location loc,
|
|||||||
else {
|
else {
|
||||||
/* Sub-iter - calculate on the fly */
|
/* Sub-iter - calculate on the fly */
|
||||||
VISIT(c, expr, gen->iter);
|
VISIT(c, expr, gen->iter);
|
||||||
ADDOP(c, LOC(gen->iter), GET_AITER);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
ADDOP(c, LOC(gen->iter), GET_AITER);
|
||||||
|
|
||||||
USE_LABEL(c, start);
|
USE_LABEL(c, start);
|
||||||
/* Runtime will push a block here, so we need to account for that */
|
/* Runtime will push a block here, so we need to account for that */
|
||||||
@ -4757,19 +4767,6 @@ pop_inlined_comprehension_state(compiler *c, location loc,
|
|||||||
return SUCCESS;
|
return SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int
|
|
||||||
codegen_comprehension_iter(compiler *c, comprehension_ty comp)
|
|
||||||
{
|
|
||||||
VISIT(c, expr, comp->iter);
|
|
||||||
if (comp->is_async) {
|
|
||||||
ADDOP(c, LOC(comp->iter), GET_AITER);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
ADDOP(c, LOC(comp->iter), GET_ITER);
|
|
||||||
}
|
|
||||||
return SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
codegen_comprehension(compiler *c, expr_ty e, int type,
|
codegen_comprehension(compiler *c, expr_ty e, int type,
|
||||||
identifier name, asdl_comprehension_seq *generators, expr_ty elt,
|
identifier name, asdl_comprehension_seq *generators, expr_ty elt,
|
||||||
@ -4789,9 +4786,7 @@ codegen_comprehension(compiler *c, expr_ty e, int type,
|
|||||||
|
|
||||||
outermost = (comprehension_ty) asdl_seq_GET(generators, 0);
|
outermost = (comprehension_ty) asdl_seq_GET(generators, 0);
|
||||||
if (is_inlined) {
|
if (is_inlined) {
|
||||||
if (codegen_comprehension_iter(c, outermost)) {
|
VISIT(c, expr, outermost->iter);
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
if (push_inlined_comprehension_state(c, loc, entry, &inline_state)) {
|
if (push_inlined_comprehension_state(c, loc, entry, &inline_state)) {
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
189
Python/executor_cases.c.h
generated
189
Python/executor_cases.c.h
generated
@ -534,7 +534,7 @@
|
|||||||
stack_pointer += -1;
|
stack_pointer += -1;
|
||||||
assert(WITHIN_STACK_BOUNDS());
|
assert(WITHIN_STACK_BOUNDS());
|
||||||
_PyFrame_SetStackPointer(frame, stack_pointer);
|
_PyFrame_SetStackPointer(frame, stack_pointer);
|
||||||
PyStackRef_CLOSE(value);
|
PyStackRef_XCLOSE(value);
|
||||||
stack_pointer = _PyFrame_GetStackPointer(frame);
|
stack_pointer = _PyFrame_GetStackPointer(frame);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -577,6 +577,20 @@
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case _POP_ITER: {
|
||||||
|
_PyStackRef index_or_null;
|
||||||
|
_PyStackRef iter;
|
||||||
|
index_or_null = stack_pointer[-1];
|
||||||
|
iter = stack_pointer[-2];
|
||||||
|
(void)index_or_null;
|
||||||
|
stack_pointer += -2;
|
||||||
|
assert(WITHIN_STACK_BOUNDS());
|
||||||
|
_PyFrame_SetStackPointer(frame, stack_pointer);
|
||||||
|
PyStackRef_CLOSE(iter);
|
||||||
|
stack_pointer = _PyFrame_GetStackPointer(frame);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
case _END_SEND: {
|
case _END_SEND: {
|
||||||
_PyStackRef value;
|
_PyStackRef value;
|
||||||
_PyStackRef receiver;
|
_PyStackRef receiver;
|
||||||
@ -4172,25 +4186,37 @@
|
|||||||
case _GET_ITER: {
|
case _GET_ITER: {
|
||||||
_PyStackRef iterable;
|
_PyStackRef iterable;
|
||||||
_PyStackRef iter;
|
_PyStackRef iter;
|
||||||
|
_PyStackRef index_or_null;
|
||||||
iterable = stack_pointer[-1];
|
iterable = stack_pointer[-1];
|
||||||
#ifdef Py_STATS
|
#ifdef Py_STATS
|
||||||
_PyFrame_SetStackPointer(frame, stack_pointer);
|
_PyFrame_SetStackPointer(frame, stack_pointer);
|
||||||
_Py_GatherStats_GetIter(iterable);
|
_Py_GatherStats_GetIter(iterable);
|
||||||
stack_pointer = _PyFrame_GetStackPointer(frame);
|
stack_pointer = _PyFrame_GetStackPointer(frame);
|
||||||
#endif
|
#endif
|
||||||
_PyFrame_SetStackPointer(frame, stack_pointer);
|
|
||||||
PyObject *iter_o = PyObject_GetIter(PyStackRef_AsPyObjectBorrow(iterable));
|
PyTypeObject *tp = PyStackRef_TYPE(iterable);
|
||||||
stack_pointer = _PyFrame_GetStackPointer(frame);
|
if (tp == &PyTuple_Type || tp == &PyList_Type) {
|
||||||
stack_pointer += -1;
|
iter = iterable;
|
||||||
assert(WITHIN_STACK_BOUNDS());
|
index_or_null = PyStackRef_TagInt(0);
|
||||||
_PyFrame_SetStackPointer(frame, stack_pointer);
|
|
||||||
PyStackRef_CLOSE(iterable);
|
|
||||||
stack_pointer = _PyFrame_GetStackPointer(frame);
|
|
||||||
if (iter_o == NULL) {
|
|
||||||
JUMP_TO_ERROR();
|
|
||||||
}
|
}
|
||||||
iter = PyStackRef_FromPyObjectSteal(iter_o);
|
else {
|
||||||
stack_pointer[0] = iter;
|
_PyFrame_SetStackPointer(frame, stack_pointer);
|
||||||
|
PyObject *iter_o = PyObject_GetIter(PyStackRef_AsPyObjectBorrow(iterable));
|
||||||
|
stack_pointer = _PyFrame_GetStackPointer(frame);
|
||||||
|
stack_pointer += -1;
|
||||||
|
assert(WITHIN_STACK_BOUNDS());
|
||||||
|
_PyFrame_SetStackPointer(frame, stack_pointer);
|
||||||
|
PyStackRef_CLOSE(iterable);
|
||||||
|
stack_pointer = _PyFrame_GetStackPointer(frame);
|
||||||
|
if (iter_o == NULL) {
|
||||||
|
JUMP_TO_ERROR();
|
||||||
|
}
|
||||||
|
iter = PyStackRef_FromPyObjectSteal(iter_o);
|
||||||
|
index_or_null = PyStackRef_NULL;
|
||||||
|
stack_pointer += 1;
|
||||||
|
}
|
||||||
|
stack_pointer[-1] = iter;
|
||||||
|
stack_pointer[0] = index_or_null;
|
||||||
stack_pointer += 1;
|
stack_pointer += 1;
|
||||||
assert(WITHIN_STACK_BOUNDS());
|
assert(WITHIN_STACK_BOUNDS());
|
||||||
break;
|
break;
|
||||||
@ -4237,10 +4263,16 @@
|
|||||||
/* _FOR_ITER is not a viable micro-op for tier 2 because it is replaced */
|
/* _FOR_ITER is not a viable micro-op for tier 2 because it is replaced */
|
||||||
|
|
||||||
case _FOR_ITER_TIER_TWO: {
|
case _FOR_ITER_TIER_TWO: {
|
||||||
|
_PyStackRef null_or_index;
|
||||||
_PyStackRef iter;
|
_PyStackRef iter;
|
||||||
_PyStackRef next;
|
_PyStackRef next;
|
||||||
iter = stack_pointer[-1];
|
null_or_index = stack_pointer[-1];
|
||||||
|
iter = stack_pointer[-2];
|
||||||
PyObject *iter_o = PyStackRef_AsPyObjectBorrow(iter);
|
PyObject *iter_o = PyStackRef_AsPyObjectBorrow(iter);
|
||||||
|
if (!PyStackRef_IsNull(null_or_index)) {
|
||||||
|
UOP_STAT_INC(uopcode, miss);
|
||||||
|
JUMP_TO_JUMP_TARGET();
|
||||||
|
}
|
||||||
_PyFrame_SetStackPointer(frame, stack_pointer);
|
_PyFrame_SetStackPointer(frame, stack_pointer);
|
||||||
PyObject *next_o = (*Py_TYPE(iter_o)->tp_iternext)(iter_o);
|
PyObject *next_o = (*Py_TYPE(iter_o)->tp_iternext)(iter_o);
|
||||||
stack_pointer = _PyFrame_GetStackPointer(frame);
|
stack_pointer = _PyFrame_GetStackPointer(frame);
|
||||||
@ -4272,21 +4304,18 @@
|
|||||||
/* _INSTRUMENTED_FOR_ITER is not a viable micro-op for tier 2 because it is instrumented */
|
/* _INSTRUMENTED_FOR_ITER is not a viable micro-op for tier 2 because it is instrumented */
|
||||||
|
|
||||||
case _ITER_CHECK_LIST: {
|
case _ITER_CHECK_LIST: {
|
||||||
|
_PyStackRef null_or_index;
|
||||||
_PyStackRef iter;
|
_PyStackRef iter;
|
||||||
iter = stack_pointer[-1];
|
null_or_index = stack_pointer[-1];
|
||||||
|
iter = stack_pointer[-2];
|
||||||
PyObject *iter_o = PyStackRef_AsPyObjectBorrow(iter);
|
PyObject *iter_o = PyStackRef_AsPyObjectBorrow(iter);
|
||||||
if (Py_TYPE(iter_o) != &PyListIter_Type) {
|
if (Py_TYPE(iter_o) != &PyList_Type) {
|
||||||
UOP_STAT_INC(uopcode, miss);
|
UOP_STAT_INC(uopcode, miss);
|
||||||
JUMP_TO_JUMP_TARGET();
|
JUMP_TO_JUMP_TARGET();
|
||||||
}
|
}
|
||||||
|
assert(PyStackRef_IsTaggedInt(null_or_index));
|
||||||
#ifdef Py_GIL_DISABLED
|
#ifdef Py_GIL_DISABLED
|
||||||
if (!_PyObject_IsUniquelyReferenced(iter_o)) {
|
if (!_Py_IsOwnedByCurrentThread(iter_o) && !_PyObject_GC_IS_SHARED(iter_o)) {
|
||||||
UOP_STAT_INC(uopcode, miss);
|
|
||||||
JUMP_TO_JUMP_TARGET();
|
|
||||||
}
|
|
||||||
_PyListIterObject *it = (_PyListIterObject *)iter_o;
|
|
||||||
if (!_Py_IsOwnedByCurrentThread((PyObject *)it->it_seq) ||
|
|
||||||
!_PyObject_GC_IS_SHARED(it->it_seq)) {
|
|
||||||
UOP_STAT_INC(uopcode, miss);
|
UOP_STAT_INC(uopcode, miss);
|
||||||
JUMP_TO_JUMP_TARGET();
|
JUMP_TO_JUMP_TARGET();
|
||||||
}
|
}
|
||||||
@ -4297,24 +4326,17 @@
|
|||||||
/* _ITER_JUMP_LIST is not a viable micro-op for tier 2 because it is replaced */
|
/* _ITER_JUMP_LIST is not a viable micro-op for tier 2 because it is replaced */
|
||||||
|
|
||||||
case _GUARD_NOT_EXHAUSTED_LIST: {
|
case _GUARD_NOT_EXHAUSTED_LIST: {
|
||||||
|
_PyStackRef null_or_index;
|
||||||
_PyStackRef iter;
|
_PyStackRef iter;
|
||||||
iter = stack_pointer[-1];
|
null_or_index = stack_pointer[-1];
|
||||||
|
iter = stack_pointer[-2];
|
||||||
#ifndef Py_GIL_DISABLED
|
#ifndef Py_GIL_DISABLED
|
||||||
PyObject *iter_o = PyStackRef_AsPyObjectBorrow(iter);
|
PyObject *list_o = PyStackRef_AsPyObjectBorrow(iter);
|
||||||
_PyListIterObject *it = (_PyListIterObject *)iter_o;
|
assert(Py_TYPE(list_o) == &PyList_Type);
|
||||||
assert(Py_TYPE(iter_o) == &PyListIter_Type);
|
if ((size_t)PyStackRef_UntagInt(null_or_index) >= (size_t)PyList_GET_SIZE(list_o)) {
|
||||||
PyListObject *seq = it->it_seq;
|
|
||||||
if (seq == NULL) {
|
|
||||||
UOP_STAT_INC(uopcode, miss);
|
UOP_STAT_INC(uopcode, miss);
|
||||||
JUMP_TO_JUMP_TARGET();
|
JUMP_TO_JUMP_TARGET();
|
||||||
}
|
}
|
||||||
if ((size_t)it->it_index >= (size_t)PyList_GET_SIZE(seq)) {
|
|
||||||
it->it_index = -1;
|
|
||||||
if (1) {
|
|
||||||
UOP_STAT_INC(uopcode, miss);
|
|
||||||
JUMP_TO_JUMP_TARGET();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -4322,38 +4344,30 @@
|
|||||||
/* _ITER_NEXT_LIST is not a viable micro-op for tier 2 because it is replaced */
|
/* _ITER_NEXT_LIST is not a viable micro-op for tier 2 because it is replaced */
|
||||||
|
|
||||||
case _ITER_NEXT_LIST_TIER_TWO: {
|
case _ITER_NEXT_LIST_TIER_TWO: {
|
||||||
|
_PyStackRef null_or_index;
|
||||||
_PyStackRef iter;
|
_PyStackRef iter;
|
||||||
_PyStackRef next;
|
_PyStackRef next;
|
||||||
iter = stack_pointer[-1];
|
null_or_index = stack_pointer[-1];
|
||||||
PyObject *iter_o = PyStackRef_AsPyObjectBorrow(iter);
|
iter = stack_pointer[-2];
|
||||||
_PyListIterObject *it = (_PyListIterObject *)iter_o;
|
PyObject *list_o = PyStackRef_AsPyObjectBorrow(iter);
|
||||||
assert(Py_TYPE(iter_o) == &PyListIter_Type);
|
assert(PyList_CheckExact(list_o));
|
||||||
PyListObject *seq = it->it_seq;
|
|
||||||
assert(seq);
|
|
||||||
#ifdef Py_GIL_DISABLED
|
#ifdef Py_GIL_DISABLED
|
||||||
assert(_PyObject_IsUniquelyReferenced(iter_o));
|
assert(_Py_IsOwnedByCurrentThread((PyObject *)list_o) ||
|
||||||
assert(_Py_IsOwnedByCurrentThread((PyObject *)seq) ||
|
_PyObject_GC_IS_SHARED(list_o));
|
||||||
_PyObject_GC_IS_SHARED(seq));
|
|
||||||
STAT_INC(FOR_ITER, hit);
|
STAT_INC(FOR_ITER, hit);
|
||||||
_PyFrame_SetStackPointer(frame, stack_pointer);
|
_PyFrame_SetStackPointer(frame, stack_pointer);
|
||||||
int result = _PyList_GetItemRefNoLock(seq, it->it_index, &next);
|
int result = _PyList_GetItemRefNoLock((PyListObject *)list_o, PyStackRef_UntagInt(null_or_index), &next);
|
||||||
stack_pointer = _PyFrame_GetStackPointer(frame);
|
stack_pointer = _PyFrame_GetStackPointer(frame);
|
||||||
if (result < 0) {
|
if (result <= 0) {
|
||||||
UOP_STAT_INC(uopcode, miss);
|
UOP_STAT_INC(uopcode, miss);
|
||||||
JUMP_TO_JUMP_TARGET();
|
JUMP_TO_JUMP_TARGET();
|
||||||
}
|
}
|
||||||
if (result == 0) {
|
|
||||||
it->it_index = -1;
|
|
||||||
if (1) {
|
|
||||||
UOP_STAT_INC(uopcode, miss);
|
|
||||||
JUMP_TO_JUMP_TARGET();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
it->it_index++;
|
|
||||||
#else
|
#else
|
||||||
assert(it->it_index < PyList_GET_SIZE(seq));
|
assert(PyStackRef_UntagInt(null_or_index) < PyList_GET_SIZE(list_o));
|
||||||
next = PyStackRef_FromPyObjectNew(PyList_GET_ITEM(seq, it->it_index++));
|
next = PyStackRef_FromPyObjectNew(PyList_GET_ITEM(list_o, PyStackRef_UntagInt(null_or_index)));
|
||||||
#endif
|
#endif
|
||||||
|
null_or_index = PyStackRef_IncrementTaggedIntNoOverflow(null_or_index);
|
||||||
|
stack_pointer[-1] = null_or_index;
|
||||||
stack_pointer[0] = next;
|
stack_pointer[0] = next;
|
||||||
stack_pointer += 1;
|
stack_pointer += 1;
|
||||||
assert(WITHIN_STACK_BOUNDS());
|
assert(WITHIN_STACK_BOUNDS());
|
||||||
@ -4361,39 +4375,29 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
case _ITER_CHECK_TUPLE: {
|
case _ITER_CHECK_TUPLE: {
|
||||||
|
_PyStackRef null_or_index;
|
||||||
_PyStackRef iter;
|
_PyStackRef iter;
|
||||||
iter = stack_pointer[-1];
|
null_or_index = stack_pointer[-1];
|
||||||
|
iter = stack_pointer[-2];
|
||||||
PyObject *iter_o = PyStackRef_AsPyObjectBorrow(iter);
|
PyObject *iter_o = PyStackRef_AsPyObjectBorrow(iter);
|
||||||
if (Py_TYPE(iter_o) != &PyTupleIter_Type) {
|
if (Py_TYPE(iter_o) != &PyTuple_Type) {
|
||||||
UOP_STAT_INC(uopcode, miss);
|
UOP_STAT_INC(uopcode, miss);
|
||||||
JUMP_TO_JUMP_TARGET();
|
JUMP_TO_JUMP_TARGET();
|
||||||
}
|
}
|
||||||
#ifdef Py_GIL_DISABLED
|
assert(PyStackRef_IsTaggedInt(null_or_index));
|
||||||
if (!_PyObject_IsUniquelyReferenced(iter_o)) {
|
|
||||||
UOP_STAT_INC(uopcode, miss);
|
|
||||||
JUMP_TO_JUMP_TARGET();
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* _ITER_JUMP_TUPLE is not a viable micro-op for tier 2 because it is replaced */
|
/* _ITER_JUMP_TUPLE is not a viable micro-op for tier 2 because it is replaced */
|
||||||
|
|
||||||
case _GUARD_NOT_EXHAUSTED_TUPLE: {
|
case _GUARD_NOT_EXHAUSTED_TUPLE: {
|
||||||
|
_PyStackRef null_or_index;
|
||||||
_PyStackRef iter;
|
_PyStackRef iter;
|
||||||
iter = stack_pointer[-1];
|
null_or_index = stack_pointer[-1];
|
||||||
PyObject *iter_o = PyStackRef_AsPyObjectBorrow(iter);
|
iter = stack_pointer[-2];
|
||||||
_PyTupleIterObject *it = (_PyTupleIterObject *)iter_o;
|
PyObject *tuple_o = PyStackRef_AsPyObjectBorrow(iter);
|
||||||
assert(Py_TYPE(iter_o) == &PyTupleIter_Type);
|
assert(Py_TYPE(tuple_o) == &PyTuple_Type);
|
||||||
#ifdef Py_GIL_DISABLED
|
if ((size_t)PyStackRef_UntagInt(null_or_index) >= (size_t)PyTuple_GET_SIZE(tuple_o)) {
|
||||||
assert(_PyObject_IsUniquelyReferenced(iter_o));
|
|
||||||
#endif
|
|
||||||
PyTupleObject *seq = it->it_seq;
|
|
||||||
if (seq == NULL) {
|
|
||||||
UOP_STAT_INC(uopcode, miss);
|
|
||||||
JUMP_TO_JUMP_TARGET();
|
|
||||||
}
|
|
||||||
if (it->it_index >= PyTuple_GET_SIZE(seq)) {
|
|
||||||
UOP_STAT_INC(uopcode, miss);
|
UOP_STAT_INC(uopcode, miss);
|
||||||
JUMP_TO_JUMP_TARGET();
|
JUMP_TO_JUMP_TARGET();
|
||||||
}
|
}
|
||||||
@ -4401,19 +4405,18 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
case _ITER_NEXT_TUPLE: {
|
case _ITER_NEXT_TUPLE: {
|
||||||
|
_PyStackRef null_or_index;
|
||||||
_PyStackRef iter;
|
_PyStackRef iter;
|
||||||
_PyStackRef next;
|
_PyStackRef next;
|
||||||
iter = stack_pointer[-1];
|
null_or_index = stack_pointer[-1];
|
||||||
PyObject *iter_o = PyStackRef_AsPyObjectBorrow(iter);
|
iter = stack_pointer[-2];
|
||||||
_PyTupleIterObject *it = (_PyTupleIterObject *)iter_o;
|
PyObject *tuple_o = PyStackRef_AsPyObjectBorrow(iter);
|
||||||
assert(Py_TYPE(iter_o) == &PyTupleIter_Type);
|
assert(Py_TYPE(tuple_o) == &PyTuple_Type);
|
||||||
PyTupleObject *seq = it->it_seq;
|
uintptr_t i = PyStackRef_UntagInt(null_or_index);
|
||||||
#ifdef Py_GIL_DISABLED
|
assert((size_t)i < (size_t)PyTuple_GET_SIZE(tuple_o));
|
||||||
assert(_PyObject_IsUniquelyReferenced(iter_o));
|
next = PyStackRef_FromPyObjectNew(PyTuple_GET_ITEM(tuple_o, i));
|
||||||
#endif
|
null_or_index = PyStackRef_IncrementTaggedIntNoOverflow(null_or_index);
|
||||||
assert(seq);
|
stack_pointer[-1] = null_or_index;
|
||||||
assert(it->it_index < PyTuple_GET_SIZE(seq));
|
|
||||||
next = PyStackRef_FromPyObjectNew(PyTuple_GET_ITEM(seq, it->it_index++));
|
|
||||||
stack_pointer[0] = next;
|
stack_pointer[0] = next;
|
||||||
stack_pointer += 1;
|
stack_pointer += 1;
|
||||||
assert(WITHIN_STACK_BOUNDS());
|
assert(WITHIN_STACK_BOUNDS());
|
||||||
@ -4422,7 +4425,7 @@
|
|||||||
|
|
||||||
case _ITER_CHECK_RANGE: {
|
case _ITER_CHECK_RANGE: {
|
||||||
_PyStackRef iter;
|
_PyStackRef iter;
|
||||||
iter = stack_pointer[-1];
|
iter = stack_pointer[-2];
|
||||||
_PyRangeIterObject *r = (_PyRangeIterObject *)PyStackRef_AsPyObjectBorrow(iter);
|
_PyRangeIterObject *r = (_PyRangeIterObject *)PyStackRef_AsPyObjectBorrow(iter);
|
||||||
if (Py_TYPE(r) != &PyRangeIter_Type) {
|
if (Py_TYPE(r) != &PyRangeIter_Type) {
|
||||||
UOP_STAT_INC(uopcode, miss);
|
UOP_STAT_INC(uopcode, miss);
|
||||||
@ -4441,7 +4444,7 @@
|
|||||||
|
|
||||||
case _GUARD_NOT_EXHAUSTED_RANGE: {
|
case _GUARD_NOT_EXHAUSTED_RANGE: {
|
||||||
_PyStackRef iter;
|
_PyStackRef iter;
|
||||||
iter = stack_pointer[-1];
|
iter = stack_pointer[-2];
|
||||||
_PyRangeIterObject *r = (_PyRangeIterObject *)PyStackRef_AsPyObjectBorrow(iter);
|
_PyRangeIterObject *r = (_PyRangeIterObject *)PyStackRef_AsPyObjectBorrow(iter);
|
||||||
assert(Py_TYPE(r) == &PyRangeIter_Type);
|
assert(Py_TYPE(r) == &PyRangeIter_Type);
|
||||||
if (r->len <= 0) {
|
if (r->len <= 0) {
|
||||||
@ -4454,7 +4457,7 @@
|
|||||||
case _ITER_NEXT_RANGE: {
|
case _ITER_NEXT_RANGE: {
|
||||||
_PyStackRef iter;
|
_PyStackRef iter;
|
||||||
_PyStackRef next;
|
_PyStackRef next;
|
||||||
iter = stack_pointer[-1];
|
iter = stack_pointer[-2];
|
||||||
_PyRangeIterObject *r = (_PyRangeIterObject *)PyStackRef_AsPyObjectBorrow(iter);
|
_PyRangeIterObject *r = (_PyRangeIterObject *)PyStackRef_AsPyObjectBorrow(iter);
|
||||||
assert(Py_TYPE(r) == &PyRangeIter_Type);
|
assert(Py_TYPE(r) == &PyRangeIter_Type);
|
||||||
#ifdef Py_GIL_DISABLED
|
#ifdef Py_GIL_DISABLED
|
||||||
@ -4479,7 +4482,7 @@
|
|||||||
_PyStackRef iter;
|
_PyStackRef iter;
|
||||||
_PyInterpreterFrame *gen_frame;
|
_PyInterpreterFrame *gen_frame;
|
||||||
oparg = CURRENT_OPARG();
|
oparg = CURRENT_OPARG();
|
||||||
iter = stack_pointer[-1];
|
iter = stack_pointer[-2];
|
||||||
PyGenObject *gen = (PyGenObject *)PyStackRef_AsPyObjectBorrow(iter);
|
PyGenObject *gen = (PyGenObject *)PyStackRef_AsPyObjectBorrow(iter);
|
||||||
if (Py_TYPE(gen) != &PyGen_Type) {
|
if (Py_TYPE(gen) != &PyGen_Type) {
|
||||||
UOP_STAT_INC(uopcode, miss);
|
UOP_STAT_INC(uopcode, miss);
|
||||||
|
@ -299,26 +299,34 @@ basicblock_returns(const basicblock *b) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
dump_basicblock(const basicblock *b)
|
dump_basicblock(const basicblock *b, bool highlight)
|
||||||
{
|
{
|
||||||
const char *b_return = basicblock_returns(b) ? "return " : "";
|
const char *b_return = basicblock_returns(b) ? "return " : "";
|
||||||
|
if (highlight) {
|
||||||
|
fprintf(stderr, ">>> ");
|
||||||
|
}
|
||||||
fprintf(stderr, "%d: [EH=%d CLD=%d WRM=%d NO_FT=%d %p] used: %d, depth: %d, preds: %d %s\n",
|
fprintf(stderr, "%d: [EH=%d CLD=%d WRM=%d NO_FT=%d %p] used: %d, depth: %d, preds: %d %s\n",
|
||||||
b->b_label.id, b->b_except_handler, b->b_cold, b->b_warm, BB_NO_FALLTHROUGH(b), b, b->b_iused,
|
b->b_label.id, b->b_except_handler, b->b_cold, b->b_warm, BB_NO_FALLTHROUGH(b), b, b->b_iused,
|
||||||
b->b_startdepth, b->b_predecessors, b_return);
|
b->b_startdepth, b->b_predecessors, b_return);
|
||||||
|
int depth = b->b_startdepth;
|
||||||
if (b->b_instr) {
|
if (b->b_instr) {
|
||||||
int i;
|
int i;
|
||||||
for (i = 0; i < b->b_iused; i++) {
|
for (i = 0; i < b->b_iused; i++) {
|
||||||
fprintf(stderr, " [%02d] ", i);
|
fprintf(stderr, " [%02d] depth: %d ", i, depth);
|
||||||
dump_instr(b->b_instr + i);
|
dump_instr(b->b_instr + i);
|
||||||
|
|
||||||
|
int popped = _PyOpcode_num_popped(b->b_instr[i].i_opcode, b->b_instr[i].i_oparg);
|
||||||
|
int pushed = _PyOpcode_num_pushed(b->b_instr[i].i_opcode, b->b_instr[i].i_oparg);
|
||||||
|
depth += (pushed - popped);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
_PyCfgBuilder_DumpGraph(const basicblock *entryblock)
|
_PyCfgBuilder_DumpGraph(const basicblock *entryblock, const basicblock *mark)
|
||||||
{
|
{
|
||||||
for (const basicblock *b = entryblock; b != NULL; b = b->b_next) {
|
for (const basicblock *b = entryblock; b != NULL; b = b->b_next) {
|
||||||
dump_basicblock(b);
|
dump_basicblock(b, b == mark);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2863,6 +2871,7 @@ optimize_load_fast(cfg_builder *g)
|
|||||||
|
|
||||||
// Opcodes that consume no inputs
|
// Opcodes that consume no inputs
|
||||||
case GET_ANEXT:
|
case GET_ANEXT:
|
||||||
|
case GET_ITER:
|
||||||
case GET_LEN:
|
case GET_LEN:
|
||||||
case IMPORT_FROM:
|
case IMPORT_FROM:
|
||||||
case MATCH_KEYS:
|
case MATCH_KEYS:
|
||||||
|
293
Python/generated_cases.c.h
generated
293
Python/generated_cases.c.h
generated
@ -5731,17 +5731,19 @@
|
|||||||
_Py_CODEUNIT* const this_instr = next_instr - 2;
|
_Py_CODEUNIT* const this_instr = next_instr - 2;
|
||||||
(void)this_instr;
|
(void)this_instr;
|
||||||
_PyStackRef iter;
|
_PyStackRef iter;
|
||||||
|
_PyStackRef null_or_index;
|
||||||
_PyStackRef next;
|
_PyStackRef next;
|
||||||
// _SPECIALIZE_FOR_ITER
|
// _SPECIALIZE_FOR_ITER
|
||||||
{
|
{
|
||||||
iter = stack_pointer[-1];
|
null_or_index = stack_pointer[-1];
|
||||||
|
iter = stack_pointer[-2];
|
||||||
uint16_t counter = read_u16(&this_instr[1].cache);
|
uint16_t counter = read_u16(&this_instr[1].cache);
|
||||||
(void)counter;
|
(void)counter;
|
||||||
#if ENABLE_SPECIALIZATION_FT
|
#if ENABLE_SPECIALIZATION_FT
|
||||||
if (ADAPTIVE_COUNTER_TRIGGERS(counter)) {
|
if (ADAPTIVE_COUNTER_TRIGGERS(counter)) {
|
||||||
next_instr = this_instr;
|
next_instr = this_instr;
|
||||||
_PyFrame_SetStackPointer(frame, stack_pointer);
|
_PyFrame_SetStackPointer(frame, stack_pointer);
|
||||||
_Py_Specialize_ForIter(iter, next_instr, oparg);
|
_Py_Specialize_ForIter(iter, null_or_index, next_instr, oparg);
|
||||||
stack_pointer = _PyFrame_GetStackPointer(frame);
|
stack_pointer = _PyFrame_GetStackPointer(frame);
|
||||||
DISPATCH_SAME_OPARG();
|
DISPATCH_SAME_OPARG();
|
||||||
}
|
}
|
||||||
@ -5752,29 +5754,44 @@
|
|||||||
// _FOR_ITER
|
// _FOR_ITER
|
||||||
{
|
{
|
||||||
PyObject *iter_o = PyStackRef_AsPyObjectBorrow(iter);
|
PyObject *iter_o = PyStackRef_AsPyObjectBorrow(iter);
|
||||||
_PyFrame_SetStackPointer(frame, stack_pointer);
|
if (PyStackRef_IsTaggedInt(null_or_index)) {
|
||||||
PyObject *next_o = (*Py_TYPE(iter_o)->tp_iternext)(iter_o);
|
_PyFrame_SetStackPointer(frame, stack_pointer);
|
||||||
stack_pointer = _PyFrame_GetStackPointer(frame);
|
next = _PyForIter_NextWithIndex(iter_o, null_or_index);
|
||||||
if (next_o == NULL) {
|
stack_pointer = _PyFrame_GetStackPointer(frame);
|
||||||
if (_PyErr_Occurred(tstate)) {
|
if (PyStackRef_IsNull(next)) {
|
||||||
_PyFrame_SetStackPointer(frame, stack_pointer);
|
null_or_index = PyStackRef_TagInt(-1);
|
||||||
int matches = _PyErr_ExceptionMatches(tstate, PyExc_StopIteration);
|
JUMPBY(oparg + 1);
|
||||||
stack_pointer = _PyFrame_GetStackPointer(frame);
|
stack_pointer[-1] = null_or_index;
|
||||||
if (!matches) {
|
DISPATCH();
|
||||||
JUMP_TO_LABEL(error);
|
|
||||||
}
|
|
||||||
_PyFrame_SetStackPointer(frame, stack_pointer);
|
|
||||||
_PyEval_MonitorRaise(tstate, frame, this_instr);
|
|
||||||
_PyErr_Clear(tstate);
|
|
||||||
stack_pointer = _PyFrame_GetStackPointer(frame);
|
|
||||||
}
|
}
|
||||||
assert(next_instr[oparg].op.code == END_FOR ||
|
null_or_index = PyStackRef_IncrementTaggedIntNoOverflow(null_or_index);
|
||||||
next_instr[oparg].op.code == INSTRUMENTED_END_FOR);
|
}
|
||||||
JUMPBY(oparg + 1);
|
else {
|
||||||
DISPATCH();
|
_PyFrame_SetStackPointer(frame, stack_pointer);
|
||||||
|
PyObject *next_o = (*Py_TYPE(iter_o)->tp_iternext)(iter_o);
|
||||||
|
stack_pointer = _PyFrame_GetStackPointer(frame);
|
||||||
|
if (next_o == NULL) {
|
||||||
|
if (_PyErr_Occurred(tstate)) {
|
||||||
|
_PyFrame_SetStackPointer(frame, stack_pointer);
|
||||||
|
int matches = _PyErr_ExceptionMatches(tstate, PyExc_StopIteration);
|
||||||
|
stack_pointer = _PyFrame_GetStackPointer(frame);
|
||||||
|
if (!matches) {
|
||||||
|
JUMP_TO_LABEL(error);
|
||||||
|
}
|
||||||
|
_PyFrame_SetStackPointer(frame, stack_pointer);
|
||||||
|
_PyEval_MonitorRaise(tstate, frame, this_instr);
|
||||||
|
_PyErr_Clear(tstate);
|
||||||
|
stack_pointer = _PyFrame_GetStackPointer(frame);
|
||||||
|
}
|
||||||
|
assert(next_instr[oparg].op.code == END_FOR ||
|
||||||
|
next_instr[oparg].op.code == INSTRUMENTED_END_FOR);
|
||||||
|
JUMPBY(oparg + 1);
|
||||||
|
DISPATCH();
|
||||||
|
}
|
||||||
|
next = PyStackRef_FromPyObjectSteal(next_o);
|
||||||
}
|
}
|
||||||
next = PyStackRef_FromPyObjectSteal(next_o);
|
|
||||||
}
|
}
|
||||||
|
stack_pointer[-1] = null_or_index;
|
||||||
stack_pointer[0] = next;
|
stack_pointer[0] = next;
|
||||||
stack_pointer += 1;
|
stack_pointer += 1;
|
||||||
assert(WITHIN_STACK_BOUNDS());
|
assert(WITHIN_STACK_BOUNDS());
|
||||||
@ -5806,7 +5823,7 @@
|
|||||||
}
|
}
|
||||||
// _FOR_ITER_GEN_FRAME
|
// _FOR_ITER_GEN_FRAME
|
||||||
{
|
{
|
||||||
iter = stack_pointer[-1];
|
iter = stack_pointer[-2];
|
||||||
PyGenObject *gen = (PyGenObject *)PyStackRef_AsPyObjectBorrow(iter);
|
PyGenObject *gen = (PyGenObject *)PyStackRef_AsPyObjectBorrow(iter);
|
||||||
if (Py_TYPE(gen) != &PyGen_Type) {
|
if (Py_TYPE(gen) != &PyGen_Type) {
|
||||||
UPDATE_MISS_STATS(FOR_ITER);
|
UPDATE_MISS_STATS(FOR_ITER);
|
||||||
@ -5863,26 +5880,22 @@
|
|||||||
INSTRUCTION_STATS(FOR_ITER_LIST);
|
INSTRUCTION_STATS(FOR_ITER_LIST);
|
||||||
static_assert(INLINE_CACHE_ENTRIES_FOR_ITER == 1, "incorrect cache size");
|
static_assert(INLINE_CACHE_ENTRIES_FOR_ITER == 1, "incorrect cache size");
|
||||||
_PyStackRef iter;
|
_PyStackRef iter;
|
||||||
|
_PyStackRef null_or_index;
|
||||||
_PyStackRef next;
|
_PyStackRef next;
|
||||||
/* Skip 1 cache entry */
|
/* Skip 1 cache entry */
|
||||||
// _ITER_CHECK_LIST
|
// _ITER_CHECK_LIST
|
||||||
{
|
{
|
||||||
iter = stack_pointer[-1];
|
null_or_index = stack_pointer[-1];
|
||||||
|
iter = stack_pointer[-2];
|
||||||
PyObject *iter_o = PyStackRef_AsPyObjectBorrow(iter);
|
PyObject *iter_o = PyStackRef_AsPyObjectBorrow(iter);
|
||||||
if (Py_TYPE(iter_o) != &PyListIter_Type) {
|
if (Py_TYPE(iter_o) != &PyList_Type) {
|
||||||
UPDATE_MISS_STATS(FOR_ITER);
|
UPDATE_MISS_STATS(FOR_ITER);
|
||||||
assert(_PyOpcode_Deopt[opcode] == (FOR_ITER));
|
assert(_PyOpcode_Deopt[opcode] == (FOR_ITER));
|
||||||
JUMP_TO_PREDICTED(FOR_ITER);
|
JUMP_TO_PREDICTED(FOR_ITER);
|
||||||
}
|
}
|
||||||
|
assert(PyStackRef_IsTaggedInt(null_or_index));
|
||||||
#ifdef Py_GIL_DISABLED
|
#ifdef Py_GIL_DISABLED
|
||||||
if (!_PyObject_IsUniquelyReferenced(iter_o)) {
|
if (!_Py_IsOwnedByCurrentThread(iter_o) && !_PyObject_GC_IS_SHARED(iter_o)) {
|
||||||
UPDATE_MISS_STATS(FOR_ITER);
|
|
||||||
assert(_PyOpcode_Deopt[opcode] == (FOR_ITER));
|
|
||||||
JUMP_TO_PREDICTED(FOR_ITER);
|
|
||||||
}
|
|
||||||
_PyListIterObject *it = (_PyListIterObject *)iter_o;
|
|
||||||
if (!_Py_IsOwnedByCurrentThread((PyObject *)it->it_seq) ||
|
|
||||||
!_PyObject_GC_IS_SHARED(it->it_seq)) {
|
|
||||||
UPDATE_MISS_STATS(FOR_ITER);
|
UPDATE_MISS_STATS(FOR_ITER);
|
||||||
assert(_PyOpcode_Deopt[opcode] == (FOR_ITER));
|
assert(_PyOpcode_Deopt[opcode] == (FOR_ITER));
|
||||||
JUMP_TO_PREDICTED(FOR_ITER);
|
JUMP_TO_PREDICTED(FOR_ITER);
|
||||||
@ -5891,42 +5904,30 @@
|
|||||||
}
|
}
|
||||||
// _ITER_JUMP_LIST
|
// _ITER_JUMP_LIST
|
||||||
{
|
{
|
||||||
PyObject *iter_o = PyStackRef_AsPyObjectBorrow(iter);
|
|
||||||
assert(Py_TYPE(iter_o) == &PyListIter_Type);
|
|
||||||
#ifdef Py_GIL_DISABLED
|
#ifdef Py_GIL_DISABLED
|
||||||
assert(_PyObject_IsUniquelyReferenced(iter_o));
|
|
||||||
(void)iter_o;
|
|
||||||
#else
|
#else
|
||||||
_PyListIterObject *it = (_PyListIterObject *)iter_o;
|
PyObject *list_o = PyStackRef_AsPyObjectBorrow(iter);
|
||||||
|
assert(Py_TYPE(list_o) == &PyList_Type);
|
||||||
STAT_INC(FOR_ITER, hit);
|
STAT_INC(FOR_ITER, hit);
|
||||||
PyListObject *seq = it->it_seq;
|
if ((size_t)PyStackRef_UntagInt(null_or_index) >= (size_t)PyList_GET_SIZE(list_o)) {
|
||||||
if (seq == NULL || (size_t)it->it_index >= (size_t)PyList_GET_SIZE(seq)) {
|
null_or_index = PyStackRef_TagInt(-1);
|
||||||
it->it_index = -1;
|
|
||||||
if (seq != NULL) {
|
|
||||||
it->it_seq = NULL;
|
|
||||||
_PyFrame_SetStackPointer(frame, stack_pointer);
|
|
||||||
Py_DECREF(seq);
|
|
||||||
stack_pointer = _PyFrame_GetStackPointer(frame);
|
|
||||||
}
|
|
||||||
JUMPBY(oparg + 1);
|
JUMPBY(oparg + 1);
|
||||||
|
stack_pointer[-1] = null_or_index;
|
||||||
DISPATCH();
|
DISPATCH();
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
// _ITER_NEXT_LIST
|
// _ITER_NEXT_LIST
|
||||||
{
|
{
|
||||||
PyObject *iter_o = PyStackRef_AsPyObjectBorrow(iter);
|
PyObject *list_o = PyStackRef_AsPyObjectBorrow(iter);
|
||||||
_PyListIterObject *it = (_PyListIterObject *)iter_o;
|
assert(PyList_CheckExact(list_o));
|
||||||
assert(Py_TYPE(iter_o) == &PyListIter_Type);
|
|
||||||
PyListObject *seq = it->it_seq;
|
|
||||||
assert(seq);
|
|
||||||
#ifdef Py_GIL_DISABLED
|
#ifdef Py_GIL_DISABLED
|
||||||
assert(_PyObject_IsUniquelyReferenced(iter_o));
|
assert(_Py_IsOwnedByCurrentThread(list_o) ||
|
||||||
assert(_Py_IsOwnedByCurrentThread((PyObject *)seq) ||
|
_PyObject_GC_IS_SHARED(list_o));
|
||||||
_PyObject_GC_IS_SHARED(seq));
|
|
||||||
STAT_INC(FOR_ITER, hit);
|
STAT_INC(FOR_ITER, hit);
|
||||||
_PyFrame_SetStackPointer(frame, stack_pointer);
|
_PyFrame_SetStackPointer(frame, stack_pointer);
|
||||||
int result = _PyList_GetItemRefNoLock(seq, it->it_index, &next);
|
int result = _PyList_GetItemRefNoLock((PyListObject *)list_o, PyStackRef_UntagInt(null_or_index), &next);
|
||||||
stack_pointer = _PyFrame_GetStackPointer(frame);
|
stack_pointer = _PyFrame_GetStackPointer(frame);
|
||||||
if (result < 0) {
|
if (result < 0) {
|
||||||
UPDATE_MISS_STATS(FOR_ITER);
|
UPDATE_MISS_STATS(FOR_ITER);
|
||||||
@ -5934,16 +5935,17 @@
|
|||||||
JUMP_TO_PREDICTED(FOR_ITER);
|
JUMP_TO_PREDICTED(FOR_ITER);
|
||||||
}
|
}
|
||||||
if (result == 0) {
|
if (result == 0) {
|
||||||
it->it_index = -1;
|
null_or_index = PyStackRef_TagInt(-1);
|
||||||
JUMPBY(oparg + 1);
|
JUMPBY(oparg + 1);
|
||||||
|
stack_pointer[-1] = null_or_index;
|
||||||
DISPATCH();
|
DISPATCH();
|
||||||
}
|
}
|
||||||
it->it_index++;
|
|
||||||
#else
|
#else
|
||||||
assert(it->it_index < PyList_GET_SIZE(seq));
|
next = PyStackRef_FromPyObjectNew(PyList_GET_ITEM(list_o, PyStackRef_UntagInt(null_or_index)));
|
||||||
next = PyStackRef_FromPyObjectNew(PyList_GET_ITEM(seq, it->it_index++));
|
|
||||||
#endif
|
#endif
|
||||||
|
null_or_index = PyStackRef_IncrementTaggedIntNoOverflow(null_or_index);
|
||||||
}
|
}
|
||||||
|
stack_pointer[-1] = null_or_index;
|
||||||
stack_pointer[0] = next;
|
stack_pointer[0] = next;
|
||||||
stack_pointer += 1;
|
stack_pointer += 1;
|
||||||
assert(WITHIN_STACK_BOUNDS());
|
assert(WITHIN_STACK_BOUNDS());
|
||||||
@ -5966,7 +5968,7 @@
|
|||||||
/* Skip 1 cache entry */
|
/* Skip 1 cache entry */
|
||||||
// _ITER_CHECK_RANGE
|
// _ITER_CHECK_RANGE
|
||||||
{
|
{
|
||||||
iter = stack_pointer[-1];
|
iter = stack_pointer[-2];
|
||||||
_PyRangeIterObject *r = (_PyRangeIterObject *)PyStackRef_AsPyObjectBorrow(iter);
|
_PyRangeIterObject *r = (_PyRangeIterObject *)PyStackRef_AsPyObjectBorrow(iter);
|
||||||
if (Py_TYPE(r) != &PyRangeIter_Type) {
|
if (Py_TYPE(r) != &PyRangeIter_Type) {
|
||||||
UPDATE_MISS_STATS(FOR_ITER);
|
UPDATE_MISS_STATS(FOR_ITER);
|
||||||
@ -6029,63 +6031,44 @@
|
|||||||
INSTRUCTION_STATS(FOR_ITER_TUPLE);
|
INSTRUCTION_STATS(FOR_ITER_TUPLE);
|
||||||
static_assert(INLINE_CACHE_ENTRIES_FOR_ITER == 1, "incorrect cache size");
|
static_assert(INLINE_CACHE_ENTRIES_FOR_ITER == 1, "incorrect cache size");
|
||||||
_PyStackRef iter;
|
_PyStackRef iter;
|
||||||
|
_PyStackRef null_or_index;
|
||||||
_PyStackRef next;
|
_PyStackRef next;
|
||||||
/* Skip 1 cache entry */
|
/* Skip 1 cache entry */
|
||||||
// _ITER_CHECK_TUPLE
|
// _ITER_CHECK_TUPLE
|
||||||
{
|
{
|
||||||
iter = stack_pointer[-1];
|
null_or_index = stack_pointer[-1];
|
||||||
|
iter = stack_pointer[-2];
|
||||||
PyObject *iter_o = PyStackRef_AsPyObjectBorrow(iter);
|
PyObject *iter_o = PyStackRef_AsPyObjectBorrow(iter);
|
||||||
if (Py_TYPE(iter_o) != &PyTupleIter_Type) {
|
if (Py_TYPE(iter_o) != &PyTuple_Type) {
|
||||||
UPDATE_MISS_STATS(FOR_ITER);
|
UPDATE_MISS_STATS(FOR_ITER);
|
||||||
assert(_PyOpcode_Deopt[opcode] == (FOR_ITER));
|
assert(_PyOpcode_Deopt[opcode] == (FOR_ITER));
|
||||||
JUMP_TO_PREDICTED(FOR_ITER);
|
JUMP_TO_PREDICTED(FOR_ITER);
|
||||||
}
|
}
|
||||||
#ifdef Py_GIL_DISABLED
|
assert(PyStackRef_IsTaggedInt(null_or_index));
|
||||||
if (!_PyObject_IsUniquelyReferenced(iter_o)) {
|
|
||||||
UPDATE_MISS_STATS(FOR_ITER);
|
|
||||||
assert(_PyOpcode_Deopt[opcode] == (FOR_ITER));
|
|
||||||
JUMP_TO_PREDICTED(FOR_ITER);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
// _ITER_JUMP_TUPLE
|
// _ITER_JUMP_TUPLE
|
||||||
{
|
{
|
||||||
PyObject *iter_o = PyStackRef_AsPyObjectBorrow(iter);
|
PyObject *tuple_o = PyStackRef_AsPyObjectBorrow(iter);
|
||||||
(void)iter_o;
|
(void)tuple_o;
|
||||||
assert(Py_TYPE(iter_o) == &PyTupleIter_Type);
|
assert(Py_TYPE(tuple_o) == &PyTuple_Type);
|
||||||
#ifdef Py_GIL_DISABLED
|
|
||||||
assert(_PyObject_IsUniquelyReferenced(iter_o));
|
|
||||||
#endif
|
|
||||||
_PyTupleIterObject *it = (_PyTupleIterObject *)iter_o;
|
|
||||||
STAT_INC(FOR_ITER, hit);
|
STAT_INC(FOR_ITER, hit);
|
||||||
PyTupleObject *seq = it->it_seq;
|
if ((size_t)PyStackRef_UntagInt(null_or_index) >= (size_t)PyTuple_GET_SIZE(tuple_o)) {
|
||||||
if (seq == NULL || (size_t)it->it_index >= (size_t)PyTuple_GET_SIZE(seq)) {
|
null_or_index = PyStackRef_TagInt(-1);
|
||||||
#ifndef Py_GIL_DISABLED
|
|
||||||
if (seq != NULL) {
|
|
||||||
it->it_seq = NULL;
|
|
||||||
_PyFrame_SetStackPointer(frame, stack_pointer);
|
|
||||||
Py_DECREF(seq);
|
|
||||||
stack_pointer = _PyFrame_GetStackPointer(frame);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
JUMPBY(oparg + 1);
|
JUMPBY(oparg + 1);
|
||||||
|
stack_pointer[-1] = null_or_index;
|
||||||
DISPATCH();
|
DISPATCH();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// _ITER_NEXT_TUPLE
|
// _ITER_NEXT_TUPLE
|
||||||
{
|
{
|
||||||
PyObject *iter_o = PyStackRef_AsPyObjectBorrow(iter);
|
PyObject *tuple_o = PyStackRef_AsPyObjectBorrow(iter);
|
||||||
_PyTupleIterObject *it = (_PyTupleIterObject *)iter_o;
|
assert(Py_TYPE(tuple_o) == &PyTuple_Type);
|
||||||
assert(Py_TYPE(iter_o) == &PyTupleIter_Type);
|
uintptr_t i = PyStackRef_UntagInt(null_or_index);
|
||||||
PyTupleObject *seq = it->it_seq;
|
assert((size_t)i < (size_t)PyTuple_GET_SIZE(tuple_o));
|
||||||
#ifdef Py_GIL_DISABLED
|
next = PyStackRef_FromPyObjectNew(PyTuple_GET_ITEM(tuple_o, i));
|
||||||
assert(_PyObject_IsUniquelyReferenced(iter_o));
|
null_or_index = PyStackRef_IncrementTaggedIntNoOverflow(null_or_index);
|
||||||
#endif
|
|
||||||
assert(seq);
|
|
||||||
assert(it->it_index < PyTuple_GET_SIZE(seq));
|
|
||||||
next = PyStackRef_FromPyObjectNew(PyTuple_GET_ITEM(seq, it->it_index++));
|
|
||||||
}
|
}
|
||||||
|
stack_pointer[-1] = null_or_index;
|
||||||
stack_pointer[0] = next;
|
stack_pointer[0] = next;
|
||||||
stack_pointer += 1;
|
stack_pointer += 1;
|
||||||
assert(WITHIN_STACK_BOUNDS());
|
assert(WITHIN_STACK_BOUNDS());
|
||||||
@ -6216,25 +6199,37 @@
|
|||||||
INSTRUCTION_STATS(GET_ITER);
|
INSTRUCTION_STATS(GET_ITER);
|
||||||
_PyStackRef iterable;
|
_PyStackRef iterable;
|
||||||
_PyStackRef iter;
|
_PyStackRef iter;
|
||||||
|
_PyStackRef index_or_null;
|
||||||
iterable = stack_pointer[-1];
|
iterable = stack_pointer[-1];
|
||||||
#ifdef Py_STATS
|
#ifdef Py_STATS
|
||||||
_PyFrame_SetStackPointer(frame, stack_pointer);
|
_PyFrame_SetStackPointer(frame, stack_pointer);
|
||||||
_Py_GatherStats_GetIter(iterable);
|
_Py_GatherStats_GetIter(iterable);
|
||||||
stack_pointer = _PyFrame_GetStackPointer(frame);
|
stack_pointer = _PyFrame_GetStackPointer(frame);
|
||||||
#endif
|
#endif
|
||||||
_PyFrame_SetStackPointer(frame, stack_pointer);
|
|
||||||
PyObject *iter_o = PyObject_GetIter(PyStackRef_AsPyObjectBorrow(iterable));
|
PyTypeObject *tp = PyStackRef_TYPE(iterable);
|
||||||
stack_pointer = _PyFrame_GetStackPointer(frame);
|
if (tp == &PyTuple_Type || tp == &PyList_Type) {
|
||||||
stack_pointer += -1;
|
iter = iterable;
|
||||||
assert(WITHIN_STACK_BOUNDS());
|
index_or_null = PyStackRef_TagInt(0);
|
||||||
_PyFrame_SetStackPointer(frame, stack_pointer);
|
|
||||||
PyStackRef_CLOSE(iterable);
|
|
||||||
stack_pointer = _PyFrame_GetStackPointer(frame);
|
|
||||||
if (iter_o == NULL) {
|
|
||||||
JUMP_TO_LABEL(error);
|
|
||||||
}
|
}
|
||||||
iter = PyStackRef_FromPyObjectSteal(iter_o);
|
else {
|
||||||
stack_pointer[0] = iter;
|
_PyFrame_SetStackPointer(frame, stack_pointer);
|
||||||
|
PyObject *iter_o = PyObject_GetIter(PyStackRef_AsPyObjectBorrow(iterable));
|
||||||
|
stack_pointer = _PyFrame_GetStackPointer(frame);
|
||||||
|
stack_pointer += -1;
|
||||||
|
assert(WITHIN_STACK_BOUNDS());
|
||||||
|
_PyFrame_SetStackPointer(frame, stack_pointer);
|
||||||
|
PyStackRef_CLOSE(iterable);
|
||||||
|
stack_pointer = _PyFrame_GetStackPointer(frame);
|
||||||
|
if (iter_o == NULL) {
|
||||||
|
JUMP_TO_LABEL(error);
|
||||||
|
}
|
||||||
|
iter = PyStackRef_FromPyObjectSteal(iter_o);
|
||||||
|
index_or_null = PyStackRef_NULL;
|
||||||
|
stack_pointer += 1;
|
||||||
|
}
|
||||||
|
stack_pointer[-1] = iter;
|
||||||
|
stack_pointer[0] = index_or_null;
|
||||||
stack_pointer += 1;
|
stack_pointer += 1;
|
||||||
assert(WITHIN_STACK_BOUNDS());
|
assert(WITHIN_STACK_BOUNDS());
|
||||||
DISPATCH();
|
DISPATCH();
|
||||||
@ -6999,7 +6994,7 @@
|
|||||||
_PyStackRef receiver;
|
_PyStackRef receiver;
|
||||||
_PyStackRef value;
|
_PyStackRef value;
|
||||||
value = stack_pointer[-1];
|
value = stack_pointer[-1];
|
||||||
receiver = stack_pointer[-2];
|
receiver = stack_pointer[-3];
|
||||||
if (PyStackRef_GenCheck(receiver)) {
|
if (PyStackRef_GenCheck(receiver)) {
|
||||||
_PyFrame_SetStackPointer(frame, stack_pointer);
|
_PyFrame_SetStackPointer(frame, stack_pointer);
|
||||||
int err = monitor_stop_iteration(tstate, frame, this_instr, PyStackRef_AsPyObjectBorrow(value));
|
int err = monitor_stop_iteration(tstate, frame, this_instr, PyStackRef_AsPyObjectBorrow(value));
|
||||||
@ -7061,34 +7056,48 @@
|
|||||||
next_instr += 2;
|
next_instr += 2;
|
||||||
INSTRUCTION_STATS(INSTRUMENTED_FOR_ITER);
|
INSTRUCTION_STATS(INSTRUMENTED_FOR_ITER);
|
||||||
_PyStackRef iter;
|
_PyStackRef iter;
|
||||||
|
_PyStackRef null_or_index;
|
||||||
_PyStackRef next;
|
_PyStackRef next;
|
||||||
/* Skip 1 cache entry */
|
/* Skip 1 cache entry */
|
||||||
iter = stack_pointer[-1];
|
null_or_index = stack_pointer[-1];
|
||||||
|
iter = stack_pointer[-2];
|
||||||
PyObject *iter_o = PyStackRef_AsPyObjectBorrow(iter);
|
PyObject *iter_o = PyStackRef_AsPyObjectBorrow(iter);
|
||||||
_PyFrame_SetStackPointer(frame, stack_pointer);
|
if (PyStackRef_IsTaggedInt(null_or_index)) {
|
||||||
PyObject *next_o = (*Py_TYPE(iter_o)->tp_iternext)(iter_o);
|
_PyFrame_SetStackPointer(frame, stack_pointer);
|
||||||
stack_pointer = _PyFrame_GetStackPointer(frame);
|
next = _PyForIter_NextWithIndex(iter_o, null_or_index);
|
||||||
if (next_o != NULL) {
|
stack_pointer = _PyFrame_GetStackPointer(frame);
|
||||||
next = PyStackRef_FromPyObjectSteal(next_o);
|
if (PyStackRef_IsNull(next)) {
|
||||||
|
JUMPBY(oparg + 1);
|
||||||
|
DISPATCH();
|
||||||
|
}
|
||||||
INSTRUMENTED_JUMP(this_instr, next_instr, PY_MONITORING_EVENT_BRANCH_LEFT);
|
INSTRUMENTED_JUMP(this_instr, next_instr, PY_MONITORING_EVENT_BRANCH_LEFT);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (_PyErr_Occurred(tstate)) {
|
_PyFrame_SetStackPointer(frame, stack_pointer);
|
||||||
_PyFrame_SetStackPointer(frame, stack_pointer);
|
PyObject *next_o = (*Py_TYPE(iter_o)->tp_iternext)(iter_o);
|
||||||
int matches = _PyErr_ExceptionMatches(tstate, PyExc_StopIteration);
|
stack_pointer = _PyFrame_GetStackPointer(frame);
|
||||||
stack_pointer = _PyFrame_GetStackPointer(frame);
|
if (next_o != NULL) {
|
||||||
if (!matches) {
|
next = PyStackRef_FromPyObjectSteal(next_o);
|
||||||
JUMP_TO_LABEL(error);
|
INSTRUMENTED_JUMP(this_instr, next_instr, PY_MONITORING_EVENT_BRANCH_LEFT);
|
||||||
}
|
}
|
||||||
_PyFrame_SetStackPointer(frame, stack_pointer);
|
else {
|
||||||
_PyEval_MonitorRaise(tstate, frame, this_instr);
|
if (_PyErr_Occurred(tstate)) {
|
||||||
_PyErr_Clear(tstate);
|
_PyFrame_SetStackPointer(frame, stack_pointer);
|
||||||
stack_pointer = _PyFrame_GetStackPointer(frame);
|
int matches = _PyErr_ExceptionMatches(tstate, PyExc_StopIteration);
|
||||||
|
stack_pointer = _PyFrame_GetStackPointer(frame);
|
||||||
|
if (!matches) {
|
||||||
|
JUMP_TO_LABEL(error);
|
||||||
|
}
|
||||||
|
_PyFrame_SetStackPointer(frame, stack_pointer);
|
||||||
|
_PyEval_MonitorRaise(tstate, frame, this_instr);
|
||||||
|
_PyErr_Clear(tstate);
|
||||||
|
stack_pointer = _PyFrame_GetStackPointer(frame);
|
||||||
|
}
|
||||||
|
assert(next_instr[oparg].op.code == END_FOR ||
|
||||||
|
next_instr[oparg].op.code == INSTRUMENTED_END_FOR);
|
||||||
|
JUMPBY(oparg + 1);
|
||||||
|
DISPATCH();
|
||||||
}
|
}
|
||||||
assert(next_instr[oparg].op.code == END_FOR ||
|
|
||||||
next_instr[oparg].op.code == INSTRUMENTED_END_FOR);
|
|
||||||
JUMPBY(oparg + 1);
|
|
||||||
DISPATCH();
|
|
||||||
}
|
}
|
||||||
stack_pointer[0] = next;
|
stack_pointer[0] = next;
|
||||||
stack_pointer += 1;
|
stack_pointer += 1;
|
||||||
@ -7356,9 +7365,12 @@
|
|||||||
next_instr += 1;
|
next_instr += 1;
|
||||||
INSTRUCTION_STATS(INSTRUMENTED_POP_ITER);
|
INSTRUCTION_STATS(INSTRUMENTED_POP_ITER);
|
||||||
_PyStackRef iter;
|
_PyStackRef iter;
|
||||||
iter = stack_pointer[-1];
|
_PyStackRef index_or_null;
|
||||||
|
index_or_null = stack_pointer[-1];
|
||||||
|
iter = stack_pointer[-2];
|
||||||
|
(void)index_or_null;
|
||||||
INSTRUMENTED_JUMP(prev_instr, this_instr+1, PY_MONITORING_EVENT_BRANCH_RIGHT);
|
INSTRUMENTED_JUMP(prev_instr, this_instr+1, PY_MONITORING_EVENT_BRANCH_RIGHT);
|
||||||
stack_pointer += -1;
|
stack_pointer += -2;
|
||||||
assert(WITHIN_STACK_BOUNDS());
|
assert(WITHIN_STACK_BOUNDS());
|
||||||
_PyFrame_SetStackPointer(frame, stack_pointer);
|
_PyFrame_SetStackPointer(frame, stack_pointer);
|
||||||
PyStackRef_CLOSE(iter);
|
PyStackRef_CLOSE(iter);
|
||||||
@ -10122,12 +10134,15 @@
|
|||||||
frame->instr_ptr = next_instr;
|
frame->instr_ptr = next_instr;
|
||||||
next_instr += 1;
|
next_instr += 1;
|
||||||
INSTRUCTION_STATS(POP_ITER);
|
INSTRUCTION_STATS(POP_ITER);
|
||||||
_PyStackRef value;
|
_PyStackRef iter;
|
||||||
value = stack_pointer[-1];
|
_PyStackRef index_or_null;
|
||||||
stack_pointer += -1;
|
index_or_null = stack_pointer[-1];
|
||||||
|
iter = stack_pointer[-2];
|
||||||
|
(void)index_or_null;
|
||||||
|
stack_pointer += -2;
|
||||||
assert(WITHIN_STACK_BOUNDS());
|
assert(WITHIN_STACK_BOUNDS());
|
||||||
_PyFrame_SetStackPointer(frame, stack_pointer);
|
_PyFrame_SetStackPointer(frame, stack_pointer);
|
||||||
PyStackRef_CLOSE(value);
|
PyStackRef_CLOSE(iter);
|
||||||
stack_pointer = _PyFrame_GetStackPointer(frame);
|
stack_pointer = _PyFrame_GetStackPointer(frame);
|
||||||
DISPATCH();
|
DISPATCH();
|
||||||
}
|
}
|
||||||
@ -10275,7 +10290,7 @@
|
|||||||
stack_pointer += -1;
|
stack_pointer += -1;
|
||||||
assert(WITHIN_STACK_BOUNDS());
|
assert(WITHIN_STACK_BOUNDS());
|
||||||
_PyFrame_SetStackPointer(frame, stack_pointer);
|
_PyFrame_SetStackPointer(frame, stack_pointer);
|
||||||
PyStackRef_CLOSE(value);
|
PyStackRef_XCLOSE(value);
|
||||||
stack_pointer = _PyFrame_GetStackPointer(frame);
|
stack_pointer = _PyFrame_GetStackPointer(frame);
|
||||||
DISPATCH();
|
DISPATCH();
|
||||||
}
|
}
|
||||||
|
@ -840,7 +840,7 @@ dummy_func(void) {
|
|||||||
value = sym_new_unknown(ctx);
|
value = sym_new_unknown(ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
op(_FOR_ITER_GEN_FRAME, (unused -- unused, gen_frame: _Py_UOpsAbstractFrame*)) {
|
op(_FOR_ITER_GEN_FRAME, (unused, unused -- unused, unused, gen_frame: _Py_UOpsAbstractFrame*)) {
|
||||||
gen_frame = NULL;
|
gen_frame = NULL;
|
||||||
/* We are about to hit the end of the trace */
|
/* We are about to hit the end of the trace */
|
||||||
ctx->done = true;
|
ctx->done = true;
|
||||||
@ -914,7 +914,7 @@ dummy_func(void) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
op(_ITER_NEXT_RANGE, (iter -- iter, next)) {
|
op(_ITER_NEXT_RANGE, (iter, null_or_index -- iter, null_or_index, next)) {
|
||||||
next = sym_new_type(ctx, &PyLong_Type);
|
next = sym_new_type(ctx, &PyLong_Type);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
11
Python/optimizer_cases.c.h
generated
11
Python/optimizer_cases.c.h
generated
@ -126,6 +126,12 @@
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case _POP_ITER: {
|
||||||
|
stack_pointer += -2;
|
||||||
|
assert(WITHIN_STACK_BOUNDS());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
case _END_SEND: {
|
case _END_SEND: {
|
||||||
JitOptSymbol *val;
|
JitOptSymbol *val;
|
||||||
val = sym_new_not_null(ctx);
|
val = sym_new_not_null(ctx);
|
||||||
@ -1557,8 +1563,13 @@
|
|||||||
|
|
||||||
case _GET_ITER: {
|
case _GET_ITER: {
|
||||||
JitOptSymbol *iter;
|
JitOptSymbol *iter;
|
||||||
|
JitOptSymbol *index_or_null;
|
||||||
iter = sym_new_not_null(ctx);
|
iter = sym_new_not_null(ctx);
|
||||||
|
index_or_null = sym_new_not_null(ctx);
|
||||||
stack_pointer[-1] = iter;
|
stack_pointer[-1] = iter;
|
||||||
|
stack_pointer[0] = index_or_null;
|
||||||
|
stack_pointer += 1;
|
||||||
|
assert(WITHIN_STACK_BOUNDS());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2904,53 +2904,57 @@ int
|
|||||||
#endif // Py_STATS
|
#endif // Py_STATS
|
||||||
|
|
||||||
Py_NO_INLINE void
|
Py_NO_INLINE void
|
||||||
_Py_Specialize_ForIter(_PyStackRef iter, _Py_CODEUNIT *instr, int oparg)
|
_Py_Specialize_ForIter(_PyStackRef iter, _PyStackRef null_or_index, _Py_CODEUNIT *instr, int oparg)
|
||||||
{
|
{
|
||||||
assert(ENABLE_SPECIALIZATION_FT);
|
assert(ENABLE_SPECIALIZATION_FT);
|
||||||
assert(_PyOpcode_Caches[FOR_ITER] == INLINE_CACHE_ENTRIES_FOR_ITER);
|
assert(_PyOpcode_Caches[FOR_ITER] == INLINE_CACHE_ENTRIES_FOR_ITER);
|
||||||
PyObject *iter_o = PyStackRef_AsPyObjectBorrow(iter);
|
PyObject *iter_o = PyStackRef_AsPyObjectBorrow(iter);
|
||||||
PyTypeObject *tp = Py_TYPE(iter_o);
|
PyTypeObject *tp = Py_TYPE(iter_o);
|
||||||
|
|
||||||
|
if (PyStackRef_IsNull(null_or_index)) {
|
||||||
#ifdef Py_GIL_DISABLED
|
#ifdef Py_GIL_DISABLED
|
||||||
// Only specialize for uniquely referenced iterators, so that we know
|
// Only specialize for uniquely referenced iterators, so that we know
|
||||||
// they're only referenced by this one thread. This is more limiting
|
// they're only referenced by this one thread. This is more limiting
|
||||||
// than we need (even `it = iter(mylist); for item in it:` won't get
|
// than we need (even `it = iter(mylist); for item in it:` won't get
|
||||||
// specialized) but we don't have a way to check whether we're the only
|
// specialized) but we don't have a way to check whether we're the only
|
||||||
// _thread_ who has access to the object.
|
// _thread_ who has access to the object.
|
||||||
if (!_PyObject_IsUniquelyReferenced(iter_o))
|
if (!_PyObject_IsUniquelyReferenced(iter_o)) {
|
||||||
goto failure;
|
|
||||||
#endif
|
|
||||||
if (tp == &PyListIter_Type) {
|
|
||||||
#ifdef Py_GIL_DISABLED
|
|
||||||
_PyListIterObject *it = (_PyListIterObject *)iter_o;
|
|
||||||
if (!_Py_IsOwnedByCurrentThread((PyObject *)it->it_seq) &&
|
|
||||||
!_PyObject_GC_IS_SHARED(it->it_seq)) {
|
|
||||||
// Maybe this should just set GC_IS_SHARED in a critical
|
|
||||||
// section, instead of leaving it to the first iteration?
|
|
||||||
goto failure;
|
goto failure;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
specialize(instr, FOR_ITER_LIST);
|
if (tp == &PyRangeIter_Type) {
|
||||||
return;
|
specialize(instr, FOR_ITER_RANGE);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else if (tp == &PyGen_Type && oparg <= SHRT_MAX) {
|
||||||
|
// Generators are very much not thread-safe, so don't worry about
|
||||||
|
// the specialization not being thread-safe.
|
||||||
|
assert(instr[oparg + INLINE_CACHE_ENTRIES_FOR_ITER + 1].op.code == END_FOR ||
|
||||||
|
instr[oparg + INLINE_CACHE_ENTRIES_FOR_ITER + 1].op.code == INSTRUMENTED_END_FOR
|
||||||
|
);
|
||||||
|
/* Don't specialize if PEP 523 is active */
|
||||||
|
if (_PyInterpreterState_GET()->eval_frame) {
|
||||||
|
goto failure;
|
||||||
|
}
|
||||||
|
specialize(instr, FOR_ITER_GEN);
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if (tp == &PyTupleIter_Type) {
|
else {
|
||||||
specialize(instr, FOR_ITER_TUPLE);
|
if (tp == &PyList_Type) {
|
||||||
return;
|
#ifdef Py_GIL_DISABLED
|
||||||
}
|
// Only specialize for lists owned by this thread or shared
|
||||||
else if (tp == &PyRangeIter_Type) {
|
if (!_Py_IsOwnedByCurrentThread(iter_o) && !_PyObject_GC_IS_SHARED(iter_o)) {
|
||||||
specialize(instr, FOR_ITER_RANGE);
|
goto failure;
|
||||||
return;
|
}
|
||||||
}
|
#endif
|
||||||
else if (tp == &PyGen_Type && oparg <= SHRT_MAX) {
|
specialize(instr, FOR_ITER_LIST);
|
||||||
// Generators are very much not thread-safe, so don't worry about
|
return;
|
||||||
// the specialization not being thread-safe.
|
}
|
||||||
assert(instr[oparg + INLINE_CACHE_ENTRIES_FOR_ITER + 1].op.code == END_FOR ||
|
else if (tp == &PyTuple_Type) {
|
||||||
instr[oparg + INLINE_CACHE_ENTRIES_FOR_ITER + 1].op.code == INSTRUMENTED_END_FOR
|
specialize(instr, FOR_ITER_TUPLE);
|
||||||
);
|
return;
|
||||||
/* Don't specialize if PEP 523 is active */
|
}
|
||||||
if (_PyInterpreterState_GET()->eval_frame)
|
|
||||||
goto failure;
|
|
||||||
specialize(instr, FOR_ITER_GEN);
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
failure:
|
failure:
|
||||||
SPECIALIZATION_FAIL(FOR_ITER,
|
SPECIALIZATION_FAIL(FOR_ITER,
|
||||||
|
@ -216,4 +216,12 @@ PyStackRef_IsNullOrInt(_PyStackRef ref)
|
|||||||
return PyStackRef_IsNull(ref) || PyStackRef_IsTaggedInt(ref);
|
return PyStackRef_IsNull(ref) || PyStackRef_IsTaggedInt(ref);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_PyStackRef
|
||||||
|
PyStackRef_IncrementTaggedIntNoOverflow(_PyStackRef ref)
|
||||||
|
{
|
||||||
|
assert(ref.index <= INT_MAX - 2); // No overflow
|
||||||
|
return (_PyStackRef){ .index = ref.index + 2 };
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -679,8 +679,11 @@ NON_ESCAPING_FUNCTIONS = (
|
|||||||
"PyStackRef_IsTaggedInt",
|
"PyStackRef_IsTaggedInt",
|
||||||
"PyStackRef_TagInt",
|
"PyStackRef_TagInt",
|
||||||
"PyStackRef_UntagInt",
|
"PyStackRef_UntagInt",
|
||||||
|
"PyStackRef_IncrementTaggedIntNoOverflow",
|
||||||
|
"PyStackRef_IsNullOrInt",
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def check_escaping_calls(instr: parser.CodeDef, escapes: dict[SimpleStmt, EscapingCall]) -> None:
|
def check_escaping_calls(instr: parser.CodeDef, escapes: dict[SimpleStmt, EscapingCall]) -> None:
|
||||||
error: lexer.Token | None = None
|
error: lexer.Token | None = None
|
||||||
calls = {e.call for e in escapes.values()}
|
calls = {e.call for e in escapes.values()}
|
||||||
|
@ -140,6 +140,7 @@ class Emitter:
|
|||||||
) -> bool:
|
) -> bool:
|
||||||
if storage.spilled:
|
if storage.spilled:
|
||||||
raise analysis_error("stack_pointer needs reloading before dispatch", tkn)
|
raise analysis_error("stack_pointer needs reloading before dispatch", tkn)
|
||||||
|
storage.stack.flush(self.out)
|
||||||
self.emit(tkn)
|
self.emit(tkn)
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user