summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGuido van Rossum <guido@python.org>2023-06-27 02:02:57 (GMT)
committerGitHub <noreply@github.com>2023-06-27 02:02:57 (GMT)
commit51fc72511733353de15bc633a3d7b6da366842e4 (patch)
tree13c7075d57530adf90f82ba0025649f163b51abb
parentd3af83b9342457d8b24476baeb799f7506ff04f3 (diff)
downloadcpython-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--.gitattributes1
-rw-r--r--Include/cpython/optimizer.h1
-rw-r--r--Include/internal/pycore_uops.h31
-rw-r--r--Include/pystats.h3
-rw-r--r--Makefile.pre.in21
-rw-r--r--Misc/NEWS.d/next/Core and Builtins/2023-06-27-00-58-26.gh-issue-104584.Wu-uXy.rst1
-rw-r--r--Modules/_testinternalcapi.c7
-rw-r--r--Python/bytecodes.c4
-rw-r--r--Python/ceval.c137
-rw-r--r--Python/ceval_macros.h10
-rw-r--r--Python/executor_cases.c.h1606
-rw-r--r--Python/generated_cases.c.h518
-rw-r--r--Python/opcode_metadata.h106
-rw-r--r--Python/optimizer.c199
-rw-r--r--Python/pylifecycle.c13
-rw-r--r--Python/specialize.c4
-rw-r--r--Tools/c-analyzer/cpython/_parser.py1
-rw-r--r--Tools/c-analyzer/cpython/ignored.tsv2
-rw-r--r--Tools/cases_generator/README.md2
-rw-r--r--Tools/cases_generator/generate_cases.py187
-rw-r--r--Tools/cases_generator/test_generator.py10
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: