diff options
author | Guido van Rossum <guido@python.org> | 2023-06-27 02:02:57 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-06-27 02:02:57 (GMT) |
commit | 51fc72511733353de15bc633a3d7b6da366842e4 (patch) | |
tree | 13c7075d57530adf90f82ba0025649f163b51abb | |
parent | d3af83b9342457d8b24476baeb799f7506ff04f3 (diff) | |
download | cpython-51fc72511733353de15bc633a3d7b6da366842e4.zip cpython-51fc72511733353de15bc633a3d7b6da366842e4.tar.gz cpython-51fc72511733353de15bc633a3d7b6da366842e4.tar.bz2 |
gh-104584: Baby steps towards generating and executing traces (#105924)
Added a new, experimental, tracing optimizer and interpreter (a.k.a. "tier 2"). This currently pessimizes, so don't use yet -- this is infrastructure so we can experiment with optimizing passes. To enable it, pass ``-Xuops`` or set ``PYTHONUOPS=1``. To get debug output, set ``PYTHONUOPSDEBUG=N`` where ``N`` is a debug level (0-4, where 0 is no debug output and 4 is excessively verbose).
All of this code is likely to change dramatically before the 3.13 feature freeze. But this is a first step.
-rw-r--r-- | .gitattributes | 1 | ||||
-rw-r--r-- | Include/cpython/optimizer.h | 1 | ||||
-rw-r--r-- | Include/internal/pycore_uops.h | 31 | ||||
-rw-r--r-- | Include/pystats.h | 3 | ||||
-rw-r--r-- | Makefile.pre.in | 21 | ||||
-rw-r--r-- | Misc/NEWS.d/next/Core and Builtins/2023-06-27-00-58-26.gh-issue-104584.Wu-uXy.rst | 1 | ||||
-rw-r--r-- | Modules/_testinternalcapi.c | 7 | ||||
-rw-r--r-- | Python/bytecodes.c | 4 | ||||
-rw-r--r-- | Python/ceval.c | 137 | ||||
-rw-r--r-- | Python/ceval_macros.h | 10 | ||||
-rw-r--r-- | Python/executor_cases.c.h | 1606 | ||||
-rw-r--r-- | Python/generated_cases.c.h | 518 | ||||
-rw-r--r-- | Python/opcode_metadata.h | 106 | ||||
-rw-r--r-- | Python/optimizer.c | 199 | ||||
-rw-r--r-- | Python/pylifecycle.c | 13 | ||||
-rw-r--r-- | Python/specialize.c | 4 | ||||
-rw-r--r-- | Tools/c-analyzer/cpython/_parser.py | 1 | ||||
-rw-r--r-- | Tools/c-analyzer/cpython/ignored.tsv | 2 | ||||
-rw-r--r-- | Tools/cases_generator/README.md | 2 | ||||
-rw-r--r-- | Tools/cases_generator/generate_cases.py | 187 | ||||
-rw-r--r-- | Tools/cases_generator/test_generator.py | 10 |
21 files changed, 2559 insertions, 305 deletions
diff --git a/.gitattributes b/.gitattributes index bab1ef0..a2ff14c 100644 --- a/.gitattributes +++ b/.gitattributes @@ -86,6 +86,7 @@ Parser/token.c generated Programs/test_frozenmain.h generated Python/Python-ast.c generated Python/generated_cases.c.h generated +Python/executor_cases.c.h generated Python/opcode_targets.h generated Python/stdlib_module_names.h generated Tools/peg_generator/pegen/grammar_parser.py generated diff --git a/Include/cpython/optimizer.h b/Include/cpython/optimizer.h index b2d173f..2664f5b 100644 --- a/Include/cpython/optimizer.h +++ b/Include/cpython/optimizer.h @@ -45,6 +45,7 @@ extern _PyOptimizerObject _PyOptimizer_Default; /* For testing */ PyAPI_FUNC(PyObject *)PyUnstable_Optimizer_NewCounter(void); +PyAPI_FUNC(PyObject *)PyUnstable_Optimizer_NewUOpOptimizer(void); #define OPTIMIZER_BITS_IN_COUNTER 4 diff --git a/Include/internal/pycore_uops.h b/Include/internal/pycore_uops.h new file mode 100644 index 0000000..0e88d7e --- /dev/null +++ b/Include/internal/pycore_uops.h @@ -0,0 +1,31 @@ +#ifndef Py_INTERNAL_UOPS_H +#define Py_INTERNAL_UOPS_H +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef Py_BUILD_CORE +# error "this header requires Py_BUILD_CORE define" +#endif + +#define _Py_UOP_MAX_TRACE_LENGTH 16 + +typedef struct { + int opcode; + uint64_t operand; // Sometimes oparg, sometimes a cache entry +} _PyUOpInstruction; + +typedef struct { + _PyExecutorObject base; + _PyUOpInstruction trace[_Py_UOP_MAX_TRACE_LENGTH]; // TODO: variable length +} _PyUOpExecutorObject; + +_PyInterpreterFrame *_PyUopExecute( + _PyExecutorObject *executor, + _PyInterpreterFrame *frame, + PyObject **stack_pointer); + +#ifdef __cplusplus +} +#endif +#endif /* !Py_INTERNAL_UOPS_H */ diff --git a/Include/pystats.h b/Include/pystats.h index 034bf05..54c9b8d 100644 --- a/Include/pystats.h +++ b/Include/pystats.h @@ -71,6 +71,9 @@ typedef struct _object_stats { uint64_t type_cache_dunder_misses; uint64_t type_cache_collisions; uint64_t optimization_attempts; + uint64_t optimization_traces_created; + uint64_t optimization_traces_executed; + uint64_t optimization_uops_executed; } ObjectStats; typedef struct _stats { diff --git a/Makefile.pre.in b/Makefile.pre.in index e9a8d8f..98b58cf 100644 --- a/Makefile.pre.in +++ b/Makefile.pre.in @@ -1542,19 +1542,9 @@ regen-opcode-targets: .PHONY: regen-cases regen-cases: - # Regenerate Python/generated_cases.c.h - # and Python/opcode_metadata.h - # from Python/bytecodes.c - # using Tools/cases_generator/generate_cases.py + # Regenerate various files from Python/bytecodes.c PYTHONPATH=$(srcdir)/Tools/cases_generator \ - $(PYTHON_FOR_REGEN) \ - $(srcdir)/Tools/cases_generator/generate_cases.py \ - --emit-line-directives \ - -o $(srcdir)/Python/generated_cases.c.h.new \ - -m $(srcdir)/Python/opcode_metadata.h.new \ - $(srcdir)/Python/bytecodes.c - $(UPDATE_FILE) $(srcdir)/Python/generated_cases.c.h $(srcdir)/Python/generated_cases.c.h.new - $(UPDATE_FILE) $(srcdir)/Python/opcode_metadata.h $(srcdir)/Python/opcode_metadata.h.new + $(PYTHON_FOR_REGEN) $(srcdir)/Tools/cases_generator/generate_cases.py -l Python/compile.o: $(srcdir)/Python/opcode_metadata.h @@ -1565,6 +1555,13 @@ Python/ceval.o: \ $(srcdir)/Python/opcode_metadata.h \ $(srcdir)/Python/opcode_targets.h +Python/flowgraph.o: \ + $(srcdir)/Python/opcode_metadata.h + +Python/optimizer.o: \ + $(srcdir)/Python/executor_cases.c.h \ + $(srcdir)/Python/opcode_metadata.h + Python/frozen.o: $(FROZEN_FILES_OUT) # Generate DTrace probe macros, then rename them (PYTHON_ -> PyDTrace_) to diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-06-27-00-58-26.gh-issue-104584.Wu-uXy.rst b/Misc/NEWS.d/next/Core and Builtins/2023-06-27-00-58-26.gh-issue-104584.Wu-uXy.rst new file mode 100644 index 0000000..a364901 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2023-06-27-00-58-26.gh-issue-104584.Wu-uXy.rst @@ -0,0 +1 @@ +Added a new, experimental, tracing optimizer and interpreter (a.k.a. "tier 2"). This currently pessimizes, so don't use yet -- this is infrastructure so we can experiment with optimizing passes. To enable it, pass ``-Xuops`` or set ``PYTHONUOPS=1``. To get debug output, set ``PYTHONUOPSDEBUG=N`` where ``N`` is a debug level (0-4, where 0 is no debug output and 4 is excessively verbose). diff --git a/Modules/_testinternalcapi.c b/Modules/_testinternalcapi.c index 0a3b0dd..3c0c2ad 100644 --- a/Modules/_testinternalcapi.c +++ b/Modules/_testinternalcapi.c @@ -831,6 +831,12 @@ get_counter_optimizer(PyObject *self, PyObject *arg) } static PyObject * +get_uop_optimizer(PyObject *self, PyObject *arg) +{ + return PyUnstable_Optimizer_NewUOpOptimizer(); +} + +static PyObject * set_optimizer(PyObject *self, PyObject *opt) { if (opt == Py_None) { @@ -994,6 +1000,7 @@ static PyMethodDef module_functions[] = { {"get_optimizer", get_optimizer, METH_NOARGS, NULL}, {"set_optimizer", set_optimizer, METH_O, NULL}, {"get_counter_optimizer", get_counter_optimizer, METH_NOARGS, NULL}, + {"get_uop_optimizer", get_uop_optimizer, METH_NOARGS, NULL}, {"pending_threadfunc", _PyCFunction_CAST(pending_threadfunc), METH_VARARGS | METH_KEYWORDS}, // {"pending_fd_identify", pending_fd_identify, METH_VARARGS, NULL}, diff --git a/Python/bytecodes.c b/Python/bytecodes.c index 3ef8ed0..0285710 100644 --- a/Python/bytecodes.c +++ b/Python/bytecodes.c @@ -52,8 +52,6 @@ #define family(name, ...) static int family_##name #define pseudo(name) static int pseudo_##name -typedef PyObject *(*convertion_func_ptr)(PyObject *); - // Dummy variables for stack effects. static PyObject *value, *value1, *value2, *left, *right, *res, *sum, *prod, *sub; static PyObject *container, *start, *stop, *v, *lhs, *rhs, *res2; @@ -2182,7 +2180,7 @@ dummy_func( frame = executor->execute(executor, frame, stack_pointer); if (frame == NULL) { frame = cframe.current_frame; - goto error; + goto resume_with_error; } goto resume_frame; } diff --git a/Python/ceval.c b/Python/ceval.c index 5310701..3e0dcf8 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -22,6 +22,7 @@ #include "pycore_sysmodule.h" // _PySys_Audit() #include "pycore_tuple.h" // _PyTuple_ITEMS() #include "pycore_typeobject.h" // _PySuper_Lookup() +#include "pycore_uops.h" // _PyUOpExecutorObject #include "pycore_emscripten_signal.h" // _Py_CHECK_EMSCRIPTEN_SIGNALS #include "pycore_dict.h" @@ -223,14 +224,6 @@ _PyEvalFramePushAndInit_Ex(PyThreadState *tstate, PyFunctionObject *func, static void _PyEvalFrameClearAndPop(PyThreadState *tstate, _PyInterpreterFrame *frame); -typedef PyObject *(*convertion_func_ptr)(PyObject *); - -static const convertion_func_ptr CONVERSION_FUNCTIONS[4] = { - [FVC_STR] = PyObject_Str, - [FVC_REPR] = PyObject_Repr, - [FVC_ASCII] = PyObject_ASCII -}; - #define UNBOUNDLOCAL_ERROR_MSG \ "cannot access local variable '%s' where it is not associated with a value" #define UNBOUNDFREE_ERROR_MSG \ @@ -2771,3 +2764,131 @@ void Py_LeaveRecursiveCall(void) { _Py_LeaveRecursiveCall(); } + +///////////////////// Experimental UOp Interpreter ///////////////////// + +// UPDATE_MISS_STATS (called by DEOPT_IF) uses next_instr +// TODO: Make it do something useful +#undef UPDATE_MISS_STATS +#define UPDATE_MISS_STATS(INSTNAME) ((void)0) + +_PyInterpreterFrame * +_PyUopExecute(_PyExecutorObject *executor, _PyInterpreterFrame *frame, PyObject **stack_pointer) +{ +#ifdef LLTRACE + char *uop_debug = Py_GETENV("PYTHONUOPSDEBUG"); + int lltrace = 0; + if (uop_debug != NULL && *uop_debug >= '0') { + lltrace = *uop_debug - '0'; // TODO: Parse an int and all that + } + if (lltrace >= 2) { + PyCodeObject *code = _PyFrame_GetCode(frame); + _Py_CODEUNIT *instr = frame->prev_instr + 1; + fprintf(stderr, + "Entering _PyUopExecute for %s (%s:%d) at offset %ld\n", + PyUnicode_AsUTF8(code->co_qualname), + PyUnicode_AsUTF8(code->co_filename), + code->co_firstlineno, + (long)(instr - (_Py_CODEUNIT *)code->co_code_adaptive)); + } +#endif + + PyThreadState *tstate = _PyThreadState_GET(); + _PyUOpExecutorObject *self = (_PyUOpExecutorObject *)executor; + + // Equivalent to CHECK_EVAL_BREAKER() + _Py_CHECK_EMSCRIPTEN_SIGNALS_PERIODICALLY(); + if (_Py_atomic_load_relaxed_int32(&tstate->interp->ceval.eval_breaker)) { + if (_Py_HandlePending(tstate) != 0) { + goto error; + } + } + + OBJECT_STAT_INC(optimization_traces_executed); + _Py_CODEUNIT *ip_offset = (_Py_CODEUNIT *)_PyFrame_GetCode(frame)->co_code_adaptive - 1; + int pc = 0; + int opcode; + uint64_t operand; + int oparg; + for (;;) { + opcode = self->trace[pc].opcode; + operand = self->trace[pc].operand; + oparg = (int)operand; +#ifdef LLTRACE + if (lltrace >= 3) { + const char *opname = opcode < 256 ? _PyOpcode_OpName[opcode] : ""; + int stack_level = (int)(stack_pointer - _PyFrame_Stackbase(frame)); + fprintf(stderr, " uop %s %d, operand %" PRIu64 ", stack_level %d\n", + opname, opcode, operand, stack_level); + } +#endif + pc++; + OBJECT_STAT_INC(optimization_uops_executed); + switch (opcode) { + +#undef ENABLE_SPECIALIZATION +#define ENABLE_SPECIALIZATION 0 +#include "executor_cases.c.h" + + case SET_IP: + { + frame->prev_instr = ip_offset + oparg; + break; + } + + case EXIT_TRACE: + { + _PyFrame_SetStackPointer(frame, stack_pointer); + Py_DECREF(self); + return frame; + } + + default: + { + fprintf(stderr, "Unknown uop %d, operand %" PRIu64 "\n", opcode, operand); + Py_FatalError("Unknown uop"); + abort(); // Unreachable + for (;;) {} + // Really unreachable + } + + } + } + +pop_4_error: + STACK_SHRINK(1); +pop_3_error: + STACK_SHRINK(1); +pop_2_error: + STACK_SHRINK(1); +pop_1_error: + STACK_SHRINK(1); +error: + // On ERROR_IF we return NULL as the frame. + // The caller recovers the frame from cframe.current_frame. +#ifdef LLTRACE + if (lltrace >= 2) { + fprintf(stderr, "Error: [Opcode %d, operand %" PRIu64 "]\n", opcode, operand); + } +#endif + _PyFrame_SetStackPointer(frame, stack_pointer); + Py_DECREF(self); + return NULL; + +PREDICTED(UNPACK_SEQUENCE) +PREDICTED(COMPARE_OP) +PREDICTED(LOAD_SUPER_ATTR) +PREDICTED(STORE_SUBSCR) +PREDICTED(BINARY_SUBSCR) +PREDICTED(BINARY_OP) + // On DEOPT_IF we just repeat the last instruction. + // This presumes nothing was popped from the stack (nor pushed). +#ifdef LLTRACE + if (lltrace >= 2) { + fprintf(stderr, "DEOPT: [Opcode %d, operand %" PRIu64 "]\n", opcode, operand); + } +#endif + _PyFrame_SetStackPointer(frame, stack_pointer); + Py_DECREF(self); + return frame; +} diff --git a/Python/ceval_macros.h b/Python/ceval_macros.h index 706a9a2..0d41ef5 100644 --- a/Python/ceval_macros.h +++ b/Python/ceval_macros.h @@ -1,4 +1,4 @@ -// Macros needed by ceval.c and bytecodes.c +// Macros and other things needed by ceval.c and bytecodes.c /* Computed GOTOs, or the-optimization-commonly-but-improperly-known-as-"threaded code" @@ -339,3 +339,11 @@ do { \ goto error; \ } \ } while (0); + +typedef PyObject *(*convertion_func_ptr)(PyObject *); + +static const convertion_func_ptr CONVERSION_FUNCTIONS[4] = { + [FVC_STR] = PyObject_Str, + [FVC_REPR] = PyObject_Repr, + [FVC_ASCII] = PyObject_ASCII +}; diff --git a/Python/executor_cases.c.h b/Python/executor_cases.c.h new file mode 100644 index 0000000..1bdee40 --- /dev/null +++ b/Python/executor_cases.c.h @@ -0,0 +1,1606 @@ +// This file is generated by Tools/cases_generator/generate_cases.py +// from: +// Python/bytecodes.c +// Do not edit! + + case NOP: { + break; + } + + case LOAD_FAST: { + PyObject *value; + value = GETLOCAL(oparg); + assert(value != NULL); + Py_INCREF(value); + STACK_GROW(1); + stack_pointer[-1] = value; + break; + } + + case LOAD_FAST_AND_CLEAR: { + PyObject *value; + value = GETLOCAL(oparg); + // do not use SETLOCAL here, it decrefs the old value + GETLOCAL(oparg) = NULL; + STACK_GROW(1); + stack_pointer[-1] = value; + break; + } + + case LOAD_CONST: { + PyObject *value; + value = GETITEM(FRAME_CO_CONSTS, oparg); + Py_INCREF(value); + STACK_GROW(1); + stack_pointer[-1] = value; + break; + } + + case STORE_FAST: { + PyObject *value = stack_pointer[-1]; + SETLOCAL(oparg, value); + STACK_SHRINK(1); + break; + } + + case POP_TOP: { + PyObject *value = stack_pointer[-1]; + Py_DECREF(value); + STACK_SHRINK(1); + break; + } + + case PUSH_NULL: { + PyObject *res; + res = NULL; + STACK_GROW(1); + stack_pointer[-1] = res; + break; + } + + case END_SEND: { + PyObject *value = stack_pointer[-1]; + PyObject *receiver = stack_pointer[-2]; + Py_DECREF(receiver); + STACK_SHRINK(1); + stack_pointer[-1] = value; + break; + } + + case UNARY_NEGATIVE: { + PyObject *value = stack_pointer[-1]; + PyObject *res; + res = PyNumber_Negative(value); + Py_DECREF(value); + if (res == NULL) goto pop_1_error; + stack_pointer[-1] = res; + break; + } + + case UNARY_NOT: { + PyObject *value = stack_pointer[-1]; + PyObject *res; + int err = PyObject_IsTrue(value); + Py_DECREF(value); + if (err < 0) goto pop_1_error; + if (err == 0) { + res = Py_True; + } + else { + res = Py_False; + } + stack_pointer[-1] = res; + break; + } + + case UNARY_INVERT: { + PyObject *value = stack_pointer[-1]; + PyObject *res; + res = PyNumber_Invert(value); + Py_DECREF(value); + if (res == NULL) goto pop_1_error; + stack_pointer[-1] = res; + break; + } + + case _GUARD_BOTH_INT: { + PyObject *right = stack_pointer[-1]; + PyObject *left = stack_pointer[-2]; + DEOPT_IF(!PyLong_CheckExact(left), BINARY_OP); + DEOPT_IF(!PyLong_CheckExact(right), BINARY_OP); + break; + } + + case _BINARY_OP_MULTIPLY_INT: { + PyObject *right = stack_pointer[-1]; + PyObject *left = stack_pointer[-2]; + PyObject *res; + STAT_INC(BINARY_OP, hit); + res = _PyLong_Multiply((PyLongObject *)left, (PyLongObject *)right); + _Py_DECREF_SPECIALIZED(right, (destructor)PyObject_Free); + _Py_DECREF_SPECIALIZED(left, (destructor)PyObject_Free); + if (res == NULL) goto pop_2_error; + STACK_SHRINK(1); + stack_pointer[-1] = res; + break; + } + + case _BINARY_OP_ADD_INT: { + PyObject *right = stack_pointer[-1]; + PyObject *left = stack_pointer[-2]; + PyObject *res; + STAT_INC(BINARY_OP, hit); + res = _PyLong_Add((PyLongObject *)left, (PyLongObject *)right); + _Py_DECREF_SPECIALIZED(right, (destructor)PyObject_Free); + _Py_DECREF_SPECIALIZED(left, (destructor)PyObject_Free); + if (res == NULL) goto pop_2_error; + STACK_SHRINK(1); + stack_pointer[-1] = res; + break; + } + + case _BINARY_OP_SUBTRACT_INT: { + PyObject *right = stack_pointer[-1]; + PyObject *left = stack_pointer[-2]; + PyObject *res; + STAT_INC(BINARY_OP, hit); + res = _PyLong_Subtract((PyLongObject *)left, (PyLongObject *)right); + _Py_DECREF_SPECIALIZED(right, (destructor)PyObject_Free); + _Py_DECREF_SPECIALIZED(left, (destructor)PyObject_Free); + if (res == NULL) goto pop_2_error; + STACK_SHRINK(1); + stack_pointer[-1] = res; + break; + } + + case _GUARD_BOTH_FLOAT: { + PyObject *right = stack_pointer[-1]; + PyObject *left = stack_pointer[-2]; + DEOPT_IF(!PyFloat_CheckExact(left), BINARY_OP); + DEOPT_IF(!PyFloat_CheckExact(right), BINARY_OP); + break; + } + + case _BINARY_OP_MULTIPLY_FLOAT: { + PyObject *right = stack_pointer[-1]; + PyObject *left = stack_pointer[-2]; + PyObject *res; + STAT_INC(BINARY_OP, hit); + double dres = + ((PyFloatObject *)left)->ob_fval * + ((PyFloatObject *)right)->ob_fval; + DECREF_INPUTS_AND_REUSE_FLOAT(left, right, dres, res); + STACK_SHRINK(1); + stack_pointer[-1] = res; + break; + } + + case _BINARY_OP_ADD_FLOAT: { + PyObject *right = stack_pointer[-1]; + PyObject *left = stack_pointer[-2]; + PyObject *res; + STAT_INC(BINARY_OP, hit); + double dres = + ((PyFloatObject *)left)->ob_fval + + ((PyFloatObject *)right)->ob_fval; + DECREF_INPUTS_AND_REUSE_FLOAT(left, right, dres, res); + STACK_SHRINK(1); + stack_pointer[-1] = res; + break; + } + + case _BINARY_OP_SUBTRACT_FLOAT: { + PyObject *right = stack_pointer[-1]; + PyObject *left = stack_pointer[-2]; + PyObject *res; + STAT_INC(BINARY_OP, hit); + double dres = + ((PyFloatObject *)left)->ob_fval - + ((PyFloatObject *)right)->ob_fval; + DECREF_INPUTS_AND_REUSE_FLOAT(left, right, dres, res); + STACK_SHRINK(1); + stack_pointer[-1] = res; + break; + } + + case _GUARD_BOTH_UNICODE: { + PyObject *right = stack_pointer[-1]; + PyObject *left = stack_pointer[-2]; + DEOPT_IF(!PyUnicode_CheckExact(left), BINARY_OP); + DEOPT_IF(!PyUnicode_CheckExact(right), BINARY_OP); + break; + } + + case _BINARY_OP_ADD_UNICODE: { + PyObject *right = stack_pointer[-1]; + PyObject *left = stack_pointer[-2]; + PyObject *res; + STAT_INC(BINARY_OP, hit); + res = PyUnicode_Concat(left, right); + _Py_DECREF_SPECIALIZED(left, _PyUnicode_ExactDealloc); + _Py_DECREF_SPECIALIZED(right, _PyUnicode_ExactDealloc); + if (res == NULL) goto pop_2_error; + STACK_SHRINK(1); + stack_pointer[-1] = res; + break; + } + + case BINARY_SLICE: { + PyObject *stop = stack_pointer[-1]; + PyObject *start = stack_pointer[-2]; + PyObject *container = stack_pointer[-3]; + PyObject *res; + PyObject *slice = _PyBuildSlice_ConsumeRefs(start, stop); + // Can't use ERROR_IF() here, because we haven't + // DECREF'ed container yet, and we still own slice. + if (slice == NULL) { + res = NULL; + } + else { + res = PyObject_GetItem(container, slice); + Py_DECREF(slice); + } + Py_DECREF(container); + if (res == NULL) goto pop_3_error; + STACK_SHRINK(2); + stack_pointer[-1] = res; + break; + } + + case STORE_SLICE: { + PyObject *stop = stack_pointer[-1]; + PyObject *start = stack_pointer[-2]; + PyObject *container = stack_pointer[-3]; + PyObject *v = stack_pointer[-4]; + PyObject *slice = _PyBuildSlice_ConsumeRefs(start, stop); + int err; + if (slice == NULL) { + err = 1; + } + else { + err = PyObject_SetItem(container, slice, v); + Py_DECREF(slice); + } + Py_DECREF(v); + Py_DECREF(container); + if (err) goto pop_4_error; + STACK_SHRINK(4); + break; + } + + case BINARY_SUBSCR_LIST_INT: { + PyObject *sub = stack_pointer[-1]; + PyObject *list = stack_pointer[-2]; + PyObject *res; + DEOPT_IF(!PyLong_CheckExact(sub), BINARY_SUBSCR); + DEOPT_IF(!PyList_CheckExact(list), BINARY_SUBSCR); + + // Deopt unless 0 <= sub < PyList_Size(list) + DEOPT_IF(!_PyLong_IsNonNegativeCompact((PyLongObject *)sub), BINARY_SUBSCR); + Py_ssize_t index = ((PyLongObject*)sub)->long_value.ob_digit[0]; + DEOPT_IF(index >= PyList_GET_SIZE(list), BINARY_SUBSCR); + STAT_INC(BINARY_SUBSCR, hit); + res = PyList_GET_ITEM(list, index); + assert(res != NULL); + Py_INCREF(res); + _Py_DECREF_SPECIALIZED(sub, (destructor)PyObject_Free); + Py_DECREF(list); + STACK_SHRINK(1); + stack_pointer[-1] = res; + break; + } + + case BINARY_SUBSCR_TUPLE_INT: { + PyObject *sub = stack_pointer[-1]; + PyObject *tuple = stack_pointer[-2]; + PyObject *res; + DEOPT_IF(!PyLong_CheckExact(sub), BINARY_SUBSCR); + DEOPT_IF(!PyTuple_CheckExact(tuple), BINARY_SUBSCR); + + // Deopt unless 0 <= sub < PyTuple_Size(list) + DEOPT_IF(!_PyLong_IsNonNegativeCompact((PyLongObject *)sub), BINARY_SUBSCR); + Py_ssize_t index = ((PyLongObject*)sub)->long_value.ob_digit[0]; + DEOPT_IF(index >= PyTuple_GET_SIZE(tuple), BINARY_SUBSCR); + STAT_INC(BINARY_SUBSCR, hit); + res = PyTuple_GET_ITEM(tuple, index); + assert(res != NULL); + Py_INCREF(res); + _Py_DECREF_SPECIALIZED(sub, (destructor)PyObject_Free); + Py_DECREF(tuple); + STACK_SHRINK(1); + stack_pointer[-1] = res; + break; + } + + case BINARY_SUBSCR_DICT: { + PyObject *sub = stack_pointer[-1]; + PyObject *dict = stack_pointer[-2]; + PyObject *res; + DEOPT_IF(!PyDict_CheckExact(dict), BINARY_SUBSCR); + STAT_INC(BINARY_SUBSCR, hit); + res = PyDict_GetItemWithError(dict, sub); + if (res == NULL) { + if (!_PyErr_Occurred(tstate)) { + _PyErr_SetKeyError(sub); + } + Py_DECREF(dict); + Py_DECREF(sub); + if (true) goto pop_2_error; + } + Py_INCREF(res); // Do this before DECREF'ing dict, sub + Py_DECREF(dict); + Py_DECREF(sub); + STACK_SHRINK(1); + stack_pointer[-1] = res; + break; + } + + case LIST_APPEND: { + PyObject *v = stack_pointer[-1]; + PyObject *list = stack_pointer[-(2 + (oparg-1))]; + if (_PyList_AppendTakeRef((PyListObject *)list, v) < 0) goto pop_1_error; + STACK_SHRINK(1); + break; + } + + case SET_ADD: { + PyObject *v = stack_pointer[-1]; + PyObject *set = stack_pointer[-(2 + (oparg-1))]; + int err = PySet_Add(set, v); + Py_DECREF(v); + if (err) goto pop_1_error; + STACK_SHRINK(1); + break; + } + + case STORE_SUBSCR_LIST_INT: { + PyObject *sub = stack_pointer[-1]; + PyObject *list = stack_pointer[-2]; + PyObject *value = stack_pointer[-3]; + DEOPT_IF(!PyLong_CheckExact(sub), STORE_SUBSCR); + DEOPT_IF(!PyList_CheckExact(list), STORE_SUBSCR); + + // Ensure nonnegative, zero-or-one-digit ints. + DEOPT_IF(!_PyLong_IsNonNegativeCompact((PyLongObject *)sub), STORE_SUBSCR); + Py_ssize_t index = ((PyLongObject*)sub)->long_value.ob_digit[0]; + // Ensure index < len(list) + DEOPT_IF(index >= PyList_GET_SIZE(list), STORE_SUBSCR); + STAT_INC(STORE_SUBSCR, hit); + + PyObject *old_value = PyList_GET_ITEM(list, index); + PyList_SET_ITEM(list, index, value); + assert(old_value != NULL); + Py_DECREF(old_value); + _Py_DECREF_SPECIALIZED(sub, (destructor)PyObject_Free); + Py_DECREF(list); + STACK_SHRINK(3); + break; + } + + case STORE_SUBSCR_DICT: { + PyObject *sub = stack_pointer[-1]; + PyObject *dict = stack_pointer[-2]; + PyObject *value = stack_pointer[-3]; + DEOPT_IF(!PyDict_CheckExact(dict), STORE_SUBSCR); + STAT_INC(STORE_SUBSCR, hit); + int err = _PyDict_SetItem_Take2((PyDictObject *)dict, sub, value); + Py_DECREF(dict); + if (err) goto pop_3_error; + STACK_SHRINK(3); + break; + } + + case DELETE_SUBSCR: { + PyObject *sub = stack_pointer[-1]; + PyObject *container = stack_pointer[-2]; + /* del container[sub] */ + int err = PyObject_DelItem(container, sub); + Py_DECREF(container); + Py_DECREF(sub); + if (err) goto pop_2_error; + STACK_SHRINK(2); + break; + } + + case CALL_INTRINSIC_1: { + PyObject *value = stack_pointer[-1]; + PyObject *res; + assert(oparg <= MAX_INTRINSIC_1); + res = _PyIntrinsics_UnaryFunctions[oparg](tstate, value); + Py_DECREF(value); + if (res == NULL) goto pop_1_error; + stack_pointer[-1] = res; + break; + } + + case CALL_INTRINSIC_2: { + PyObject *value1 = stack_pointer[-1]; + PyObject *value2 = stack_pointer[-2]; + PyObject *res; + assert(oparg <= MAX_INTRINSIC_2); + res = _PyIntrinsics_BinaryFunctions[oparg](tstate, value2, value1); + Py_DECREF(value2); + Py_DECREF(value1); + if (res == NULL) goto pop_2_error; + STACK_SHRINK(1); + stack_pointer[-1] = res; + break; + } + + case GET_AITER: { + PyObject *obj = stack_pointer[-1]; + PyObject *iter; + unaryfunc getter = NULL; + PyTypeObject *type = Py_TYPE(obj); + + if (type->tp_as_async != NULL) { + getter = type->tp_as_async->am_aiter; + } + + if (getter == NULL) { + _PyErr_Format(tstate, PyExc_TypeError, + "'async for' requires an object with " + "__aiter__ method, got %.100s", + type->tp_name); + Py_DECREF(obj); + if (true) goto pop_1_error; + } + + iter = (*getter)(obj); + Py_DECREF(obj); + if (iter == NULL) goto pop_1_error; + + if (Py_TYPE(iter)->tp_as_async == NULL || + Py_TYPE(iter)->tp_as_async->am_anext == NULL) { + + _PyErr_Format(tstate, PyExc_TypeError, + "'async for' received an object from __aiter__ " + "that does not implement __anext__: %.100s", + Py_TYPE(iter)->tp_name); + Py_DECREF(iter); + if (true) goto pop_1_error; + } + stack_pointer[-1] = iter; + break; + } + + case GET_ANEXT: { + PyObject *aiter = stack_pointer[-1]; + PyObject *awaitable; + unaryfunc getter = NULL; + PyObject *next_iter = NULL; + PyTypeObject *type = Py_TYPE(aiter); + + if (PyAsyncGen_CheckExact(aiter)) { + awaitable = type->tp_as_async->am_anext(aiter); + if (awaitable == NULL) { + goto error; + } + } else { + if (type->tp_as_async != NULL){ + getter = type->tp_as_async->am_anext; + } + + if (getter != NULL) { + next_iter = (*getter)(aiter); + if (next_iter == NULL) { + goto error; + } + } + else { + _PyErr_Format(tstate, PyExc_TypeError, + "'async for' requires an iterator with " + "__anext__ method, got %.100s", + type->tp_name); + goto error; + } + + awaitable = _PyCoro_GetAwaitableIter(next_iter); + if (awaitable == NULL) { + _PyErr_FormatFromCause( + PyExc_TypeError, + "'async for' received an invalid object " + "from __anext__: %.100s", + Py_TYPE(next_iter)->tp_name); + + Py_DECREF(next_iter); + goto error; + } else { + Py_DECREF(next_iter); + } + } + STACK_GROW(1); + stack_pointer[-1] = awaitable; + break; + } + + case GET_AWAITABLE: { + PyObject *iterable = stack_pointer[-1]; + PyObject *iter; + iter = _PyCoro_GetAwaitableIter(iterable); + + if (iter == NULL) { + format_awaitable_error(tstate, Py_TYPE(iterable), oparg); + } + + Py_DECREF(iterable); + + if (iter != NULL && PyCoro_CheckExact(iter)) { + PyObject *yf = _PyGen_yf((PyGenObject*)iter); + if (yf != NULL) { + /* `iter` is a coroutine object that is being + awaited, `yf` is a pointer to the current awaitable + being awaited on. */ + Py_DECREF(yf); + Py_CLEAR(iter); + _PyErr_SetString(tstate, PyExc_RuntimeError, + "coroutine is being awaited already"); + /* The code below jumps to `error` if `iter` is NULL. */ + } + } + + if (iter == NULL) goto pop_1_error; + stack_pointer[-1] = iter; + break; + } + + case POP_EXCEPT: { + PyObject *exc_value = stack_pointer[-1]; + _PyErr_StackItem *exc_info = tstate->exc_info; + Py_XSETREF(exc_info->exc_value, exc_value); + STACK_SHRINK(1); + break; + } + + case LOAD_ASSERTION_ERROR: { + PyObject *value; + value = Py_NewRef(PyExc_AssertionError); + STACK_GROW(1); + stack_pointer[-1] = value; + break; + } + + case LOAD_BUILD_CLASS: { + PyObject *bc; + if (PyDict_CheckExact(BUILTINS())) { + bc = _PyDict_GetItemWithError(BUILTINS(), + &_Py_ID(__build_class__)); + if (bc == NULL) { + if (!_PyErr_Occurred(tstate)) { + _PyErr_SetString(tstate, PyExc_NameError, + "__build_class__ not found"); + } + if (true) goto error; + } + Py_INCREF(bc); + } + else { + bc = PyObject_GetItem(BUILTINS(), &_Py_ID(__build_class__)); + if (bc == NULL) { + if (_PyErr_ExceptionMatches(tstate, PyExc_KeyError)) + _PyErr_SetString(tstate, PyExc_NameError, + "__build_class__ not found"); + if (true) goto error; + } + } + STACK_GROW(1); + stack_pointer[-1] = bc; + break; + } + + case STORE_NAME: { + PyObject *v = stack_pointer[-1]; + PyObject *name = GETITEM(FRAME_CO_NAMES, oparg); + PyObject *ns = LOCALS(); + int err; + if (ns == NULL) { + _PyErr_Format(tstate, PyExc_SystemError, + "no locals found when storing %R", name); + Py_DECREF(v); + if (true) goto pop_1_error; + } + if (PyDict_CheckExact(ns)) + err = PyDict_SetItem(ns, name, v); + else + err = PyObject_SetItem(ns, name, v); + Py_DECREF(v); + if (err) goto pop_1_error; + STACK_SHRINK(1); + break; + } + + case DELETE_NAME: { + PyObject *name = GETITEM(FRAME_CO_NAMES, oparg); + PyObject *ns = LOCALS(); + int err; + if (ns == NULL) { + _PyErr_Format(tstate, PyExc_SystemError, + "no locals when deleting %R", name); + goto error; + } + err = PyObject_DelItem(ns, name); + // Can't use ERROR_IF here. + if (err != 0) { + format_exc_check_arg(tstate, PyExc_NameError, + NAME_ERROR_MSG, + name); + goto error; + } + break; + } + + case UNPACK_SEQUENCE_TWO_TUPLE: { + PyObject *seq = stack_pointer[-1]; + PyObject **values = stack_pointer - (1); + DEOPT_IF(!PyTuple_CheckExact(seq), UNPACK_SEQUENCE); + DEOPT_IF(PyTuple_GET_SIZE(seq) != 2, UNPACK_SEQUENCE); + assert(oparg == 2); + STAT_INC(UNPACK_SEQUENCE, hit); + values[0] = Py_NewRef(PyTuple_GET_ITEM(seq, 1)); + values[1] = Py_NewRef(PyTuple_GET_ITEM(seq, 0)); + Py_DECREF(seq); + STACK_SHRINK(1); + STACK_GROW(oparg); + break; + } + + case UNPACK_SEQUENCE_TUPLE: { + PyObject *seq = stack_pointer[-1]; + PyObject **values = stack_pointer - (1); + DEOPT_IF(!PyTuple_CheckExact(seq), UNPACK_SEQUENCE); + DEOPT_IF(PyTuple_GET_SIZE(seq) != oparg, UNPACK_SEQUENCE); + STAT_INC(UNPACK_SEQUENCE, hit); + PyObject **items = _PyTuple_ITEMS(seq); + for (int i = oparg; --i >= 0; ) { + *values++ = Py_NewRef(items[i]); + } + Py_DECREF(seq); + STACK_SHRINK(1); + STACK_GROW(oparg); + break; + } + + case UNPACK_SEQUENCE_LIST: { + PyObject *seq = stack_pointer[-1]; + PyObject **values = stack_pointer - (1); + DEOPT_IF(!PyList_CheckExact(seq), UNPACK_SEQUENCE); + DEOPT_IF(PyList_GET_SIZE(seq) != oparg, UNPACK_SEQUENCE); + STAT_INC(UNPACK_SEQUENCE, hit); + PyObject **items = _PyList_ITEMS(seq); + for (int i = oparg; --i >= 0; ) { + *values++ = Py_NewRef(items[i]); + } + Py_DECREF(seq); + STACK_SHRINK(1); + STACK_GROW(oparg); + break; + } + + case UNPACK_EX: { + PyObject *seq = stack_pointer[-1]; + int totalargs = 1 + (oparg & 0xFF) + (oparg >> 8); + PyObject **top = stack_pointer + totalargs - 1; + int res = unpack_iterable(tstate, seq, oparg & 0xFF, oparg >> 8, top); + Py_DECREF(seq); + if (res == 0) goto pop_1_error; + STACK_GROW((oparg & 0xFF) + (oparg >> 8)); + break; + } + + case DELETE_ATTR: { + PyObject *owner = stack_pointer[-1]; + PyObject *name = GETITEM(FRAME_CO_NAMES, oparg); + int err = PyObject_SetAttr(owner, name, (PyObject *)NULL); + Py_DECREF(owner); + if (err) goto pop_1_error; + STACK_SHRINK(1); + break; + } + + case STORE_GLOBAL: { + PyObject *v = stack_pointer[-1]; + PyObject *name = GETITEM(FRAME_CO_NAMES, oparg); + int err = PyDict_SetItem(GLOBALS(), name, v); + Py_DECREF(v); + if (err) goto pop_1_error; + STACK_SHRINK(1); + break; + } + + case DELETE_GLOBAL: { + PyObject *name = GETITEM(FRAME_CO_NAMES, oparg); + int err; + err = PyDict_DelItem(GLOBALS(), name); + // Can't use ERROR_IF here. + if (err != 0) { + if (_PyErr_ExceptionMatches(tstate, PyExc_KeyError)) { + format_exc_check_arg(tstate, PyExc_NameError, + NAME_ERROR_MSG, name); + } + goto error; + } + break; + } + + case _LOAD_LOCALS: { + PyObject *locals; + locals = LOCALS(); + if (locals == NULL) { + _PyErr_SetString(tstate, PyExc_SystemError, + "no locals found"); + if (true) goto error; + } + Py_INCREF(locals); + STACK_GROW(1); + stack_pointer[-1] = locals; + break; + } + + case _LOAD_FROM_DICT_OR_GLOBALS: { + PyObject *mod_or_class_dict = stack_pointer[-1]; + PyObject *v; + PyObject *name = GETITEM(FRAME_CO_NAMES, oparg); + if (PyDict_CheckExact(mod_or_class_dict)) { + v = PyDict_GetItemWithError(mod_or_class_dict, name); + if (v != NULL) { + Py_INCREF(v); + } + else if (_PyErr_Occurred(tstate)) { + Py_DECREF(mod_or_class_dict); + goto error; + } + } + else { + v = PyObject_GetItem(mod_or_class_dict, name); + if (v == NULL) { + if (!_PyErr_ExceptionMatches(tstate, PyExc_KeyError)) { + Py_DECREF(mod_or_class_dict); + goto error; + } + _PyErr_Clear(tstate); + } + } + Py_DECREF(mod_or_class_dict); + if (v == NULL) { + v = PyDict_GetItemWithError(GLOBALS(), name); + if (v != NULL) { + Py_INCREF(v); + } + else if (_PyErr_Occurred(tstate)) { + goto error; + } + else { + if (PyDict_CheckExact(BUILTINS())) { + v = PyDict_GetItemWithError(BUILTINS(), name); + if (v == NULL) { + if (!_PyErr_Occurred(tstate)) { + format_exc_check_arg( + tstate, PyExc_NameError, + NAME_ERROR_MSG, name); + } + goto error; + } + Py_INCREF(v); + } + else { + v = PyObject_GetItem(BUILTINS(), name); + if (v == NULL) { + if (_PyErr_ExceptionMatches(tstate, PyExc_KeyError)) { + format_exc_check_arg( + tstate, PyExc_NameError, + NAME_ERROR_MSG, name); + } + goto error; + } + } + } + } + stack_pointer[-1] = v; + break; + } + + case DELETE_DEREF: { + PyObject *cell = GETLOCAL(oparg); + PyObject *oldobj = PyCell_GET(cell); + // Can't use ERROR_IF here. + // Fortunately we don't need its superpower. + if (oldobj == NULL) { + format_exc_unbound(tstate, _PyFrame_GetCode(frame), oparg); + goto error; + } + PyCell_SET(cell, NULL); + Py_DECREF(oldobj); + break; + } + + case LOAD_FROM_DICT_OR_DEREF: { + PyObject *class_dict = stack_pointer[-1]; + PyObject *value; + PyObject *name; + assert(class_dict); + assert(oparg >= 0 && oparg < _PyFrame_GetCode(frame)->co_nlocalsplus); + name = PyTuple_GET_ITEM(_PyFrame_GetCode(frame)->co_localsplusnames, oparg); + if (PyDict_CheckExact(class_dict)) { + value = PyDict_GetItemWithError(class_dict, name); + if (value != NULL) { + Py_INCREF(value); + } + else if (_PyErr_Occurred(tstate)) { + Py_DECREF(class_dict); + goto error; + } + } + else { + value = PyObject_GetItem(class_dict, name); + if (value == NULL) { + if (!_PyErr_ExceptionMatches(tstate, PyExc_KeyError)) { + Py_DECREF(class_dict); + goto error; + } + _PyErr_Clear(tstate); + } + } + Py_DECREF(class_dict); + if (!value) { + PyObject *cell = GETLOCAL(oparg); + value = PyCell_GET(cell); + if (value == NULL) { + format_exc_unbound(tstate, _PyFrame_GetCode(frame), oparg); + goto error; + } + Py_INCREF(value); + } + stack_pointer[-1] = value; + break; + } + + case LOAD_DEREF: { + PyObject *value; + PyObject *cell = GETLOCAL(oparg); + value = PyCell_GET(cell); + if (value == NULL) { + format_exc_unbound(tstate, _PyFrame_GetCode(frame), oparg); + if (true) goto error; + } + Py_INCREF(value); + STACK_GROW(1); + stack_pointer[-1] = value; + break; + } + + case STORE_DEREF: { + PyObject *v = stack_pointer[-1]; + PyObject *cell = GETLOCAL(oparg); + PyObject *oldobj = PyCell_GET(cell); + PyCell_SET(cell, v); + Py_XDECREF(oldobj); + STACK_SHRINK(1); + break; + } + + case COPY_FREE_VARS: { + /* Copy closure variables to free variables */ + PyCodeObject *co = _PyFrame_GetCode(frame); + assert(PyFunction_Check(frame->f_funcobj)); + PyObject *closure = ((PyFunctionObject *)frame->f_funcobj)->func_closure; + assert(oparg == co->co_nfreevars); + int offset = co->co_nlocalsplus - oparg; + for (int i = 0; i < oparg; ++i) { + PyObject *o = PyTuple_GET_ITEM(closure, i); + frame->localsplus[offset + i] = Py_NewRef(o); + } + break; + } + + case BUILD_STRING: { + PyObject **pieces = (stack_pointer - oparg); + PyObject *str; + str = _PyUnicode_JoinArray(&_Py_STR(empty), pieces, oparg); + for (int _i = oparg; --_i >= 0;) { + Py_DECREF(pieces[_i]); + } + if (str == NULL) { STACK_SHRINK(oparg); goto error; } + STACK_SHRINK(oparg); + STACK_GROW(1); + stack_pointer[-1] = str; + break; + } + + case BUILD_TUPLE: { + PyObject **values = (stack_pointer - oparg); + PyObject *tup; + tup = _PyTuple_FromArraySteal(values, oparg); + if (tup == NULL) { STACK_SHRINK(oparg); goto error; } + STACK_SHRINK(oparg); + STACK_GROW(1); + stack_pointer[-1] = tup; + break; + } + + case BUILD_LIST: { + PyObject **values = (stack_pointer - oparg); + PyObject *list; + list = _PyList_FromArraySteal(values, oparg); + if (list == NULL) { STACK_SHRINK(oparg); goto error; } + STACK_SHRINK(oparg); + STACK_GROW(1); + stack_pointer[-1] = list; + break; + } + + case LIST_EXTEND: { + PyObject *iterable = stack_pointer[-1]; + PyObject *list = stack_pointer[-(2 + (oparg-1))]; + PyObject *none_val = _PyList_Extend((PyListObject *)list, iterable); + if (none_val == NULL) { + if (_PyErr_ExceptionMatches(tstate, PyExc_TypeError) && + (Py_TYPE(iterable)->tp_iter == NULL && !PySequence_Check(iterable))) + { + _PyErr_Clear(tstate); + _PyErr_Format(tstate, PyExc_TypeError, + "Value after * must be an iterable, not %.200s", + Py_TYPE(iterable)->tp_name); + } + Py_DECREF(iterable); + if (true) goto pop_1_error; + } + assert(Py_IsNone(none_val)); + Py_DECREF(iterable); + STACK_SHRINK(1); + break; + } + + case SET_UPDATE: { + PyObject *iterable = stack_pointer[-1]; + PyObject *set = stack_pointer[-(2 + (oparg-1))]; + int err = _PySet_Update(set, iterable); + Py_DECREF(iterable); + if (err < 0) goto pop_1_error; + STACK_SHRINK(1); + break; + } + + case BUILD_SET: { + PyObject **values = (stack_pointer - oparg); + PyObject *set; + set = PySet_New(NULL); + if (set == NULL) + goto error; + int err = 0; + for (int i = 0; i < oparg; i++) { + PyObject *item = values[i]; + if (err == 0) + err = PySet_Add(set, item); + Py_DECREF(item); + } + if (err != 0) { + Py_DECREF(set); + if (true) { STACK_SHRINK(oparg); goto error; } + } + STACK_SHRINK(oparg); + STACK_GROW(1); + stack_pointer[-1] = set; + break; + } + + case BUILD_MAP: { + PyObject **values = (stack_pointer - oparg*2); + PyObject *map; + map = _PyDict_FromItems( + values, 2, + values+1, 2, + oparg); + if (map == NULL) + goto error; + + for (int _i = oparg*2; --_i >= 0;) { + Py_DECREF(values[_i]); + } + if (map == NULL) { STACK_SHRINK(oparg*2); goto error; } + STACK_SHRINK(oparg*2); + STACK_GROW(1); + stack_pointer[-1] = map; + break; + } + + case SETUP_ANNOTATIONS: { + int err; + PyObject *ann_dict; + if (LOCALS() == NULL) { + _PyErr_Format(tstate, PyExc_SystemError, + "no locals found when setting up annotations"); + if (true) goto error; + } + /* check if __annotations__ in locals()... */ + if (PyDict_CheckExact(LOCALS())) { + ann_dict = _PyDict_GetItemWithError(LOCALS(), + &_Py_ID(__annotations__)); + if (ann_dict == NULL) { + if (_PyErr_Occurred(tstate)) goto error; + /* ...if not, create a new one */ + ann_dict = PyDict_New(); + if (ann_dict == NULL) goto error; + err = PyDict_SetItem(LOCALS(), &_Py_ID(__annotations__), + ann_dict); + Py_DECREF(ann_dict); + if (err) goto error; + } + } + else { + /* do the same if locals() is not a dict */ + ann_dict = PyObject_GetItem(LOCALS(), &_Py_ID(__annotations__)); + if (ann_dict == NULL) { + if (!_PyErr_ExceptionMatches(tstate, PyExc_KeyError)) goto error; + _PyErr_Clear(tstate); + ann_dict = PyDict_New(); + if (ann_dict == NULL) goto error; + err = PyObject_SetItem(LOCALS(), &_Py_ID(__annotations__), + ann_dict); + Py_DECREF(ann_dict); + if (err) goto error; + } + else { + Py_DECREF(ann_dict); + } + } + break; + } + + case BUILD_CONST_KEY_MAP: { + PyObject *keys = stack_pointer[-1]; + PyObject **values = (stack_pointer - (1 + oparg)); + PyObject *map; + if (!PyTuple_CheckExact(keys) || + PyTuple_GET_SIZE(keys) != (Py_ssize_t)oparg) { + _PyErr_SetString(tstate, PyExc_SystemError, + "bad BUILD_CONST_KEY_MAP keys argument"); + goto error; // Pop the keys and values. + } + map = _PyDict_FromItems( + &PyTuple_GET_ITEM(keys, 0), 1, + values, 1, oparg); + for (int _i = oparg; --_i >= 0;) { + Py_DECREF(values[_i]); + } + Py_DECREF(keys); + if (map == NULL) { STACK_SHRINK(oparg); goto pop_1_error; } + STACK_SHRINK(oparg); + stack_pointer[-1] = map; + break; + } + + case DICT_UPDATE: { + PyObject *update = stack_pointer[-1]; + PyObject *dict = PEEK(oparg + 1); // update is still on the stack + if (PyDict_Update(dict, update) < 0) { + if (_PyErr_ExceptionMatches(tstate, PyExc_AttributeError)) { + _PyErr_Format(tstate, PyExc_TypeError, + "'%.200s' object is not a mapping", + Py_TYPE(update)->tp_name); + } + Py_DECREF(update); + if (true) goto pop_1_error; + } + Py_DECREF(update); + STACK_SHRINK(1); + break; + } + + case DICT_MERGE: { + PyObject *update = stack_pointer[-1]; + PyObject *dict = PEEK(oparg + 1); // update is still on the stack + + if (_PyDict_MergeEx(dict, update, 2) < 0) { + format_kwargs_error(tstate, PEEK(3 + oparg), update); + Py_DECREF(update); + if (true) goto pop_1_error; + } + Py_DECREF(update); + STACK_SHRINK(1); + break; + } + + case MAP_ADD: { + PyObject *value = stack_pointer[-1]; + PyObject *key = stack_pointer[-2]; + PyObject *dict = PEEK(oparg + 2); // key, value are still on the stack + assert(PyDict_CheckExact(dict)); + /* dict[key] = value */ + // Do not DECREF INPUTS because the function steals the references + if (_PyDict_SetItem_Take2((PyDictObject *)dict, key, value) != 0) goto pop_2_error; + STACK_SHRINK(2); + break; + } + + case LOAD_SUPER_ATTR_ATTR: { + PyObject *self = stack_pointer[-1]; + PyObject *class = stack_pointer[-2]; + PyObject *global_super = stack_pointer[-3]; + PyObject *res2 = NULL; + PyObject *res; + assert(!(oparg & 1)); + DEOPT_IF(global_super != (PyObject *)&PySuper_Type, LOAD_SUPER_ATTR); + DEOPT_IF(!PyType_Check(class), LOAD_SUPER_ATTR); + STAT_INC(LOAD_SUPER_ATTR, hit); + PyObject *name = GETITEM(FRAME_CO_NAMES, oparg >> 2); + res = _PySuper_Lookup((PyTypeObject *)class, self, name, NULL); + Py_DECREF(global_super); + Py_DECREF(class); + Py_DECREF(self); + if (res == NULL) goto pop_3_error; + STACK_SHRINK(2); + STACK_GROW(((oparg & 1) ? 1 : 0)); + stack_pointer[-1] = res; + if (oparg & 1) { stack_pointer[-(1 + ((oparg & 1) ? 1 : 0))] = res2; } + break; + } + + case LOAD_SUPER_ATTR_METHOD: { + PyObject *self = stack_pointer[-1]; + PyObject *class = stack_pointer[-2]; + PyObject *global_super = stack_pointer[-3]; + PyObject *res2; + PyObject *res; + assert(oparg & 1); + DEOPT_IF(global_super != (PyObject *)&PySuper_Type, LOAD_SUPER_ATTR); + DEOPT_IF(!PyType_Check(class), LOAD_SUPER_ATTR); + STAT_INC(LOAD_SUPER_ATTR, hit); + PyObject *name = GETITEM(FRAME_CO_NAMES, oparg >> 2); + PyTypeObject *cls = (PyTypeObject *)class; + int method_found = 0; + res2 = _PySuper_Lookup(cls, self, name, + cls->tp_getattro == PyObject_GenericGetAttr ? &method_found : NULL); + Py_DECREF(global_super); + Py_DECREF(class); + if (res2 == NULL) { + Py_DECREF(self); + if (true) goto pop_3_error; + } + if (method_found) { + res = self; // transfer ownership + } else { + Py_DECREF(self); + res = res2; + res2 = NULL; + } + STACK_SHRINK(1); + stack_pointer[-1] = res; + stack_pointer[-2] = res2; + break; + } + + case COMPARE_OP_FLOAT: { + PyObject *right = stack_pointer[-1]; + PyObject *left = stack_pointer[-2]; + PyObject *res; + DEOPT_IF(!PyFloat_CheckExact(left), COMPARE_OP); + DEOPT_IF(!PyFloat_CheckExact(right), COMPARE_OP); + STAT_INC(COMPARE_OP, hit); + double dleft = PyFloat_AS_DOUBLE(left); + double dright = PyFloat_AS_DOUBLE(right); + // 1 if NaN, 2 if <, 4 if >, 8 if ==; this matches low four bits of the oparg + int sign_ish = COMPARISON_BIT(dleft, dright); + _Py_DECREF_SPECIALIZED(left, _PyFloat_ExactDealloc); + _Py_DECREF_SPECIALIZED(right, _PyFloat_ExactDealloc); + res = (sign_ish & oparg) ? Py_True : Py_False; + STACK_SHRINK(1); + stack_pointer[-1] = res; + break; + } + + case COMPARE_OP_INT: { + PyObject *right = stack_pointer[-1]; + PyObject *left = stack_pointer[-2]; + PyObject *res; + DEOPT_IF(!PyLong_CheckExact(left), COMPARE_OP); + DEOPT_IF(!PyLong_CheckExact(right), COMPARE_OP); + DEOPT_IF(!_PyLong_IsCompact((PyLongObject *)left), COMPARE_OP); + DEOPT_IF(!_PyLong_IsCompact((PyLongObject *)right), COMPARE_OP); + STAT_INC(COMPARE_OP, hit); + assert(_PyLong_DigitCount((PyLongObject *)left) <= 1 && + _PyLong_DigitCount((PyLongObject *)right) <= 1); + Py_ssize_t ileft = _PyLong_CompactValue((PyLongObject *)left); + Py_ssize_t iright = _PyLong_CompactValue((PyLongObject *)right); + // 2 if <, 4 if >, 8 if ==; this matches the low 4 bits of the oparg + int sign_ish = COMPARISON_BIT(ileft, iright); + _Py_DECREF_SPECIALIZED(left, (destructor)PyObject_Free); + _Py_DECREF_SPECIALIZED(right, (destructor)PyObject_Free); + res = (sign_ish & oparg) ? Py_True : Py_False; + STACK_SHRINK(1); + stack_pointer[-1] = res; + break; + } + + case COMPARE_OP_STR: { + PyObject *right = stack_pointer[-1]; + PyObject *left = stack_pointer[-2]; + PyObject *res; + DEOPT_IF(!PyUnicode_CheckExact(left), COMPARE_OP); + DEOPT_IF(!PyUnicode_CheckExact(right), COMPARE_OP); + STAT_INC(COMPARE_OP, hit); + int eq = _PyUnicode_Equal(left, right); + assert((oparg >>4) == Py_EQ || (oparg >>4) == Py_NE); + _Py_DECREF_SPECIALIZED(left, _PyUnicode_ExactDealloc); + _Py_DECREF_SPECIALIZED(right, _PyUnicode_ExactDealloc); + assert(eq == 0 || eq == 1); + assert((oparg & 0xf) == COMPARISON_NOT_EQUALS || (oparg & 0xf) == COMPARISON_EQUALS); + assert(COMPARISON_NOT_EQUALS + 1 == COMPARISON_EQUALS); + res = ((COMPARISON_NOT_EQUALS + eq) & oparg) ? Py_True : Py_False; + STACK_SHRINK(1); + stack_pointer[-1] = res; + break; + } + + case IS_OP: { + PyObject *right = stack_pointer[-1]; + PyObject *left = stack_pointer[-2]; + PyObject *b; + int res = Py_Is(left, right) ^ oparg; + Py_DECREF(left); + Py_DECREF(right); + b = res ? Py_True : Py_False; + STACK_SHRINK(1); + stack_pointer[-1] = b; + break; + } + + case CONTAINS_OP: { + PyObject *right = stack_pointer[-1]; + PyObject *left = stack_pointer[-2]; + PyObject *b; + int res = PySequence_Contains(right, left); + Py_DECREF(left); + Py_DECREF(right); + if (res < 0) goto pop_2_error; + b = (res ^ oparg) ? Py_True : Py_False; + STACK_SHRINK(1); + stack_pointer[-1] = b; + break; + } + + case CHECK_EG_MATCH: { + PyObject *match_type = stack_pointer[-1]; + PyObject *exc_value = stack_pointer[-2]; + PyObject *rest; + PyObject *match; + if (check_except_star_type_valid(tstate, match_type) < 0) { + Py_DECREF(exc_value); + Py_DECREF(match_type); + if (true) goto pop_2_error; + } + + match = NULL; + rest = NULL; + int res = exception_group_match(exc_value, match_type, + &match, &rest); + Py_DECREF(exc_value); + Py_DECREF(match_type); + if (res < 0) goto pop_2_error; + + assert((match == NULL) == (rest == NULL)); + if (match == NULL) goto pop_2_error; + + if (!Py_IsNone(match)) { + PyErr_SetHandledException(match); + } + stack_pointer[-1] = match; + stack_pointer[-2] = rest; + break; + } + + case CHECK_EXC_MATCH: { + PyObject *right = stack_pointer[-1]; + PyObject *left = stack_pointer[-2]; + PyObject *b; + assert(PyExceptionInstance_Check(left)); + if (check_except_type_valid(tstate, right) < 0) { + Py_DECREF(right); + if (true) goto pop_1_error; + } + + int res = PyErr_GivenExceptionMatches(left, right); + Py_DECREF(right); + b = res ? Py_True : Py_False; + stack_pointer[-1] = b; + break; + } + + case GET_LEN: { + PyObject *obj = stack_pointer[-1]; + PyObject *len_o; + // PUSH(len(TOS)) + Py_ssize_t len_i = PyObject_Length(obj); + if (len_i < 0) goto error; + len_o = PyLong_FromSsize_t(len_i); + if (len_o == NULL) goto error; + STACK_GROW(1); + stack_pointer[-1] = len_o; + break; + } + + case MATCH_CLASS: { + PyObject *names = stack_pointer[-1]; + PyObject *type = stack_pointer[-2]; + PyObject *subject = stack_pointer[-3]; + PyObject *attrs; + // Pop TOS and TOS1. Set TOS to a tuple of attributes on success, or + // None on failure. + assert(PyTuple_CheckExact(names)); + attrs = match_class(tstate, subject, type, oparg, names); + Py_DECREF(subject); + Py_DECREF(type); + Py_DECREF(names); + if (attrs) { + assert(PyTuple_CheckExact(attrs)); // Success! + } + else { + if (_PyErr_Occurred(tstate)) goto pop_3_error; + attrs = Py_None; // Failure! + } + STACK_SHRINK(2); + stack_pointer[-1] = attrs; + break; + } + + case MATCH_MAPPING: { + PyObject *subject = stack_pointer[-1]; + PyObject *res; + int match = Py_TYPE(subject)->tp_flags & Py_TPFLAGS_MAPPING; + res = match ? Py_True : Py_False; + STACK_GROW(1); + stack_pointer[-1] = res; + break; + } + + case MATCH_SEQUENCE: { + PyObject *subject = stack_pointer[-1]; + PyObject *res; + int match = Py_TYPE(subject)->tp_flags & Py_TPFLAGS_SEQUENCE; + res = match ? Py_True : Py_False; + STACK_GROW(1); + stack_pointer[-1] = res; + break; + } + + case MATCH_KEYS: { + PyObject *keys = stack_pointer[-1]; + PyObject *subject = stack_pointer[-2]; + PyObject *values_or_none; + // On successful match, PUSH(values). Otherwise, PUSH(None). + values_or_none = match_keys(tstate, subject, keys); + if (values_or_none == NULL) goto error; + STACK_GROW(1); + stack_pointer[-1] = values_or_none; + break; + } + + case GET_ITER: { + PyObject *iterable = stack_pointer[-1]; + PyObject *iter; + /* before: [obj]; after [getiter(obj)] */ + iter = PyObject_GetIter(iterable); + Py_DECREF(iterable); + if (iter == NULL) goto pop_1_error; + stack_pointer[-1] = iter; + break; + } + + case GET_YIELD_FROM_ITER: { + PyObject *iterable = stack_pointer[-1]; + PyObject *iter; + /* before: [obj]; after [getiter(obj)] */ + if (PyCoro_CheckExact(iterable)) { + /* `iterable` is a coroutine */ + if (!(_PyFrame_GetCode(frame)->co_flags & (CO_COROUTINE | CO_ITERABLE_COROUTINE))) { + /* and it is used in a 'yield from' expression of a + regular generator. */ + _PyErr_SetString(tstate, PyExc_TypeError, + "cannot 'yield from' a coroutine object " + "in a non-coroutine generator"); + goto error; + } + iter = iterable; + } + else if (PyGen_CheckExact(iterable)) { + iter = iterable; + } + else { + /* `iterable` is not a generator. */ + iter = PyObject_GetIter(iterable); + if (iter == NULL) { + goto error; + } + Py_DECREF(iterable); + } + stack_pointer[-1] = iter; + break; + } + + case WITH_EXCEPT_START: { + PyObject *val = stack_pointer[-1]; + PyObject *lasti = stack_pointer[-3]; + PyObject *exit_func = stack_pointer[-4]; + PyObject *res; + /* At the top of the stack are 4 values: + - val: TOP = exc_info() + - unused: SECOND = previous exception + - lasti: THIRD = lasti of exception in exc_info() + - exit_func: FOURTH = the context.__exit__ bound method + We call FOURTH(type(TOP), TOP, GetTraceback(TOP)). + Then we push the __exit__ return value. + */ + PyObject *exc, *tb; + + assert(val && PyExceptionInstance_Check(val)); + exc = PyExceptionInstance_Class(val); + tb = PyException_GetTraceback(val); + Py_XDECREF(tb); + assert(PyLong_Check(lasti)); + (void)lasti; // Shut up compiler warning if asserts are off + PyObject *stack[4] = {NULL, exc, val, tb}; + res = PyObject_Vectorcall(exit_func, stack + 1, + 3 | PY_VECTORCALL_ARGUMENTS_OFFSET, NULL); + if (res == NULL) goto error; + STACK_GROW(1); + stack_pointer[-1] = res; + break; + } + + case PUSH_EXC_INFO: { + PyObject *new_exc = stack_pointer[-1]; + PyObject *prev_exc; + _PyErr_StackItem *exc_info = tstate->exc_info; + if (exc_info->exc_value != NULL) { + prev_exc = exc_info->exc_value; + } + else { + prev_exc = Py_None; + } + assert(PyExceptionInstance_Check(new_exc)); + exc_info->exc_value = Py_NewRef(new_exc); + STACK_GROW(1); + stack_pointer[-1] = new_exc; + stack_pointer[-2] = prev_exc; + break; + } + + case EXIT_INIT_CHECK: { + PyObject *should_be_none = stack_pointer[-1]; + assert(STACK_LEVEL() == 2); + if (should_be_none != Py_None) { + PyErr_Format(PyExc_TypeError, + "__init__() should return None, not '%.200s'", + Py_TYPE(should_be_none)->tp_name); + goto error; + } + STACK_SHRINK(1); + break; + } + + case MAKE_FUNCTION: { + PyObject *codeobj = stack_pointer[-1]; + PyObject *func; + + PyFunctionObject *func_obj = (PyFunctionObject *) + PyFunction_New(codeobj, GLOBALS()); + + Py_DECREF(codeobj); + if (func_obj == NULL) { + goto error; + } + + func_obj->func_version = ((PyCodeObject *)codeobj)->co_version; + func = (PyObject *)func_obj; + stack_pointer[-1] = func; + break; + } + + case SET_FUNCTION_ATTRIBUTE: { + PyObject *func = stack_pointer[-1]; + PyObject *attr = stack_pointer[-2]; + assert(PyFunction_Check(func)); + PyFunctionObject *func_obj = (PyFunctionObject *)func; + switch(oparg) { + case MAKE_FUNCTION_CLOSURE: + assert(func_obj->func_closure == NULL); + func_obj->func_closure = attr; + break; + case MAKE_FUNCTION_ANNOTATIONS: + assert(func_obj->func_annotations == NULL); + func_obj->func_annotations = attr; + break; + case MAKE_FUNCTION_KWDEFAULTS: + assert(PyDict_CheckExact(attr)); + assert(func_obj->func_kwdefaults == NULL); + func_obj->func_kwdefaults = attr; + break; + case MAKE_FUNCTION_DEFAULTS: + assert(PyTuple_CheckExact(attr)); + assert(func_obj->func_defaults == NULL); + func_obj->func_defaults = attr; + break; + default: + Py_UNREACHABLE(); + } + STACK_SHRINK(1); + stack_pointer[-1] = func; + break; + } + + case BUILD_SLICE: { + PyObject *step = (oparg == 3) ? stack_pointer[-(((oparg == 3) ? 1 : 0))] : NULL; + PyObject *stop = stack_pointer[-(1 + ((oparg == 3) ? 1 : 0))]; + PyObject *start = stack_pointer[-(2 + ((oparg == 3) ? 1 : 0))]; + PyObject *slice; + slice = PySlice_New(start, stop, step); + Py_DECREF(start); + Py_DECREF(stop); + Py_XDECREF(step); + if (slice == NULL) { STACK_SHRINK(((oparg == 3) ? 1 : 0)); goto pop_2_error; } + STACK_SHRINK(((oparg == 3) ? 1 : 0)); + STACK_SHRINK(1); + stack_pointer[-1] = slice; + break; + } + + case CONVERT_VALUE: { + PyObject *value = stack_pointer[-1]; + PyObject *result; + convertion_func_ptr conv_fn; + assert(oparg >= FVC_STR && oparg <= FVC_ASCII); + conv_fn = CONVERSION_FUNCTIONS[oparg]; + result = conv_fn(value); + Py_DECREF(value); + if (result == NULL) goto pop_1_error; + stack_pointer[-1] = result; + break; + } + + case FORMAT_SIMPLE: { + PyObject *value = stack_pointer[-1]; + PyObject *res; + /* If value is a unicode object, then we know the result + * of format(value) is value itself. */ + if (!PyUnicode_CheckExact(value)) { + res = PyObject_Format(value, NULL); + Py_DECREF(value); + if (res == NULL) goto pop_1_error; + } + else { + res = value; + } + stack_pointer[-1] = res; + break; + } + + case FORMAT_WITH_SPEC: { + PyObject *fmt_spec = stack_pointer[-1]; + PyObject *value = stack_pointer[-2]; + PyObject *res; + res = PyObject_Format(value, fmt_spec); + Py_DECREF(value); + Py_DECREF(fmt_spec); + if (res == NULL) goto pop_2_error; + STACK_SHRINK(1); + stack_pointer[-1] = res; + break; + } + + case COPY: { + PyObject *bottom = stack_pointer[-(1 + (oparg-1))]; + PyObject *top; + assert(oparg > 0); + top = Py_NewRef(bottom); + STACK_GROW(1); + stack_pointer[-1] = top; + break; + } + + case SWAP: { + PyObject *top = stack_pointer[-1]; + PyObject *bottom = stack_pointer[-(2 + (oparg-2))]; + assert(oparg >= 2); + stack_pointer[-1] = bottom; + stack_pointer[-(2 + (oparg-2))] = top; + break; + } diff --git a/Python/generated_cases.c.h b/Python/generated_cases.c.h index 11ca535..43cfd4a 100644 --- a/Python/generated_cases.c.h +++ b/Python/generated_cases.c.h @@ -8,7 +8,7 @@ } TARGET(RESUME) { - #line 139 "Python/bytecodes.c" + #line 137 "Python/bytecodes.c" assert(tstate->cframe == &cframe); assert(frame == cframe.current_frame); /* Possibly combine this with eval breaker */ @@ -25,7 +25,7 @@ } TARGET(INSTRUMENTED_RESUME) { - #line 153 "Python/bytecodes.c" + #line 151 "Python/bytecodes.c" /* Possible performance enhancement: * We need to check the eval breaker anyway, can we * combine the instrument verison check and the eval breaker test? @@ -57,7 +57,7 @@ TARGET(LOAD_CLOSURE) { PyObject *value; - #line 181 "Python/bytecodes.c" + #line 179 "Python/bytecodes.c" /* We keep LOAD_CLOSURE so that the bytecode stays more readable. */ value = GETLOCAL(oparg); if (value == NULL) goto unbound_local_error; @@ -70,7 +70,7 @@ TARGET(LOAD_FAST_CHECK) { PyObject *value; - #line 188 "Python/bytecodes.c" + #line 186 "Python/bytecodes.c" value = GETLOCAL(oparg); if (value == NULL) goto unbound_local_error; Py_INCREF(value); @@ -82,7 +82,7 @@ TARGET(LOAD_FAST) { PyObject *value; - #line 194 "Python/bytecodes.c" + #line 192 "Python/bytecodes.c" value = GETLOCAL(oparg); assert(value != NULL); Py_INCREF(value); @@ -94,7 +94,7 @@ TARGET(LOAD_FAST_AND_CLEAR) { PyObject *value; - #line 200 "Python/bytecodes.c" + #line 198 "Python/bytecodes.c" value = GETLOCAL(oparg); // do not use SETLOCAL here, it decrefs the old value GETLOCAL(oparg) = NULL; @@ -107,7 +107,7 @@ TARGET(LOAD_FAST_LOAD_FAST) { PyObject *value1; PyObject *value2; - #line 206 "Python/bytecodes.c" + #line 204 "Python/bytecodes.c" uint32_t oparg1 = oparg >> 4; uint32_t oparg2 = oparg & 15; value1 = GETLOCAL(oparg1); @@ -123,7 +123,7 @@ TARGET(LOAD_CONST) { PyObject *value; - #line 215 "Python/bytecodes.c" + #line 213 "Python/bytecodes.c" value = GETITEM(FRAME_CO_CONSTS, oparg); Py_INCREF(value); #line 130 "Python/generated_cases.c.h" @@ -134,7 +134,7 @@ TARGET(STORE_FAST) { PyObject *value = stack_pointer[-1]; - #line 220 "Python/bytecodes.c" + #line 218 "Python/bytecodes.c" SETLOCAL(oparg, value); #line 140 "Python/generated_cases.c.h" STACK_SHRINK(1); @@ -144,7 +144,7 @@ TARGET(STORE_FAST_LOAD_FAST) { PyObject *value1 = stack_pointer[-1]; PyObject *value2; - #line 228 "Python/bytecodes.c" + #line 226 "Python/bytecodes.c" uint32_t oparg1 = oparg >> 4; uint32_t oparg2 = oparg & 15; SETLOCAL(oparg1, value1); @@ -158,7 +158,7 @@ TARGET(STORE_FAST_STORE_FAST) { PyObject *value1 = stack_pointer[-1]; PyObject *value2 = stack_pointer[-2]; - #line 236 "Python/bytecodes.c" + #line 234 "Python/bytecodes.c" uint32_t oparg1 = oparg >> 4; uint32_t oparg2 = oparg & 15; SETLOCAL(oparg1, value1); @@ -170,7 +170,7 @@ TARGET(POP_TOP) { PyObject *value = stack_pointer[-1]; - #line 243 "Python/bytecodes.c" + #line 241 "Python/bytecodes.c" #line 175 "Python/generated_cases.c.h" Py_DECREF(value); STACK_SHRINK(1); @@ -179,7 +179,7 @@ TARGET(PUSH_NULL) { PyObject *res; - #line 247 "Python/bytecodes.c" + #line 245 "Python/bytecodes.c" res = NULL; #line 185 "Python/generated_cases.c.h" STACK_GROW(1); @@ -192,13 +192,13 @@ PyObject *_tmp_2 = stack_pointer[-2]; { PyObject *value = _tmp_1; - #line 243 "Python/bytecodes.c" + #line 241 "Python/bytecodes.c" #line 197 "Python/generated_cases.c.h" Py_DECREF(value); } { PyObject *value = _tmp_2; - #line 243 "Python/bytecodes.c" + #line 241 "Python/bytecodes.c" #line 203 "Python/generated_cases.c.h" Py_DECREF(value); } @@ -209,7 +209,7 @@ TARGET(INSTRUMENTED_END_FOR) { PyObject *value = stack_pointer[-1]; PyObject *receiver = stack_pointer[-2]; - #line 253 "Python/bytecodes.c" + #line 251 "Python/bytecodes.c" /* Need to create a fake StopIteration error here, * to conform to PEP 380 */ if (PyGen_Check(receiver)) { @@ -229,7 +229,7 @@ TARGET(END_SEND) { PyObject *value = stack_pointer[-1]; PyObject *receiver = stack_pointer[-2]; - #line 266 "Python/bytecodes.c" + #line 264 "Python/bytecodes.c" Py_DECREF(receiver); #line 235 "Python/generated_cases.c.h" STACK_SHRINK(1); @@ -240,7 +240,7 @@ TARGET(INSTRUMENTED_END_SEND) { PyObject *value = stack_pointer[-1]; PyObject *receiver = stack_pointer[-2]; - #line 270 "Python/bytecodes.c" + #line 268 "Python/bytecodes.c" if (PyGen_Check(receiver) || PyCoro_CheckExact(receiver)) { PyErr_SetObject(PyExc_StopIteration, value); if (monitor_stop_iteration(tstate, frame, next_instr-1)) { @@ -258,11 +258,11 @@ TARGET(UNARY_NEGATIVE) { PyObject *value = stack_pointer[-1]; PyObject *res; - #line 281 "Python/bytecodes.c" + #line 279 "Python/bytecodes.c" res = PyNumber_Negative(value); #line 264 "Python/generated_cases.c.h" Py_DECREF(value); - #line 283 "Python/bytecodes.c" + #line 281 "Python/bytecodes.c" if (res == NULL) goto pop_1_error; #line 268 "Python/generated_cases.c.h" stack_pointer[-1] = res; @@ -272,11 +272,11 @@ TARGET(UNARY_NOT) { PyObject *value = stack_pointer[-1]; PyObject *res; - #line 287 "Python/bytecodes.c" + #line 285 "Python/bytecodes.c" int err = PyObject_IsTrue(value); #line 278 "Python/generated_cases.c.h" Py_DECREF(value); - #line 289 "Python/bytecodes.c" + #line 287 "Python/bytecodes.c" if (err < 0) goto pop_1_error; if (err == 0) { res = Py_True; @@ -292,11 +292,11 @@ TARGET(UNARY_INVERT) { PyObject *value = stack_pointer[-1]; PyObject *res; - #line 299 "Python/bytecodes.c" + #line 297 "Python/bytecodes.c" res = PyNumber_Invert(value); #line 298 "Python/generated_cases.c.h" Py_DECREF(value); - #line 301 "Python/bytecodes.c" + #line 299 "Python/bytecodes.c" if (res == NULL) goto pop_1_error; #line 302 "Python/generated_cases.c.h" stack_pointer[-1] = res; @@ -309,7 +309,7 @@ { PyObject *right = _tmp_1; PyObject *left = _tmp_2; - #line 317 "Python/bytecodes.c" + #line 315 "Python/bytecodes.c" DEOPT_IF(!PyLong_CheckExact(left), BINARY_OP); DEOPT_IF(!PyLong_CheckExact(right), BINARY_OP); #line 316 "Python/generated_cases.c.h" @@ -320,7 +320,7 @@ PyObject *right = _tmp_1; PyObject *left = _tmp_2; PyObject *res; - #line 322 "Python/bytecodes.c" + #line 320 "Python/bytecodes.c" STAT_INC(BINARY_OP, hit); res = _PyLong_Multiply((PyLongObject *)left, (PyLongObject *)right); _Py_DECREF_SPECIALIZED(right, (destructor)PyObject_Free); @@ -341,7 +341,7 @@ { PyObject *right = _tmp_1; PyObject *left = _tmp_2; - #line 317 "Python/bytecodes.c" + #line 315 "Python/bytecodes.c" DEOPT_IF(!PyLong_CheckExact(left), BINARY_OP); DEOPT_IF(!PyLong_CheckExact(right), BINARY_OP); #line 348 "Python/generated_cases.c.h" @@ -352,7 +352,7 @@ PyObject *right = _tmp_1; PyObject *left = _tmp_2; PyObject *res; - #line 330 "Python/bytecodes.c" + #line 328 "Python/bytecodes.c" STAT_INC(BINARY_OP, hit); res = _PyLong_Add((PyLongObject *)left, (PyLongObject *)right); _Py_DECREF_SPECIALIZED(right, (destructor)PyObject_Free); @@ -373,7 +373,7 @@ { PyObject *right = _tmp_1; PyObject *left = _tmp_2; - #line 317 "Python/bytecodes.c" + #line 315 "Python/bytecodes.c" DEOPT_IF(!PyLong_CheckExact(left), BINARY_OP); DEOPT_IF(!PyLong_CheckExact(right), BINARY_OP); #line 380 "Python/generated_cases.c.h" @@ -384,7 +384,7 @@ PyObject *right = _tmp_1; PyObject *left = _tmp_2; PyObject *res; - #line 338 "Python/bytecodes.c" + #line 336 "Python/bytecodes.c" STAT_INC(BINARY_OP, hit); res = _PyLong_Subtract((PyLongObject *)left, (PyLongObject *)right); _Py_DECREF_SPECIALIZED(right, (destructor)PyObject_Free); @@ -405,7 +405,7 @@ { PyObject *right = _tmp_1; PyObject *left = _tmp_2; - #line 353 "Python/bytecodes.c" + #line 351 "Python/bytecodes.c" DEOPT_IF(!PyFloat_CheckExact(left), BINARY_OP); DEOPT_IF(!PyFloat_CheckExact(right), BINARY_OP); #line 412 "Python/generated_cases.c.h" @@ -416,7 +416,7 @@ PyObject *right = _tmp_1; PyObject *left = _tmp_2; PyObject *res; - #line 358 "Python/bytecodes.c" + #line 356 "Python/bytecodes.c" STAT_INC(BINARY_OP, hit); double dres = ((PyFloatObject *)left)->ob_fval * @@ -437,7 +437,7 @@ { PyObject *right = _tmp_1; PyObject *left = _tmp_2; - #line 353 "Python/bytecodes.c" + #line 351 "Python/bytecodes.c" DEOPT_IF(!PyFloat_CheckExact(left), BINARY_OP); DEOPT_IF(!PyFloat_CheckExact(right), BINARY_OP); #line 444 "Python/generated_cases.c.h" @@ -448,7 +448,7 @@ PyObject *right = _tmp_1; PyObject *left = _tmp_2; PyObject *res; - #line 366 "Python/bytecodes.c" + #line 364 "Python/bytecodes.c" STAT_INC(BINARY_OP, hit); double dres = ((PyFloatObject *)left)->ob_fval + @@ -469,7 +469,7 @@ { PyObject *right = _tmp_1; PyObject *left = _tmp_2; - #line 353 "Python/bytecodes.c" + #line 351 "Python/bytecodes.c" DEOPT_IF(!PyFloat_CheckExact(left), BINARY_OP); DEOPT_IF(!PyFloat_CheckExact(right), BINARY_OP); #line 476 "Python/generated_cases.c.h" @@ -480,7 +480,7 @@ PyObject *right = _tmp_1; PyObject *left = _tmp_2; PyObject *res; - #line 374 "Python/bytecodes.c" + #line 372 "Python/bytecodes.c" STAT_INC(BINARY_OP, hit); double dres = ((PyFloatObject *)left)->ob_fval - @@ -501,7 +501,7 @@ { PyObject *right = _tmp_1; PyObject *left = _tmp_2; - #line 389 "Python/bytecodes.c" + #line 387 "Python/bytecodes.c" DEOPT_IF(!PyUnicode_CheckExact(left), BINARY_OP); DEOPT_IF(!PyUnicode_CheckExact(right), BINARY_OP); #line 508 "Python/generated_cases.c.h" @@ -512,7 +512,7 @@ PyObject *right = _tmp_1; PyObject *left = _tmp_2; PyObject *res; - #line 394 "Python/bytecodes.c" + #line 392 "Python/bytecodes.c" STAT_INC(BINARY_OP, hit); res = PyUnicode_Concat(left, right); _Py_DECREF_SPECIALIZED(left, _PyUnicode_ExactDealloc); @@ -533,7 +533,7 @@ { PyObject *right = _tmp_1; PyObject *left = _tmp_2; - #line 389 "Python/bytecodes.c" + #line 387 "Python/bytecodes.c" DEOPT_IF(!PyUnicode_CheckExact(left), BINARY_OP); DEOPT_IF(!PyUnicode_CheckExact(right), BINARY_OP); #line 540 "Python/generated_cases.c.h" @@ -543,7 +543,7 @@ { PyObject *right = _tmp_1; PyObject *left = _tmp_2; - #line 411 "Python/bytecodes.c" + #line 409 "Python/bytecodes.c" _Py_CODEUNIT true_next = next_instr[INLINE_CACHE_ENTRIES_BINARY_OP]; assert(true_next.op.code == STORE_FAST); PyObject **target_local = &GETLOCAL(true_next.op.arg); @@ -579,7 +579,7 @@ PyObject *sub = stack_pointer[-1]; PyObject *container = stack_pointer[-2]; PyObject *res; - #line 448 "Python/bytecodes.c" + #line 446 "Python/bytecodes.c" #if ENABLE_SPECIALIZATION _PyBinarySubscrCache *cache = (_PyBinarySubscrCache *)next_instr; if (ADAPTIVE_COUNTER_IS_ZERO(cache->counter)) { @@ -594,7 +594,7 @@ #line 595 "Python/generated_cases.c.h" Py_DECREF(container); Py_DECREF(sub); - #line 460 "Python/bytecodes.c" + #line 458 "Python/bytecodes.c" if (res == NULL) goto pop_2_error; #line 600 "Python/generated_cases.c.h" STACK_SHRINK(1); @@ -608,7 +608,7 @@ PyObject *start = stack_pointer[-2]; PyObject *container = stack_pointer[-3]; PyObject *res; - #line 464 "Python/bytecodes.c" + #line 462 "Python/bytecodes.c" PyObject *slice = _PyBuildSlice_ConsumeRefs(start, stop); // Can't use ERROR_IF() here, because we haven't // DECREF'ed container yet, and we still own slice. @@ -632,7 +632,7 @@ PyObject *start = stack_pointer[-2]; PyObject *container = stack_pointer[-3]; PyObject *v = stack_pointer[-4]; - #line 479 "Python/bytecodes.c" + #line 477 "Python/bytecodes.c" PyObject *slice = _PyBuildSlice_ConsumeRefs(start, stop); int err; if (slice == NULL) { @@ -654,7 +654,7 @@ PyObject *sub = stack_pointer[-1]; PyObject *list = stack_pointer[-2]; PyObject *res; - #line 494 "Python/bytecodes.c" + #line 492 "Python/bytecodes.c" DEOPT_IF(!PyLong_CheckExact(sub), BINARY_SUBSCR); DEOPT_IF(!PyList_CheckExact(list), BINARY_SUBSCR); @@ -679,7 +679,7 @@ PyObject *sub = stack_pointer[-1]; PyObject *tuple = stack_pointer[-2]; PyObject *res; - #line 510 "Python/bytecodes.c" + #line 508 "Python/bytecodes.c" DEOPT_IF(!PyLong_CheckExact(sub), BINARY_SUBSCR); DEOPT_IF(!PyTuple_CheckExact(tuple), BINARY_SUBSCR); @@ -704,7 +704,7 @@ PyObject *sub = stack_pointer[-1]; PyObject *dict = stack_pointer[-2]; PyObject *res; - #line 526 "Python/bytecodes.c" + #line 524 "Python/bytecodes.c" DEOPT_IF(!PyDict_CheckExact(dict), BINARY_SUBSCR); STAT_INC(BINARY_SUBSCR, hit); res = PyDict_GetItemWithError(dict, sub); @@ -715,7 +715,7 @@ #line 716 "Python/generated_cases.c.h" Py_DECREF(dict); Py_DECREF(sub); - #line 534 "Python/bytecodes.c" + #line 532 "Python/bytecodes.c" if (true) goto pop_2_error; } Py_INCREF(res); // Do this before DECREF'ing dict, sub @@ -731,7 +731,7 @@ TARGET(BINARY_SUBSCR_GETITEM) { PyObject *sub = stack_pointer[-1]; PyObject *container = stack_pointer[-2]; - #line 541 "Python/bytecodes.c" + #line 539 "Python/bytecodes.c" DEOPT_IF(tstate->interp->eval_frame, BINARY_SUBSCR); PyTypeObject *tp = Py_TYPE(container); DEOPT_IF(!PyType_HasFeature(tp, Py_TPFLAGS_HEAPTYPE), BINARY_SUBSCR); @@ -760,7 +760,7 @@ TARGET(LIST_APPEND) { PyObject *v = stack_pointer[-1]; PyObject *list = stack_pointer[-(2 + (oparg-1))]; - #line 566 "Python/bytecodes.c" + #line 564 "Python/bytecodes.c" if (_PyList_AppendTakeRef((PyListObject *)list, v) < 0) goto pop_1_error; #line 766 "Python/generated_cases.c.h" STACK_SHRINK(1); @@ -770,11 +770,11 @@ TARGET(SET_ADD) { PyObject *v = stack_pointer[-1]; PyObject *set = stack_pointer[-(2 + (oparg-1))]; - #line 570 "Python/bytecodes.c" + #line 568 "Python/bytecodes.c" int err = PySet_Add(set, v); #line 776 "Python/generated_cases.c.h" Py_DECREF(v); - #line 572 "Python/bytecodes.c" + #line 570 "Python/bytecodes.c" if (err) goto pop_1_error; #line 780 "Python/generated_cases.c.h" STACK_SHRINK(1); @@ -788,7 +788,7 @@ PyObject *container = stack_pointer[-2]; PyObject *v = stack_pointer[-3]; uint16_t counter = read_u16(&next_instr[0].cache); - #line 582 "Python/bytecodes.c" + #line 580 "Python/bytecodes.c" #if ENABLE_SPECIALIZATION if (ADAPTIVE_COUNTER_IS_ZERO(counter)) { next_instr--; @@ -807,7 +807,7 @@ Py_DECREF(v); Py_DECREF(container); Py_DECREF(sub); - #line 597 "Python/bytecodes.c" + #line 595 "Python/bytecodes.c" if (err) goto pop_3_error; #line 813 "Python/generated_cases.c.h" STACK_SHRINK(3); @@ -819,7 +819,7 @@ PyObject *sub = stack_pointer[-1]; PyObject *list = stack_pointer[-2]; PyObject *value = stack_pointer[-3]; - #line 601 "Python/bytecodes.c" + #line 599 "Python/bytecodes.c" DEOPT_IF(!PyLong_CheckExact(sub), STORE_SUBSCR); DEOPT_IF(!PyList_CheckExact(list), STORE_SUBSCR); @@ -846,7 +846,7 @@ PyObject *sub = stack_pointer[-1]; PyObject *dict = stack_pointer[-2]; PyObject *value = stack_pointer[-3]; - #line 620 "Python/bytecodes.c" + #line 618 "Python/bytecodes.c" DEOPT_IF(!PyDict_CheckExact(dict), STORE_SUBSCR); STAT_INC(STORE_SUBSCR, hit); int err = _PyDict_SetItem_Take2((PyDictObject *)dict, sub, value); @@ -861,13 +861,13 @@ TARGET(DELETE_SUBSCR) { PyObject *sub = stack_pointer[-1]; PyObject *container = stack_pointer[-2]; - #line 628 "Python/bytecodes.c" + #line 626 "Python/bytecodes.c" /* del container[sub] */ int err = PyObject_DelItem(container, sub); #line 868 "Python/generated_cases.c.h" Py_DECREF(container); Py_DECREF(sub); - #line 631 "Python/bytecodes.c" + #line 629 "Python/bytecodes.c" if (err) goto pop_2_error; #line 873 "Python/generated_cases.c.h" STACK_SHRINK(2); @@ -877,12 +877,12 @@ TARGET(CALL_INTRINSIC_1) { PyObject *value = stack_pointer[-1]; PyObject *res; - #line 635 "Python/bytecodes.c" + #line 633 "Python/bytecodes.c" assert(oparg <= MAX_INTRINSIC_1); res = _PyIntrinsics_UnaryFunctions[oparg](tstate, value); #line 884 "Python/generated_cases.c.h" Py_DECREF(value); - #line 638 "Python/bytecodes.c" + #line 636 "Python/bytecodes.c" if (res == NULL) goto pop_1_error; #line 888 "Python/generated_cases.c.h" stack_pointer[-1] = res; @@ -893,13 +893,13 @@ PyObject *value1 = stack_pointer[-1]; PyObject *value2 = stack_pointer[-2]; PyObject *res; - #line 642 "Python/bytecodes.c" + #line 640 "Python/bytecodes.c" assert(oparg <= MAX_INTRINSIC_2); res = _PyIntrinsics_BinaryFunctions[oparg](tstate, value2, value1); #line 900 "Python/generated_cases.c.h" Py_DECREF(value2); Py_DECREF(value1); - #line 645 "Python/bytecodes.c" + #line 643 "Python/bytecodes.c" if (res == NULL) goto pop_2_error; #line 905 "Python/generated_cases.c.h" STACK_SHRINK(1); @@ -909,7 +909,7 @@ TARGET(RAISE_VARARGS) { PyObject **args = (stack_pointer - oparg); - #line 649 "Python/bytecodes.c" + #line 647 "Python/bytecodes.c" PyObject *cause = NULL, *exc = NULL; switch (oparg) { case 2: @@ -932,7 +932,7 @@ TARGET(INTERPRETER_EXIT) { PyObject *retval = stack_pointer[-1]; - #line 669 "Python/bytecodes.c" + #line 667 "Python/bytecodes.c" assert(frame == &entry_frame); assert(_PyFrame_IsIncomplete(frame)); /* Restore previous cframe and return. */ @@ -946,7 +946,7 @@ TARGET(RETURN_VALUE) { PyObject *retval = stack_pointer[-1]; - #line 680 "Python/bytecodes.c" + #line 678 "Python/bytecodes.c" STACK_SHRINK(1); assert(EMPTY()); _PyFrame_SetStackPointer(frame, stack_pointer); @@ -964,7 +964,7 @@ TARGET(INSTRUMENTED_RETURN_VALUE) { PyObject *retval = stack_pointer[-1]; - #line 695 "Python/bytecodes.c" + #line 693 "Python/bytecodes.c" int err = _Py_call_instrumentation_arg( tstate, PY_MONITORING_EVENT_PY_RETURN, frame, next_instr-1, retval); @@ -985,7 +985,7 @@ } TARGET(RETURN_CONST) { - #line 714 "Python/bytecodes.c" + #line 712 "Python/bytecodes.c" PyObject *retval = GETITEM(FRAME_CO_CONSTS, oparg); Py_INCREF(retval); assert(EMPTY()); @@ -1003,7 +1003,7 @@ } TARGET(INSTRUMENTED_RETURN_CONST) { - #line 730 "Python/bytecodes.c" + #line 728 "Python/bytecodes.c" PyObject *retval = GETITEM(FRAME_CO_CONSTS, oparg); int err = _Py_call_instrumentation_arg( tstate, PY_MONITORING_EVENT_PY_RETURN, @@ -1027,7 +1027,7 @@ TARGET(GET_AITER) { PyObject *obj = stack_pointer[-1]; PyObject *iter; - #line 750 "Python/bytecodes.c" + #line 748 "Python/bytecodes.c" unaryfunc getter = NULL; PyTypeObject *type = Py_TYPE(obj); @@ -1042,14 +1042,14 @@ type->tp_name); #line 1044 "Python/generated_cases.c.h" Py_DECREF(obj); - #line 763 "Python/bytecodes.c" + #line 761 "Python/bytecodes.c" if (true) goto pop_1_error; } iter = (*getter)(obj); #line 1051 "Python/generated_cases.c.h" Py_DECREF(obj); - #line 768 "Python/bytecodes.c" + #line 766 "Python/bytecodes.c" if (iter == NULL) goto pop_1_error; if (Py_TYPE(iter)->tp_as_async == NULL || @@ -1070,7 +1070,7 @@ TARGET(GET_ANEXT) { PyObject *aiter = stack_pointer[-1]; PyObject *awaitable; - #line 783 "Python/bytecodes.c" + #line 781 "Python/bytecodes.c" unaryfunc getter = NULL; PyObject *next_iter = NULL; PyTypeObject *type = Py_TYPE(aiter); @@ -1122,7 +1122,7 @@ TARGET(GET_AWAITABLE) { PyObject *iterable = stack_pointer[-1]; PyObject *iter; - #line 828 "Python/bytecodes.c" + #line 826 "Python/bytecodes.c" iter = _PyCoro_GetAwaitableIter(iterable); if (iter == NULL) { @@ -1131,7 +1131,7 @@ #line 1133 "Python/generated_cases.c.h" Py_DECREF(iterable); - #line 835 "Python/bytecodes.c" + #line 833 "Python/bytecodes.c" if (iter != NULL && PyCoro_CheckExact(iter)) { PyObject *yf = _PyGen_yf((PyGenObject*)iter); @@ -1159,7 +1159,7 @@ PyObject *v = stack_pointer[-1]; PyObject *receiver = stack_pointer[-2]; PyObject *retval; - #line 859 "Python/bytecodes.c" + #line 857 "Python/bytecodes.c" #if ENABLE_SPECIALIZATION _PySendCache *cache = (_PySendCache *)next_instr; if (ADAPTIVE_COUNTER_IS_ZERO(cache->counter)) { @@ -1215,7 +1215,7 @@ TARGET(SEND_GEN) { PyObject *v = stack_pointer[-1]; PyObject *receiver = stack_pointer[-2]; - #line 908 "Python/bytecodes.c" + #line 906 "Python/bytecodes.c" DEOPT_IF(tstate->interp->eval_frame, SEND); PyGenObject *gen = (PyGenObject *)receiver; DEOPT_IF(Py_TYPE(gen) != &PyGen_Type && @@ -1236,7 +1236,7 @@ TARGET(INSTRUMENTED_YIELD_VALUE) { PyObject *retval = stack_pointer[-1]; - #line 926 "Python/bytecodes.c" + #line 924 "Python/bytecodes.c" assert(frame != &entry_frame); assert(oparg >= 0); /* make the generator identify this as HAS_ARG */ PyGenObject *gen = _PyFrame_GetGenerator(frame); @@ -1259,7 +1259,7 @@ TARGET(YIELD_VALUE) { PyObject *retval = stack_pointer[-1]; - #line 946 "Python/bytecodes.c" + #line 944 "Python/bytecodes.c" // NOTE: It's important that YIELD_VALUE never raises an exception! // The compiler treats any exception raised here as a failed close() // or throw() call. @@ -1281,7 +1281,7 @@ TARGET(POP_EXCEPT) { PyObject *exc_value = stack_pointer[-1]; - #line 965 "Python/bytecodes.c" + #line 963 "Python/bytecodes.c" _PyErr_StackItem *exc_info = tstate->exc_info; Py_XSETREF(exc_info->exc_value, exc_value); #line 1288 "Python/generated_cases.c.h" @@ -1292,7 +1292,7 @@ TARGET(RERAISE) { PyObject *exc = stack_pointer[-1]; PyObject **values = (stack_pointer - (1 + oparg)); - #line 970 "Python/bytecodes.c" + #line 968 "Python/bytecodes.c" assert(oparg >= 0 && oparg <= 2); if (oparg) { PyObject *lasti = values[0]; @@ -1316,13 +1316,13 @@ TARGET(END_ASYNC_FOR) { PyObject *exc = stack_pointer[-1]; PyObject *awaitable = stack_pointer[-2]; - #line 990 "Python/bytecodes.c" + #line 988 "Python/bytecodes.c" assert(exc && PyExceptionInstance_Check(exc)); if (PyErr_GivenExceptionMatches(exc, PyExc_StopAsyncIteration)) { #line 1323 "Python/generated_cases.c.h" Py_DECREF(awaitable); Py_DECREF(exc); - #line 993 "Python/bytecodes.c" + #line 991 "Python/bytecodes.c" } else { Py_INCREF(exc); @@ -1340,7 +1340,7 @@ PyObject *sub_iter = stack_pointer[-3]; PyObject *none; PyObject *value; - #line 1002 "Python/bytecodes.c" + #line 1000 "Python/bytecodes.c" assert(throwflag); assert(exc_value && PyExceptionInstance_Check(exc_value)); if (PyErr_GivenExceptionMatches(exc_value, PyExc_StopIteration)) { @@ -1349,7 +1349,7 @@ Py_DECREF(sub_iter); Py_DECREF(last_sent_val); Py_DECREF(exc_value); - #line 1007 "Python/bytecodes.c" + #line 1005 "Python/bytecodes.c" none = Py_None; } else { @@ -1365,7 +1365,7 @@ TARGET(LOAD_ASSERTION_ERROR) { PyObject *value; - #line 1016 "Python/bytecodes.c" + #line 1014 "Python/bytecodes.c" value = Py_NewRef(PyExc_AssertionError); #line 1371 "Python/generated_cases.c.h" STACK_GROW(1); @@ -1375,7 +1375,7 @@ TARGET(LOAD_BUILD_CLASS) { PyObject *bc; - #line 1020 "Python/bytecodes.c" + #line 1018 "Python/bytecodes.c" if (PyDict_CheckExact(BUILTINS())) { bc = _PyDict_GetItemWithError(BUILTINS(), &_Py_ID(__build_class__)); @@ -1405,7 +1405,7 @@ TARGET(STORE_NAME) { PyObject *v = stack_pointer[-1]; - #line 1045 "Python/bytecodes.c" + #line 1043 "Python/bytecodes.c" PyObject *name = GETITEM(FRAME_CO_NAMES, oparg); PyObject *ns = LOCALS(); int err; @@ -1414,7 +1414,7 @@ "no locals found when storing %R", name); #line 1416 "Python/generated_cases.c.h" Py_DECREF(v); - #line 1052 "Python/bytecodes.c" + #line 1050 "Python/bytecodes.c" if (true) goto pop_1_error; } if (PyDict_CheckExact(ns)) @@ -1423,7 +1423,7 @@ err = PyObject_SetItem(ns, name, v); #line 1425 "Python/generated_cases.c.h" Py_DECREF(v); - #line 1059 "Python/bytecodes.c" + #line 1057 "Python/bytecodes.c" if (err) goto pop_1_error; #line 1429 "Python/generated_cases.c.h" STACK_SHRINK(1); @@ -1431,7 +1431,7 @@ } TARGET(DELETE_NAME) { - #line 1063 "Python/bytecodes.c" + #line 1061 "Python/bytecodes.c" PyObject *name = GETITEM(FRAME_CO_NAMES, oparg); PyObject *ns = LOCALS(); int err; @@ -1456,7 +1456,7 @@ PREDICTED(UNPACK_SEQUENCE); static_assert(INLINE_CACHE_ENTRIES_UNPACK_SEQUENCE == 1, "incorrect cache size"); PyObject *seq = stack_pointer[-1]; - #line 1089 "Python/bytecodes.c" + #line 1087 "Python/bytecodes.c" #if ENABLE_SPECIALIZATION _PyUnpackSequenceCache *cache = (_PyUnpackSequenceCache *)next_instr; if (ADAPTIVE_COUNTER_IS_ZERO(cache->counter)) { @@ -1471,7 +1471,7 @@ int res = unpack_iterable(tstate, seq, oparg, -1, top); #line 1473 "Python/generated_cases.c.h" Py_DECREF(seq); - #line 1102 "Python/bytecodes.c" + #line 1100 "Python/bytecodes.c" if (res == 0) goto pop_1_error; #line 1477 "Python/generated_cases.c.h" STACK_SHRINK(1); @@ -1483,7 +1483,7 @@ TARGET(UNPACK_SEQUENCE_TWO_TUPLE) { PyObject *seq = stack_pointer[-1]; PyObject **values = stack_pointer - (1); - #line 1106 "Python/bytecodes.c" + #line 1104 "Python/bytecodes.c" DEOPT_IF(!PyTuple_CheckExact(seq), UNPACK_SEQUENCE); DEOPT_IF(PyTuple_GET_SIZE(seq) != 2, UNPACK_SEQUENCE); assert(oparg == 2); @@ -1501,7 +1501,7 @@ TARGET(UNPACK_SEQUENCE_TUPLE) { PyObject *seq = stack_pointer[-1]; PyObject **values = stack_pointer - (1); - #line 1116 "Python/bytecodes.c" + #line 1114 "Python/bytecodes.c" DEOPT_IF(!PyTuple_CheckExact(seq), UNPACK_SEQUENCE); DEOPT_IF(PyTuple_GET_SIZE(seq) != oparg, UNPACK_SEQUENCE); STAT_INC(UNPACK_SEQUENCE, hit); @@ -1520,7 +1520,7 @@ TARGET(UNPACK_SEQUENCE_LIST) { PyObject *seq = stack_pointer[-1]; PyObject **values = stack_pointer - (1); - #line 1127 "Python/bytecodes.c" + #line 1125 "Python/bytecodes.c" DEOPT_IF(!PyList_CheckExact(seq), UNPACK_SEQUENCE); DEOPT_IF(PyList_GET_SIZE(seq) != oparg, UNPACK_SEQUENCE); STAT_INC(UNPACK_SEQUENCE, hit); @@ -1538,13 +1538,13 @@ TARGET(UNPACK_EX) { PyObject *seq = stack_pointer[-1]; - #line 1138 "Python/bytecodes.c" + #line 1136 "Python/bytecodes.c" int totalargs = 1 + (oparg & 0xFF) + (oparg >> 8); PyObject **top = stack_pointer + totalargs - 1; int res = unpack_iterable(tstate, seq, oparg & 0xFF, oparg >> 8, top); #line 1546 "Python/generated_cases.c.h" Py_DECREF(seq); - #line 1142 "Python/bytecodes.c" + #line 1140 "Python/bytecodes.c" if (res == 0) goto pop_1_error; #line 1550 "Python/generated_cases.c.h" STACK_GROW((oparg & 0xFF) + (oparg >> 8)); @@ -1557,7 +1557,7 @@ PyObject *owner = stack_pointer[-1]; PyObject *v = stack_pointer[-2]; uint16_t counter = read_u16(&next_instr[0].cache); - #line 1153 "Python/bytecodes.c" + #line 1151 "Python/bytecodes.c" #if ENABLE_SPECIALIZATION if (ADAPTIVE_COUNTER_IS_ZERO(counter)) { PyObject *name = GETITEM(FRAME_CO_NAMES, oparg); @@ -1576,7 +1576,7 @@ #line 1577 "Python/generated_cases.c.h" Py_DECREF(v); Py_DECREF(owner); - #line 1169 "Python/bytecodes.c" + #line 1167 "Python/bytecodes.c" if (err) goto pop_2_error; #line 1582 "Python/generated_cases.c.h" STACK_SHRINK(2); @@ -1586,12 +1586,12 @@ TARGET(DELETE_ATTR) { PyObject *owner = stack_pointer[-1]; - #line 1173 "Python/bytecodes.c" + #line 1171 "Python/bytecodes.c" PyObject *name = GETITEM(FRAME_CO_NAMES, oparg); int err = PyObject_SetAttr(owner, name, (PyObject *)NULL); #line 1593 "Python/generated_cases.c.h" Py_DECREF(owner); - #line 1176 "Python/bytecodes.c" + #line 1174 "Python/bytecodes.c" if (err) goto pop_1_error; #line 1597 "Python/generated_cases.c.h" STACK_SHRINK(1); @@ -1600,12 +1600,12 @@ TARGET(STORE_GLOBAL) { PyObject *v = stack_pointer[-1]; - #line 1180 "Python/bytecodes.c" + #line 1178 "Python/bytecodes.c" PyObject *name = GETITEM(FRAME_CO_NAMES, oparg); int err = PyDict_SetItem(GLOBALS(), name, v); #line 1607 "Python/generated_cases.c.h" Py_DECREF(v); - #line 1183 "Python/bytecodes.c" + #line 1181 "Python/bytecodes.c" if (err) goto pop_1_error; #line 1611 "Python/generated_cases.c.h" STACK_SHRINK(1); @@ -1613,7 +1613,7 @@ } TARGET(DELETE_GLOBAL) { - #line 1187 "Python/bytecodes.c" + #line 1185 "Python/bytecodes.c" PyObject *name = GETITEM(FRAME_CO_NAMES, oparg); int err; err = PyDict_DelItem(GLOBALS(), name); @@ -1633,7 +1633,7 @@ PyObject *_tmp_1; { PyObject *locals; - #line 1201 "Python/bytecodes.c" + #line 1199 "Python/bytecodes.c" locals = LOCALS(); if (locals == NULL) { _PyErr_SetString(tstate, PyExc_SystemError, @@ -1653,7 +1653,7 @@ PyObject *_tmp_1; { PyObject *locals; - #line 1201 "Python/bytecodes.c" + #line 1199 "Python/bytecodes.c" locals = LOCALS(); if (locals == NULL) { _PyErr_SetString(tstate, PyExc_SystemError, @@ -1667,7 +1667,7 @@ { PyObject *mod_or_class_dict = _tmp_1; PyObject *v; - #line 1213 "Python/bytecodes.c" + #line 1211 "Python/bytecodes.c" PyObject *name = GETITEM(FRAME_CO_NAMES, oparg); if (PyDict_CheckExact(mod_or_class_dict)) { v = PyDict_GetItemWithError(mod_or_class_dict, name); @@ -1737,7 +1737,7 @@ { PyObject *mod_or_class_dict = _tmp_1; PyObject *v; - #line 1213 "Python/bytecodes.c" + #line 1211 "Python/bytecodes.c" PyObject *name = GETITEM(FRAME_CO_NAMES, oparg); if (PyDict_CheckExact(mod_or_class_dict)) { v = PyDict_GetItemWithError(mod_or_class_dict, name); @@ -1806,7 +1806,7 @@ static_assert(INLINE_CACHE_ENTRIES_LOAD_GLOBAL == 4, "incorrect cache size"); PyObject *null = NULL; PyObject *v; - #line 1282 "Python/bytecodes.c" + #line 1280 "Python/bytecodes.c" #if ENABLE_SPECIALIZATION _PyLoadGlobalCache *cache = (_PyLoadGlobalCache *)next_instr; if (ADAPTIVE_COUNTER_IS_ZERO(cache->counter)) { @@ -1872,7 +1872,7 @@ PyObject *res; uint16_t index = read_u16(&next_instr[1].cache); uint16_t version = read_u16(&next_instr[2].cache); - #line 1336 "Python/bytecodes.c" + #line 1334 "Python/bytecodes.c" DEOPT_IF(!PyDict_CheckExact(GLOBALS()), LOAD_GLOBAL); PyDictObject *dict = (PyDictObject *)GLOBALS(); DEOPT_IF(dict->ma_keys->dk_version != version, LOAD_GLOBAL); @@ -1898,7 +1898,7 @@ uint16_t index = read_u16(&next_instr[1].cache); uint16_t mod_version = read_u16(&next_instr[2].cache); uint16_t bltn_version = read_u16(&next_instr[3].cache); - #line 1349 "Python/bytecodes.c" + #line 1347 "Python/bytecodes.c" DEOPT_IF(!PyDict_CheckExact(GLOBALS()), LOAD_GLOBAL); DEOPT_IF(!PyDict_CheckExact(BUILTINS()), LOAD_GLOBAL); PyDictObject *mdict = (PyDictObject *)GLOBALS(); @@ -1923,7 +1923,7 @@ } TARGET(DELETE_FAST) { - #line 1366 "Python/bytecodes.c" + #line 1364 "Python/bytecodes.c" PyObject *v = GETLOCAL(oparg); if (v == NULL) goto unbound_local_error; SETLOCAL(oparg, NULL); @@ -1932,7 +1932,7 @@ } TARGET(MAKE_CELL) { - #line 1372 "Python/bytecodes.c" + #line 1370 "Python/bytecodes.c" // "initial" is probably NULL but not if it's an arg (or set // via PyFrame_LocalsToFast() before MAKE_CELL has run). PyObject *initial = GETLOCAL(oparg); @@ -1946,7 +1946,7 @@ } TARGET(DELETE_DEREF) { - #line 1383 "Python/bytecodes.c" + #line 1381 "Python/bytecodes.c" PyObject *cell = GETLOCAL(oparg); PyObject *oldobj = PyCell_GET(cell); // Can't use ERROR_IF here. @@ -1964,7 +1964,7 @@ TARGET(LOAD_FROM_DICT_OR_DEREF) { PyObject *class_dict = stack_pointer[-1]; PyObject *value; - #line 1396 "Python/bytecodes.c" + #line 1394 "Python/bytecodes.c" PyObject *name; assert(class_dict); assert(oparg >= 0 && oparg < _PyFrame_GetCode(frame)->co_nlocalsplus); @@ -2006,7 +2006,7 @@ TARGET(LOAD_DEREF) { PyObject *value; - #line 1433 "Python/bytecodes.c" + #line 1431 "Python/bytecodes.c" PyObject *cell = GETLOCAL(oparg); value = PyCell_GET(cell); if (value == NULL) { @@ -2022,7 +2022,7 @@ TARGET(STORE_DEREF) { PyObject *v = stack_pointer[-1]; - #line 1443 "Python/bytecodes.c" + #line 1441 "Python/bytecodes.c" PyObject *cell = GETLOCAL(oparg); PyObject *oldobj = PyCell_GET(cell); PyCell_SET(cell, v); @@ -2033,7 +2033,7 @@ } TARGET(COPY_FREE_VARS) { - #line 1450 "Python/bytecodes.c" + #line 1448 "Python/bytecodes.c" /* Copy closure variables to free variables */ PyCodeObject *co = _PyFrame_GetCode(frame); assert(PyFunction_Check(frame->f_funcobj)); @@ -2051,13 +2051,13 @@ TARGET(BUILD_STRING) { PyObject **pieces = (stack_pointer - oparg); PyObject *str; - #line 1463 "Python/bytecodes.c" + #line 1461 "Python/bytecodes.c" str = _PyUnicode_JoinArray(&_Py_STR(empty), pieces, oparg); #line 2057 "Python/generated_cases.c.h" for (int _i = oparg; --_i >= 0;) { Py_DECREF(pieces[_i]); } - #line 1465 "Python/bytecodes.c" + #line 1463 "Python/bytecodes.c" if (str == NULL) { STACK_SHRINK(oparg); goto error; } #line 2063 "Python/generated_cases.c.h" STACK_SHRINK(oparg); @@ -2069,7 +2069,7 @@ TARGET(BUILD_TUPLE) { PyObject **values = (stack_pointer - oparg); PyObject *tup; - #line 1469 "Python/bytecodes.c" + #line 1467 "Python/bytecodes.c" tup = _PyTuple_FromArraySteal(values, oparg); if (tup == NULL) { STACK_SHRINK(oparg); goto error; } #line 2076 "Python/generated_cases.c.h" @@ -2082,7 +2082,7 @@ TARGET(BUILD_LIST) { PyObject **values = (stack_pointer - oparg); PyObject *list; - #line 1474 "Python/bytecodes.c" + #line 1472 "Python/bytecodes.c" list = _PyList_FromArraySteal(values, oparg); if (list == NULL) { STACK_SHRINK(oparg); goto error; } #line 2089 "Python/generated_cases.c.h" @@ -2095,7 +2095,7 @@ TARGET(LIST_EXTEND) { PyObject *iterable = stack_pointer[-1]; PyObject *list = stack_pointer[-(2 + (oparg-1))]; - #line 1479 "Python/bytecodes.c" + #line 1477 "Python/bytecodes.c" PyObject *none_val = _PyList_Extend((PyListObject *)list, iterable); if (none_val == NULL) { if (_PyErr_ExceptionMatches(tstate, PyExc_TypeError) && @@ -2108,7 +2108,7 @@ } #line 2110 "Python/generated_cases.c.h" Py_DECREF(iterable); - #line 1490 "Python/bytecodes.c" + #line 1488 "Python/bytecodes.c" if (true) goto pop_1_error; } assert(Py_IsNone(none_val)); @@ -2121,11 +2121,11 @@ TARGET(SET_UPDATE) { PyObject *iterable = stack_pointer[-1]; PyObject *set = stack_pointer[-(2 + (oparg-1))]; - #line 1497 "Python/bytecodes.c" + #line 1495 "Python/bytecodes.c" int err = _PySet_Update(set, iterable); #line 2127 "Python/generated_cases.c.h" Py_DECREF(iterable); - #line 1499 "Python/bytecodes.c" + #line 1497 "Python/bytecodes.c" if (err < 0) goto pop_1_error; #line 2131 "Python/generated_cases.c.h" STACK_SHRINK(1); @@ -2135,7 +2135,7 @@ TARGET(BUILD_SET) { PyObject **values = (stack_pointer - oparg); PyObject *set; - #line 1503 "Python/bytecodes.c" + #line 1501 "Python/bytecodes.c" set = PySet_New(NULL); if (set == NULL) goto error; @@ -2160,7 +2160,7 @@ TARGET(BUILD_MAP) { PyObject **values = (stack_pointer - oparg*2); PyObject *map; - #line 1520 "Python/bytecodes.c" + #line 1518 "Python/bytecodes.c" map = _PyDict_FromItems( values, 2, values+1, 2, @@ -2172,7 +2172,7 @@ for (int _i = oparg*2; --_i >= 0;) { Py_DECREF(values[_i]); } - #line 1528 "Python/bytecodes.c" + #line 1526 "Python/bytecodes.c" if (map == NULL) { STACK_SHRINK(oparg*2); goto error; } #line 2178 "Python/generated_cases.c.h" STACK_SHRINK(oparg*2); @@ -2182,7 +2182,7 @@ } TARGET(SETUP_ANNOTATIONS) { - #line 1532 "Python/bytecodes.c" + #line 1530 "Python/bytecodes.c" int err; PyObject *ann_dict; if (LOCALS() == NULL) { @@ -2230,7 +2230,7 @@ PyObject *keys = stack_pointer[-1]; PyObject **values = (stack_pointer - (1 + oparg)); PyObject *map; - #line 1574 "Python/bytecodes.c" + #line 1572 "Python/bytecodes.c" if (!PyTuple_CheckExact(keys) || PyTuple_GET_SIZE(keys) != (Py_ssize_t)oparg) { _PyErr_SetString(tstate, PyExc_SystemError, @@ -2245,7 +2245,7 @@ Py_DECREF(values[_i]); } Py_DECREF(keys); - #line 1584 "Python/bytecodes.c" + #line 1582 "Python/bytecodes.c" if (map == NULL) { STACK_SHRINK(oparg); goto pop_1_error; } #line 2251 "Python/generated_cases.c.h" STACK_SHRINK(oparg); @@ -2255,7 +2255,7 @@ TARGET(DICT_UPDATE) { PyObject *update = stack_pointer[-1]; - #line 1588 "Python/bytecodes.c" + #line 1586 "Python/bytecodes.c" PyObject *dict = PEEK(oparg + 1); // update is still on the stack if (PyDict_Update(dict, update) < 0) { if (_PyErr_ExceptionMatches(tstate, PyExc_AttributeError)) { @@ -2265,7 +2265,7 @@ } #line 2267 "Python/generated_cases.c.h" Py_DECREF(update); - #line 1596 "Python/bytecodes.c" + #line 1594 "Python/bytecodes.c" if (true) goto pop_1_error; } #line 2272 "Python/generated_cases.c.h" @@ -2276,14 +2276,14 @@ TARGET(DICT_MERGE) { PyObject *update = stack_pointer[-1]; - #line 1602 "Python/bytecodes.c" + #line 1600 "Python/bytecodes.c" PyObject *dict = PEEK(oparg + 1); // update is still on the stack if (_PyDict_MergeEx(dict, update, 2) < 0) { format_kwargs_error(tstate, PEEK(3 + oparg), update); #line 2285 "Python/generated_cases.c.h" Py_DECREF(update); - #line 1607 "Python/bytecodes.c" + #line 1605 "Python/bytecodes.c" if (true) goto pop_1_error; } #line 2290 "Python/generated_cases.c.h" @@ -2295,7 +2295,7 @@ TARGET(MAP_ADD) { PyObject *value = stack_pointer[-1]; PyObject *key = stack_pointer[-2]; - #line 1613 "Python/bytecodes.c" + #line 1611 "Python/bytecodes.c" PyObject *dict = PEEK(oparg + 2); // key, value are still on the stack assert(PyDict_CheckExact(dict)); /* dict[key] = value */ @@ -2307,7 +2307,7 @@ } TARGET(INSTRUMENTED_LOAD_SUPER_ATTR) { - #line 1621 "Python/bytecodes.c" + #line 1619 "Python/bytecodes.c" _PySuperAttrCache *cache = (_PySuperAttrCache *)next_instr; // cancel out the decrement that will happen in LOAD_SUPER_ATTR; we // don't want to specialize instrumented instructions @@ -2324,7 +2324,7 @@ PyObject *global_super = stack_pointer[-3]; PyObject *res2 = NULL; PyObject *res; - #line 1635 "Python/bytecodes.c" + #line 1633 "Python/bytecodes.c" PyObject *name = GETITEM(FRAME_CO_NAMES, oparg >> 2); int load_method = oparg & 1; #if ENABLE_SPECIALIZATION @@ -2370,7 +2370,7 @@ Py_DECREF(global_super); Py_DECREF(class); Py_DECREF(self); - #line 1677 "Python/bytecodes.c" + #line 1675 "Python/bytecodes.c" if (super == NULL) goto pop_3_error; res = PyObject_GetAttr(super, name); Py_DECREF(super); @@ -2390,7 +2390,7 @@ PyObject *global_super = stack_pointer[-3]; PyObject *res2 = NULL; PyObject *res; - #line 1696 "Python/bytecodes.c" + #line 1694 "Python/bytecodes.c" assert(!(oparg & 1)); DEOPT_IF(global_super != (PyObject *)&PySuper_Type, LOAD_SUPER_ATTR); DEOPT_IF(!PyType_Check(class), LOAD_SUPER_ATTR); @@ -2401,7 +2401,7 @@ Py_DECREF(global_super); Py_DECREF(class); Py_DECREF(self); - #line 1703 "Python/bytecodes.c" + #line 1701 "Python/bytecodes.c" if (res == NULL) goto pop_3_error; #line 2407 "Python/generated_cases.c.h" STACK_SHRINK(2); @@ -2418,7 +2418,7 @@ PyObject *global_super = stack_pointer[-3]; PyObject *res2; PyObject *res; - #line 1707 "Python/bytecodes.c" + #line 1705 "Python/bytecodes.c" assert(oparg & 1); DEOPT_IF(global_super != (PyObject *)&PySuper_Type, LOAD_SUPER_ATTR); DEOPT_IF(!PyType_Check(class), LOAD_SUPER_ATTR); @@ -2455,7 +2455,7 @@ PyObject *owner = stack_pointer[-1]; PyObject *res2 = NULL; PyObject *res; - #line 1746 "Python/bytecodes.c" + #line 1744 "Python/bytecodes.c" #if ENABLE_SPECIALIZATION _PyAttrCache *cache = (_PyAttrCache *)next_instr; if (ADAPTIVE_COUNTER_IS_ZERO(cache->counter)) { @@ -2491,7 +2491,7 @@ */ #line 2493 "Python/generated_cases.c.h" Py_DECREF(owner); - #line 1780 "Python/bytecodes.c" + #line 1778 "Python/bytecodes.c" if (meth == NULL) goto pop_1_error; res2 = NULL; res = meth; @@ -2502,7 +2502,7 @@ res = PyObject_GetAttr(owner, name); #line 2504 "Python/generated_cases.c.h" Py_DECREF(owner); - #line 1789 "Python/bytecodes.c" + #line 1787 "Python/bytecodes.c" if (res == NULL) goto pop_1_error; } #line 2509 "Python/generated_cases.c.h" @@ -2519,7 +2519,7 @@ PyObject *res; uint32_t type_version = read_u32(&next_instr[1].cache); uint16_t index = read_u16(&next_instr[3].cache); - #line 1798 "Python/bytecodes.c" + #line 1796 "Python/bytecodes.c" PyTypeObject *tp = Py_TYPE(owner); assert(type_version != 0); DEOPT_IF(tp->tp_version_tag != type_version, LOAD_ATTR); @@ -2547,7 +2547,7 @@ PyObject *res; uint32_t type_version = read_u32(&next_instr[1].cache); uint16_t index = read_u16(&next_instr[3].cache); - #line 1814 "Python/bytecodes.c" + #line 1812 "Python/bytecodes.c" DEOPT_IF(!PyModule_CheckExact(owner), LOAD_ATTR); PyDictObject *dict = (PyDictObject *)((PyModuleObject *)owner)->md_dict; assert(dict != NULL); @@ -2575,7 +2575,7 @@ PyObject *res; uint32_t type_version = read_u32(&next_instr[1].cache); uint16_t index = read_u16(&next_instr[3].cache); - #line 1830 "Python/bytecodes.c" + #line 1828 "Python/bytecodes.c" PyTypeObject *tp = Py_TYPE(owner); assert(type_version != 0); DEOPT_IF(tp->tp_version_tag != type_version, LOAD_ATTR); @@ -2617,7 +2617,7 @@ PyObject *res; uint32_t type_version = read_u32(&next_instr[1].cache); uint16_t index = read_u16(&next_instr[3].cache); - #line 1860 "Python/bytecodes.c" + #line 1858 "Python/bytecodes.c" PyTypeObject *tp = Py_TYPE(owner); assert(type_version != 0); DEOPT_IF(tp->tp_version_tag != type_version, LOAD_ATTR); @@ -2642,7 +2642,7 @@ PyObject *res; uint32_t type_version = read_u32(&next_instr[1].cache); PyObject *descr = read_obj(&next_instr[5].cache); - #line 1873 "Python/bytecodes.c" + #line 1871 "Python/bytecodes.c" DEOPT_IF(!PyType_Check(cls), LOAD_ATTR); DEOPT_IF(((PyTypeObject *)cls)->tp_version_tag != type_version, @@ -2668,7 +2668,7 @@ uint32_t type_version = read_u32(&next_instr[1].cache); uint32_t func_version = read_u32(&next_instr[3].cache); PyObject *fget = read_obj(&next_instr[5].cache); - #line 1888 "Python/bytecodes.c" + #line 1886 "Python/bytecodes.c" DEOPT_IF(tstate->interp->eval_frame, LOAD_ATTR); PyTypeObject *cls = Py_TYPE(owner); @@ -2700,7 +2700,7 @@ uint32_t type_version = read_u32(&next_instr[1].cache); uint32_t func_version = read_u32(&next_instr[3].cache); PyObject *getattribute = read_obj(&next_instr[5].cache); - #line 1914 "Python/bytecodes.c" + #line 1912 "Python/bytecodes.c" DEOPT_IF(tstate->interp->eval_frame, LOAD_ATTR); PyTypeObject *cls = Py_TYPE(owner); DEOPT_IF(cls->tp_version_tag != type_version, LOAD_ATTR); @@ -2734,7 +2734,7 @@ PyObject *value = stack_pointer[-2]; uint32_t type_version = read_u32(&next_instr[1].cache); uint16_t index = read_u16(&next_instr[3].cache); - #line 1942 "Python/bytecodes.c" + #line 1940 "Python/bytecodes.c" PyTypeObject *tp = Py_TYPE(owner); assert(type_version != 0); DEOPT_IF(tp->tp_version_tag != type_version, STORE_ATTR); @@ -2763,7 +2763,7 @@ PyObject *value = stack_pointer[-2]; uint32_t type_version = read_u32(&next_instr[1].cache); uint16_t hint = read_u16(&next_instr[3].cache); - #line 1962 "Python/bytecodes.c" + #line 1960 "Python/bytecodes.c" PyTypeObject *tp = Py_TYPE(owner); assert(type_version != 0); DEOPT_IF(tp->tp_version_tag != type_version, STORE_ATTR); @@ -2813,7 +2813,7 @@ PyObject *value = stack_pointer[-2]; uint32_t type_version = read_u32(&next_instr[1].cache); uint16_t index = read_u16(&next_instr[3].cache); - #line 2003 "Python/bytecodes.c" + #line 2001 "Python/bytecodes.c" PyTypeObject *tp = Py_TYPE(owner); assert(type_version != 0); DEOPT_IF(tp->tp_version_tag != type_version, STORE_ATTR); @@ -2835,7 +2835,7 @@ PyObject *right = stack_pointer[-1]; PyObject *left = stack_pointer[-2]; PyObject *res; - #line 2022 "Python/bytecodes.c" + #line 2020 "Python/bytecodes.c" #if ENABLE_SPECIALIZATION _PyCompareOpCache *cache = (_PyCompareOpCache *)next_instr; if (ADAPTIVE_COUNTER_IS_ZERO(cache->counter)) { @@ -2851,7 +2851,7 @@ #line 2852 "Python/generated_cases.c.h" Py_DECREF(left); Py_DECREF(right); - #line 2035 "Python/bytecodes.c" + #line 2033 "Python/bytecodes.c" if (res == NULL) goto pop_2_error; #line 2857 "Python/generated_cases.c.h" STACK_SHRINK(1); @@ -2864,7 +2864,7 @@ PyObject *right = stack_pointer[-1]; PyObject *left = stack_pointer[-2]; PyObject *res; - #line 2039 "Python/bytecodes.c" + #line 2037 "Python/bytecodes.c" DEOPT_IF(!PyFloat_CheckExact(left), COMPARE_OP); DEOPT_IF(!PyFloat_CheckExact(right), COMPARE_OP); STAT_INC(COMPARE_OP, hit); @@ -2886,7 +2886,7 @@ PyObject *right = stack_pointer[-1]; PyObject *left = stack_pointer[-2]; PyObject *res; - #line 2053 "Python/bytecodes.c" + #line 2051 "Python/bytecodes.c" DEOPT_IF(!PyLong_CheckExact(left), COMPARE_OP); DEOPT_IF(!PyLong_CheckExact(right), COMPARE_OP); DEOPT_IF(!_PyLong_IsCompact((PyLongObject *)left), COMPARE_OP); @@ -2912,7 +2912,7 @@ PyObject *right = stack_pointer[-1]; PyObject *left = stack_pointer[-2]; PyObject *res; - #line 2071 "Python/bytecodes.c" + #line 2069 "Python/bytecodes.c" DEOPT_IF(!PyUnicode_CheckExact(left), COMPARE_OP); DEOPT_IF(!PyUnicode_CheckExact(right), COMPARE_OP); STAT_INC(COMPARE_OP, hit); @@ -2935,12 +2935,12 @@ PyObject *right = stack_pointer[-1]; PyObject *left = stack_pointer[-2]; PyObject *b; - #line 2085 "Python/bytecodes.c" + #line 2083 "Python/bytecodes.c" int res = Py_Is(left, right) ^ oparg; #line 2941 "Python/generated_cases.c.h" Py_DECREF(left); Py_DECREF(right); - #line 2087 "Python/bytecodes.c" + #line 2085 "Python/bytecodes.c" b = res ? Py_True : Py_False; #line 2946 "Python/generated_cases.c.h" STACK_SHRINK(1); @@ -2952,12 +2952,12 @@ PyObject *right = stack_pointer[-1]; PyObject *left = stack_pointer[-2]; PyObject *b; - #line 2091 "Python/bytecodes.c" + #line 2089 "Python/bytecodes.c" int res = PySequence_Contains(right, left); #line 2958 "Python/generated_cases.c.h" Py_DECREF(left); Py_DECREF(right); - #line 2093 "Python/bytecodes.c" + #line 2091 "Python/bytecodes.c" if (res < 0) goto pop_2_error; b = (res ^ oparg) ? Py_True : Py_False; #line 2964 "Python/generated_cases.c.h" @@ -2971,12 +2971,12 @@ PyObject *exc_value = stack_pointer[-2]; PyObject *rest; PyObject *match; - #line 2098 "Python/bytecodes.c" + #line 2096 "Python/bytecodes.c" if (check_except_star_type_valid(tstate, match_type) < 0) { #line 2977 "Python/generated_cases.c.h" Py_DECREF(exc_value); Py_DECREF(match_type); - #line 2100 "Python/bytecodes.c" + #line 2098 "Python/bytecodes.c" if (true) goto pop_2_error; } @@ -2987,7 +2987,7 @@ #line 2988 "Python/generated_cases.c.h" Py_DECREF(exc_value); Py_DECREF(match_type); - #line 2108 "Python/bytecodes.c" + #line 2106 "Python/bytecodes.c" if (res < 0) goto pop_2_error; assert((match == NULL) == (rest == NULL)); @@ -3006,19 +3006,19 @@ PyObject *right = stack_pointer[-1]; PyObject *left = stack_pointer[-2]; PyObject *b; - #line 2119 "Python/bytecodes.c" + #line 2117 "Python/bytecodes.c" assert(PyExceptionInstance_Check(left)); if (check_except_type_valid(tstate, right) < 0) { #line 3013 "Python/generated_cases.c.h" Py_DECREF(right); - #line 2122 "Python/bytecodes.c" + #line 2120 "Python/bytecodes.c" if (true) goto pop_1_error; } int res = PyErr_GivenExceptionMatches(left, right); #line 3020 "Python/generated_cases.c.h" Py_DECREF(right); - #line 2127 "Python/bytecodes.c" + #line 2125 "Python/bytecodes.c" b = res ? Py_True : Py_False; #line 3024 "Python/generated_cases.c.h" stack_pointer[-1] = b; @@ -3029,13 +3029,13 @@ PyObject *fromlist = stack_pointer[-1]; PyObject *level = stack_pointer[-2]; PyObject *res; - #line 2131 "Python/bytecodes.c" + #line 2129 "Python/bytecodes.c" PyObject *name = GETITEM(FRAME_CO_NAMES, oparg); res = import_name(tstate, frame, name, fromlist, level); #line 3036 "Python/generated_cases.c.h" Py_DECREF(level); Py_DECREF(fromlist); - #line 2134 "Python/bytecodes.c" + #line 2132 "Python/bytecodes.c" if (res == NULL) goto pop_2_error; #line 3041 "Python/generated_cases.c.h" STACK_SHRINK(1); @@ -3046,7 +3046,7 @@ TARGET(IMPORT_FROM) { PyObject *from = stack_pointer[-1]; PyObject *res; - #line 2138 "Python/bytecodes.c" + #line 2136 "Python/bytecodes.c" PyObject *name = GETITEM(FRAME_CO_NAMES, oparg); res = import_from(tstate, from, name); if (res == NULL) goto error; @@ -3057,14 +3057,14 @@ } TARGET(JUMP_FORWARD) { - #line 2144 "Python/bytecodes.c" + #line 2142 "Python/bytecodes.c" JUMPBY(oparg); #line 3063 "Python/generated_cases.c.h" DISPATCH(); } TARGET(JUMP_BACKWARD) { - #line 2148 "Python/bytecodes.c" + #line 2146 "Python/bytecodes.c" _Py_CODEUNIT *here = next_instr - 1; assert(oparg <= INSTR_OFFSET()); JUMPBY(1-oparg); @@ -3088,14 +3088,14 @@ } TARGET(ENTER_EXECUTOR) { - #line 2179 "Python/bytecodes.c" + #line 2177 "Python/bytecodes.c" PyCodeObject *code = _PyFrame_GetCode(frame); _PyExecutorObject *executor = (_PyExecutorObject *)code->co_executors->executors[oparg&255]; Py_INCREF(executor); frame = executor->execute(executor, frame, stack_pointer); if (frame == NULL) { frame = cframe.current_frame; - goto error; + goto resume_with_error; } goto resume_frame; #line 3102 "Python/generated_cases.c.h" @@ -3103,7 +3103,7 @@ TARGET(POP_JUMP_IF_FALSE) { PyObject *cond = stack_pointer[-1]; - #line 2191 "Python/bytecodes.c" + #line 2189 "Python/bytecodes.c" if (Py_IsFalse(cond)) { JUMPBY(oparg); } @@ -3111,7 +3111,7 @@ int err = PyObject_IsTrue(cond); #line 3113 "Python/generated_cases.c.h" Py_DECREF(cond); - #line 2197 "Python/bytecodes.c" + #line 2195 "Python/bytecodes.c" if (err == 0) { JUMPBY(oparg); } @@ -3126,7 +3126,7 @@ TARGET(POP_JUMP_IF_TRUE) { PyObject *cond = stack_pointer[-1]; - #line 2207 "Python/bytecodes.c" + #line 2205 "Python/bytecodes.c" if (Py_IsTrue(cond)) { JUMPBY(oparg); } @@ -3134,7 +3134,7 @@ int err = PyObject_IsTrue(cond); #line 3136 "Python/generated_cases.c.h" Py_DECREF(cond); - #line 2213 "Python/bytecodes.c" + #line 2211 "Python/bytecodes.c" if (err > 0) { JUMPBY(oparg); } @@ -3149,11 +3149,11 @@ TARGET(POP_JUMP_IF_NOT_NONE) { PyObject *value = stack_pointer[-1]; - #line 2223 "Python/bytecodes.c" + #line 2221 "Python/bytecodes.c" if (!Py_IsNone(value)) { #line 3155 "Python/generated_cases.c.h" Py_DECREF(value); - #line 2225 "Python/bytecodes.c" + #line 2223 "Python/bytecodes.c" JUMPBY(oparg); } #line 3160 "Python/generated_cases.c.h" @@ -3163,14 +3163,14 @@ TARGET(POP_JUMP_IF_NONE) { PyObject *value = stack_pointer[-1]; - #line 2230 "Python/bytecodes.c" + #line 2228 "Python/bytecodes.c" if (Py_IsNone(value)) { JUMPBY(oparg); } else { #line 3172 "Python/generated_cases.c.h" Py_DECREF(value); - #line 2235 "Python/bytecodes.c" + #line 2233 "Python/bytecodes.c" } #line 3176 "Python/generated_cases.c.h" STACK_SHRINK(1); @@ -3178,7 +3178,7 @@ } TARGET(JUMP_BACKWARD_NO_INTERRUPT) { - #line 2239 "Python/bytecodes.c" + #line 2237 "Python/bytecodes.c" /* This bytecode is used in the `yield from` or `await` loop. * If there is an interrupt, we want it handled in the innermost * generator or coroutine, so we deliberately do not check it here. @@ -3192,7 +3192,7 @@ TARGET(GET_LEN) { PyObject *obj = stack_pointer[-1]; PyObject *len_o; - #line 2248 "Python/bytecodes.c" + #line 2246 "Python/bytecodes.c" // PUSH(len(TOS)) Py_ssize_t len_i = PyObject_Length(obj); if (len_i < 0) goto error; @@ -3209,7 +3209,7 @@ PyObject *type = stack_pointer[-2]; PyObject *subject = stack_pointer[-3]; PyObject *attrs; - #line 2256 "Python/bytecodes.c" + #line 2254 "Python/bytecodes.c" // Pop TOS and TOS1. Set TOS to a tuple of attributes on success, or // None on failure. assert(PyTuple_CheckExact(names)); @@ -3218,7 +3218,7 @@ Py_DECREF(subject); Py_DECREF(type); Py_DECREF(names); - #line 2261 "Python/bytecodes.c" + #line 2259 "Python/bytecodes.c" if (attrs) { assert(PyTuple_CheckExact(attrs)); // Success! } @@ -3235,7 +3235,7 @@ TARGET(MATCH_MAPPING) { PyObject *subject = stack_pointer[-1]; PyObject *res; - #line 2271 "Python/bytecodes.c" + #line 2269 "Python/bytecodes.c" int match = Py_TYPE(subject)->tp_flags & Py_TPFLAGS_MAPPING; res = match ? Py_True : Py_False; #line 3242 "Python/generated_cases.c.h" @@ -3247,7 +3247,7 @@ TARGET(MATCH_SEQUENCE) { PyObject *subject = stack_pointer[-1]; PyObject *res; - #line 2276 "Python/bytecodes.c" + #line 2274 "Python/bytecodes.c" int match = Py_TYPE(subject)->tp_flags & Py_TPFLAGS_SEQUENCE; res = match ? Py_True : Py_False; #line 3254 "Python/generated_cases.c.h" @@ -3260,7 +3260,7 @@ PyObject *keys = stack_pointer[-1]; PyObject *subject = stack_pointer[-2]; PyObject *values_or_none; - #line 2281 "Python/bytecodes.c" + #line 2279 "Python/bytecodes.c" // On successful match, PUSH(values). Otherwise, PUSH(None). values_or_none = match_keys(tstate, subject, keys); if (values_or_none == NULL) goto error; @@ -3273,12 +3273,12 @@ TARGET(GET_ITER) { PyObject *iterable = stack_pointer[-1]; PyObject *iter; - #line 2287 "Python/bytecodes.c" + #line 2285 "Python/bytecodes.c" /* before: [obj]; after [getiter(obj)] */ iter = PyObject_GetIter(iterable); #line 3280 "Python/generated_cases.c.h" Py_DECREF(iterable); - #line 2290 "Python/bytecodes.c" + #line 2288 "Python/bytecodes.c" if (iter == NULL) goto pop_1_error; #line 3284 "Python/generated_cases.c.h" stack_pointer[-1] = iter; @@ -3288,7 +3288,7 @@ TARGET(GET_YIELD_FROM_ITER) { PyObject *iterable = stack_pointer[-1]; PyObject *iter; - #line 2294 "Python/bytecodes.c" + #line 2292 "Python/bytecodes.c" /* before: [obj]; after [getiter(obj)] */ if (PyCoro_CheckExact(iterable)) { /* `iterable` is a coroutine */ @@ -3313,7 +3313,7 @@ } #line 3315 "Python/generated_cases.c.h" Py_DECREF(iterable); - #line 2317 "Python/bytecodes.c" + #line 2315 "Python/bytecodes.c" } #line 3319 "Python/generated_cases.c.h" stack_pointer[-1] = iter; @@ -3325,7 +3325,7 @@ static_assert(INLINE_CACHE_ENTRIES_FOR_ITER == 1, "incorrect cache size"); PyObject *iter = stack_pointer[-1]; PyObject *next; - #line 2335 "Python/bytecodes.c" + #line 2333 "Python/bytecodes.c" #if ENABLE_SPECIALIZATION _PyForIterCache *cache = (_PyForIterCache *)next_instr; if (ADAPTIVE_COUNTER_IS_ZERO(cache->counter)) { @@ -3365,7 +3365,7 @@ } TARGET(INSTRUMENTED_FOR_ITER) { - #line 2369 "Python/bytecodes.c" + #line 2367 "Python/bytecodes.c" _Py_CODEUNIT *here = next_instr-1; _Py_CODEUNIT *target; PyObject *iter = TOP(); @@ -3398,7 +3398,7 @@ TARGET(FOR_ITER_LIST) { PyObject *iter = stack_pointer[-1]; PyObject *next; - #line 2397 "Python/bytecodes.c" + #line 2395 "Python/bytecodes.c" DEOPT_IF(Py_TYPE(iter) != &PyListIter_Type, FOR_ITER); _PyListIterObject *it = (_PyListIterObject *)iter; STAT_INC(FOR_ITER, hit); @@ -3429,7 +3429,7 @@ TARGET(FOR_ITER_TUPLE) { PyObject *iter = stack_pointer[-1]; PyObject *next; - #line 2420 "Python/bytecodes.c" + #line 2418 "Python/bytecodes.c" _PyTupleIterObject *it = (_PyTupleIterObject *)iter; DEOPT_IF(Py_TYPE(it) != &PyTupleIter_Type, FOR_ITER); STAT_INC(FOR_ITER, hit); @@ -3460,7 +3460,7 @@ TARGET(FOR_ITER_RANGE) { PyObject *iter = stack_pointer[-1]; PyObject *next; - #line 2443 "Python/bytecodes.c" + #line 2441 "Python/bytecodes.c" _PyRangeIterObject *r = (_PyRangeIterObject *)iter; DEOPT_IF(Py_TYPE(r) != &PyRangeIter_Type, FOR_ITER); STAT_INC(FOR_ITER, hit); @@ -3488,7 +3488,7 @@ TARGET(FOR_ITER_GEN) { PyObject *iter = stack_pointer[-1]; - #line 2464 "Python/bytecodes.c" + #line 2462 "Python/bytecodes.c" DEOPT_IF(tstate->interp->eval_frame, FOR_ITER); PyGenObject *gen = (PyGenObject *)iter; DEOPT_IF(Py_TYPE(gen) != &PyGen_Type, FOR_ITER); @@ -3511,7 +3511,7 @@ PyObject *mgr = stack_pointer[-1]; PyObject *exit; PyObject *res; - #line 2482 "Python/bytecodes.c" + #line 2480 "Python/bytecodes.c" PyObject *enter = _PyObject_LookupSpecial(mgr, &_Py_ID(__aenter__)); if (enter == NULL) { if (!_PyErr_Occurred(tstate)) { @@ -3536,7 +3536,7 @@ } #line 3538 "Python/generated_cases.c.h" Py_DECREF(mgr); - #line 2505 "Python/bytecodes.c" + #line 2503 "Python/bytecodes.c" res = _PyObject_CallNoArgs(enter); Py_DECREF(enter); if (res == NULL) { @@ -3554,7 +3554,7 @@ PyObject *mgr = stack_pointer[-1]; PyObject *exit; PyObject *res; - #line 2514 "Python/bytecodes.c" + #line 2512 "Python/bytecodes.c" /* pop the context manager, push its __exit__ and the * value returned from calling its __enter__ */ @@ -3582,7 +3582,7 @@ } #line 3584 "Python/generated_cases.c.h" Py_DECREF(mgr); - #line 2540 "Python/bytecodes.c" + #line 2538 "Python/bytecodes.c" res = _PyObject_CallNoArgs(enter); Py_DECREF(enter); if (res == NULL) { @@ -3601,7 +3601,7 @@ PyObject *lasti = stack_pointer[-3]; PyObject *exit_func = stack_pointer[-4]; PyObject *res; - #line 2549 "Python/bytecodes.c" + #line 2547 "Python/bytecodes.c" /* At the top of the stack are 4 values: - val: TOP = exc_info() - unused: SECOND = previous exception @@ -3631,7 +3631,7 @@ TARGET(PUSH_EXC_INFO) { PyObject *new_exc = stack_pointer[-1]; PyObject *prev_exc; - #line 2588 "Python/bytecodes.c" + #line 2586 "Python/bytecodes.c" _PyErr_StackItem *exc_info = tstate->exc_info; if (exc_info->exc_value != NULL) { prev_exc = exc_info->exc_value; @@ -3655,7 +3655,7 @@ uint32_t type_version = read_u32(&next_instr[1].cache); uint32_t keys_version = read_u32(&next_instr[3].cache); PyObject *descr = read_obj(&next_instr[5].cache); - #line 2600 "Python/bytecodes.c" + #line 2598 "Python/bytecodes.c" /* Cached method object */ PyTypeObject *self_cls = Py_TYPE(self); assert(type_version != 0); @@ -3686,7 +3686,7 @@ PyObject *res; uint32_t type_version = read_u32(&next_instr[1].cache); PyObject *descr = read_obj(&next_instr[5].cache); - #line 2619 "Python/bytecodes.c" + #line 2617 "Python/bytecodes.c" PyTypeObject *self_cls = Py_TYPE(self); DEOPT_IF(self_cls->tp_version_tag != type_version, LOAD_ATTR); assert(self_cls->tp_dictoffset == 0); @@ -3710,7 +3710,7 @@ PyObject *res; uint32_t type_version = read_u32(&next_instr[1].cache); PyObject *descr = read_obj(&next_instr[5].cache); - #line 2631 "Python/bytecodes.c" + #line 2629 "Python/bytecodes.c" PyTypeObject *self_cls = Py_TYPE(self); DEOPT_IF(self_cls->tp_version_tag != type_version, LOAD_ATTR); Py_ssize_t dictoffset = self_cls->tp_dictoffset; @@ -3733,7 +3733,7 @@ } TARGET(KW_NAMES) { - #line 2647 "Python/bytecodes.c" + #line 2645 "Python/bytecodes.c" assert(kwnames == NULL); assert(oparg < PyTuple_GET_SIZE(FRAME_CO_CONSTS)); kwnames = GETITEM(FRAME_CO_CONSTS, oparg); @@ -3742,7 +3742,7 @@ } TARGET(INSTRUMENTED_CALL) { - #line 2653 "Python/bytecodes.c" + #line 2651 "Python/bytecodes.c" int is_meth = PEEK(oparg+2) != NULL; int total_args = oparg + is_meth; PyObject *function = PEEK(total_args + 1); @@ -3765,7 +3765,7 @@ PyObject *callable = stack_pointer[-(1 + oparg)]; PyObject *method = stack_pointer[-(2 + oparg)]; PyObject *res; - #line 2699 "Python/bytecodes.c" + #line 2697 "Python/bytecodes.c" int is_meth = method != NULL; int total_args = oparg; if (is_meth) { @@ -3859,7 +3859,7 @@ TARGET(CALL_BOUND_METHOD_EXACT_ARGS) { PyObject *callable = stack_pointer[-(1 + oparg)]; PyObject *method = stack_pointer[-(2 + oparg)]; - #line 2787 "Python/bytecodes.c" + #line 2785 "Python/bytecodes.c" DEOPT_IF(method != NULL, CALL); DEOPT_IF(Py_TYPE(callable) != &PyMethod_Type, CALL); STAT_INC(CALL, hit); @@ -3878,7 +3878,7 @@ PyObject *callable = stack_pointer[-(1 + oparg)]; PyObject *method = stack_pointer[-(2 + oparg)]; uint32_t func_version = read_u32(&next_instr[1].cache); - #line 2799 "Python/bytecodes.c" + #line 2797 "Python/bytecodes.c" assert(kwnames == NULL); DEOPT_IF(tstate->interp->eval_frame, CALL); int is_meth = method != NULL; @@ -3912,7 +3912,7 @@ PyObject *callable = stack_pointer[-(1 + oparg)]; PyObject *method = stack_pointer[-(2 + oparg)]; uint32_t func_version = read_u32(&next_instr[1].cache); - #line 2827 "Python/bytecodes.c" + #line 2825 "Python/bytecodes.c" assert(kwnames == NULL); DEOPT_IF(tstate->interp->eval_frame, CALL); int is_meth = method != NULL; @@ -3956,7 +3956,7 @@ PyObject *callable = stack_pointer[-(1 + oparg)]; PyObject *null = stack_pointer[-(2 + oparg)]; PyObject *res; - #line 2865 "Python/bytecodes.c" + #line 2863 "Python/bytecodes.c" assert(kwnames == NULL); assert(oparg == 1); DEOPT_IF(null != NULL, CALL); @@ -3979,7 +3979,7 @@ PyObject *callable = stack_pointer[-(1 + oparg)]; PyObject *null = stack_pointer[-(2 + oparg)]; PyObject *res; - #line 2877 "Python/bytecodes.c" + #line 2875 "Python/bytecodes.c" assert(kwnames == NULL); assert(oparg == 1); DEOPT_IF(null != NULL, CALL); @@ -4004,7 +4004,7 @@ PyObject *callable = stack_pointer[-(1 + oparg)]; PyObject *null = stack_pointer[-(2 + oparg)]; PyObject *res; - #line 2891 "Python/bytecodes.c" + #line 2889 "Python/bytecodes.c" assert(kwnames == NULL); assert(oparg == 1); DEOPT_IF(null != NULL, CALL); @@ -4028,7 +4028,7 @@ PyObject **args = (stack_pointer - oparg); PyObject *callable = stack_pointer[-(1 + oparg)]; PyObject *null = stack_pointer[-(2 + oparg)]; - #line 2905 "Python/bytecodes.c" + #line 2903 "Python/bytecodes.c" /* This instruction does the following: * 1. Creates the object (by calling ``object.__new__``) * 2. Pushes a shim frame to the frame stack (to cleanup after ``__init__``) @@ -4083,7 +4083,7 @@ TARGET(EXIT_INIT_CHECK) { PyObject *should_be_none = stack_pointer[-1]; - #line 2957 "Python/bytecodes.c" + #line 2955 "Python/bytecodes.c" assert(STACK_LEVEL() == 2); if (should_be_none != Py_None) { PyErr_Format(PyExc_TypeError, @@ -4101,7 +4101,7 @@ PyObject *callable = stack_pointer[-(1 + oparg)]; PyObject *method = stack_pointer[-(2 + oparg)]; PyObject *res; - #line 2967 "Python/bytecodes.c" + #line 2965 "Python/bytecodes.c" int is_meth = method != NULL; int total_args = oparg; if (is_meth) { @@ -4137,7 +4137,7 @@ PyObject *callable = stack_pointer[-(1 + oparg)]; PyObject *method = stack_pointer[-(2 + oparg)]; PyObject *res; - #line 2992 "Python/bytecodes.c" + #line 2990 "Python/bytecodes.c" /* Builtin METH_O functions */ assert(kwnames == NULL); int is_meth = method != NULL; @@ -4179,7 +4179,7 @@ PyObject *callable = stack_pointer[-(1 + oparg)]; PyObject *method = stack_pointer[-(2 + oparg)]; PyObject *res; - #line 3023 "Python/bytecodes.c" + #line 3021 "Python/bytecodes.c" /* Builtin METH_FASTCALL functions, without keywords */ assert(kwnames == NULL); int is_meth = method != NULL; @@ -4225,7 +4225,7 @@ PyObject *callable = stack_pointer[-(1 + oparg)]; PyObject *method = stack_pointer[-(2 + oparg)]; PyObject *res; - #line 3058 "Python/bytecodes.c" + #line 3056 "Python/bytecodes.c" /* Builtin METH_FASTCALL | METH_KEYWORDS functions */ int is_meth = method != NULL; int total_args = oparg; @@ -4271,7 +4271,7 @@ PyObject *callable = stack_pointer[-(1 + oparg)]; PyObject *method = stack_pointer[-(2 + oparg)]; PyObject *res; - #line 3093 "Python/bytecodes.c" + #line 3091 "Python/bytecodes.c" assert(kwnames == NULL); /* len(o) */ int is_meth = method != NULL; @@ -4309,7 +4309,7 @@ PyObject *callable = stack_pointer[-(1 + oparg)]; PyObject *method = stack_pointer[-(2 + oparg)]; PyObject *res; - #line 3120 "Python/bytecodes.c" + #line 3118 "Python/bytecodes.c" assert(kwnames == NULL); /* isinstance(o, o2) */ int is_meth = method != NULL; @@ -4348,7 +4348,7 @@ PyObject **args = (stack_pointer - oparg); PyObject *self = stack_pointer[-(1 + oparg)]; PyObject *method = stack_pointer[-(2 + oparg)]; - #line 3150 "Python/bytecodes.c" + #line 3148 "Python/bytecodes.c" assert(kwnames == NULL); assert(oparg == 1); assert(method != NULL); @@ -4373,7 +4373,7 @@ PyObject **args = (stack_pointer - oparg); PyObject *method = stack_pointer[-(2 + oparg)]; PyObject *res; - #line 3170 "Python/bytecodes.c" + #line 3168 "Python/bytecodes.c" assert(kwnames == NULL); int is_meth = method != NULL; int total_args = oparg; @@ -4417,7 +4417,7 @@ PyObject **args = (stack_pointer - oparg); PyObject *method = stack_pointer[-(2 + oparg)]; PyObject *res; - #line 3204 "Python/bytecodes.c" + #line 3202 "Python/bytecodes.c" int is_meth = method != NULL; int total_args = oparg; if (is_meth) { @@ -4459,7 +4459,7 @@ PyObject **args = (stack_pointer - oparg); PyObject *method = stack_pointer[-(2 + oparg)]; PyObject *res; - #line 3236 "Python/bytecodes.c" + #line 3234 "Python/bytecodes.c" assert(kwnames == NULL); assert(oparg == 0 || oparg == 1); int is_meth = method != NULL; @@ -4501,7 +4501,7 @@ PyObject **args = (stack_pointer - oparg); PyObject *method = stack_pointer[-(2 + oparg)]; PyObject *res; - #line 3268 "Python/bytecodes.c" + #line 3266 "Python/bytecodes.c" assert(kwnames == NULL); int is_meth = method != NULL; int total_args = oparg; @@ -4539,7 +4539,7 @@ } TARGET(INSTRUMENTED_CALL_FUNCTION_EX) { - #line 3299 "Python/bytecodes.c" + #line 3297 "Python/bytecodes.c" GO_TO_INSTRUCTION(CALL_FUNCTION_EX); #line 4545 "Python/generated_cases.c.h" } @@ -4550,7 +4550,7 @@ PyObject *callargs = stack_pointer[-(1 + ((oparg & 1) ? 1 : 0))]; PyObject *func = stack_pointer[-(2 + ((oparg & 1) ? 1 : 0))]; PyObject *result; - #line 3303 "Python/bytecodes.c" + #line 3301 "Python/bytecodes.c" // DICT_MERGE is called before this opcode if there are kwargs. // It converts all dict subtypes in kwargs into regular dicts. assert(kwargs == NULL || PyDict_CheckExact(kwargs)); @@ -4616,7 +4616,7 @@ Py_DECREF(func); Py_DECREF(callargs); Py_XDECREF(kwargs); - #line 3365 "Python/bytecodes.c" + #line 3363 "Python/bytecodes.c" assert(PEEK(3 + (oparg & 1)) == NULL); if (result == NULL) { STACK_SHRINK(((oparg & 1) ? 1 : 0)); goto pop_3_error; } #line 4623 "Python/generated_cases.c.h" @@ -4630,7 +4630,7 @@ TARGET(MAKE_FUNCTION) { PyObject *codeobj = stack_pointer[-1]; PyObject *func; - #line 3371 "Python/bytecodes.c" + #line 3369 "Python/bytecodes.c" PyFunctionObject *func_obj = (PyFunctionObject *) PyFunction_New(codeobj, GLOBALS()); @@ -4650,7 +4650,7 @@ TARGET(SET_FUNCTION_ATTRIBUTE) { PyObject *func = stack_pointer[-1]; PyObject *attr = stack_pointer[-2]; - #line 3385 "Python/bytecodes.c" + #line 3383 "Python/bytecodes.c" assert(PyFunction_Check(func)); PyFunctionObject *func_obj = (PyFunctionObject *)func; switch(oparg) { @@ -4682,7 +4682,7 @@ } TARGET(RETURN_GENERATOR) { - #line 3412 "Python/bytecodes.c" + #line 3410 "Python/bytecodes.c" assert(PyFunction_Check(frame->f_funcobj)); PyFunctionObject *func = (PyFunctionObject *)frame->f_funcobj; PyGenObject *gen = (PyGenObject *)_Py_MakeCoro(func); @@ -4711,13 +4711,13 @@ PyObject *stop = stack_pointer[-(1 + ((oparg == 3) ? 1 : 0))]; PyObject *start = stack_pointer[-(2 + ((oparg == 3) ? 1 : 0))]; PyObject *slice; - #line 3435 "Python/bytecodes.c" + #line 3433 "Python/bytecodes.c" slice = PySlice_New(start, stop, step); #line 4717 "Python/generated_cases.c.h" Py_DECREF(start); Py_DECREF(stop); Py_XDECREF(step); - #line 3437 "Python/bytecodes.c" + #line 3435 "Python/bytecodes.c" if (slice == NULL) { STACK_SHRINK(((oparg == 3) ? 1 : 0)); goto pop_2_error; } #line 4723 "Python/generated_cases.c.h" STACK_SHRINK(((oparg == 3) ? 1 : 0)); @@ -4729,7 +4729,7 @@ TARGET(CONVERT_VALUE) { PyObject *value = stack_pointer[-1]; PyObject *result; - #line 3441 "Python/bytecodes.c" + #line 3439 "Python/bytecodes.c" convertion_func_ptr conv_fn; assert(oparg >= FVC_STR && oparg <= FVC_ASCII); conv_fn = CONVERSION_FUNCTIONS[oparg]; @@ -4744,7 +4744,7 @@ TARGET(FORMAT_SIMPLE) { PyObject *value = stack_pointer[-1]; PyObject *res; - #line 3450 "Python/bytecodes.c" + #line 3448 "Python/bytecodes.c" /* If value is a unicode object, then we know the result * of format(value) is value itself. */ if (!PyUnicode_CheckExact(value)) { @@ -4764,7 +4764,7 @@ PyObject *fmt_spec = stack_pointer[-1]; PyObject *value = stack_pointer[-2]; PyObject *res; - #line 3463 "Python/bytecodes.c" + #line 3461 "Python/bytecodes.c" res = PyObject_Format(value, fmt_spec); Py_DECREF(value); Py_DECREF(fmt_spec); @@ -4778,7 +4778,7 @@ TARGET(COPY) { PyObject *bottom = stack_pointer[-(1 + (oparg-1))]; PyObject *top; - #line 3470 "Python/bytecodes.c" + #line 3468 "Python/bytecodes.c" assert(oparg > 0); top = Py_NewRef(bottom); #line 4785 "Python/generated_cases.c.h" @@ -4793,7 +4793,7 @@ PyObject *rhs = stack_pointer[-1]; PyObject *lhs = stack_pointer[-2]; PyObject *res; - #line 3475 "Python/bytecodes.c" + #line 3473 "Python/bytecodes.c" #if ENABLE_SPECIALIZATION _PyBinaryOpCache *cache = (_PyBinaryOpCache *)next_instr; if (ADAPTIVE_COUNTER_IS_ZERO(cache->counter)) { @@ -4811,7 +4811,7 @@ #line 4812 "Python/generated_cases.c.h" Py_DECREF(lhs); Py_DECREF(rhs); - #line 3490 "Python/bytecodes.c" + #line 3488 "Python/bytecodes.c" if (res == NULL) goto pop_2_error; #line 4817 "Python/generated_cases.c.h" STACK_SHRINK(1); @@ -4823,7 +4823,7 @@ TARGET(SWAP) { PyObject *top = stack_pointer[-1]; PyObject *bottom = stack_pointer[-(2 + (oparg-2))]; - #line 3495 "Python/bytecodes.c" + #line 3493 "Python/bytecodes.c" assert(oparg >= 2); #line 4829 "Python/generated_cases.c.h" stack_pointer[-1] = bottom; @@ -4832,7 +4832,7 @@ } TARGET(INSTRUMENTED_INSTRUCTION) { - #line 3499 "Python/bytecodes.c" + #line 3497 "Python/bytecodes.c" int next_opcode = _Py_call_instrumentation_instruction( tstate, frame, next_instr-1); if (next_opcode < 0) goto error; @@ -4848,14 +4848,14 @@ } TARGET(INSTRUMENTED_JUMP_FORWARD) { - #line 3513 "Python/bytecodes.c" + #line 3511 "Python/bytecodes.c" INSTRUMENTED_JUMP(next_instr-1, next_instr+oparg, PY_MONITORING_EVENT_JUMP); #line 4854 "Python/generated_cases.c.h" DISPATCH(); } TARGET(INSTRUMENTED_JUMP_BACKWARD) { - #line 3517 "Python/bytecodes.c" + #line 3515 "Python/bytecodes.c" INSTRUMENTED_JUMP(next_instr-1, next_instr+1-oparg, PY_MONITORING_EVENT_JUMP); #line 4861 "Python/generated_cases.c.h" CHECK_EVAL_BREAKER(); @@ -4863,7 +4863,7 @@ } TARGET(INSTRUMENTED_POP_JUMP_IF_TRUE) { - #line 3522 "Python/bytecodes.c" + #line 3520 "Python/bytecodes.c" PyObject *cond = POP(); int err = PyObject_IsTrue(cond); Py_DECREF(cond); @@ -4877,7 +4877,7 @@ } TARGET(INSTRUMENTED_POP_JUMP_IF_FALSE) { - #line 3533 "Python/bytecodes.c" + #line 3531 "Python/bytecodes.c" PyObject *cond = POP(); int err = PyObject_IsTrue(cond); Py_DECREF(cond); @@ -4891,7 +4891,7 @@ } TARGET(INSTRUMENTED_POP_JUMP_IF_NONE) { - #line 3544 "Python/bytecodes.c" + #line 3542 "Python/bytecodes.c" PyObject *value = POP(); _Py_CODEUNIT *here = next_instr-1; int offset; @@ -4908,7 +4908,7 @@ } TARGET(INSTRUMENTED_POP_JUMP_IF_NOT_NONE) { - #line 3558 "Python/bytecodes.c" + #line 3556 "Python/bytecodes.c" PyObject *value = POP(); _Py_CODEUNIT *here = next_instr-1; int offset; @@ -4925,7 +4925,7 @@ } TARGET(EXTENDED_ARG) { - #line 3572 "Python/bytecodes.c" + #line 3570 "Python/bytecodes.c" assert(oparg); opcode = next_instr->op.code; oparg = oparg << 8 | next_instr->op.arg; @@ -4935,14 +4935,14 @@ } TARGET(CACHE) { - #line 3580 "Python/bytecodes.c" + #line 3578 "Python/bytecodes.c" assert(0 && "Executing a cache."); Py_UNREACHABLE(); #line 4942 "Python/generated_cases.c.h" } TARGET(RESERVED) { - #line 3585 "Python/bytecodes.c" + #line 3583 "Python/bytecodes.c" assert(0 && "Executing RESERVED instruction."); Py_UNREACHABLE(); #line 4949 "Python/generated_cases.c.h" diff --git a/Python/opcode_metadata.h b/Python/opcode_metadata.h index 421d979..4e31a5e 100644 --- a/Python/opcode_metadata.h +++ b/Python/opcode_metadata.h @@ -18,6 +18,21 @@ ((OP) == POP_BLOCK) || \ 0 +#define EXIT_TRACE 300 +#define SET_IP 301 +#define _GUARD_BOTH_INT 302 +#define _BINARY_OP_MULTIPLY_INT 303 +#define _BINARY_OP_ADD_INT 304 +#define _BINARY_OP_SUBTRACT_INT 305 +#define _GUARD_BOTH_FLOAT 306 +#define _BINARY_OP_MULTIPLY_FLOAT 307 +#define _BINARY_OP_ADD_FLOAT 308 +#define _BINARY_OP_SUBTRACT_FLOAT 309 +#define _GUARD_BOTH_UNICODE 310 +#define _BINARY_OP_ADD_UNICODE 311 +#define _LOAD_LOCALS 312 +#define _LOAD_FROM_DICT_OR_GLOBALS 313 + #ifndef NEED_OPCODE_METADATA extern int _PyOpcode_num_popped(int opcode, int oparg, bool jump); #else @@ -885,12 +900,19 @@ struct opcode_metadata { int flags; }; +struct opcode_macro_expansion { + int nuops; + struct { int16_t uop; int8_t size; int8_t offset; } uops[8]; +}; + + #define OPCODE_METADATA_FMT(OP) (_PyOpcode_opcode_metadata[(OP)].instr_format) #define SAME_OPCODE_METADATA(OP1, OP2) \ (OPCODE_METADATA_FMT(OP1) == OPCODE_METADATA_FMT(OP2)) #ifndef NEED_OPCODE_METADATA extern const struct opcode_metadata _PyOpcode_opcode_metadata[512]; +extern const struct opcode_macro_expansion _PyOpcode_macro_expansion[256]; #else const struct opcode_metadata _PyOpcode_opcode_metadata[512] = { [NOP] = { true, INSTR_FMT_IX, 0 }, @@ -1101,4 +1123,88 @@ const struct opcode_metadata _PyOpcode_opcode_metadata[512] = { [CACHE] = { true, INSTR_FMT_IX, 0 }, [RESERVED] = { true, INSTR_FMT_IX, 0 }, }; +const struct opcode_macro_expansion _PyOpcode_macro_expansion[256] = { + [NOP] = { .nuops = 1, .uops = { { NOP, 0, 0 } } }, + [LOAD_FAST] = { .nuops = 1, .uops = { { LOAD_FAST, 0, 0 } } }, + [LOAD_FAST_AND_CLEAR] = { .nuops = 1, .uops = { { LOAD_FAST_AND_CLEAR, 0, 0 } } }, + [LOAD_CONST] = { .nuops = 1, .uops = { { LOAD_CONST, 0, 0 } } }, + [STORE_FAST] = { .nuops = 1, .uops = { { STORE_FAST, 0, 0 } } }, + [POP_TOP] = { .nuops = 1, .uops = { { POP_TOP, 0, 0 } } }, + [PUSH_NULL] = { .nuops = 1, .uops = { { PUSH_NULL, 0, 0 } } }, + [END_SEND] = { .nuops = 1, .uops = { { END_SEND, 0, 0 } } }, + [UNARY_NEGATIVE] = { .nuops = 1, .uops = { { UNARY_NEGATIVE, 0, 0 } } }, + [UNARY_NOT] = { .nuops = 1, .uops = { { UNARY_NOT, 0, 0 } } }, + [UNARY_INVERT] = { .nuops = 1, .uops = { { UNARY_INVERT, 0, 0 } } }, + [BINARY_SLICE] = { .nuops = 1, .uops = { { BINARY_SLICE, 0, 0 } } }, + [STORE_SLICE] = { .nuops = 1, .uops = { { STORE_SLICE, 0, 0 } } }, + [BINARY_SUBSCR_LIST_INT] = { .nuops = 1, .uops = { { BINARY_SUBSCR_LIST_INT, 0, 0 } } }, + [BINARY_SUBSCR_TUPLE_INT] = { .nuops = 1, .uops = { { BINARY_SUBSCR_TUPLE_INT, 0, 0 } } }, + [BINARY_SUBSCR_DICT] = { .nuops = 1, .uops = { { BINARY_SUBSCR_DICT, 0, 0 } } }, + [LIST_APPEND] = { .nuops = 1, .uops = { { LIST_APPEND, 0, 0 } } }, + [SET_ADD] = { .nuops = 1, .uops = { { SET_ADD, 0, 0 } } }, + [STORE_SUBSCR_LIST_INT] = { .nuops = 1, .uops = { { STORE_SUBSCR_LIST_INT, 0, 0 } } }, + [STORE_SUBSCR_DICT] = { .nuops = 1, .uops = { { STORE_SUBSCR_DICT, 0, 0 } } }, + [DELETE_SUBSCR] = { .nuops = 1, .uops = { { DELETE_SUBSCR, 0, 0 } } }, + [CALL_INTRINSIC_1] = { .nuops = 1, .uops = { { CALL_INTRINSIC_1, 0, 0 } } }, + [CALL_INTRINSIC_2] = { .nuops = 1, .uops = { { CALL_INTRINSIC_2, 0, 0 } } }, + [GET_AITER] = { .nuops = 1, .uops = { { GET_AITER, 0, 0 } } }, + [GET_ANEXT] = { .nuops = 1, .uops = { { GET_ANEXT, 0, 0 } } }, + [GET_AWAITABLE] = { .nuops = 1, .uops = { { GET_AWAITABLE, 0, 0 } } }, + [POP_EXCEPT] = { .nuops = 1, .uops = { { POP_EXCEPT, 0, 0 } } }, + [LOAD_ASSERTION_ERROR] = { .nuops = 1, .uops = { { LOAD_ASSERTION_ERROR, 0, 0 } } }, + [LOAD_BUILD_CLASS] = { .nuops = 1, .uops = { { LOAD_BUILD_CLASS, 0, 0 } } }, + [STORE_NAME] = { .nuops = 1, .uops = { { STORE_NAME, 0, 0 } } }, + [DELETE_NAME] = { .nuops = 1, .uops = { { DELETE_NAME, 0, 0 } } }, + [UNPACK_SEQUENCE_TWO_TUPLE] = { .nuops = 1, .uops = { { UNPACK_SEQUENCE_TWO_TUPLE, 0, 0 } } }, + [UNPACK_SEQUENCE_TUPLE] = { .nuops = 1, .uops = { { UNPACK_SEQUENCE_TUPLE, 0, 0 } } }, + [UNPACK_SEQUENCE_LIST] = { .nuops = 1, .uops = { { UNPACK_SEQUENCE_LIST, 0, 0 } } }, + [UNPACK_EX] = { .nuops = 1, .uops = { { UNPACK_EX, 0, 0 } } }, + [DELETE_ATTR] = { .nuops = 1, .uops = { { DELETE_ATTR, 0, 0 } } }, + [STORE_GLOBAL] = { .nuops = 1, .uops = { { STORE_GLOBAL, 0, 0 } } }, + [DELETE_GLOBAL] = { .nuops = 1, .uops = { { DELETE_GLOBAL, 0, 0 } } }, + [DELETE_DEREF] = { .nuops = 1, .uops = { { DELETE_DEREF, 0, 0 } } }, + [LOAD_FROM_DICT_OR_DEREF] = { .nuops = 1, .uops = { { LOAD_FROM_DICT_OR_DEREF, 0, 0 } } }, + [LOAD_DEREF] = { .nuops = 1, .uops = { { LOAD_DEREF, 0, 0 } } }, + [STORE_DEREF] = { .nuops = 1, .uops = { { STORE_DEREF, 0, 0 } } }, + [COPY_FREE_VARS] = { .nuops = 1, .uops = { { COPY_FREE_VARS, 0, 0 } } }, + [BUILD_STRING] = { .nuops = 1, .uops = { { BUILD_STRING, 0, 0 } } }, + [BUILD_TUPLE] = { .nuops = 1, .uops = { { BUILD_TUPLE, 0, 0 } } }, + [BUILD_LIST] = { .nuops = 1, .uops = { { BUILD_LIST, 0, 0 } } }, + [LIST_EXTEND] = { .nuops = 1, .uops = { { LIST_EXTEND, 0, 0 } } }, + [SET_UPDATE] = { .nuops = 1, .uops = { { SET_UPDATE, 0, 0 } } }, + [BUILD_SET] = { .nuops = 1, .uops = { { BUILD_SET, 0, 0 } } }, + [BUILD_MAP] = { .nuops = 1, .uops = { { BUILD_MAP, 0, 0 } } }, + [SETUP_ANNOTATIONS] = { .nuops = 1, .uops = { { SETUP_ANNOTATIONS, 0, 0 } } }, + [BUILD_CONST_KEY_MAP] = { .nuops = 1, .uops = { { BUILD_CONST_KEY_MAP, 0, 0 } } }, + [DICT_UPDATE] = { .nuops = 1, .uops = { { DICT_UPDATE, 0, 0 } } }, + [DICT_MERGE] = { .nuops = 1, .uops = { { DICT_MERGE, 0, 0 } } }, + [MAP_ADD] = { .nuops = 1, .uops = { { MAP_ADD, 0, 0 } } }, + [LOAD_SUPER_ATTR_ATTR] = { .nuops = 1, .uops = { { LOAD_SUPER_ATTR_ATTR, 0, 0 } } }, + [LOAD_SUPER_ATTR_METHOD] = { .nuops = 1, .uops = { { LOAD_SUPER_ATTR_METHOD, 0, 0 } } }, + [COMPARE_OP_FLOAT] = { .nuops = 1, .uops = { { COMPARE_OP_FLOAT, 0, 0 } } }, + [COMPARE_OP_INT] = { .nuops = 1, .uops = { { COMPARE_OP_INT, 0, 0 } } }, + [COMPARE_OP_STR] = { .nuops = 1, .uops = { { COMPARE_OP_STR, 0, 0 } } }, + [IS_OP] = { .nuops = 1, .uops = { { IS_OP, 0, 0 } } }, + [CONTAINS_OP] = { .nuops = 1, .uops = { { CONTAINS_OP, 0, 0 } } }, + [CHECK_EG_MATCH] = { .nuops = 1, .uops = { { CHECK_EG_MATCH, 0, 0 } } }, + [CHECK_EXC_MATCH] = { .nuops = 1, .uops = { { CHECK_EXC_MATCH, 0, 0 } } }, + [GET_LEN] = { .nuops = 1, .uops = { { GET_LEN, 0, 0 } } }, + [MATCH_CLASS] = { .nuops = 1, .uops = { { MATCH_CLASS, 0, 0 } } }, + [MATCH_MAPPING] = { .nuops = 1, .uops = { { MATCH_MAPPING, 0, 0 } } }, + [MATCH_SEQUENCE] = { .nuops = 1, .uops = { { MATCH_SEQUENCE, 0, 0 } } }, + [MATCH_KEYS] = { .nuops = 1, .uops = { { MATCH_KEYS, 0, 0 } } }, + [GET_ITER] = { .nuops = 1, .uops = { { GET_ITER, 0, 0 } } }, + [GET_YIELD_FROM_ITER] = { .nuops = 1, .uops = { { GET_YIELD_FROM_ITER, 0, 0 } } }, + [WITH_EXCEPT_START] = { .nuops = 1, .uops = { { WITH_EXCEPT_START, 0, 0 } } }, + [PUSH_EXC_INFO] = { .nuops = 1, .uops = { { PUSH_EXC_INFO, 0, 0 } } }, + [EXIT_INIT_CHECK] = { .nuops = 1, .uops = { { EXIT_INIT_CHECK, 0, 0 } } }, + [MAKE_FUNCTION] = { .nuops = 1, .uops = { { MAKE_FUNCTION, 0, 0 } } }, + [SET_FUNCTION_ATTRIBUTE] = { .nuops = 1, .uops = { { SET_FUNCTION_ATTRIBUTE, 0, 0 } } }, + [BUILD_SLICE] = { .nuops = 1, .uops = { { BUILD_SLICE, 0, 0 } } }, + [CONVERT_VALUE] = { .nuops = 1, .uops = { { CONVERT_VALUE, 0, 0 } } }, + [FORMAT_SIMPLE] = { .nuops = 1, .uops = { { FORMAT_SIMPLE, 0, 0 } } }, + [FORMAT_WITH_SPEC] = { .nuops = 1, .uops = { { FORMAT_WITH_SPEC, 0, 0 } } }, + [COPY] = { .nuops = 1, .uops = { { COPY, 0, 0 } } }, + [SWAP] = { .nuops = 1, .uops = { { SWAP, 0, 0 } } }, +}; #endif diff --git a/Python/optimizer.c b/Python/optimizer.c index 95cd782..0a6cc5c 100644 --- a/Python/optimizer.c +++ b/Python/optimizer.c @@ -3,7 +3,9 @@ #include "opcode.h" #include "pycore_interp.h" #include "pycore_opcode.h" +#include "opcode_metadata.h" #include "pycore_pystate.h" +#include "pycore_uops.h" #include "cpython/optimizer.h" #include <stdbool.h> #include <stdint.h> @@ -278,3 +280,200 @@ PyUnstable_Optimizer_NewCounter(void) opt->count = 0; return (PyObject *)opt; } + +///////////////////// Experimental UOp Optimizer ///////////////////// + +#ifdef Py_DEBUG + /* For debugging the interpreter: */ +# define LLTRACE 1 /* Low-level trace feature */ +#endif + +static void +uop_dealloc(_PyUOpExecutorObject *self) { + PyObject_Free(self); +} + +static PyTypeObject UOpExecutor_Type = { + PyVarObject_HEAD_INIT(&PyType_Type, 0) + .tp_name = "uop_executor", + .tp_basicsize = sizeof(_PyUOpExecutorObject), + .tp_itemsize = 0, + .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_DISALLOW_INSTANTIATION, + .tp_dealloc = (destructor)uop_dealloc, +}; + +static int +translate_bytecode_to_trace( + PyCodeObject *code, + _Py_CODEUNIT *instr, + _PyUOpInstruction *trace, + int max_length) +{ +#ifdef LLTRACE + char *uop_debug = Py_GETENV("PYTHONUOPSDEBUG"); + int lltrace = 0; + if (uop_debug != NULL && *uop_debug >= '0') { + lltrace = *uop_debug - '0'; // TODO: Parse an int and all that + } + if (lltrace >= 4) { + fprintf(stderr, + "Optimizing %s (%s:%d) at offset %ld\n", + PyUnicode_AsUTF8(code->co_qualname), + PyUnicode_AsUTF8(code->co_filename), + code->co_firstlineno, + (long)(instr - (_Py_CODEUNIT *)code->co_code_adaptive)); + } +#define ADD_TO_TRACE(OPCODE, OPERAND) \ + if (lltrace >= 2) { \ + const char *opname = (OPCODE) < 256 ? _PyOpcode_OpName[(OPCODE)] : ""; \ + fprintf(stderr, " ADD_TO_TRACE(%s %d, %" PRIu64 ")\n", opname, (OPCODE), (uint64_t)(OPERAND)); \ + } \ + trace[trace_length].opcode = (OPCODE); \ + trace[trace_length].operand = (OPERAND); \ + trace_length++; +#else +#define ADD_TO_TRACE(OPCODE, OPERAND) \ + trace[trace_length].opcode = (OPCODE); \ + trace[trace_length].operand = (OPERAND); \ + trace_length++; +#endif + + int trace_length = 0; + // Always reserve space for one uop, plus SET_UP, plus EXIT_TRACE + while (trace_length + 3 <= max_length) { + int opcode = instr->op.code; + uint64_t operand = instr->op.arg; + switch (opcode) { + case LOAD_FAST_LOAD_FAST: + { + // Reserve space for two uops (+ SETUP + EXIT_TRACE) + if (trace_length + 4 > max_length) { + goto done; + } + uint64_t oparg1 = operand >> 4; + uint64_t oparg2 = operand & 15; + ADD_TO_TRACE(LOAD_FAST, oparg1); + ADD_TO_TRACE(LOAD_FAST, oparg2); + break; + } + default: + { + const struct opcode_macro_expansion *expansion = &_PyOpcode_macro_expansion[opcode]; + if (expansion->nuops > 0) { + // Reserve space for nuops (+ SETUP + EXIT_TRACE) + int nuops = expansion->nuops; + if (trace_length + nuops + 2 > max_length) { + goto done; + } + for (int i = 0; i < nuops; i++) { + int offset = expansion->uops[i].offset; + switch (expansion->uops[i].size) { + case 0: + break; + case 1: + operand = read_u16(&instr[offset].cache); + break; + case 2: + operand = read_u32(&instr[offset].cache); + break; + case 4: + operand = read_u64(&instr[offset].cache); + break; + default: + fprintf(stderr, + "opcode=%d, operand=%" PRIu64 "; nuops=%d, i=%d; size=%d, offset=%d\n", + opcode, operand, nuops, i, + expansion->uops[i].size, + expansion->uops[i].offset); + Py_FatalError("garbled expansion"); + } + ADD_TO_TRACE(expansion->uops[i].uop, operand); + assert(expansion->uops[0].size == 0); // TODO + } + break; + } + // fprintf(stderr, "Unsupported opcode %d\n", opcode); + goto done; // Break out of while loop + } + } + instr++; + // Add cache size for opcode + instr += _PyOpcode_Caches[_PyOpcode_Deopt[opcode]]; + ADD_TO_TRACE(SET_IP, (int)(instr - (_Py_CODEUNIT *)code->co_code_adaptive)); + } +done: + if (trace_length > 0) { + ADD_TO_TRACE(EXIT_TRACE, 0); +#ifdef LLTRACE + if (lltrace >= 1) { + fprintf(stderr, + "Created a trace for %s (%s:%d) at offset %ld -- length %d\n", + PyUnicode_AsUTF8(code->co_qualname), + PyUnicode_AsUTF8(code->co_filename), + code->co_firstlineno, + (long)(instr - (_Py_CODEUNIT *)code->co_code_adaptive), + trace_length); + } +#endif + } + else { +#ifdef LLTRACE + if (lltrace >= 4) { + fprintf(stderr, + "No trace for %s (%s:%d) at offset %ld\n", + PyUnicode_AsUTF8(code->co_qualname), + PyUnicode_AsUTF8(code->co_filename), + code->co_firstlineno, + (long)(instr - (_Py_CODEUNIT *)code->co_code_adaptive)); + } +#endif + } + return trace_length; + +#undef ADD_TO_TRACE +} + +static int +uop_optimize( + _PyOptimizerObject *self, + PyCodeObject *code, + _Py_CODEUNIT *instr, + _PyExecutorObject **exec_ptr) +{ + _PyUOpInstruction trace[_Py_UOP_MAX_TRACE_LENGTH]; + int trace_length = translate_bytecode_to_trace(code, instr, trace, _Py_UOP_MAX_TRACE_LENGTH); + if (trace_length <= 0) { + // Error or nothing translated + return trace_length; + } + OBJECT_STAT_INC(optimization_traces_created); + _PyUOpExecutorObject *executor = (_PyUOpExecutorObject *)_PyObject_New(&UOpExecutor_Type); + if (executor == NULL) { + return -1; + } + executor->base.execute = _PyUopExecute; + memcpy(executor->trace, trace, trace_length * sizeof(_PyUOpInstruction)); + *exec_ptr = (_PyExecutorObject *)executor; + return 1; +} + +static PyTypeObject UOpOptimizer_Type = { + PyVarObject_HEAD_INIT(&PyType_Type, 0) + .tp_name = "uop_optimizer", + .tp_basicsize = sizeof(_PyOptimizerObject), + .tp_itemsize = 0, + .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_DISALLOW_INSTANTIATION, +}; + +PyObject * +PyUnstable_Optimizer_NewUOpOptimizer(void) +{ + _PyOptimizerObject *opt = (_PyOptimizerObject *)_PyObject_New(&UOpOptimizer_Type); + if (opt == NULL) { + return NULL; + } + opt->optimize = uop_optimize; + opt->resume_threshold = UINT16_MAX; + opt->backedge_threshold = 0; + return (PyObject *)opt; +} diff --git a/Python/pylifecycle.c b/Python/pylifecycle.c index 5a5b14f..6117f3a 100644 --- a/Python/pylifecycle.c +++ b/Python/pylifecycle.c @@ -1181,6 +1181,19 @@ init_interp_main(PyThreadState *tstate) #endif } + // Turn on experimental tier 2 (uops-based) optimizer + if (is_main_interp) { + char *envvar = Py_GETENV("PYTHONUOPS"); + int enabled = envvar != NULL && *envvar > '0'; + if (_Py_get_xoption(&config->xoptions, L"uops") != NULL) { + enabled = 1; + } + if (enabled) { + PyObject *opt = PyUnstable_Optimizer_NewUOpOptimizer(); + PyUnstable_SetOptimizer((_PyOptimizerObject *)opt); + } + } + assert(!_PyErr_Occurred(tstate)); return _PyStatus_OK(); diff --git a/Python/specialize.c b/Python/specialize.c index 0006aa7..3f51432 100644 --- a/Python/specialize.c +++ b/Python/specialize.c @@ -195,6 +195,10 @@ print_object_stats(FILE *out, ObjectStats *stats) fprintf(out, "Object method cache collisions: %" PRIu64 "\n", stats->type_cache_collisions); fprintf(out, "Object method cache dunder hits: %" PRIu64 "\n", stats->type_cache_dunder_hits); fprintf(out, "Object method cache dunder misses: %" PRIu64 "\n", stats->type_cache_dunder_misses); + fprintf(out, "Optimization attempts: %" PRIu64 "\n", stats->optimization_attempts); + fprintf(out, "Optimization traces created: %" PRIu64 "\n", stats->optimization_traces_created); + fprintf(out, "Optimization traces executed: %" PRIu64 "\n", stats->optimization_traces_executed); + fprintf(out, "Optimization uops executed: %" PRIu64 "\n", stats->optimization_uops_executed); } static void diff --git a/Tools/c-analyzer/cpython/_parser.py b/Tools/c-analyzer/cpython/_parser.py index 51b79c2..9bc7285 100644 --- a/Tools/c-analyzer/cpython/_parser.py +++ b/Tools/c-analyzer/cpython/_parser.py @@ -83,6 +83,7 @@ Objects/unicodetype_db.h Python/deepfreeze/*.c Python/frozen_modules/*.h Python/generated_cases.c.h +Python/executor_cases.c.h # not actually source Python/bytecodes.c diff --git a/Tools/c-analyzer/cpython/ignored.tsv b/Tools/c-analyzer/cpython/ignored.tsv index 9cce3f3..73eec66 100644 --- a/Tools/c-analyzer/cpython/ignored.tsv +++ b/Tools/c-analyzer/cpython/ignored.tsv @@ -366,6 +366,8 @@ Python/sysmodule.c - whatstrings - Python/optimizer.c - DefaultOptimizer_Type - Python/optimizer.c - CounterExecutor_Type - Python/optimizer.c - CounterOptimizer_Type - +Python/optimizer.c - UOpExecutor_Type - +Python/optimizer.c - UOpOptimizer_Type - Python/optimizer.c - _PyOptimizer_Default - ##----------------------- diff --git a/Tools/cases_generator/README.md b/Tools/cases_generator/README.md index c595a93..fc93316 100644 --- a/Tools/cases_generator/README.md +++ b/Tools/cases_generator/README.md @@ -9,7 +9,7 @@ What's currently here: - `plexer.py`: OO interface on top of lexer.py; main class: `PLexer` - `parser.py`: Parser for instruction definition DSL; main class `Parser` - `generate_cases.py`: driver script to read `Python/bytecodes.c` and - write `Python/generated_cases.c.h` + write `Python/generated_cases.c.h` (and several other files) - `test_generator.py`: tests, require manual running using `pytest` Note that there is some dummy C code at the top and bottom of diff --git a/Tools/cases_generator/generate_cases.py b/Tools/cases_generator/generate_cases.py index 1afdeef..afeb31d 100644 --- a/Tools/cases_generator/generate_cases.py +++ b/Tools/cases_generator/generate_cases.py @@ -29,6 +29,9 @@ DEFAULT_METADATA_OUTPUT = os.path.relpath( DEFAULT_PYMETADATA_OUTPUT = os.path.relpath( os.path.join(ROOT, "Lib/_opcode_metadata.py") ) +DEFAULT_EXECUTOR_OUTPUT = os.path.relpath( + os.path.join(ROOT, "Python/executor_cases.c.h") +) BEGIN_MARKER = "// BEGIN BYTECODES //" END_MARKER = "// END BYTECODES //" RE_PREDICTED = ( @@ -61,6 +64,13 @@ arg_parser.add_argument( arg_parser.add_argument( "input", nargs=argparse.REMAINDER, help="Instruction definition file(s)" ) +arg_parser.add_argument( + "-e", + "--executor-cases", + type=str, + help="Write executor cases to this file", + default=DEFAULT_EXECUTOR_OUTPUT, +) def effect_size(effect: StackEffect) -> tuple[int, str]: @@ -176,14 +186,14 @@ class Formatter: self.prefix = self.prefix[:-4] @contextlib.contextmanager - def block(self, head: str): + def block(self, head: str, tail: str = ""): if head: self.emit(head + " {") else: self.emit("{") with self.indent(): yield - self.emit("}") + self.emit("}" + tail) def stack_adjust( self, @@ -290,6 +300,29 @@ class InstructionFlags: f"(_PyOpcode_opcode_metadata[(OP)].flags & ({name}))") +FORBIDDEN_NAMES_IN_UOPS = ( + "resume_with_error", # Proxy for "goto", which isn't an IDENTIFIER + "unbound_local_error", + "kwnames", + "next_instr", + "oparg1", # Proxy for super-instructions like LOAD_FAST_LOAD_FAST + "JUMPBY", + "DISPATCH", + "INSTRUMENTED_JUMP", + "throwflag", + "exception_unwind", + "import_from", + "import_name", + "_PyObject_CallNoArgs", # Proxy for BEFORE_WITH +) + + +# Interpreter tiers +TIER_ONE = 1 # Specializing adaptive interpreter (PEP 659) +TIER_TWO = 2 # Experimental tracing interpreter +Tiers: typing.TypeAlias = typing.Literal[1, 2] + + @dataclasses.dataclass class Instruction: """An instruction with additional data and code.""" @@ -353,7 +386,32 @@ class Instruction: cache = "0" self.instr_fmt = fmt - def write(self, out: Formatter) -> None: + def is_viable_uop(self) -> bool: + """Whether this instruction is viable as a uop.""" + if self.always_exits: + return False + if self.instr_flags.HAS_ARG_FLAG: + # If the instruction uses oparg, it cannot use any caches + for c in self.cache_effects: + if c.name != UNUSED: + return False + else: + # If it doesn't use oparg, it can have one cache entry + caches: list[parser.CacheEffect] = [] + cache_offset = 0 + for c in self.cache_effects: + if c.name != UNUSED: + caches.append(c) + cache_offset += c.size + if len(caches) > 1: + return False + for forbidden in FORBIDDEN_NAMES_IN_UOPS: + # TODO: Don't check in '#ifdef ENABLE_SPECIALIZATION' regions + if variable_used(self.inst, forbidden): + return False + return True + + def write(self, out: Formatter, tier: Tiers = TIER_ONE) -> None: """Write one instruction, sans prologue and epilogue.""" # Write a static assertion that a family's cache size is correct if family := self.family: @@ -400,7 +458,7 @@ class Instruction: # out.emit(f"next_instr += OPSIZE({self.inst.name}) - 1;") - self.write_body(out, 0) + self.write_body(out, 0, tier=tier) # Skip the rest if the block always exits if self.always_exits: @@ -427,10 +485,16 @@ class Instruction: out.assign(dst, oeffect) # Write cache effect - if self.cache_offset: + if tier == TIER_ONE and self.cache_offset: out.emit(f"next_instr += {self.cache_offset};") - def write_body(self, out: Formatter, dedent: int, cache_adjust: int = 0) -> None: + def write_body( + self, + out: Formatter, + dedent: int, + cache_adjust: int = 0, + tier: Tiers = TIER_ONE, + ) -> None: """Write the instruction body.""" # Write cache effect variable declarations and initializations cache_offset = cache_adjust @@ -447,9 +511,12 @@ class Instruction: else: typ = f"uint{bits}_t " func = f"read_u{bits}" - out.emit( - f"{typ}{ceffect.name} = {func}(&next_instr[{cache_offset}].cache);" - ) + if tier == TIER_ONE: + out.emit( + f"{typ}{ceffect.name} = {func}(&next_instr[{cache_offset}].cache);" + ) + else: + out.emit(f"{typ}{ceffect.name} = operand;") cache_offset += ceffect.size assert cache_offset == self.cache_offset + cache_adjust @@ -573,16 +640,24 @@ class Analyzer: output_filename: str metadata_filename: str pymetadata_filename: str + executor_filename: str errors: int = 0 emit_line_directives: bool = False - def __init__(self, input_filenames: list[str], output_filename: str, - metadata_filename: str, pymetadata_filename: str): + def __init__( + self, + input_filenames: list[str], + output_filename: str, + metadata_filename: str, + pymetadata_filename: str, + executor_filename: str, + ): """Read the input file.""" self.input_filenames = input_filenames self.output_filename = output_filename self.metadata_filename = metadata_filename self.pymetadata_filename = pymetadata_filename + self.executor_filename = executor_filename def error(self, msg: str, node: parser.Node) -> None: lineno = 0 @@ -1107,6 +1182,8 @@ class Analyzer: self.write_pseudo_instrs() + self.write_uop_defines() + self.write_stack_effect_functions() # Write type definitions @@ -1114,12 +1191,17 @@ class Analyzer: InstructionFlags.emit_macros(self.out) - self.out.emit("struct opcode_metadata {") - with self.out.indent(): + with self.out.block("struct opcode_metadata", ";"): self.out.emit("bool valid_entry;") self.out.emit("enum InstructionFormat instr_format;") self.out.emit("int flags;") - self.out.emit("};") + self.out.emit("") + + with self.out.block("struct opcode_macro_expansion", ";"): + self.out.emit("int nuops;") + self.out.emit("struct { int16_t uop; int8_t size; int8_t offset; } uops[8];") + self.out.emit("") + self.out.emit("") self.out.emit("#define OPCODE_METADATA_FMT(OP) " "(_PyOpcode_opcode_metadata[(OP)].instr_format)") @@ -1130,7 +1212,9 @@ class Analyzer: # Write metadata array declaration self.out.emit("#ifndef NEED_OPCODE_METADATA") self.out.emit("extern const struct opcode_metadata _PyOpcode_opcode_metadata[512];") + self.out.emit("extern const struct opcode_macro_expansion _PyOpcode_macro_expansion[256];") self.out.emit("#else") + self.out.emit("const struct opcode_metadata _PyOpcode_opcode_metadata[512] = {") # Write metadata for each instruction @@ -1150,6 +1234,31 @@ class Analyzer: # Write end of array self.out.emit("};") + + with self.out.block( + "const struct opcode_macro_expansion _PyOpcode_macro_expansion[256] =", + ";", + ): + # Write macro expansion for each non-pseudo instruction + for thing in self.everything: + match thing: + case OverriddenInstructionPlaceHolder(): + pass + case parser.InstDef(name=name): + instr = self.instrs[name] + if instr.kind != "op" and instr.is_viable_uop(): + self.out.emit( + f"[{name}] = " + f"{{ .nuops = 1, .uops = {{ {{ {name}, 0, 0 }} }} }}," + ) + case parser.Macro(): + # TODO: emit expansion if all parts are viable uops + pass + case parser.Pseudo(): + pass + case _: + typing.assert_never(thing) + self.out.emit("#endif") with open(self.pymetadata_filename, "w") as f: @@ -1184,7 +1293,6 @@ class Analyzer: "opcode for family in _specializations.values() for opcode in family" "]") - def write_pseudo_instrs(self) -> None: """Write the IS_PSEUDO_INSTR macro""" self.out.emit("\n\n#define IS_PSEUDO_INSTR(OP) \\") @@ -1192,6 +1300,20 @@ class Analyzer: self.out.emit(f" ((OP) == {op}) || \\") self.out.emit(f" 0") + def write_uop_defines(self) -> None: + """Write '#define XXX NNN' for each uop""" + self.out.emit("") + counter = 300 + def add(name: str) -> None: + nonlocal counter + self.out.emit(f"#define {name} {counter}") + counter += 1 + add("EXIT_TRACE") + add("SET_IP") + for instr in self.instrs.values(): + if instr.kind == "op" and instr.is_viable_uop(): + add(instr.name) + def emit_metadata_entry( self, name: str, fmt: str, flags: InstructionFlags ) -> None: @@ -1221,10 +1343,7 @@ class Analyzer: # Create formatter self.out = Formatter(f, 8, self.emit_line_directives) - # Write provenance header - self.out.write_raw(f"{self.out.comment} This file is generated by {THIS}\n") - self.out.write_raw(self.from_source_files()) - self.out.write_raw(f"{self.out.comment} Do not edit!\n") + self.write_provenance_header() # Write and count instructions of all kinds n_instrs = 0 @@ -1252,6 +1371,33 @@ class Analyzer: file=sys.stderr, ) + def write_executor_instructions(self) -> None: + """Generate cases for the Tier 2 interpreter.""" + with open(self.executor_filename, "w") as f: + self.out = Formatter(f, 8) + self.write_provenance_header() + for thing in self.everything: + match thing: + case OverriddenInstructionPlaceHolder(): + self.write_overridden_instr_place_holder(thing) + case parser.InstDef(): + instr = self.instrs[thing.name] + if instr.is_viable_uop(): + self.out.emit("") + with self.out.block(f"case {thing.name}:"): + instr.write(self.out, tier=TIER_TWO) + self.out.emit("break;") + case parser.Macro(): + pass # TODO + case parser.Pseudo(): + pass + case _: + typing.assert_never(thing) + print( + f"Wrote some stuff to {self.executor_filename}", + file=sys.stderr, + ) + def write_overridden_instr_place_holder(self, place_holder: OverriddenInstructionPlaceHolder) -> None: self.out.emit("") @@ -1405,7 +1551,7 @@ def main(): args.input.append(DEFAULT_INPUT) # Raises OSError if input unreadable - a = Analyzer(args.input, args.output, args.metadata, args.pymetadata) + a = Analyzer(args.input, args.output, args.metadata, args.pymetadata, args.executor_cases) if args.emit_line_directives: a.emit_line_directives = True @@ -1415,6 +1561,7 @@ def main(): sys.exit(f"Found {a.errors} errors") a.write_instructions() # Raises OSError if output can't be written a.write_metadata() + a.write_executor_instructions() if __name__ == "__main__": diff --git a/Tools/cases_generator/test_generator.py b/Tools/cases_generator/test_generator.py index 9ff4c97..e374ac4 100644 --- a/Tools/cases_generator/test_generator.py +++ b/Tools/cases_generator/test_generator.py @@ -44,7 +44,15 @@ def run_cases_test(input: str, expected: str): temp_input.flush() temp_output = tempfile.NamedTemporaryFile("w+") temp_metadata = tempfile.NamedTemporaryFile("w+") - a = generate_cases.Analyzer([temp_input.name], temp_output.name, temp_metadata.name) + temp_pymetadata = tempfile.NamedTemporaryFile("w+") + temp_executor = tempfile.NamedTemporaryFile("w+") + a = generate_cases.Analyzer( + [temp_input.name], + temp_output.name, + temp_metadata.name, + temp_pymetadata.name, + temp_executor.name, + ) a.parse() a.analyze() if a.errors: |