From c0fdfba7ff981c55ac13325e4dddaf382601b246 Mon Sep 17 00:00:00 2001 From: Guido van Rossum Date: Mon, 26 Feb 2024 08:42:53 -0800 Subject: Rename tier 2 redundancy eliminator to optimizer (#115888) The original name is just too much of a mouthful. --- .gitattributes | 2 +- .github/CODEOWNERS | 2 +- .github/workflows/jit.yml | 4 +- Lib/test/test_generated_cases.py | 4 +- Makefile.pre.in | 10 +- PCbuild/regen.targets | 6 +- Python/optimizer_analysis.c | 8 +- Python/optimizer_bytecodes.c | 409 +++++ Python/optimizer_cases.c.h | 1802 +++++++++++++++++++++ Python/tier2_redundancy_eliminator_bytecodes.c | 409 ----- Python/tier2_redundancy_eliminator_cases.c.h | 1802 --------------------- Tools/c-analyzer/cpython/_parser.py | 4 +- Tools/cases_generator/README.md | 6 +- Tools/cases_generator/optimizer_generator.py | 237 +++ Tools/cases_generator/tier2_abstract_generator.py | 237 --- 15 files changed, 2471 insertions(+), 2471 deletions(-) create mode 100644 Python/optimizer_bytecodes.c create mode 100644 Python/optimizer_cases.c.h delete mode 100644 Python/tier2_redundancy_eliminator_bytecodes.c delete mode 100644 Python/tier2_redundancy_eliminator_cases.c.h create mode 100644 Tools/cases_generator/optimizer_generator.py delete mode 100644 Tools/cases_generator/tier2_abstract_generator.py diff --git a/.gitattributes b/.gitattributes index 159cd83..4f82cea 100644 --- a/.gitattributes +++ b/.gitattributes @@ -95,7 +95,7 @@ Programs/test_frozenmain.h generated Python/Python-ast.c generated Python/executor_cases.c.h generated Python/generated_cases.c.h generated -Python/tier2_redundancy_eliminator_cases.c.h generated +Python/optimizer_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/.github/CODEOWNERS b/.github/CODEOWNERS index 7e20294..1d0bce1 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -38,7 +38,7 @@ Python/ast_opt.c @isidentical Python/bytecodes.c @markshannon @gvanrossum Python/optimizer*.c @markshannon @gvanrossum Python/optimizer_analysis.c @Fidget-Spinner -Python/tier2_redundancy_eliminator_bytecodes.c @Fidget-Spinner +Python/optimizer_bytecodes.c @Fidget-Spinner Lib/test/test_patma.py @brandtbucher Lib/test/test_type_*.py @JelleZijlstra Lib/test/test_capi/test_misc.py @markshannon @gvanrossum diff --git a/.github/workflows/jit.yml b/.github/workflows/jit.yml index 69c7b45..21d4603 100644 --- a/.github/workflows/jit.yml +++ b/.github/workflows/jit.yml @@ -5,13 +5,13 @@ on: - '**jit**' - 'Python/bytecodes.c' - 'Python/optimizer*.c' - - 'Python/tier2_redundancy_eliminator_bytecodes.c' + - 'Python/optimizer_bytecodes.c' push: paths: - '**jit**' - 'Python/bytecodes.c' - 'Python/optimizer*.c' - - 'Python/tier2_redundancy_eliminator_bytecodes.c' + - 'Python/optimizer_bytecodes.c' workflow_dispatch: concurrency: diff --git a/Lib/test/test_generated_cases.py b/Lib/test/test_generated_cases.py index 0d2ccd5..6a55868 100644 --- a/Lib/test/test_generated_cases.py +++ b/Lib/test/test_generated_cases.py @@ -33,7 +33,7 @@ with test_tools.imports_under_tool("cases_generator"): import parser from stack import Stack import tier1_generator - import tier2_abstract_generator + import optimizer_generator def handle_stderr(): @@ -841,7 +841,7 @@ class TestGeneratedAbstractCases(unittest.TestCase): temp_input.flush() with handle_stderr(): - tier2_abstract_generator.generate_tier2_abstract_from_files( + optimizer_generator.generate_tier2_abstract_from_files( [self.temp_input_filename, self.temp_input2_filename], self.temp_output_filename ) diff --git a/Makefile.pre.in b/Makefile.pre.in index 8893da8..e4c64ae 100644 --- a/Makefile.pre.in +++ b/Makefile.pre.in @@ -1889,9 +1889,9 @@ regen-cases: -o $(srcdir)/Python/generated_cases.c.h.new $(srcdir)/Python/bytecodes.c $(PYTHON_FOR_REGEN) $(srcdir)/Tools/cases_generator/tier2_generator.py \ -o $(srcdir)/Python/executor_cases.c.h.new $(srcdir)/Python/bytecodes.c - $(PYTHON_FOR_REGEN) $(srcdir)/Tools/cases_generator/tier2_abstract_generator.py \ - -o $(srcdir)/Python/tier2_redundancy_eliminator_cases.c.h.new \ - $(srcdir)/Python/tier2_redundancy_eliminator_bytecodes.c \ + $(PYTHON_FOR_REGEN) $(srcdir)/Tools/cases_generator/optimizer_generator.py \ + -o $(srcdir)/Python/optimizer_cases.c.h.new \ + $(srcdir)/Python/optimizer_bytecodes.c \ $(srcdir)/Python/bytecodes.c $(PYTHON_FOR_REGEN) $(srcdir)/Tools/cases_generator/opcode_metadata_generator.py \ -o $(srcdir)/Include/internal/pycore_opcode_metadata.h.new $(srcdir)/Python/bytecodes.c @@ -1904,7 +1904,7 @@ regen-cases: $(UPDATE_FILE) $(srcdir)/Include/internal/pycore_opcode_metadata.h $(srcdir)/Include/internal/pycore_opcode_metadata.h.new $(UPDATE_FILE) $(srcdir)/Include/internal/pycore_uop_metadata.h $(srcdir)/Include/internal/pycore_uop_metadata.h.new $(UPDATE_FILE) $(srcdir)/Python/executor_cases.c.h $(srcdir)/Python/executor_cases.c.h.new - $(UPDATE_FILE) $(srcdir)/Python/tier2_redundancy_eliminator_cases.c.h $(srcdir)/Python/tier2_redundancy_eliminator_cases.c.h.new + $(UPDATE_FILE) $(srcdir)/Python/optimizer_cases.c.h $(srcdir)/Python/optimizer_cases.c.h.new $(UPDATE_FILE) $(srcdir)/Lib/_opcode_metadata.py $(srcdir)/Lib/_opcode_metadata.py.new Python/compile.o: $(srcdir)/Include/internal/pycore_opcode_metadata.h @@ -1927,7 +1927,7 @@ Python/optimizer.o: \ Python/optimizer_analysis.o: \ $(srcdir)/Include/internal/pycore_opcode_metadata.h \ $(srcdir)/Include/internal/pycore_optimizer.h \ - $(srcdir)/Python/tier2_redundancy_eliminator_cases.c.h + $(srcdir)/Python/optimizer_cases.c.h Python/frozen.o: $(FROZEN_FILES_OUT) diff --git a/PCbuild/regen.targets b/PCbuild/regen.targets index 8f31803..f363872 100644 --- a/PCbuild/regen.targets +++ b/PCbuild/regen.targets @@ -31,8 +31,8 @@ <_JITSources Include="$(PySourcePath)Python\executor_cases.c.h;$(GeneratedPyConfigDir)pyconfig.h;$(PySourcePath)Tools\jit\**"/> <_JITOutputs Include="$(GeneratedPyConfigDir)jit_stencils.h"/> - <_CasesSources Include="$(PySourcePath)Python\bytecodes.c;$(PySourcePath)Python\tier2_redundancy_eliminator_bytecodes.c;"/> - <_CasesOutputs Include="$(PySourcePath)Python\generated_cases.c.h;$(PySourcePath)Include\opcode_ids.h;$(PySourcePath)Include\internal\pycore_uop_ids.h;$(PySourcePath)Python\opcode_targets.h;$(PySourcePath)Include\internal\pycore_opcode_metadata.h;$(PySourcePath)Include\internal\pycore_uop_metadata.h;$(PySourcePath)Python\tier2_redundancy_eliminator_cases.c.h;$(PySourcePath)Lib\_opcode_metadata.py"/> + <_CasesSources Include="$(PySourcePath)Python\bytecodes.c;$(PySourcePath)Python\optimizer_bytecodes.c;"/> + <_CasesOutputs Include="$(PySourcePath)Python\generated_cases.c.h;$(PySourcePath)Include\opcode_ids.h;$(PySourcePath)Include\internal\pycore_uop_ids.h;$(PySourcePath)Python\opcode_targets.h;$(PySourcePath)Include\internal\pycore_opcode_metadata.h;$(PySourcePath)Include\internal\pycore_uop_metadata.h;$(PySourcePath)Python\optimizer_cases.c.h;$(PySourcePath)Lib\_opcode_metadata.py"/> @@ -98,7 +98,7 @@ WorkingDirectory="$(PySourcePath)" /> - diff --git a/Python/optimizer_analysis.c b/Python/optimizer_analysis.c index 47bfc8c..1a9e829 100644 --- a/Python/optimizer_analysis.c +++ b/Python/optimizer_analysis.c @@ -1,5 +1,5 @@ /* - * This file contains the support code for CPython's uops redundancy eliminator. + * This file contains the support code for CPython's uops optimizer. * It also performs some simple optimizations. * It performs a traditional data-flow analysis[1] over the trace of uops. * Using the information gained, it chooses to emit, or skip certain instructions @@ -606,7 +606,7 @@ remove_globals(_PyInterpreterFrame *frame, _PyUOpInstruction *buffer, /* 1 for success, 0 for not ready, cannot error at the moment. */ static int -uop_redundancy_eliminator( +optimize_uops( PyCodeObject *co, _PyUOpInstruction *trace, int trace_len, @@ -638,7 +638,7 @@ uop_redundancy_eliminator( _PyUOpName(opcode), oparg); switch (opcode) { -#include "tier2_redundancy_eliminator_cases.c.h" +#include "optimizer_cases.c.h" default: DPRINTF(1, "Unknown opcode in abstract interpreter\n"); @@ -812,7 +812,7 @@ _Py_uop_analyze_and_optimize( char *uop_optimize = Py_GETENV("PYTHONUOPSOPTIMIZE"); if (uop_optimize != NULL && *uop_optimize > '0') { - err = uop_redundancy_eliminator( + err = optimize_uops( (PyCodeObject *)frame->f_executable, buffer, buffer_size, curr_stacklen, dependencies); } diff --git a/Python/optimizer_bytecodes.c b/Python/optimizer_bytecodes.c new file mode 100644 index 0000000..b9afd30 --- /dev/null +++ b/Python/optimizer_bytecodes.c @@ -0,0 +1,409 @@ +#include "Python.h" +#include "pycore_uops.h" +#include "pycore_uop_ids.h" +#include "internal/pycore_moduleobject.h" + +#define op(name, ...) /* NAME is ignored */ + +typedef struct _Py_UOpsSymType _Py_UOpsSymType; +typedef struct _Py_UOpsAbstractInterpContext _Py_UOpsAbstractInterpContext; +typedef struct _Py_UOpsAbstractFrame _Py_UOpsAbstractFrame; + +static int +dummy_func(void) { + + PyCodeObject *code; + int oparg; + _Py_UOpsSymType *flag; + _Py_UOpsSymType *left; + _Py_UOpsSymType *right; + _Py_UOpsSymType *value; + _Py_UOpsSymType *res; + _Py_UOpsSymType *iter; + _Py_UOpsSymType *top; + _Py_UOpsSymType *bottom; + _Py_UOpsAbstractFrame *frame; + _Py_UOpsAbstractInterpContext *ctx; + _PyUOpInstruction *this_instr; + _PyBloomFilter *dependencies; + int modified; + +// BEGIN BYTECODES // + + op(_LOAD_FAST_CHECK, (-- value)) { + value = GETLOCAL(oparg); + // We guarantee this will error - just bail and don't optimize it. + if (sym_is_null(value)) { + goto out_of_space; + } + } + + op(_LOAD_FAST, (-- value)) { + value = GETLOCAL(oparg); + } + + op(_LOAD_FAST_AND_CLEAR, (-- value)) { + value = GETLOCAL(oparg); + _Py_UOpsSymType *temp; + OUT_OF_SPACE_IF_NULL(temp = sym_new_null(ctx)); + GETLOCAL(oparg) = temp; + } + + op(_STORE_FAST, (value --)) { + GETLOCAL(oparg) = value; + } + + op(_PUSH_NULL, (-- res)) { + res = sym_new_null(ctx); + if (res == NULL) { + goto out_of_space; + }; + } + + op(_GUARD_BOTH_INT, (left, right -- left, right)) { + if (sym_matches_type(left, &PyLong_Type) && + sym_matches_type(right, &PyLong_Type)) { + REPLACE_OP(this_instr, _NOP, 0, 0); + } + sym_set_type(left, &PyLong_Type); + sym_set_type(right, &PyLong_Type); + } + + op(_GUARD_BOTH_FLOAT, (left, right -- left, right)) { + if (sym_matches_type(left, &PyFloat_Type) && + sym_matches_type(right, &PyFloat_Type)) { + REPLACE_OP(this_instr, _NOP, 0 ,0); + } + sym_set_type(left, &PyFloat_Type); + sym_set_type(right, &PyFloat_Type); + } + + op(_GUARD_BOTH_UNICODE, (left, right -- left, right)) { + if (sym_matches_type(left, &PyUnicode_Type) && + sym_matches_type(right, &PyUnicode_Type)) { + REPLACE_OP(this_instr, _NOP, 0 ,0); + } + sym_set_type(left, &PyUnicode_Type); + sym_set_type(right, &PyUnicode_Type); + } + + op(_BINARY_OP_ADD_INT, (left, right -- res)) { + if (sym_is_const(left) && sym_is_const(right)) { + assert(PyLong_CheckExact(sym_get_const(left))); + assert(PyLong_CheckExact(sym_get_const(right))); + PyObject *temp = _PyLong_Add((PyLongObject *)sym_get_const(left), + (PyLongObject *)sym_get_const(right)); + if (temp == NULL) { + goto error; + } + OUT_OF_SPACE_IF_NULL(res = sym_new_const(ctx, temp)); + // TODO gh-115506: + // replace opcode with constant propagated one and add tests! + } + else { + OUT_OF_SPACE_IF_NULL(res = sym_new_known_type(ctx, &PyLong_Type)); + } + } + + op(_BINARY_OP_SUBTRACT_INT, (left, right -- res)) { + if (sym_is_const(left) && sym_is_const(right)) { + assert(PyLong_CheckExact(sym_get_const(left))); + assert(PyLong_CheckExact(sym_get_const(right))); + PyObject *temp = _PyLong_Subtract((PyLongObject *)sym_get_const(left), + (PyLongObject *)sym_get_const(right)); + if (temp == NULL) { + goto error; + } + OUT_OF_SPACE_IF_NULL(res = sym_new_const(ctx, temp)); + // TODO gh-115506: + // replace opcode with constant propagated one and add tests! + } + else { + OUT_OF_SPACE_IF_NULL(res = sym_new_known_type(ctx, &PyLong_Type)); + } + } + + op(_BINARY_OP_MULTIPLY_INT, (left, right -- res)) { + if (sym_is_const(left) && sym_is_const(right)) { + assert(PyLong_CheckExact(sym_get_const(left))); + assert(PyLong_CheckExact(sym_get_const(right))); + PyObject *temp = _PyLong_Multiply((PyLongObject *)sym_get_const(left), + (PyLongObject *)sym_get_const(right)); + if (temp == NULL) { + goto error; + } + OUT_OF_SPACE_IF_NULL(res = sym_new_const(ctx, temp)); + // TODO gh-115506: + // replace opcode with constant propagated one and add tests! + } + else { + OUT_OF_SPACE_IF_NULL(res = sym_new_known_type(ctx, &PyLong_Type)); + } + } + + op(_BINARY_OP_ADD_FLOAT, (left, right -- res)) { + if (sym_is_const(left) && sym_is_const(right)) { + assert(PyFloat_CheckExact(sym_get_const(left))); + assert(PyFloat_CheckExact(sym_get_const(right))); + PyObject *temp = PyFloat_FromDouble( + PyFloat_AS_DOUBLE(sym_get_const(left)) + + PyFloat_AS_DOUBLE(sym_get_const(right))); + if (temp == NULL) { + goto error; + } + res = sym_new_const(ctx, temp); + // TODO gh-115506: + // replace opcode with constant propagated one and update tests! + } + else { + OUT_OF_SPACE_IF_NULL(res = sym_new_known_type(ctx, &PyFloat_Type)); + } + } + + op(_BINARY_OP_SUBTRACT_FLOAT, (left, right -- res)) { + if (sym_is_const(left) && sym_is_const(right)) { + assert(PyFloat_CheckExact(sym_get_const(left))); + assert(PyFloat_CheckExact(sym_get_const(right))); + PyObject *temp = PyFloat_FromDouble( + PyFloat_AS_DOUBLE(sym_get_const(left)) - + PyFloat_AS_DOUBLE(sym_get_const(right))); + if (temp == NULL) { + goto error; + } + res = sym_new_const(ctx, temp); + // TODO gh-115506: + // replace opcode with constant propagated one and update tests! + } + else { + OUT_OF_SPACE_IF_NULL(res = sym_new_known_type(ctx, &PyFloat_Type)); + } + } + + op(_BINARY_OP_MULTIPLY_FLOAT, (left, right -- res)) { + if (sym_is_const(left) && sym_is_const(right)) { + assert(PyFloat_CheckExact(sym_get_const(left))); + assert(PyFloat_CheckExact(sym_get_const(right))); + PyObject *temp = PyFloat_FromDouble( + PyFloat_AS_DOUBLE(sym_get_const(left)) * + PyFloat_AS_DOUBLE(sym_get_const(right))); + if (temp == NULL) { + goto error; + } + res = sym_new_const(ctx, temp); + // TODO gh-115506: + // replace opcode with constant propagated one and update tests! + } + else { + OUT_OF_SPACE_IF_NULL(res = sym_new_known_type(ctx, &PyFloat_Type)); + } + } + + op(_LOAD_CONST, (-- value)) { + // There should be no LOAD_CONST. It should be all + // replaced by peephole_opt. + Py_UNREACHABLE(); + } + + op(_LOAD_CONST_INLINE, (ptr/4 -- value)) { + OUT_OF_SPACE_IF_NULL(value = sym_new_const(ctx, ptr)); + } + + op(_LOAD_CONST_INLINE_BORROW, (ptr/4 -- value)) { + OUT_OF_SPACE_IF_NULL(value = sym_new_const(ctx, ptr)); + } + + op(_LOAD_CONST_INLINE_WITH_NULL, (ptr/4 -- value, null)) { + OUT_OF_SPACE_IF_NULL(value = sym_new_const(ctx, ptr)); + OUT_OF_SPACE_IF_NULL(null = sym_new_null(ctx)); + } + + op(_LOAD_CONST_INLINE_BORROW_WITH_NULL, (ptr/4 -- value, null)) { + OUT_OF_SPACE_IF_NULL(value = sym_new_const(ctx, ptr)); + OUT_OF_SPACE_IF_NULL(null = sym_new_null(ctx)); + } + + + op(_COPY, (bottom, unused[oparg-1] -- bottom, unused[oparg-1], top)) { + assert(oparg > 0); + top = bottom; + } + + op(_SWAP, (bottom, unused[oparg-2], top -- + top, unused[oparg-2], bottom)) { + } + + op(_LOAD_ATTR_INSTANCE_VALUE, (index/1, owner -- attr, null if (oparg & 1))) { + _LOAD_ATTR_NOT_NULL + (void)index; + (void)owner; + } + + op(_CHECK_ATTR_MODULE, (dict_version/2, owner -- owner)) { + (void)dict_version; + if (sym_is_const(owner)) { + PyObject *cnst = sym_get_const(owner); + if (PyModule_CheckExact(cnst)) { + PyModuleObject *mod = (PyModuleObject *)cnst; + PyObject *dict = mod->md_dict; + uint64_t watched_mutations = get_mutations(dict); + if (watched_mutations < _Py_MAX_ALLOWED_GLOBALS_MODIFICATIONS) { + PyDict_Watch(GLOBALS_WATCHER_ID, dict); + _Py_BloomFilter_Add(dependencies, dict); + this_instr->opcode = _NOP; + } + } + } + } + + op(_LOAD_ATTR_MODULE, (index/1, owner -- attr, null if (oparg & 1))) { + (void)index; + OUT_OF_SPACE_IF_NULL(null = sym_new_null(ctx)); + attr = NULL; + if (this_instr[-1].opcode == _NOP) { + // Preceding _CHECK_ATTR_MODULE was removed: mod is const and dict is watched. + assert(sym_is_const(owner)); + PyModuleObject *mod = (PyModuleObject *)sym_get_const(owner); + assert(PyModule_CheckExact(mod)); + PyObject *dict = mod->md_dict; + PyObject *res = convert_global_to_const(this_instr, dict); + if (res != NULL) { + this_instr[-1].opcode = _POP_TOP; + OUT_OF_SPACE_IF_NULL(attr = sym_new_const(ctx, res)); + } + } + if (attr == NULL) { + /* No conversion made. We don't know what `attr` is. */ + OUT_OF_SPACE_IF_NULL(attr = sym_new_known_notnull(ctx)); + } + } + + op(_LOAD_ATTR_WITH_HINT, (hint/1, owner -- attr, null if (oparg & 1))) { + _LOAD_ATTR_NOT_NULL + (void)hint; + (void)owner; + } + + op(_LOAD_ATTR_SLOT, (index/1, owner -- attr, null if (oparg & 1))) { + _LOAD_ATTR_NOT_NULL + (void)index; + (void)owner; + } + + op(_LOAD_ATTR_CLASS, (descr/4, owner -- attr, null if (oparg & 1))) { + _LOAD_ATTR_NOT_NULL + (void)descr; + (void)owner; + } + + op(_LOAD_ATTR_METHOD_WITH_VALUES, (descr/4, owner -- attr, self if (1))) { + (void)descr; + OUT_OF_SPACE_IF_NULL(attr = sym_new_known_notnull(ctx)); + self = owner; + } + + op(_LOAD_ATTR_METHOD_NO_DICT, (descr/4, owner -- attr, self if (1))) { + (void)descr; + OUT_OF_SPACE_IF_NULL(attr = sym_new_known_notnull(ctx)); + self = owner; + } + + op(_LOAD_ATTR_METHOD_LAZY_DICT, (descr/4, owner -- attr, self if (1))) { + (void)descr; + OUT_OF_SPACE_IF_NULL(attr = sym_new_known_notnull(ctx)); + self = owner; + } + + op(_INIT_CALL_BOUND_METHOD_EXACT_ARGS, (callable, unused, unused[oparg] -- func, self, unused[oparg])) { + (void)callable; + OUT_OF_SPACE_IF_NULL(func = sym_new_known_notnull(ctx)); + OUT_OF_SPACE_IF_NULL(self = sym_new_known_notnull(ctx)); + } + + + op(_CHECK_FUNCTION_EXACT_ARGS, (func_version/2, callable, self_or_null, unused[oparg] -- callable, self_or_null, unused[oparg])) { + sym_set_type(callable, &PyFunction_Type); + (void)self_or_null; + (void)func_version; + } + + op(_CHECK_CALL_BOUND_METHOD_EXACT_ARGS, (callable, null, unused[oparg] -- callable, null, unused[oparg])) { + sym_set_null(null); + sym_set_type(callable, &PyMethod_Type); + } + + op(_INIT_CALL_PY_EXACT_ARGS, (callable, self_or_null, args[oparg] -- new_frame: _Py_UOpsAbstractFrame *)) { + int argcount = oparg; + + (void)callable; + + PyFunctionObject *func = (PyFunctionObject *)(this_instr + 2)->operand; + if (func == NULL) { + goto error; + } + PyCodeObject *co = (PyCodeObject *)func->func_code; + + assert(self_or_null != NULL); + assert(args != NULL); + if (sym_is_not_null(self_or_null)) { + // Bound method fiddling, same as _INIT_CALL_PY_EXACT_ARGS in VM + args--; + argcount++; + } + + _Py_UOpsSymType **localsplus_start = ctx->n_consumed; + int n_locals_already_filled = 0; + // Can determine statically, so we interleave the new locals + // and make the current stack the new locals. + // This also sets up for true call inlining. + if (sym_is_known(self_or_null)) { + localsplus_start = args; + n_locals_already_filled = argcount; + } + OUT_OF_SPACE_IF_NULL(new_frame = + ctx_frame_new(ctx, co, localsplus_start, n_locals_already_filled, 0)); + } + + op(_POP_FRAME, (retval -- res)) { + SYNC_SP(); + ctx->frame->stack_pointer = stack_pointer; + ctx_frame_pop(ctx); + stack_pointer = ctx->frame->stack_pointer; + res = retval; + } + + op(_PUSH_FRAME, (new_frame: _Py_UOpsAbstractFrame * -- unused if (0))) { + SYNC_SP(); + ctx->frame->stack_pointer = stack_pointer; + ctx->frame = new_frame; + ctx->curr_frame_depth++; + stack_pointer = new_frame->stack_pointer; + } + + op(_UNPACK_SEQUENCE, (seq -- values[oparg])) { + /* This has to be done manually */ + (void)seq; + for (int i = 0; i < oparg; i++) { + OUT_OF_SPACE_IF_NULL(values[i] = sym_new_unknown(ctx)); + } + } + + op(_UNPACK_EX, (seq -- values[oparg & 0xFF], unused, unused[oparg >> 8])) { + /* This has to be done manually */ + (void)seq; + int totalargs = (oparg & 0xFF) + (oparg >> 8) + 1; + for (int i = 0; i < totalargs; i++) { + OUT_OF_SPACE_IF_NULL(values[i] = sym_new_unknown(ctx)); + } + } + + op(_ITER_NEXT_RANGE, (iter -- iter, next)) { + OUT_OF_SPACE_IF_NULL(next = sym_new_known_type(ctx, &PyLong_Type)); + (void)iter; + } + + + + +// END BYTECODES // + +} diff --git a/Python/optimizer_cases.c.h b/Python/optimizer_cases.c.h new file mode 100644 index 0000000..e8146dc --- /dev/null +++ b/Python/optimizer_cases.c.h @@ -0,0 +1,1802 @@ +// This file is generated by Tools/cases_generator/optimizer_generator.py +// from: +// Python/optimizer_bytecodes.c +// Do not edit! + + case _NOP: { + break; + } + + case _RESUME_CHECK: { + break; + } + + /* _INSTRUMENTED_RESUME is not a viable micro-op for tier 2 */ + + case _LOAD_FAST_CHECK: { + _Py_UOpsSymType *value; + value = GETLOCAL(oparg); + // We guarantee this will error - just bail and don't optimize it. + if (sym_is_null(value)) { + goto out_of_space; + } + stack_pointer[0] = value; + stack_pointer += 1; + break; + } + + case _LOAD_FAST: { + _Py_UOpsSymType *value; + value = GETLOCAL(oparg); + stack_pointer[0] = value; + stack_pointer += 1; + break; + } + + case _LOAD_FAST_AND_CLEAR: { + _Py_UOpsSymType *value; + value = GETLOCAL(oparg); + _Py_UOpsSymType *temp; + OUT_OF_SPACE_IF_NULL(temp = sym_new_null(ctx)); + GETLOCAL(oparg) = temp; + stack_pointer[0] = value; + stack_pointer += 1; + break; + } + + case _LOAD_CONST: { + _Py_UOpsSymType *value; + // There should be no LOAD_CONST. It should be all + // replaced by peephole_opt. + Py_UNREACHABLE(); + stack_pointer[0] = value; + stack_pointer += 1; + break; + } + + case _STORE_FAST: { + _Py_UOpsSymType *value; + value = stack_pointer[-1]; + GETLOCAL(oparg) = value; + stack_pointer += -1; + break; + } + + case _POP_TOP: { + stack_pointer += -1; + break; + } + + case _PUSH_NULL: { + _Py_UOpsSymType *res; + res = sym_new_null(ctx); + if (res == NULL) { + goto out_of_space; + }; + stack_pointer[0] = res; + stack_pointer += 1; + break; + } + + case _END_SEND: { + _Py_UOpsSymType *value; + value = sym_new_unknown(ctx); + if (value == NULL) goto out_of_space; + stack_pointer[-2] = value; + stack_pointer += -1; + break; + } + + case _UNARY_NEGATIVE: { + _Py_UOpsSymType *res; + res = sym_new_unknown(ctx); + if (res == NULL) goto out_of_space; + stack_pointer[-1] = res; + break; + } + + case _UNARY_NOT: { + _Py_UOpsSymType *res; + res = sym_new_unknown(ctx); + if (res == NULL) goto out_of_space; + stack_pointer[-1] = res; + break; + } + + case _TO_BOOL: { + _Py_UOpsSymType *res; + res = sym_new_unknown(ctx); + if (res == NULL) goto out_of_space; + stack_pointer[-1] = res; + break; + } + + case _TO_BOOL_BOOL: { + break; + } + + case _TO_BOOL_INT: { + _Py_UOpsSymType *res; + res = sym_new_unknown(ctx); + if (res == NULL) goto out_of_space; + stack_pointer[-1] = res; + break; + } + + case _TO_BOOL_LIST: { + _Py_UOpsSymType *res; + res = sym_new_unknown(ctx); + if (res == NULL) goto out_of_space; + stack_pointer[-1] = res; + break; + } + + case _TO_BOOL_NONE: { + _Py_UOpsSymType *res; + res = sym_new_unknown(ctx); + if (res == NULL) goto out_of_space; + stack_pointer[-1] = res; + break; + } + + case _TO_BOOL_STR: { + _Py_UOpsSymType *res; + res = sym_new_unknown(ctx); + if (res == NULL) goto out_of_space; + stack_pointer[-1] = res; + break; + } + + case _TO_BOOL_ALWAYS_TRUE: { + _Py_UOpsSymType *res; + res = sym_new_unknown(ctx); + if (res == NULL) goto out_of_space; + stack_pointer[-1] = res; + break; + } + + case _UNARY_INVERT: { + _Py_UOpsSymType *res; + res = sym_new_unknown(ctx); + if (res == NULL) goto out_of_space; + stack_pointer[-1] = res; + break; + } + + case _GUARD_BOTH_INT: { + _Py_UOpsSymType *right; + _Py_UOpsSymType *left; + right = stack_pointer[-1]; + left = stack_pointer[-2]; + if (sym_matches_type(left, &PyLong_Type) && + sym_matches_type(right, &PyLong_Type)) { + REPLACE_OP(this_instr, _NOP, 0, 0); + } + sym_set_type(left, &PyLong_Type); + sym_set_type(right, &PyLong_Type); + break; + } + + case _BINARY_OP_MULTIPLY_INT: { + _Py_UOpsSymType *right; + _Py_UOpsSymType *left; + _Py_UOpsSymType *res; + right = stack_pointer[-1]; + left = stack_pointer[-2]; + if (sym_is_const(left) && sym_is_const(right)) { + assert(PyLong_CheckExact(sym_get_const(left))); + assert(PyLong_CheckExact(sym_get_const(right))); + PyObject *temp = _PyLong_Multiply((PyLongObject *)sym_get_const(left), + (PyLongObject *)sym_get_const(right)); + if (temp == NULL) { + goto error; + } + OUT_OF_SPACE_IF_NULL(res = sym_new_const(ctx, temp)); + // TODO gh-115506: + // replace opcode with constant propagated one and add tests! + } + else { + OUT_OF_SPACE_IF_NULL(res = sym_new_known_type(ctx, &PyLong_Type)); + } + stack_pointer[-2] = res; + stack_pointer += -1; + break; + } + + case _BINARY_OP_ADD_INT: { + _Py_UOpsSymType *right; + _Py_UOpsSymType *left; + _Py_UOpsSymType *res; + right = stack_pointer[-1]; + left = stack_pointer[-2]; + if (sym_is_const(left) && sym_is_const(right)) { + assert(PyLong_CheckExact(sym_get_const(left))); + assert(PyLong_CheckExact(sym_get_const(right))); + PyObject *temp = _PyLong_Add((PyLongObject *)sym_get_const(left), + (PyLongObject *)sym_get_const(right)); + if (temp == NULL) { + goto error; + } + OUT_OF_SPACE_IF_NULL(res = sym_new_const(ctx, temp)); + // TODO gh-115506: + // replace opcode with constant propagated one and add tests! + } + else { + OUT_OF_SPACE_IF_NULL(res = sym_new_known_type(ctx, &PyLong_Type)); + } + stack_pointer[-2] = res; + stack_pointer += -1; + break; + } + + case _BINARY_OP_SUBTRACT_INT: { + _Py_UOpsSymType *right; + _Py_UOpsSymType *left; + _Py_UOpsSymType *res; + right = stack_pointer[-1]; + left = stack_pointer[-2]; + if (sym_is_const(left) && sym_is_const(right)) { + assert(PyLong_CheckExact(sym_get_const(left))); + assert(PyLong_CheckExact(sym_get_const(right))); + PyObject *temp = _PyLong_Subtract((PyLongObject *)sym_get_const(left), + (PyLongObject *)sym_get_const(right)); + if (temp == NULL) { + goto error; + } + OUT_OF_SPACE_IF_NULL(res = sym_new_const(ctx, temp)); + // TODO gh-115506: + // replace opcode with constant propagated one and add tests! + } + else { + OUT_OF_SPACE_IF_NULL(res = sym_new_known_type(ctx, &PyLong_Type)); + } + stack_pointer[-2] = res; + stack_pointer += -1; + break; + } + + case _GUARD_BOTH_FLOAT: { + _Py_UOpsSymType *right; + _Py_UOpsSymType *left; + right = stack_pointer[-1]; + left = stack_pointer[-2]; + if (sym_matches_type(left, &PyFloat_Type) && + sym_matches_type(right, &PyFloat_Type)) { + REPLACE_OP(this_instr, _NOP, 0 ,0); + } + sym_set_type(left, &PyFloat_Type); + sym_set_type(right, &PyFloat_Type); + break; + } + + case _BINARY_OP_MULTIPLY_FLOAT: { + _Py_UOpsSymType *right; + _Py_UOpsSymType *left; + _Py_UOpsSymType *res; + right = stack_pointer[-1]; + left = stack_pointer[-2]; + if (sym_is_const(left) && sym_is_const(right)) { + assert(PyFloat_CheckExact(sym_get_const(left))); + assert(PyFloat_CheckExact(sym_get_const(right))); + PyObject *temp = PyFloat_FromDouble( + PyFloat_AS_DOUBLE(sym_get_const(left)) * + PyFloat_AS_DOUBLE(sym_get_const(right))); + if (temp == NULL) { + goto error; + } + res = sym_new_const(ctx, temp); + // TODO gh-115506: + // replace opcode with constant propagated one and update tests! + } + else { + OUT_OF_SPACE_IF_NULL(res = sym_new_known_type(ctx, &PyFloat_Type)); + } + stack_pointer[-2] = res; + stack_pointer += -1; + break; + } + + case _BINARY_OP_ADD_FLOAT: { + _Py_UOpsSymType *right; + _Py_UOpsSymType *left; + _Py_UOpsSymType *res; + right = stack_pointer[-1]; + left = stack_pointer[-2]; + if (sym_is_const(left) && sym_is_const(right)) { + assert(PyFloat_CheckExact(sym_get_const(left))); + assert(PyFloat_CheckExact(sym_get_const(right))); + PyObject *temp = PyFloat_FromDouble( + PyFloat_AS_DOUBLE(sym_get_const(left)) + + PyFloat_AS_DOUBLE(sym_get_const(right))); + if (temp == NULL) { + goto error; + } + res = sym_new_const(ctx, temp); + // TODO gh-115506: + // replace opcode with constant propagated one and update tests! + } + else { + OUT_OF_SPACE_IF_NULL(res = sym_new_known_type(ctx, &PyFloat_Type)); + } + stack_pointer[-2] = res; + stack_pointer += -1; + break; + } + + case _BINARY_OP_SUBTRACT_FLOAT: { + _Py_UOpsSymType *right; + _Py_UOpsSymType *left; + _Py_UOpsSymType *res; + right = stack_pointer[-1]; + left = stack_pointer[-2]; + if (sym_is_const(left) && sym_is_const(right)) { + assert(PyFloat_CheckExact(sym_get_const(left))); + assert(PyFloat_CheckExact(sym_get_const(right))); + PyObject *temp = PyFloat_FromDouble( + PyFloat_AS_DOUBLE(sym_get_const(left)) - + PyFloat_AS_DOUBLE(sym_get_const(right))); + if (temp == NULL) { + goto error; + } + res = sym_new_const(ctx, temp); + // TODO gh-115506: + // replace opcode with constant propagated one and update tests! + } + else { + OUT_OF_SPACE_IF_NULL(res = sym_new_known_type(ctx, &PyFloat_Type)); + } + stack_pointer[-2] = res; + stack_pointer += -1; + break; + } + + case _GUARD_BOTH_UNICODE: { + _Py_UOpsSymType *right; + _Py_UOpsSymType *left; + right = stack_pointer[-1]; + left = stack_pointer[-2]; + if (sym_matches_type(left, &PyUnicode_Type) && + sym_matches_type(right, &PyUnicode_Type)) { + REPLACE_OP(this_instr, _NOP, 0 ,0); + } + sym_set_type(left, &PyUnicode_Type); + sym_set_type(right, &PyUnicode_Type); + break; + } + + case _BINARY_OP_ADD_UNICODE: { + _Py_UOpsSymType *res; + res = sym_new_unknown(ctx); + if (res == NULL) goto out_of_space; + stack_pointer[-2] = res; + stack_pointer += -1; + break; + } + + case _BINARY_SUBSCR: { + _Py_UOpsSymType *res; + res = sym_new_unknown(ctx); + if (res == NULL) goto out_of_space; + stack_pointer[-2] = res; + stack_pointer += -1; + break; + } + + case _BINARY_SLICE: { + _Py_UOpsSymType *res; + res = sym_new_unknown(ctx); + if (res == NULL) goto out_of_space; + stack_pointer[-3] = res; + stack_pointer += -2; + break; + } + + case _STORE_SLICE: { + stack_pointer += -4; + break; + } + + case _BINARY_SUBSCR_LIST_INT: { + _Py_UOpsSymType *res; + res = sym_new_unknown(ctx); + if (res == NULL) goto out_of_space; + stack_pointer[-2] = res; + stack_pointer += -1; + break; + } + + case _BINARY_SUBSCR_STR_INT: { + _Py_UOpsSymType *res; + res = sym_new_unknown(ctx); + if (res == NULL) goto out_of_space; + stack_pointer[-2] = res; + stack_pointer += -1; + break; + } + + case _BINARY_SUBSCR_TUPLE_INT: { + _Py_UOpsSymType *res; + res = sym_new_unknown(ctx); + if (res == NULL) goto out_of_space; + stack_pointer[-2] = res; + stack_pointer += -1; + break; + } + + case _BINARY_SUBSCR_DICT: { + _Py_UOpsSymType *res; + res = sym_new_unknown(ctx); + if (res == NULL) goto out_of_space; + stack_pointer[-2] = res; + stack_pointer += -1; + break; + } + + /* _BINARY_SUBSCR_GETITEM is not a viable micro-op for tier 2 */ + + case _LIST_APPEND: { + stack_pointer += -1; + break; + } + + case _SET_ADD: { + stack_pointer += -1; + break; + } + + case _STORE_SUBSCR: { + stack_pointer += -3; + break; + } + + case _STORE_SUBSCR_LIST_INT: { + stack_pointer += -3; + break; + } + + case _STORE_SUBSCR_DICT: { + stack_pointer += -3; + break; + } + + case _DELETE_SUBSCR: { + stack_pointer += -2; + break; + } + + case _CALL_INTRINSIC_1: { + _Py_UOpsSymType *res; + res = sym_new_unknown(ctx); + if (res == NULL) goto out_of_space; + stack_pointer[-1] = res; + break; + } + + case _CALL_INTRINSIC_2: { + _Py_UOpsSymType *res; + res = sym_new_unknown(ctx); + if (res == NULL) goto out_of_space; + stack_pointer[-2] = res; + stack_pointer += -1; + break; + } + + case _POP_FRAME: { + _Py_UOpsSymType *retval; + _Py_UOpsSymType *res; + retval = stack_pointer[-1]; + stack_pointer += -1; + ctx->frame->stack_pointer = stack_pointer; + ctx_frame_pop(ctx); + stack_pointer = ctx->frame->stack_pointer; + res = retval; + stack_pointer[0] = res; + stack_pointer += 1; + break; + } + + /* _INSTRUMENTED_RETURN_VALUE is not a viable micro-op for tier 2 */ + + /* _INSTRUMENTED_RETURN_CONST is not a viable micro-op for tier 2 */ + + case _GET_AITER: { + _Py_UOpsSymType *iter; + iter = sym_new_unknown(ctx); + if (iter == NULL) goto out_of_space; + stack_pointer[-1] = iter; + break; + } + + case _GET_ANEXT: { + _Py_UOpsSymType *awaitable; + awaitable = sym_new_unknown(ctx); + if (awaitable == NULL) goto out_of_space; + stack_pointer[0] = awaitable; + stack_pointer += 1; + break; + } + + case _GET_AWAITABLE: { + _Py_UOpsSymType *iter; + iter = sym_new_unknown(ctx); + if (iter == NULL) goto out_of_space; + stack_pointer[-1] = iter; + break; + } + + /* _SEND is not a viable micro-op for tier 2 */ + + /* _SEND_GEN is not a viable micro-op for tier 2 */ + + /* _INSTRUMENTED_YIELD_VALUE is not a viable micro-op for tier 2 */ + + case _POP_EXCEPT: { + stack_pointer += -1; + break; + } + + case _LOAD_ASSERTION_ERROR: { + _Py_UOpsSymType *value; + value = sym_new_unknown(ctx); + if (value == NULL) goto out_of_space; + stack_pointer[0] = value; + stack_pointer += 1; + break; + } + + case _LOAD_BUILD_CLASS: { + _Py_UOpsSymType *bc; + bc = sym_new_unknown(ctx); + if (bc == NULL) goto out_of_space; + stack_pointer[0] = bc; + stack_pointer += 1; + break; + } + + case _STORE_NAME: { + stack_pointer += -1; + break; + } + + case _DELETE_NAME: { + break; + } + + case _UNPACK_SEQUENCE: { + _Py_UOpsSymType *seq; + _Py_UOpsSymType **values; + seq = stack_pointer[-1]; + values = &stack_pointer[-1]; + /* This has to be done manually */ + (void)seq; + for (int i = 0; i < oparg; i++) { + OUT_OF_SPACE_IF_NULL(values[i] = sym_new_unknown(ctx)); + } + stack_pointer += -1 + oparg; + break; + } + + case _UNPACK_SEQUENCE_TWO_TUPLE: { + _Py_UOpsSymType **values; + values = &stack_pointer[-1]; + for (int _i = oparg; --_i >= 0;) { + values[_i] = sym_new_unknown(ctx); + if (values[_i] == NULL) goto out_of_space; + } + stack_pointer += -1 + oparg; + break; + } + + case _UNPACK_SEQUENCE_TUPLE: { + _Py_UOpsSymType **values; + values = &stack_pointer[-1]; + for (int _i = oparg; --_i >= 0;) { + values[_i] = sym_new_unknown(ctx); + if (values[_i] == NULL) goto out_of_space; + } + stack_pointer += -1 + oparg; + break; + } + + case _UNPACK_SEQUENCE_LIST: { + _Py_UOpsSymType **values; + values = &stack_pointer[-1]; + for (int _i = oparg; --_i >= 0;) { + values[_i] = sym_new_unknown(ctx); + if (values[_i] == NULL) goto out_of_space; + } + stack_pointer += -1 + oparg; + break; + } + + case _UNPACK_EX: { + _Py_UOpsSymType *seq; + _Py_UOpsSymType **values; + seq = stack_pointer[-1]; + values = &stack_pointer[-1]; + /* This has to be done manually */ + (void)seq; + int totalargs = (oparg & 0xFF) + (oparg >> 8) + 1; + for (int i = 0; i < totalargs; i++) { + OUT_OF_SPACE_IF_NULL(values[i] = sym_new_unknown(ctx)); + } + stack_pointer += (oparg >> 8) + (oparg & 0xFF); + break; + } + + case _STORE_ATTR: { + stack_pointer += -2; + break; + } + + case _DELETE_ATTR: { + stack_pointer += -1; + break; + } + + case _STORE_GLOBAL: { + stack_pointer += -1; + break; + } + + case _DELETE_GLOBAL: { + break; + } + + case _LOAD_LOCALS: { + _Py_UOpsSymType *locals; + locals = sym_new_unknown(ctx); + if (locals == NULL) goto out_of_space; + stack_pointer[0] = locals; + stack_pointer += 1; + break; + } + + case _LOAD_FROM_DICT_OR_GLOBALS: { + _Py_UOpsSymType *v; + v = sym_new_unknown(ctx); + if (v == NULL) goto out_of_space; + stack_pointer[-1] = v; + break; + } + + case _LOAD_NAME: { + _Py_UOpsSymType *v; + v = sym_new_unknown(ctx); + if (v == NULL) goto out_of_space; + stack_pointer[0] = v; + stack_pointer += 1; + break; + } + + case _LOAD_GLOBAL: { + _Py_UOpsSymType *res; + _Py_UOpsSymType *null = NULL; + res = sym_new_unknown(ctx); + if (res == NULL) goto out_of_space; + null = sym_new_null(ctx); + if (null == NULL) goto out_of_space; + stack_pointer[0] = res; + if (oparg & 1) stack_pointer[1] = null; + stack_pointer += 1 + (oparg & 1); + break; + } + + case _GUARD_GLOBALS_VERSION: { + break; + } + + case _GUARD_BUILTINS_VERSION: { + break; + } + + case _LOAD_GLOBAL_MODULE: { + _Py_UOpsSymType *res; + _Py_UOpsSymType *null = NULL; + res = sym_new_unknown(ctx); + if (res == NULL) goto out_of_space; + null = sym_new_null(ctx); + if (null == NULL) goto out_of_space; + stack_pointer[0] = res; + if (oparg & 1) stack_pointer[1] = null; + stack_pointer += 1 + (oparg & 1); + break; + } + + case _LOAD_GLOBAL_BUILTINS: { + _Py_UOpsSymType *res; + _Py_UOpsSymType *null = NULL; + res = sym_new_unknown(ctx); + if (res == NULL) goto out_of_space; + null = sym_new_null(ctx); + if (null == NULL) goto out_of_space; + stack_pointer[0] = res; + if (oparg & 1) stack_pointer[1] = null; + stack_pointer += 1 + (oparg & 1); + break; + } + + case _DELETE_FAST: { + break; + } + + case _MAKE_CELL: { + break; + } + + case _DELETE_DEREF: { + break; + } + + case _LOAD_FROM_DICT_OR_DEREF: { + _Py_UOpsSymType *value; + value = sym_new_unknown(ctx); + if (value == NULL) goto out_of_space; + stack_pointer[-1] = value; + break; + } + + case _LOAD_DEREF: { + _Py_UOpsSymType *value; + value = sym_new_unknown(ctx); + if (value == NULL) goto out_of_space; + stack_pointer[0] = value; + stack_pointer += 1; + break; + } + + case _STORE_DEREF: { + stack_pointer += -1; + break; + } + + case _COPY_FREE_VARS: { + break; + } + + case _BUILD_STRING: { + _Py_UOpsSymType *str; + str = sym_new_unknown(ctx); + if (str == NULL) goto out_of_space; + stack_pointer[-oparg] = str; + stack_pointer += 1 - oparg; + break; + } + + case _BUILD_TUPLE: { + _Py_UOpsSymType *tup; + tup = sym_new_unknown(ctx); + if (tup == NULL) goto out_of_space; + stack_pointer[-oparg] = tup; + stack_pointer += 1 - oparg; + break; + } + + case _BUILD_LIST: { + _Py_UOpsSymType *list; + list = sym_new_unknown(ctx); + if (list == NULL) goto out_of_space; + stack_pointer[-oparg] = list; + stack_pointer += 1 - oparg; + break; + } + + case _LIST_EXTEND: { + stack_pointer += -1; + break; + } + + case _SET_UPDATE: { + stack_pointer += -1; + break; + } + + case _BUILD_SET: { + _Py_UOpsSymType *set; + set = sym_new_unknown(ctx); + if (set == NULL) goto out_of_space; + stack_pointer[-oparg] = set; + stack_pointer += 1 - oparg; + break; + } + + case _BUILD_MAP: { + _Py_UOpsSymType *map; + map = sym_new_unknown(ctx); + if (map == NULL) goto out_of_space; + stack_pointer[-oparg*2] = map; + stack_pointer += 1 - oparg*2; + break; + } + + case _SETUP_ANNOTATIONS: { + break; + } + + case _BUILD_CONST_KEY_MAP: { + _Py_UOpsSymType *map; + map = sym_new_unknown(ctx); + if (map == NULL) goto out_of_space; + stack_pointer[-1 - oparg] = map; + stack_pointer += -oparg; + break; + } + + case _DICT_UPDATE: { + stack_pointer += -1; + break; + } + + case _DICT_MERGE: { + stack_pointer += -1; + break; + } + + case _MAP_ADD: { + stack_pointer += -2; + break; + } + + /* _INSTRUMENTED_LOAD_SUPER_ATTR is not a viable micro-op for tier 2 */ + + case _LOAD_SUPER_ATTR_ATTR: { + _Py_UOpsSymType *attr; + attr = sym_new_unknown(ctx); + if (attr == NULL) goto out_of_space; + stack_pointer[-3] = attr; + stack_pointer += -2; + break; + } + + case _LOAD_SUPER_ATTR_METHOD: { + _Py_UOpsSymType *attr; + _Py_UOpsSymType *self_or_null; + attr = sym_new_unknown(ctx); + if (attr == NULL) goto out_of_space; + self_or_null = sym_new_unknown(ctx); + if (self_or_null == NULL) goto out_of_space; + stack_pointer[-3] = attr; + stack_pointer[-2] = self_or_null; + stack_pointer += -1; + break; + } + + case _LOAD_ATTR: { + _Py_UOpsSymType *attr; + _Py_UOpsSymType *self_or_null = NULL; + attr = sym_new_unknown(ctx); + if (attr == NULL) goto out_of_space; + self_or_null = sym_new_unknown(ctx); + if (self_or_null == NULL) goto out_of_space; + stack_pointer[-1] = attr; + if (oparg & 1) stack_pointer[0] = self_or_null; + stack_pointer += (oparg & 1); + break; + } + + case _GUARD_TYPE_VERSION: { + break; + } + + case _CHECK_MANAGED_OBJECT_HAS_VALUES: { + break; + } + + case _LOAD_ATTR_INSTANCE_VALUE: { + _Py_UOpsSymType *owner; + _Py_UOpsSymType *attr; + _Py_UOpsSymType *null = NULL; + owner = stack_pointer[-1]; + uint16_t index = (uint16_t)this_instr->operand; + _LOAD_ATTR_NOT_NULL + (void)index; + (void)owner; + stack_pointer[-1] = attr; + if (oparg & 1) stack_pointer[0] = null; + stack_pointer += (oparg & 1); + break; + } + + case _CHECK_ATTR_MODULE: { + _Py_UOpsSymType *owner; + owner = stack_pointer[-1]; + uint32_t dict_version = (uint32_t)this_instr->operand; + (void)dict_version; + if (sym_is_const(owner)) { + PyObject *cnst = sym_get_const(owner); + if (PyModule_CheckExact(cnst)) { + PyModuleObject *mod = (PyModuleObject *)cnst; + PyObject *dict = mod->md_dict; + uint64_t watched_mutations = get_mutations(dict); + if (watched_mutations < _Py_MAX_ALLOWED_GLOBALS_MODIFICATIONS) { + PyDict_Watch(GLOBALS_WATCHER_ID, dict); + _Py_BloomFilter_Add(dependencies, dict); + this_instr->opcode = _NOP; + } + } + } + break; + } + + case _LOAD_ATTR_MODULE: { + _Py_UOpsSymType *owner; + _Py_UOpsSymType *attr; + _Py_UOpsSymType *null = NULL; + owner = stack_pointer[-1]; + uint16_t index = (uint16_t)this_instr->operand; + (void)index; + OUT_OF_SPACE_IF_NULL(null = sym_new_null(ctx)); + attr = NULL; + if (this_instr[-1].opcode == _NOP) { + // Preceding _CHECK_ATTR_MODULE was removed: mod is const and dict is watched. + assert(sym_is_const(owner)); + PyModuleObject *mod = (PyModuleObject *)sym_get_const(owner); + assert(PyModule_CheckExact(mod)); + PyObject *dict = mod->md_dict; + PyObject *res = convert_global_to_const(this_instr, dict); + if (res != NULL) { + this_instr[-1].opcode = _POP_TOP; + OUT_OF_SPACE_IF_NULL(attr = sym_new_const(ctx, res)); + } + } + if (attr == NULL) { + /* No conversion made. We don't know what `attr` is. */ + OUT_OF_SPACE_IF_NULL(attr = sym_new_known_notnull(ctx)); + } + stack_pointer[-1] = attr; + if (oparg & 1) stack_pointer[0] = null; + stack_pointer += (oparg & 1); + break; + } + + case _CHECK_ATTR_WITH_HINT: { + break; + } + + case _LOAD_ATTR_WITH_HINT: { + _Py_UOpsSymType *owner; + _Py_UOpsSymType *attr; + _Py_UOpsSymType *null = NULL; + owner = stack_pointer[-1]; + uint16_t hint = (uint16_t)this_instr->operand; + _LOAD_ATTR_NOT_NULL + (void)hint; + (void)owner; + stack_pointer[-1] = attr; + if (oparg & 1) stack_pointer[0] = null; + stack_pointer += (oparg & 1); + break; + } + + case _LOAD_ATTR_SLOT: { + _Py_UOpsSymType *owner; + _Py_UOpsSymType *attr; + _Py_UOpsSymType *null = NULL; + owner = stack_pointer[-1]; + uint16_t index = (uint16_t)this_instr->operand; + _LOAD_ATTR_NOT_NULL + (void)index; + (void)owner; + stack_pointer[-1] = attr; + if (oparg & 1) stack_pointer[0] = null; + stack_pointer += (oparg & 1); + break; + } + + case _CHECK_ATTR_CLASS: { + break; + } + + case _LOAD_ATTR_CLASS: { + _Py_UOpsSymType *owner; + _Py_UOpsSymType *attr; + _Py_UOpsSymType *null = NULL; + owner = stack_pointer[-1]; + PyObject *descr = (PyObject *)this_instr->operand; + _LOAD_ATTR_NOT_NULL + (void)descr; + (void)owner; + stack_pointer[-1] = attr; + if (oparg & 1) stack_pointer[0] = null; + stack_pointer += (oparg & 1); + break; + } + + /* _LOAD_ATTR_PROPERTY is not a viable micro-op for tier 2 */ + + /* _LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN is not a viable micro-op for tier 2 */ + + case _GUARD_DORV_VALUES: { + break; + } + + case _STORE_ATTR_INSTANCE_VALUE: { + stack_pointer += -2; + break; + } + + /* _STORE_ATTR_WITH_HINT is not a viable micro-op for tier 2 */ + + case _STORE_ATTR_SLOT: { + stack_pointer += -2; + break; + } + + case _COMPARE_OP: { + _Py_UOpsSymType *res; + res = sym_new_unknown(ctx); + if (res == NULL) goto out_of_space; + stack_pointer[-2] = res; + stack_pointer += -1; + break; + } + + case _COMPARE_OP_FLOAT: { + _Py_UOpsSymType *res; + res = sym_new_unknown(ctx); + if (res == NULL) goto out_of_space; + stack_pointer[-2] = res; + stack_pointer += -1; + break; + } + + case _COMPARE_OP_INT: { + _Py_UOpsSymType *res; + res = sym_new_unknown(ctx); + if (res == NULL) goto out_of_space; + stack_pointer[-2] = res; + stack_pointer += -1; + break; + } + + case _COMPARE_OP_STR: { + _Py_UOpsSymType *res; + res = sym_new_unknown(ctx); + if (res == NULL) goto out_of_space; + stack_pointer[-2] = res; + stack_pointer += -1; + break; + } + + case _IS_OP: { + _Py_UOpsSymType *b; + b = sym_new_unknown(ctx); + if (b == NULL) goto out_of_space; + stack_pointer[-2] = b; + stack_pointer += -1; + break; + } + + case _CONTAINS_OP: { + _Py_UOpsSymType *b; + b = sym_new_unknown(ctx); + if (b == NULL) goto out_of_space; + stack_pointer[-2] = b; + stack_pointer += -1; + break; + } + + case _CHECK_EG_MATCH: { + _Py_UOpsSymType *rest; + _Py_UOpsSymType *match; + rest = sym_new_unknown(ctx); + if (rest == NULL) goto out_of_space; + match = sym_new_unknown(ctx); + if (match == NULL) goto out_of_space; + stack_pointer[-2] = rest; + stack_pointer[-1] = match; + break; + } + + case _CHECK_EXC_MATCH: { + _Py_UOpsSymType *b; + b = sym_new_unknown(ctx); + if (b == NULL) goto out_of_space; + stack_pointer[-1] = b; + break; + } + + /* _POP_JUMP_IF_FALSE is not a viable micro-op for tier 2 */ + + /* _POP_JUMP_IF_TRUE is not a viable micro-op for tier 2 */ + + case _IS_NONE: { + _Py_UOpsSymType *b; + b = sym_new_unknown(ctx); + if (b == NULL) goto out_of_space; + stack_pointer[-1] = b; + break; + } + + case _GET_LEN: { + _Py_UOpsSymType *len_o; + len_o = sym_new_unknown(ctx); + if (len_o == NULL) goto out_of_space; + stack_pointer[0] = len_o; + stack_pointer += 1; + break; + } + + case _MATCH_CLASS: { + _Py_UOpsSymType *attrs; + attrs = sym_new_unknown(ctx); + if (attrs == NULL) goto out_of_space; + stack_pointer[-3] = attrs; + stack_pointer += -2; + break; + } + + case _MATCH_MAPPING: { + _Py_UOpsSymType *res; + res = sym_new_unknown(ctx); + if (res == NULL) goto out_of_space; + stack_pointer[0] = res; + stack_pointer += 1; + break; + } + + case _MATCH_SEQUENCE: { + _Py_UOpsSymType *res; + res = sym_new_unknown(ctx); + if (res == NULL) goto out_of_space; + stack_pointer[0] = res; + stack_pointer += 1; + break; + } + + case _MATCH_KEYS: { + _Py_UOpsSymType *values_or_none; + values_or_none = sym_new_unknown(ctx); + if (values_or_none == NULL) goto out_of_space; + stack_pointer[0] = values_or_none; + stack_pointer += 1; + break; + } + + case _GET_ITER: { + _Py_UOpsSymType *iter; + iter = sym_new_unknown(ctx); + if (iter == NULL) goto out_of_space; + stack_pointer[-1] = iter; + break; + } + + case _GET_YIELD_FROM_ITER: { + _Py_UOpsSymType *iter; + iter = sym_new_unknown(ctx); + if (iter == NULL) goto out_of_space; + stack_pointer[-1] = iter; + break; + } + + /* _FOR_ITER is not a viable micro-op for tier 2 */ + + case _FOR_ITER_TIER_TWO: { + _Py_UOpsSymType *next; + next = sym_new_unknown(ctx); + if (next == NULL) goto out_of_space; + stack_pointer[0] = next; + stack_pointer += 1; + break; + } + + /* _INSTRUMENTED_FOR_ITER is not a viable micro-op for tier 2 */ + + case _ITER_CHECK_LIST: { + break; + } + + /* _ITER_JUMP_LIST is not a viable micro-op for tier 2 */ + + case _GUARD_NOT_EXHAUSTED_LIST: { + break; + } + + case _ITER_NEXT_LIST: { + _Py_UOpsSymType *next; + next = sym_new_unknown(ctx); + if (next == NULL) goto out_of_space; + stack_pointer[0] = next; + stack_pointer += 1; + break; + } + + case _ITER_CHECK_TUPLE: { + break; + } + + /* _ITER_JUMP_TUPLE is not a viable micro-op for tier 2 */ + + case _GUARD_NOT_EXHAUSTED_TUPLE: { + break; + } + + case _ITER_NEXT_TUPLE: { + _Py_UOpsSymType *next; + next = sym_new_unknown(ctx); + if (next == NULL) goto out_of_space; + stack_pointer[0] = next; + stack_pointer += 1; + break; + } + + case _ITER_CHECK_RANGE: { + break; + } + + /* _ITER_JUMP_RANGE is not a viable micro-op for tier 2 */ + + case _GUARD_NOT_EXHAUSTED_RANGE: { + break; + } + + case _ITER_NEXT_RANGE: { + _Py_UOpsSymType *iter; + _Py_UOpsSymType *next; + iter = stack_pointer[-1]; + OUT_OF_SPACE_IF_NULL(next = sym_new_known_type(ctx, &PyLong_Type)); + (void)iter; + stack_pointer[0] = next; + stack_pointer += 1; + break; + } + + /* _FOR_ITER_GEN is not a viable micro-op for tier 2 */ + + case _BEFORE_ASYNC_WITH: { + _Py_UOpsSymType *exit; + _Py_UOpsSymType *res; + exit = sym_new_unknown(ctx); + if (exit == NULL) goto out_of_space; + res = sym_new_unknown(ctx); + if (res == NULL) goto out_of_space; + stack_pointer[-1] = exit; + stack_pointer[0] = res; + stack_pointer += 1; + break; + } + + case _BEFORE_WITH: { + _Py_UOpsSymType *exit; + _Py_UOpsSymType *res; + exit = sym_new_unknown(ctx); + if (exit == NULL) goto out_of_space; + res = sym_new_unknown(ctx); + if (res == NULL) goto out_of_space; + stack_pointer[-1] = exit; + stack_pointer[0] = res; + stack_pointer += 1; + break; + } + + case _WITH_EXCEPT_START: { + _Py_UOpsSymType *res; + res = sym_new_unknown(ctx); + if (res == NULL) goto out_of_space; + stack_pointer[0] = res; + stack_pointer += 1; + break; + } + + case _PUSH_EXC_INFO: { + _Py_UOpsSymType *prev_exc; + _Py_UOpsSymType *new_exc; + prev_exc = sym_new_unknown(ctx); + if (prev_exc == NULL) goto out_of_space; + new_exc = sym_new_unknown(ctx); + if (new_exc == NULL) goto out_of_space; + stack_pointer[-1] = prev_exc; + stack_pointer[0] = new_exc; + stack_pointer += 1; + break; + } + + case _GUARD_DORV_VALUES_INST_ATTR_FROM_DICT: { + break; + } + + case _GUARD_KEYS_VERSION: { + break; + } + + case _LOAD_ATTR_METHOD_WITH_VALUES: { + _Py_UOpsSymType *owner; + _Py_UOpsSymType *attr; + _Py_UOpsSymType *self = NULL; + owner = stack_pointer[-1]; + PyObject *descr = (PyObject *)this_instr->operand; + (void)descr; + OUT_OF_SPACE_IF_NULL(attr = sym_new_known_notnull(ctx)); + self = owner; + stack_pointer[-1] = attr; + stack_pointer[0] = self; + stack_pointer += 1; + break; + } + + case _LOAD_ATTR_METHOD_NO_DICT: { + _Py_UOpsSymType *owner; + _Py_UOpsSymType *attr; + _Py_UOpsSymType *self = NULL; + owner = stack_pointer[-1]; + PyObject *descr = (PyObject *)this_instr->operand; + (void)descr; + OUT_OF_SPACE_IF_NULL(attr = sym_new_known_notnull(ctx)); + self = owner; + stack_pointer[-1] = attr; + stack_pointer[0] = self; + stack_pointer += 1; + break; + } + + case _LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES: { + _Py_UOpsSymType *attr; + attr = sym_new_unknown(ctx); + if (attr == NULL) goto out_of_space; + stack_pointer[-1] = attr; + break; + } + + case _LOAD_ATTR_NONDESCRIPTOR_NO_DICT: { + _Py_UOpsSymType *attr; + attr = sym_new_unknown(ctx); + if (attr == NULL) goto out_of_space; + stack_pointer[-1] = attr; + break; + } + + case _CHECK_ATTR_METHOD_LAZY_DICT: { + break; + } + + case _LOAD_ATTR_METHOD_LAZY_DICT: { + _Py_UOpsSymType *owner; + _Py_UOpsSymType *attr; + _Py_UOpsSymType *self = NULL; + owner = stack_pointer[-1]; + PyObject *descr = (PyObject *)this_instr->operand; + (void)descr; + OUT_OF_SPACE_IF_NULL(attr = sym_new_known_notnull(ctx)); + self = owner; + stack_pointer[-1] = attr; + stack_pointer[0] = self; + stack_pointer += 1; + break; + } + + /* _INSTRUMENTED_CALL is not a viable micro-op for tier 2 */ + + /* _CALL is not a viable micro-op for tier 2 */ + + case _CHECK_CALL_BOUND_METHOD_EXACT_ARGS: { + _Py_UOpsSymType *null; + _Py_UOpsSymType *callable; + null = stack_pointer[-1 - oparg]; + callable = stack_pointer[-2 - oparg]; + sym_set_null(null); + sym_set_type(callable, &PyMethod_Type); + break; + } + + case _INIT_CALL_BOUND_METHOD_EXACT_ARGS: { + _Py_UOpsSymType *callable; + _Py_UOpsSymType *func; + _Py_UOpsSymType *self; + callable = stack_pointer[-2 - oparg]; + (void)callable; + OUT_OF_SPACE_IF_NULL(func = sym_new_known_notnull(ctx)); + OUT_OF_SPACE_IF_NULL(self = sym_new_known_notnull(ctx)); + stack_pointer[-2 - oparg] = func; + stack_pointer[-1 - oparg] = self; + break; + } + + case _CHECK_PEP_523: { + break; + } + + case _CHECK_FUNCTION_EXACT_ARGS: { + _Py_UOpsSymType *self_or_null; + _Py_UOpsSymType *callable; + self_or_null = stack_pointer[-1 - oparg]; + callable = stack_pointer[-2 - oparg]; + uint32_t func_version = (uint32_t)this_instr->operand; + sym_set_type(callable, &PyFunction_Type); + (void)self_or_null; + (void)func_version; + break; + } + + case _CHECK_STACK_SPACE: { + break; + } + + case _INIT_CALL_PY_EXACT_ARGS: { + _Py_UOpsSymType **args; + _Py_UOpsSymType *self_or_null; + _Py_UOpsSymType *callable; + _Py_UOpsAbstractFrame *new_frame; + args = &stack_pointer[-oparg]; + self_or_null = stack_pointer[-1 - oparg]; + callable = stack_pointer[-2 - oparg]; + int argcount = oparg; + (void)callable; + PyFunctionObject *func = (PyFunctionObject *)(this_instr + 2)->operand; + if (func == NULL) { + goto error; + } + PyCodeObject *co = (PyCodeObject *)func->func_code; + assert(self_or_null != NULL); + assert(args != NULL); + if (sym_is_not_null(self_or_null)) { + // Bound method fiddling, same as _INIT_CALL_PY_EXACT_ARGS in VM + args--; + argcount++; + } + _Py_UOpsSymType **localsplus_start = ctx->n_consumed; + int n_locals_already_filled = 0; + // Can determine statically, so we interleave the new locals + // and make the current stack the new locals. + // This also sets up for true call inlining. + if (sym_is_known(self_or_null)) { + localsplus_start = args; + n_locals_already_filled = argcount; + } + OUT_OF_SPACE_IF_NULL(new_frame = + ctx_frame_new(ctx, co, localsplus_start, n_locals_already_filled, 0)); + stack_pointer[-2 - oparg] = (_Py_UOpsSymType *)new_frame; + stack_pointer += -1 - oparg; + break; + } + + case _PUSH_FRAME: { + _Py_UOpsAbstractFrame *new_frame; + new_frame = (_Py_UOpsAbstractFrame *)stack_pointer[-1]; + stack_pointer += -1; + ctx->frame->stack_pointer = stack_pointer; + ctx->frame = new_frame; + ctx->curr_frame_depth++; + stack_pointer = new_frame->stack_pointer; + break; + } + + /* _CALL_PY_WITH_DEFAULTS is not a viable micro-op for tier 2 */ + + case _CALL_TYPE_1: { + _Py_UOpsSymType *res; + res = sym_new_unknown(ctx); + if (res == NULL) goto out_of_space; + stack_pointer[-2 - oparg] = res; + stack_pointer += -1 - oparg; + break; + } + + case _CALL_STR_1: { + _Py_UOpsSymType *res; + res = sym_new_unknown(ctx); + if (res == NULL) goto out_of_space; + stack_pointer[-2 - oparg] = res; + stack_pointer += -1 - oparg; + break; + } + + case _CALL_TUPLE_1: { + _Py_UOpsSymType *res; + res = sym_new_unknown(ctx); + if (res == NULL) goto out_of_space; + stack_pointer[-2 - oparg] = res; + stack_pointer += -1 - oparg; + break; + } + + /* _CALL_ALLOC_AND_ENTER_INIT is not a viable micro-op for tier 2 */ + + case _EXIT_INIT_CHECK: { + stack_pointer += -1; + break; + } + + case _CALL_BUILTIN_CLASS: { + _Py_UOpsSymType *res; + res = sym_new_unknown(ctx); + if (res == NULL) goto out_of_space; + stack_pointer[-2 - oparg] = res; + stack_pointer += -1 - oparg; + break; + } + + case _CALL_BUILTIN_O: { + _Py_UOpsSymType *res; + res = sym_new_unknown(ctx); + if (res == NULL) goto out_of_space; + stack_pointer[-2 - oparg] = res; + stack_pointer += -1 - oparg; + break; + } + + case _CALL_BUILTIN_FAST: { + _Py_UOpsSymType *res; + res = sym_new_unknown(ctx); + if (res == NULL) goto out_of_space; + stack_pointer[-2 - oparg] = res; + stack_pointer += -1 - oparg; + break; + } + + case _CALL_BUILTIN_FAST_WITH_KEYWORDS: { + _Py_UOpsSymType *res; + res = sym_new_unknown(ctx); + if (res == NULL) goto out_of_space; + stack_pointer[-2 - oparg] = res; + stack_pointer += -1 - oparg; + break; + } + + case _CALL_LEN: { + _Py_UOpsSymType *res; + res = sym_new_unknown(ctx); + if (res == NULL) goto out_of_space; + stack_pointer[-2 - oparg] = res; + stack_pointer += -1 - oparg; + break; + } + + case _CALL_ISINSTANCE: { + _Py_UOpsSymType *res; + res = sym_new_unknown(ctx); + if (res == NULL) goto out_of_space; + stack_pointer[-2 - oparg] = res; + stack_pointer += -1 - oparg; + break; + } + + case _CALL_METHOD_DESCRIPTOR_O: { + _Py_UOpsSymType *res; + res = sym_new_unknown(ctx); + if (res == NULL) goto out_of_space; + stack_pointer[-2 - oparg] = res; + stack_pointer += -1 - oparg; + break; + } + + case _CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS: { + _Py_UOpsSymType *res; + res = sym_new_unknown(ctx); + if (res == NULL) goto out_of_space; + stack_pointer[-2 - oparg] = res; + stack_pointer += -1 - oparg; + break; + } + + case _CALL_METHOD_DESCRIPTOR_NOARGS: { + _Py_UOpsSymType *res; + res = sym_new_unknown(ctx); + if (res == NULL) goto out_of_space; + stack_pointer[-2 - oparg] = res; + stack_pointer += -1 - oparg; + break; + } + + case _CALL_METHOD_DESCRIPTOR_FAST: { + _Py_UOpsSymType *res; + res = sym_new_unknown(ctx); + if (res == NULL) goto out_of_space; + stack_pointer[-2 - oparg] = res; + stack_pointer += -1 - oparg; + break; + } + + /* _INSTRUMENTED_CALL_KW is not a viable micro-op for tier 2 */ + + /* _CALL_KW is not a viable micro-op for tier 2 */ + + /* _INSTRUMENTED_CALL_FUNCTION_EX is not a viable micro-op for tier 2 */ + + /* _CALL_FUNCTION_EX is not a viable micro-op for tier 2 */ + + case _MAKE_FUNCTION: { + _Py_UOpsSymType *func; + func = sym_new_unknown(ctx); + if (func == NULL) goto out_of_space; + stack_pointer[-1] = func; + break; + } + + case _SET_FUNCTION_ATTRIBUTE: { + _Py_UOpsSymType *func; + func = sym_new_unknown(ctx); + if (func == NULL) goto out_of_space; + stack_pointer[-2] = func; + stack_pointer += -1; + break; + } + + case _BUILD_SLICE: { + _Py_UOpsSymType *slice; + slice = sym_new_unknown(ctx); + if (slice == NULL) goto out_of_space; + stack_pointer[-2 - ((oparg == 3) ? 1 : 0)] = slice; + stack_pointer += -1 - ((oparg == 3) ? 1 : 0); + break; + } + + case _CONVERT_VALUE: { + _Py_UOpsSymType *result; + result = sym_new_unknown(ctx); + if (result == NULL) goto out_of_space; + stack_pointer[-1] = result; + break; + } + + case _FORMAT_SIMPLE: { + _Py_UOpsSymType *res; + res = sym_new_unknown(ctx); + if (res == NULL) goto out_of_space; + stack_pointer[-1] = res; + break; + } + + case _FORMAT_WITH_SPEC: { + _Py_UOpsSymType *res; + res = sym_new_unknown(ctx); + if (res == NULL) goto out_of_space; + stack_pointer[-2] = res; + stack_pointer += -1; + break; + } + + case _COPY: { + _Py_UOpsSymType *bottom; + _Py_UOpsSymType *top; + bottom = stack_pointer[-1 - (oparg-1)]; + assert(oparg > 0); + top = bottom; + stack_pointer[0] = top; + stack_pointer += 1; + break; + } + + case _BINARY_OP: { + _Py_UOpsSymType *res; + res = sym_new_unknown(ctx); + if (res == NULL) goto out_of_space; + stack_pointer[-2] = res; + stack_pointer += -1; + break; + } + + case _SWAP: { + _Py_UOpsSymType *top; + _Py_UOpsSymType *bottom; + top = stack_pointer[-1]; + bottom = stack_pointer[-2 - (oparg-2)]; + stack_pointer[-2 - (oparg-2)] = top; + stack_pointer[-1] = bottom; + break; + } + + /* _INSTRUMENTED_INSTRUCTION is not a viable micro-op for tier 2 */ + + /* _INSTRUMENTED_JUMP_FORWARD is not a viable micro-op for tier 2 */ + + /* _INSTRUMENTED_JUMP_BACKWARD is not a viable micro-op for tier 2 */ + + /* _INSTRUMENTED_POP_JUMP_IF_TRUE is not a viable micro-op for tier 2 */ + + /* _INSTRUMENTED_POP_JUMP_IF_FALSE is not a viable micro-op for tier 2 */ + + /* _INSTRUMENTED_POP_JUMP_IF_NONE is not a viable micro-op for tier 2 */ + + /* _INSTRUMENTED_POP_JUMP_IF_NOT_NONE is not a viable micro-op for tier 2 */ + + case _GUARD_IS_TRUE_POP: { + stack_pointer += -1; + break; + } + + case _GUARD_IS_FALSE_POP: { + stack_pointer += -1; + break; + } + + case _GUARD_IS_NONE_POP: { + stack_pointer += -1; + break; + } + + case _GUARD_IS_NOT_NONE_POP: { + stack_pointer += -1; + break; + } + + case _JUMP_TO_TOP: { + break; + } + + case _SET_IP: { + break; + } + + case _SAVE_RETURN_OFFSET: { + break; + } + + case _EXIT_TRACE: { + break; + } + + case _CHECK_VALIDITY: { + break; + } + + case _LOAD_CONST_INLINE: { + _Py_UOpsSymType *value; + PyObject *ptr = (PyObject *)this_instr->operand; + OUT_OF_SPACE_IF_NULL(value = sym_new_const(ctx, ptr)); + stack_pointer[0] = value; + stack_pointer += 1; + break; + } + + case _LOAD_CONST_INLINE_BORROW: { + _Py_UOpsSymType *value; + PyObject *ptr = (PyObject *)this_instr->operand; + OUT_OF_SPACE_IF_NULL(value = sym_new_const(ctx, ptr)); + stack_pointer[0] = value; + stack_pointer += 1; + break; + } + + case _LOAD_CONST_INLINE_WITH_NULL: { + _Py_UOpsSymType *value; + _Py_UOpsSymType *null; + PyObject *ptr = (PyObject *)this_instr->operand; + OUT_OF_SPACE_IF_NULL(value = sym_new_const(ctx, ptr)); + OUT_OF_SPACE_IF_NULL(null = sym_new_null(ctx)); + stack_pointer[0] = value; + stack_pointer[1] = null; + stack_pointer += 2; + break; + } + + case _LOAD_CONST_INLINE_BORROW_WITH_NULL: { + _Py_UOpsSymType *value; + _Py_UOpsSymType *null; + PyObject *ptr = (PyObject *)this_instr->operand; + OUT_OF_SPACE_IF_NULL(value = sym_new_const(ctx, ptr)); + OUT_OF_SPACE_IF_NULL(null = sym_new_null(ctx)); + stack_pointer[0] = value; + stack_pointer[1] = null; + stack_pointer += 2; + break; + } + + case _CHECK_GLOBALS: { + break; + } + + case _CHECK_BUILTINS: { + break; + } + + case _INTERNAL_INCREMENT_OPT_COUNTER: { + stack_pointer += -1; + break; + } + + case _COLD_EXIT: { + break; + } + + case _START_EXECUTOR: { + break; + } + + case _FATAL_ERROR: { + break; + } + + case _CHECK_VALIDITY_AND_SET_IP: { + break; + } + diff --git a/Python/tier2_redundancy_eliminator_bytecodes.c b/Python/tier2_redundancy_eliminator_bytecodes.c deleted file mode 100644 index b9afd30..0000000 --- a/Python/tier2_redundancy_eliminator_bytecodes.c +++ /dev/null @@ -1,409 +0,0 @@ -#include "Python.h" -#include "pycore_uops.h" -#include "pycore_uop_ids.h" -#include "internal/pycore_moduleobject.h" - -#define op(name, ...) /* NAME is ignored */ - -typedef struct _Py_UOpsSymType _Py_UOpsSymType; -typedef struct _Py_UOpsAbstractInterpContext _Py_UOpsAbstractInterpContext; -typedef struct _Py_UOpsAbstractFrame _Py_UOpsAbstractFrame; - -static int -dummy_func(void) { - - PyCodeObject *code; - int oparg; - _Py_UOpsSymType *flag; - _Py_UOpsSymType *left; - _Py_UOpsSymType *right; - _Py_UOpsSymType *value; - _Py_UOpsSymType *res; - _Py_UOpsSymType *iter; - _Py_UOpsSymType *top; - _Py_UOpsSymType *bottom; - _Py_UOpsAbstractFrame *frame; - _Py_UOpsAbstractInterpContext *ctx; - _PyUOpInstruction *this_instr; - _PyBloomFilter *dependencies; - int modified; - -// BEGIN BYTECODES // - - op(_LOAD_FAST_CHECK, (-- value)) { - value = GETLOCAL(oparg); - // We guarantee this will error - just bail and don't optimize it. - if (sym_is_null(value)) { - goto out_of_space; - } - } - - op(_LOAD_FAST, (-- value)) { - value = GETLOCAL(oparg); - } - - op(_LOAD_FAST_AND_CLEAR, (-- value)) { - value = GETLOCAL(oparg); - _Py_UOpsSymType *temp; - OUT_OF_SPACE_IF_NULL(temp = sym_new_null(ctx)); - GETLOCAL(oparg) = temp; - } - - op(_STORE_FAST, (value --)) { - GETLOCAL(oparg) = value; - } - - op(_PUSH_NULL, (-- res)) { - res = sym_new_null(ctx); - if (res == NULL) { - goto out_of_space; - }; - } - - op(_GUARD_BOTH_INT, (left, right -- left, right)) { - if (sym_matches_type(left, &PyLong_Type) && - sym_matches_type(right, &PyLong_Type)) { - REPLACE_OP(this_instr, _NOP, 0, 0); - } - sym_set_type(left, &PyLong_Type); - sym_set_type(right, &PyLong_Type); - } - - op(_GUARD_BOTH_FLOAT, (left, right -- left, right)) { - if (sym_matches_type(left, &PyFloat_Type) && - sym_matches_type(right, &PyFloat_Type)) { - REPLACE_OP(this_instr, _NOP, 0 ,0); - } - sym_set_type(left, &PyFloat_Type); - sym_set_type(right, &PyFloat_Type); - } - - op(_GUARD_BOTH_UNICODE, (left, right -- left, right)) { - if (sym_matches_type(left, &PyUnicode_Type) && - sym_matches_type(right, &PyUnicode_Type)) { - REPLACE_OP(this_instr, _NOP, 0 ,0); - } - sym_set_type(left, &PyUnicode_Type); - sym_set_type(right, &PyUnicode_Type); - } - - op(_BINARY_OP_ADD_INT, (left, right -- res)) { - if (sym_is_const(left) && sym_is_const(right)) { - assert(PyLong_CheckExact(sym_get_const(left))); - assert(PyLong_CheckExact(sym_get_const(right))); - PyObject *temp = _PyLong_Add((PyLongObject *)sym_get_const(left), - (PyLongObject *)sym_get_const(right)); - if (temp == NULL) { - goto error; - } - OUT_OF_SPACE_IF_NULL(res = sym_new_const(ctx, temp)); - // TODO gh-115506: - // replace opcode with constant propagated one and add tests! - } - else { - OUT_OF_SPACE_IF_NULL(res = sym_new_known_type(ctx, &PyLong_Type)); - } - } - - op(_BINARY_OP_SUBTRACT_INT, (left, right -- res)) { - if (sym_is_const(left) && sym_is_const(right)) { - assert(PyLong_CheckExact(sym_get_const(left))); - assert(PyLong_CheckExact(sym_get_const(right))); - PyObject *temp = _PyLong_Subtract((PyLongObject *)sym_get_const(left), - (PyLongObject *)sym_get_const(right)); - if (temp == NULL) { - goto error; - } - OUT_OF_SPACE_IF_NULL(res = sym_new_const(ctx, temp)); - // TODO gh-115506: - // replace opcode with constant propagated one and add tests! - } - else { - OUT_OF_SPACE_IF_NULL(res = sym_new_known_type(ctx, &PyLong_Type)); - } - } - - op(_BINARY_OP_MULTIPLY_INT, (left, right -- res)) { - if (sym_is_const(left) && sym_is_const(right)) { - assert(PyLong_CheckExact(sym_get_const(left))); - assert(PyLong_CheckExact(sym_get_const(right))); - PyObject *temp = _PyLong_Multiply((PyLongObject *)sym_get_const(left), - (PyLongObject *)sym_get_const(right)); - if (temp == NULL) { - goto error; - } - OUT_OF_SPACE_IF_NULL(res = sym_new_const(ctx, temp)); - // TODO gh-115506: - // replace opcode with constant propagated one and add tests! - } - else { - OUT_OF_SPACE_IF_NULL(res = sym_new_known_type(ctx, &PyLong_Type)); - } - } - - op(_BINARY_OP_ADD_FLOAT, (left, right -- res)) { - if (sym_is_const(left) && sym_is_const(right)) { - assert(PyFloat_CheckExact(sym_get_const(left))); - assert(PyFloat_CheckExact(sym_get_const(right))); - PyObject *temp = PyFloat_FromDouble( - PyFloat_AS_DOUBLE(sym_get_const(left)) + - PyFloat_AS_DOUBLE(sym_get_const(right))); - if (temp == NULL) { - goto error; - } - res = sym_new_const(ctx, temp); - // TODO gh-115506: - // replace opcode with constant propagated one and update tests! - } - else { - OUT_OF_SPACE_IF_NULL(res = sym_new_known_type(ctx, &PyFloat_Type)); - } - } - - op(_BINARY_OP_SUBTRACT_FLOAT, (left, right -- res)) { - if (sym_is_const(left) && sym_is_const(right)) { - assert(PyFloat_CheckExact(sym_get_const(left))); - assert(PyFloat_CheckExact(sym_get_const(right))); - PyObject *temp = PyFloat_FromDouble( - PyFloat_AS_DOUBLE(sym_get_const(left)) - - PyFloat_AS_DOUBLE(sym_get_const(right))); - if (temp == NULL) { - goto error; - } - res = sym_new_const(ctx, temp); - // TODO gh-115506: - // replace opcode with constant propagated one and update tests! - } - else { - OUT_OF_SPACE_IF_NULL(res = sym_new_known_type(ctx, &PyFloat_Type)); - } - } - - op(_BINARY_OP_MULTIPLY_FLOAT, (left, right -- res)) { - if (sym_is_const(left) && sym_is_const(right)) { - assert(PyFloat_CheckExact(sym_get_const(left))); - assert(PyFloat_CheckExact(sym_get_const(right))); - PyObject *temp = PyFloat_FromDouble( - PyFloat_AS_DOUBLE(sym_get_const(left)) * - PyFloat_AS_DOUBLE(sym_get_const(right))); - if (temp == NULL) { - goto error; - } - res = sym_new_const(ctx, temp); - // TODO gh-115506: - // replace opcode with constant propagated one and update tests! - } - else { - OUT_OF_SPACE_IF_NULL(res = sym_new_known_type(ctx, &PyFloat_Type)); - } - } - - op(_LOAD_CONST, (-- value)) { - // There should be no LOAD_CONST. It should be all - // replaced by peephole_opt. - Py_UNREACHABLE(); - } - - op(_LOAD_CONST_INLINE, (ptr/4 -- value)) { - OUT_OF_SPACE_IF_NULL(value = sym_new_const(ctx, ptr)); - } - - op(_LOAD_CONST_INLINE_BORROW, (ptr/4 -- value)) { - OUT_OF_SPACE_IF_NULL(value = sym_new_const(ctx, ptr)); - } - - op(_LOAD_CONST_INLINE_WITH_NULL, (ptr/4 -- value, null)) { - OUT_OF_SPACE_IF_NULL(value = sym_new_const(ctx, ptr)); - OUT_OF_SPACE_IF_NULL(null = sym_new_null(ctx)); - } - - op(_LOAD_CONST_INLINE_BORROW_WITH_NULL, (ptr/4 -- value, null)) { - OUT_OF_SPACE_IF_NULL(value = sym_new_const(ctx, ptr)); - OUT_OF_SPACE_IF_NULL(null = sym_new_null(ctx)); - } - - - op(_COPY, (bottom, unused[oparg-1] -- bottom, unused[oparg-1], top)) { - assert(oparg > 0); - top = bottom; - } - - op(_SWAP, (bottom, unused[oparg-2], top -- - top, unused[oparg-2], bottom)) { - } - - op(_LOAD_ATTR_INSTANCE_VALUE, (index/1, owner -- attr, null if (oparg & 1))) { - _LOAD_ATTR_NOT_NULL - (void)index; - (void)owner; - } - - op(_CHECK_ATTR_MODULE, (dict_version/2, owner -- owner)) { - (void)dict_version; - if (sym_is_const(owner)) { - PyObject *cnst = sym_get_const(owner); - if (PyModule_CheckExact(cnst)) { - PyModuleObject *mod = (PyModuleObject *)cnst; - PyObject *dict = mod->md_dict; - uint64_t watched_mutations = get_mutations(dict); - if (watched_mutations < _Py_MAX_ALLOWED_GLOBALS_MODIFICATIONS) { - PyDict_Watch(GLOBALS_WATCHER_ID, dict); - _Py_BloomFilter_Add(dependencies, dict); - this_instr->opcode = _NOP; - } - } - } - } - - op(_LOAD_ATTR_MODULE, (index/1, owner -- attr, null if (oparg & 1))) { - (void)index; - OUT_OF_SPACE_IF_NULL(null = sym_new_null(ctx)); - attr = NULL; - if (this_instr[-1].opcode == _NOP) { - // Preceding _CHECK_ATTR_MODULE was removed: mod is const and dict is watched. - assert(sym_is_const(owner)); - PyModuleObject *mod = (PyModuleObject *)sym_get_const(owner); - assert(PyModule_CheckExact(mod)); - PyObject *dict = mod->md_dict; - PyObject *res = convert_global_to_const(this_instr, dict); - if (res != NULL) { - this_instr[-1].opcode = _POP_TOP; - OUT_OF_SPACE_IF_NULL(attr = sym_new_const(ctx, res)); - } - } - if (attr == NULL) { - /* No conversion made. We don't know what `attr` is. */ - OUT_OF_SPACE_IF_NULL(attr = sym_new_known_notnull(ctx)); - } - } - - op(_LOAD_ATTR_WITH_HINT, (hint/1, owner -- attr, null if (oparg & 1))) { - _LOAD_ATTR_NOT_NULL - (void)hint; - (void)owner; - } - - op(_LOAD_ATTR_SLOT, (index/1, owner -- attr, null if (oparg & 1))) { - _LOAD_ATTR_NOT_NULL - (void)index; - (void)owner; - } - - op(_LOAD_ATTR_CLASS, (descr/4, owner -- attr, null if (oparg & 1))) { - _LOAD_ATTR_NOT_NULL - (void)descr; - (void)owner; - } - - op(_LOAD_ATTR_METHOD_WITH_VALUES, (descr/4, owner -- attr, self if (1))) { - (void)descr; - OUT_OF_SPACE_IF_NULL(attr = sym_new_known_notnull(ctx)); - self = owner; - } - - op(_LOAD_ATTR_METHOD_NO_DICT, (descr/4, owner -- attr, self if (1))) { - (void)descr; - OUT_OF_SPACE_IF_NULL(attr = sym_new_known_notnull(ctx)); - self = owner; - } - - op(_LOAD_ATTR_METHOD_LAZY_DICT, (descr/4, owner -- attr, self if (1))) { - (void)descr; - OUT_OF_SPACE_IF_NULL(attr = sym_new_known_notnull(ctx)); - self = owner; - } - - op(_INIT_CALL_BOUND_METHOD_EXACT_ARGS, (callable, unused, unused[oparg] -- func, self, unused[oparg])) { - (void)callable; - OUT_OF_SPACE_IF_NULL(func = sym_new_known_notnull(ctx)); - OUT_OF_SPACE_IF_NULL(self = sym_new_known_notnull(ctx)); - } - - - op(_CHECK_FUNCTION_EXACT_ARGS, (func_version/2, callable, self_or_null, unused[oparg] -- callable, self_or_null, unused[oparg])) { - sym_set_type(callable, &PyFunction_Type); - (void)self_or_null; - (void)func_version; - } - - op(_CHECK_CALL_BOUND_METHOD_EXACT_ARGS, (callable, null, unused[oparg] -- callable, null, unused[oparg])) { - sym_set_null(null); - sym_set_type(callable, &PyMethod_Type); - } - - op(_INIT_CALL_PY_EXACT_ARGS, (callable, self_or_null, args[oparg] -- new_frame: _Py_UOpsAbstractFrame *)) { - int argcount = oparg; - - (void)callable; - - PyFunctionObject *func = (PyFunctionObject *)(this_instr + 2)->operand; - if (func == NULL) { - goto error; - } - PyCodeObject *co = (PyCodeObject *)func->func_code; - - assert(self_or_null != NULL); - assert(args != NULL); - if (sym_is_not_null(self_or_null)) { - // Bound method fiddling, same as _INIT_CALL_PY_EXACT_ARGS in VM - args--; - argcount++; - } - - _Py_UOpsSymType **localsplus_start = ctx->n_consumed; - int n_locals_already_filled = 0; - // Can determine statically, so we interleave the new locals - // and make the current stack the new locals. - // This also sets up for true call inlining. - if (sym_is_known(self_or_null)) { - localsplus_start = args; - n_locals_already_filled = argcount; - } - OUT_OF_SPACE_IF_NULL(new_frame = - ctx_frame_new(ctx, co, localsplus_start, n_locals_already_filled, 0)); - } - - op(_POP_FRAME, (retval -- res)) { - SYNC_SP(); - ctx->frame->stack_pointer = stack_pointer; - ctx_frame_pop(ctx); - stack_pointer = ctx->frame->stack_pointer; - res = retval; - } - - op(_PUSH_FRAME, (new_frame: _Py_UOpsAbstractFrame * -- unused if (0))) { - SYNC_SP(); - ctx->frame->stack_pointer = stack_pointer; - ctx->frame = new_frame; - ctx->curr_frame_depth++; - stack_pointer = new_frame->stack_pointer; - } - - op(_UNPACK_SEQUENCE, (seq -- values[oparg])) { - /* This has to be done manually */ - (void)seq; - for (int i = 0; i < oparg; i++) { - OUT_OF_SPACE_IF_NULL(values[i] = sym_new_unknown(ctx)); - } - } - - op(_UNPACK_EX, (seq -- values[oparg & 0xFF], unused, unused[oparg >> 8])) { - /* This has to be done manually */ - (void)seq; - int totalargs = (oparg & 0xFF) + (oparg >> 8) + 1; - for (int i = 0; i < totalargs; i++) { - OUT_OF_SPACE_IF_NULL(values[i] = sym_new_unknown(ctx)); - } - } - - op(_ITER_NEXT_RANGE, (iter -- iter, next)) { - OUT_OF_SPACE_IF_NULL(next = sym_new_known_type(ctx, &PyLong_Type)); - (void)iter; - } - - - - -// END BYTECODES // - -} diff --git a/Python/tier2_redundancy_eliminator_cases.c.h b/Python/tier2_redundancy_eliminator_cases.c.h deleted file mode 100644 index ca341e4..0000000 --- a/Python/tier2_redundancy_eliminator_cases.c.h +++ /dev/null @@ -1,1802 +0,0 @@ -// This file is generated by Tools/cases_generator/tier2_abstract_generator.py -// from: -// Python/tier2_redundancy_eliminator_bytecodes.c -// Do not edit! - - case _NOP: { - break; - } - - case _RESUME_CHECK: { - break; - } - - /* _INSTRUMENTED_RESUME is not a viable micro-op for tier 2 */ - - case _LOAD_FAST_CHECK: { - _Py_UOpsSymType *value; - value = GETLOCAL(oparg); - // We guarantee this will error - just bail and don't optimize it. - if (sym_is_null(value)) { - goto out_of_space; - } - stack_pointer[0] = value; - stack_pointer += 1; - break; - } - - case _LOAD_FAST: { - _Py_UOpsSymType *value; - value = GETLOCAL(oparg); - stack_pointer[0] = value; - stack_pointer += 1; - break; - } - - case _LOAD_FAST_AND_CLEAR: { - _Py_UOpsSymType *value; - value = GETLOCAL(oparg); - _Py_UOpsSymType *temp; - OUT_OF_SPACE_IF_NULL(temp = sym_new_null(ctx)); - GETLOCAL(oparg) = temp; - stack_pointer[0] = value; - stack_pointer += 1; - break; - } - - case _LOAD_CONST: { - _Py_UOpsSymType *value; - // There should be no LOAD_CONST. It should be all - // replaced by peephole_opt. - Py_UNREACHABLE(); - stack_pointer[0] = value; - stack_pointer += 1; - break; - } - - case _STORE_FAST: { - _Py_UOpsSymType *value; - value = stack_pointer[-1]; - GETLOCAL(oparg) = value; - stack_pointer += -1; - break; - } - - case _POP_TOP: { - stack_pointer += -1; - break; - } - - case _PUSH_NULL: { - _Py_UOpsSymType *res; - res = sym_new_null(ctx); - if (res == NULL) { - goto out_of_space; - }; - stack_pointer[0] = res; - stack_pointer += 1; - break; - } - - case _END_SEND: { - _Py_UOpsSymType *value; - value = sym_new_unknown(ctx); - if (value == NULL) goto out_of_space; - stack_pointer[-2] = value; - stack_pointer += -1; - break; - } - - case _UNARY_NEGATIVE: { - _Py_UOpsSymType *res; - res = sym_new_unknown(ctx); - if (res == NULL) goto out_of_space; - stack_pointer[-1] = res; - break; - } - - case _UNARY_NOT: { - _Py_UOpsSymType *res; - res = sym_new_unknown(ctx); - if (res == NULL) goto out_of_space; - stack_pointer[-1] = res; - break; - } - - case _TO_BOOL: { - _Py_UOpsSymType *res; - res = sym_new_unknown(ctx); - if (res == NULL) goto out_of_space; - stack_pointer[-1] = res; - break; - } - - case _TO_BOOL_BOOL: { - break; - } - - case _TO_BOOL_INT: { - _Py_UOpsSymType *res; - res = sym_new_unknown(ctx); - if (res == NULL) goto out_of_space; - stack_pointer[-1] = res; - break; - } - - case _TO_BOOL_LIST: { - _Py_UOpsSymType *res; - res = sym_new_unknown(ctx); - if (res == NULL) goto out_of_space; - stack_pointer[-1] = res; - break; - } - - case _TO_BOOL_NONE: { - _Py_UOpsSymType *res; - res = sym_new_unknown(ctx); - if (res == NULL) goto out_of_space; - stack_pointer[-1] = res; - break; - } - - case _TO_BOOL_STR: { - _Py_UOpsSymType *res; - res = sym_new_unknown(ctx); - if (res == NULL) goto out_of_space; - stack_pointer[-1] = res; - break; - } - - case _TO_BOOL_ALWAYS_TRUE: { - _Py_UOpsSymType *res; - res = sym_new_unknown(ctx); - if (res == NULL) goto out_of_space; - stack_pointer[-1] = res; - break; - } - - case _UNARY_INVERT: { - _Py_UOpsSymType *res; - res = sym_new_unknown(ctx); - if (res == NULL) goto out_of_space; - stack_pointer[-1] = res; - break; - } - - case _GUARD_BOTH_INT: { - _Py_UOpsSymType *right; - _Py_UOpsSymType *left; - right = stack_pointer[-1]; - left = stack_pointer[-2]; - if (sym_matches_type(left, &PyLong_Type) && - sym_matches_type(right, &PyLong_Type)) { - REPLACE_OP(this_instr, _NOP, 0, 0); - } - sym_set_type(left, &PyLong_Type); - sym_set_type(right, &PyLong_Type); - break; - } - - case _BINARY_OP_MULTIPLY_INT: { - _Py_UOpsSymType *right; - _Py_UOpsSymType *left; - _Py_UOpsSymType *res; - right = stack_pointer[-1]; - left = stack_pointer[-2]; - if (sym_is_const(left) && sym_is_const(right)) { - assert(PyLong_CheckExact(sym_get_const(left))); - assert(PyLong_CheckExact(sym_get_const(right))); - PyObject *temp = _PyLong_Multiply((PyLongObject *)sym_get_const(left), - (PyLongObject *)sym_get_const(right)); - if (temp == NULL) { - goto error; - } - OUT_OF_SPACE_IF_NULL(res = sym_new_const(ctx, temp)); - // TODO gh-115506: - // replace opcode with constant propagated one and add tests! - } - else { - OUT_OF_SPACE_IF_NULL(res = sym_new_known_type(ctx, &PyLong_Type)); - } - stack_pointer[-2] = res; - stack_pointer += -1; - break; - } - - case _BINARY_OP_ADD_INT: { - _Py_UOpsSymType *right; - _Py_UOpsSymType *left; - _Py_UOpsSymType *res; - right = stack_pointer[-1]; - left = stack_pointer[-2]; - if (sym_is_const(left) && sym_is_const(right)) { - assert(PyLong_CheckExact(sym_get_const(left))); - assert(PyLong_CheckExact(sym_get_const(right))); - PyObject *temp = _PyLong_Add((PyLongObject *)sym_get_const(left), - (PyLongObject *)sym_get_const(right)); - if (temp == NULL) { - goto error; - } - OUT_OF_SPACE_IF_NULL(res = sym_new_const(ctx, temp)); - // TODO gh-115506: - // replace opcode with constant propagated one and add tests! - } - else { - OUT_OF_SPACE_IF_NULL(res = sym_new_known_type(ctx, &PyLong_Type)); - } - stack_pointer[-2] = res; - stack_pointer += -1; - break; - } - - case _BINARY_OP_SUBTRACT_INT: { - _Py_UOpsSymType *right; - _Py_UOpsSymType *left; - _Py_UOpsSymType *res; - right = stack_pointer[-1]; - left = stack_pointer[-2]; - if (sym_is_const(left) && sym_is_const(right)) { - assert(PyLong_CheckExact(sym_get_const(left))); - assert(PyLong_CheckExact(sym_get_const(right))); - PyObject *temp = _PyLong_Subtract((PyLongObject *)sym_get_const(left), - (PyLongObject *)sym_get_const(right)); - if (temp == NULL) { - goto error; - } - OUT_OF_SPACE_IF_NULL(res = sym_new_const(ctx, temp)); - // TODO gh-115506: - // replace opcode with constant propagated one and add tests! - } - else { - OUT_OF_SPACE_IF_NULL(res = sym_new_known_type(ctx, &PyLong_Type)); - } - stack_pointer[-2] = res; - stack_pointer += -1; - break; - } - - case _GUARD_BOTH_FLOAT: { - _Py_UOpsSymType *right; - _Py_UOpsSymType *left; - right = stack_pointer[-1]; - left = stack_pointer[-2]; - if (sym_matches_type(left, &PyFloat_Type) && - sym_matches_type(right, &PyFloat_Type)) { - REPLACE_OP(this_instr, _NOP, 0 ,0); - } - sym_set_type(left, &PyFloat_Type); - sym_set_type(right, &PyFloat_Type); - break; - } - - case _BINARY_OP_MULTIPLY_FLOAT: { - _Py_UOpsSymType *right; - _Py_UOpsSymType *left; - _Py_UOpsSymType *res; - right = stack_pointer[-1]; - left = stack_pointer[-2]; - if (sym_is_const(left) && sym_is_const(right)) { - assert(PyFloat_CheckExact(sym_get_const(left))); - assert(PyFloat_CheckExact(sym_get_const(right))); - PyObject *temp = PyFloat_FromDouble( - PyFloat_AS_DOUBLE(sym_get_const(left)) * - PyFloat_AS_DOUBLE(sym_get_const(right))); - if (temp == NULL) { - goto error; - } - res = sym_new_const(ctx, temp); - // TODO gh-115506: - // replace opcode with constant propagated one and update tests! - } - else { - OUT_OF_SPACE_IF_NULL(res = sym_new_known_type(ctx, &PyFloat_Type)); - } - stack_pointer[-2] = res; - stack_pointer += -1; - break; - } - - case _BINARY_OP_ADD_FLOAT: { - _Py_UOpsSymType *right; - _Py_UOpsSymType *left; - _Py_UOpsSymType *res; - right = stack_pointer[-1]; - left = stack_pointer[-2]; - if (sym_is_const(left) && sym_is_const(right)) { - assert(PyFloat_CheckExact(sym_get_const(left))); - assert(PyFloat_CheckExact(sym_get_const(right))); - PyObject *temp = PyFloat_FromDouble( - PyFloat_AS_DOUBLE(sym_get_const(left)) + - PyFloat_AS_DOUBLE(sym_get_const(right))); - if (temp == NULL) { - goto error; - } - res = sym_new_const(ctx, temp); - // TODO gh-115506: - // replace opcode with constant propagated one and update tests! - } - else { - OUT_OF_SPACE_IF_NULL(res = sym_new_known_type(ctx, &PyFloat_Type)); - } - stack_pointer[-2] = res; - stack_pointer += -1; - break; - } - - case _BINARY_OP_SUBTRACT_FLOAT: { - _Py_UOpsSymType *right; - _Py_UOpsSymType *left; - _Py_UOpsSymType *res; - right = stack_pointer[-1]; - left = stack_pointer[-2]; - if (sym_is_const(left) && sym_is_const(right)) { - assert(PyFloat_CheckExact(sym_get_const(left))); - assert(PyFloat_CheckExact(sym_get_const(right))); - PyObject *temp = PyFloat_FromDouble( - PyFloat_AS_DOUBLE(sym_get_const(left)) - - PyFloat_AS_DOUBLE(sym_get_const(right))); - if (temp == NULL) { - goto error; - } - res = sym_new_const(ctx, temp); - // TODO gh-115506: - // replace opcode with constant propagated one and update tests! - } - else { - OUT_OF_SPACE_IF_NULL(res = sym_new_known_type(ctx, &PyFloat_Type)); - } - stack_pointer[-2] = res; - stack_pointer += -1; - break; - } - - case _GUARD_BOTH_UNICODE: { - _Py_UOpsSymType *right; - _Py_UOpsSymType *left; - right = stack_pointer[-1]; - left = stack_pointer[-2]; - if (sym_matches_type(left, &PyUnicode_Type) && - sym_matches_type(right, &PyUnicode_Type)) { - REPLACE_OP(this_instr, _NOP, 0 ,0); - } - sym_set_type(left, &PyUnicode_Type); - sym_set_type(right, &PyUnicode_Type); - break; - } - - case _BINARY_OP_ADD_UNICODE: { - _Py_UOpsSymType *res; - res = sym_new_unknown(ctx); - if (res == NULL) goto out_of_space; - stack_pointer[-2] = res; - stack_pointer += -1; - break; - } - - case _BINARY_SUBSCR: { - _Py_UOpsSymType *res; - res = sym_new_unknown(ctx); - if (res == NULL) goto out_of_space; - stack_pointer[-2] = res; - stack_pointer += -1; - break; - } - - case _BINARY_SLICE: { - _Py_UOpsSymType *res; - res = sym_new_unknown(ctx); - if (res == NULL) goto out_of_space; - stack_pointer[-3] = res; - stack_pointer += -2; - break; - } - - case _STORE_SLICE: { - stack_pointer += -4; - break; - } - - case _BINARY_SUBSCR_LIST_INT: { - _Py_UOpsSymType *res; - res = sym_new_unknown(ctx); - if (res == NULL) goto out_of_space; - stack_pointer[-2] = res; - stack_pointer += -1; - break; - } - - case _BINARY_SUBSCR_STR_INT: { - _Py_UOpsSymType *res; - res = sym_new_unknown(ctx); - if (res == NULL) goto out_of_space; - stack_pointer[-2] = res; - stack_pointer += -1; - break; - } - - case _BINARY_SUBSCR_TUPLE_INT: { - _Py_UOpsSymType *res; - res = sym_new_unknown(ctx); - if (res == NULL) goto out_of_space; - stack_pointer[-2] = res; - stack_pointer += -1; - break; - } - - case _BINARY_SUBSCR_DICT: { - _Py_UOpsSymType *res; - res = sym_new_unknown(ctx); - if (res == NULL) goto out_of_space; - stack_pointer[-2] = res; - stack_pointer += -1; - break; - } - - /* _BINARY_SUBSCR_GETITEM is not a viable micro-op for tier 2 */ - - case _LIST_APPEND: { - stack_pointer += -1; - break; - } - - case _SET_ADD: { - stack_pointer += -1; - break; - } - - case _STORE_SUBSCR: { - stack_pointer += -3; - break; - } - - case _STORE_SUBSCR_LIST_INT: { - stack_pointer += -3; - break; - } - - case _STORE_SUBSCR_DICT: { - stack_pointer += -3; - break; - } - - case _DELETE_SUBSCR: { - stack_pointer += -2; - break; - } - - case _CALL_INTRINSIC_1: { - _Py_UOpsSymType *res; - res = sym_new_unknown(ctx); - if (res == NULL) goto out_of_space; - stack_pointer[-1] = res; - break; - } - - case _CALL_INTRINSIC_2: { - _Py_UOpsSymType *res; - res = sym_new_unknown(ctx); - if (res == NULL) goto out_of_space; - stack_pointer[-2] = res; - stack_pointer += -1; - break; - } - - case _POP_FRAME: { - _Py_UOpsSymType *retval; - _Py_UOpsSymType *res; - retval = stack_pointer[-1]; - stack_pointer += -1; - ctx->frame->stack_pointer = stack_pointer; - ctx_frame_pop(ctx); - stack_pointer = ctx->frame->stack_pointer; - res = retval; - stack_pointer[0] = res; - stack_pointer += 1; - break; - } - - /* _INSTRUMENTED_RETURN_VALUE is not a viable micro-op for tier 2 */ - - /* _INSTRUMENTED_RETURN_CONST is not a viable micro-op for tier 2 */ - - case _GET_AITER: { - _Py_UOpsSymType *iter; - iter = sym_new_unknown(ctx); - if (iter == NULL) goto out_of_space; - stack_pointer[-1] = iter; - break; - } - - case _GET_ANEXT: { - _Py_UOpsSymType *awaitable; - awaitable = sym_new_unknown(ctx); - if (awaitable == NULL) goto out_of_space; - stack_pointer[0] = awaitable; - stack_pointer += 1; - break; - } - - case _GET_AWAITABLE: { - _Py_UOpsSymType *iter; - iter = sym_new_unknown(ctx); - if (iter == NULL) goto out_of_space; - stack_pointer[-1] = iter; - break; - } - - /* _SEND is not a viable micro-op for tier 2 */ - - /* _SEND_GEN is not a viable micro-op for tier 2 */ - - /* _INSTRUMENTED_YIELD_VALUE is not a viable micro-op for tier 2 */ - - case _POP_EXCEPT: { - stack_pointer += -1; - break; - } - - case _LOAD_ASSERTION_ERROR: { - _Py_UOpsSymType *value; - value = sym_new_unknown(ctx); - if (value == NULL) goto out_of_space; - stack_pointer[0] = value; - stack_pointer += 1; - break; - } - - case _LOAD_BUILD_CLASS: { - _Py_UOpsSymType *bc; - bc = sym_new_unknown(ctx); - if (bc == NULL) goto out_of_space; - stack_pointer[0] = bc; - stack_pointer += 1; - break; - } - - case _STORE_NAME: { - stack_pointer += -1; - break; - } - - case _DELETE_NAME: { - break; - } - - case _UNPACK_SEQUENCE: { - _Py_UOpsSymType *seq; - _Py_UOpsSymType **values; - seq = stack_pointer[-1]; - values = &stack_pointer[-1]; - /* This has to be done manually */ - (void)seq; - for (int i = 0; i < oparg; i++) { - OUT_OF_SPACE_IF_NULL(values[i] = sym_new_unknown(ctx)); - } - stack_pointer += -1 + oparg; - break; - } - - case _UNPACK_SEQUENCE_TWO_TUPLE: { - _Py_UOpsSymType **values; - values = &stack_pointer[-1]; - for (int _i = oparg; --_i >= 0;) { - values[_i] = sym_new_unknown(ctx); - if (values[_i] == NULL) goto out_of_space; - } - stack_pointer += -1 + oparg; - break; - } - - case _UNPACK_SEQUENCE_TUPLE: { - _Py_UOpsSymType **values; - values = &stack_pointer[-1]; - for (int _i = oparg; --_i >= 0;) { - values[_i] = sym_new_unknown(ctx); - if (values[_i] == NULL) goto out_of_space; - } - stack_pointer += -1 + oparg; - break; - } - - case _UNPACK_SEQUENCE_LIST: { - _Py_UOpsSymType **values; - values = &stack_pointer[-1]; - for (int _i = oparg; --_i >= 0;) { - values[_i] = sym_new_unknown(ctx); - if (values[_i] == NULL) goto out_of_space; - } - stack_pointer += -1 + oparg; - break; - } - - case _UNPACK_EX: { - _Py_UOpsSymType *seq; - _Py_UOpsSymType **values; - seq = stack_pointer[-1]; - values = &stack_pointer[-1]; - /* This has to be done manually */ - (void)seq; - int totalargs = (oparg & 0xFF) + (oparg >> 8) + 1; - for (int i = 0; i < totalargs; i++) { - OUT_OF_SPACE_IF_NULL(values[i] = sym_new_unknown(ctx)); - } - stack_pointer += (oparg >> 8) + (oparg & 0xFF); - break; - } - - case _STORE_ATTR: { - stack_pointer += -2; - break; - } - - case _DELETE_ATTR: { - stack_pointer += -1; - break; - } - - case _STORE_GLOBAL: { - stack_pointer += -1; - break; - } - - case _DELETE_GLOBAL: { - break; - } - - case _LOAD_LOCALS: { - _Py_UOpsSymType *locals; - locals = sym_new_unknown(ctx); - if (locals == NULL) goto out_of_space; - stack_pointer[0] = locals; - stack_pointer += 1; - break; - } - - case _LOAD_FROM_DICT_OR_GLOBALS: { - _Py_UOpsSymType *v; - v = sym_new_unknown(ctx); - if (v == NULL) goto out_of_space; - stack_pointer[-1] = v; - break; - } - - case _LOAD_NAME: { - _Py_UOpsSymType *v; - v = sym_new_unknown(ctx); - if (v == NULL) goto out_of_space; - stack_pointer[0] = v; - stack_pointer += 1; - break; - } - - case _LOAD_GLOBAL: { - _Py_UOpsSymType *res; - _Py_UOpsSymType *null = NULL; - res = sym_new_unknown(ctx); - if (res == NULL) goto out_of_space; - null = sym_new_null(ctx); - if (null == NULL) goto out_of_space; - stack_pointer[0] = res; - if (oparg & 1) stack_pointer[1] = null; - stack_pointer += 1 + (oparg & 1); - break; - } - - case _GUARD_GLOBALS_VERSION: { - break; - } - - case _GUARD_BUILTINS_VERSION: { - break; - } - - case _LOAD_GLOBAL_MODULE: { - _Py_UOpsSymType *res; - _Py_UOpsSymType *null = NULL; - res = sym_new_unknown(ctx); - if (res == NULL) goto out_of_space; - null = sym_new_null(ctx); - if (null == NULL) goto out_of_space; - stack_pointer[0] = res; - if (oparg & 1) stack_pointer[1] = null; - stack_pointer += 1 + (oparg & 1); - break; - } - - case _LOAD_GLOBAL_BUILTINS: { - _Py_UOpsSymType *res; - _Py_UOpsSymType *null = NULL; - res = sym_new_unknown(ctx); - if (res == NULL) goto out_of_space; - null = sym_new_null(ctx); - if (null == NULL) goto out_of_space; - stack_pointer[0] = res; - if (oparg & 1) stack_pointer[1] = null; - stack_pointer += 1 + (oparg & 1); - break; - } - - case _DELETE_FAST: { - break; - } - - case _MAKE_CELL: { - break; - } - - case _DELETE_DEREF: { - break; - } - - case _LOAD_FROM_DICT_OR_DEREF: { - _Py_UOpsSymType *value; - value = sym_new_unknown(ctx); - if (value == NULL) goto out_of_space; - stack_pointer[-1] = value; - break; - } - - case _LOAD_DEREF: { - _Py_UOpsSymType *value; - value = sym_new_unknown(ctx); - if (value == NULL) goto out_of_space; - stack_pointer[0] = value; - stack_pointer += 1; - break; - } - - case _STORE_DEREF: { - stack_pointer += -1; - break; - } - - case _COPY_FREE_VARS: { - break; - } - - case _BUILD_STRING: { - _Py_UOpsSymType *str; - str = sym_new_unknown(ctx); - if (str == NULL) goto out_of_space; - stack_pointer[-oparg] = str; - stack_pointer += 1 - oparg; - break; - } - - case _BUILD_TUPLE: { - _Py_UOpsSymType *tup; - tup = sym_new_unknown(ctx); - if (tup == NULL) goto out_of_space; - stack_pointer[-oparg] = tup; - stack_pointer += 1 - oparg; - break; - } - - case _BUILD_LIST: { - _Py_UOpsSymType *list; - list = sym_new_unknown(ctx); - if (list == NULL) goto out_of_space; - stack_pointer[-oparg] = list; - stack_pointer += 1 - oparg; - break; - } - - case _LIST_EXTEND: { - stack_pointer += -1; - break; - } - - case _SET_UPDATE: { - stack_pointer += -1; - break; - } - - case _BUILD_SET: { - _Py_UOpsSymType *set; - set = sym_new_unknown(ctx); - if (set == NULL) goto out_of_space; - stack_pointer[-oparg] = set; - stack_pointer += 1 - oparg; - break; - } - - case _BUILD_MAP: { - _Py_UOpsSymType *map; - map = sym_new_unknown(ctx); - if (map == NULL) goto out_of_space; - stack_pointer[-oparg*2] = map; - stack_pointer += 1 - oparg*2; - break; - } - - case _SETUP_ANNOTATIONS: { - break; - } - - case _BUILD_CONST_KEY_MAP: { - _Py_UOpsSymType *map; - map = sym_new_unknown(ctx); - if (map == NULL) goto out_of_space; - stack_pointer[-1 - oparg] = map; - stack_pointer += -oparg; - break; - } - - case _DICT_UPDATE: { - stack_pointer += -1; - break; - } - - case _DICT_MERGE: { - stack_pointer += -1; - break; - } - - case _MAP_ADD: { - stack_pointer += -2; - break; - } - - /* _INSTRUMENTED_LOAD_SUPER_ATTR is not a viable micro-op for tier 2 */ - - case _LOAD_SUPER_ATTR_ATTR: { - _Py_UOpsSymType *attr; - attr = sym_new_unknown(ctx); - if (attr == NULL) goto out_of_space; - stack_pointer[-3] = attr; - stack_pointer += -2; - break; - } - - case _LOAD_SUPER_ATTR_METHOD: { - _Py_UOpsSymType *attr; - _Py_UOpsSymType *self_or_null; - attr = sym_new_unknown(ctx); - if (attr == NULL) goto out_of_space; - self_or_null = sym_new_unknown(ctx); - if (self_or_null == NULL) goto out_of_space; - stack_pointer[-3] = attr; - stack_pointer[-2] = self_or_null; - stack_pointer += -1; - break; - } - - case _LOAD_ATTR: { - _Py_UOpsSymType *attr; - _Py_UOpsSymType *self_or_null = NULL; - attr = sym_new_unknown(ctx); - if (attr == NULL) goto out_of_space; - self_or_null = sym_new_unknown(ctx); - if (self_or_null == NULL) goto out_of_space; - stack_pointer[-1] = attr; - if (oparg & 1) stack_pointer[0] = self_or_null; - stack_pointer += (oparg & 1); - break; - } - - case _GUARD_TYPE_VERSION: { - break; - } - - case _CHECK_MANAGED_OBJECT_HAS_VALUES: { - break; - } - - case _LOAD_ATTR_INSTANCE_VALUE: { - _Py_UOpsSymType *owner; - _Py_UOpsSymType *attr; - _Py_UOpsSymType *null = NULL; - owner = stack_pointer[-1]; - uint16_t index = (uint16_t)this_instr->operand; - _LOAD_ATTR_NOT_NULL - (void)index; - (void)owner; - stack_pointer[-1] = attr; - if (oparg & 1) stack_pointer[0] = null; - stack_pointer += (oparg & 1); - break; - } - - case _CHECK_ATTR_MODULE: { - _Py_UOpsSymType *owner; - owner = stack_pointer[-1]; - uint32_t dict_version = (uint32_t)this_instr->operand; - (void)dict_version; - if (sym_is_const(owner)) { - PyObject *cnst = sym_get_const(owner); - if (PyModule_CheckExact(cnst)) { - PyModuleObject *mod = (PyModuleObject *)cnst; - PyObject *dict = mod->md_dict; - uint64_t watched_mutations = get_mutations(dict); - if (watched_mutations < _Py_MAX_ALLOWED_GLOBALS_MODIFICATIONS) { - PyDict_Watch(GLOBALS_WATCHER_ID, dict); - _Py_BloomFilter_Add(dependencies, dict); - this_instr->opcode = _NOP; - } - } - } - break; - } - - case _LOAD_ATTR_MODULE: { - _Py_UOpsSymType *owner; - _Py_UOpsSymType *attr; - _Py_UOpsSymType *null = NULL; - owner = stack_pointer[-1]; - uint16_t index = (uint16_t)this_instr->operand; - (void)index; - OUT_OF_SPACE_IF_NULL(null = sym_new_null(ctx)); - attr = NULL; - if (this_instr[-1].opcode == _NOP) { - // Preceding _CHECK_ATTR_MODULE was removed: mod is const and dict is watched. - assert(sym_is_const(owner)); - PyModuleObject *mod = (PyModuleObject *)sym_get_const(owner); - assert(PyModule_CheckExact(mod)); - PyObject *dict = mod->md_dict; - PyObject *res = convert_global_to_const(this_instr, dict); - if (res != NULL) { - this_instr[-1].opcode = _POP_TOP; - OUT_OF_SPACE_IF_NULL(attr = sym_new_const(ctx, res)); - } - } - if (attr == NULL) { - /* No conversion made. We don't know what `attr` is. */ - OUT_OF_SPACE_IF_NULL(attr = sym_new_known_notnull(ctx)); - } - stack_pointer[-1] = attr; - if (oparg & 1) stack_pointer[0] = null; - stack_pointer += (oparg & 1); - break; - } - - case _CHECK_ATTR_WITH_HINT: { - break; - } - - case _LOAD_ATTR_WITH_HINT: { - _Py_UOpsSymType *owner; - _Py_UOpsSymType *attr; - _Py_UOpsSymType *null = NULL; - owner = stack_pointer[-1]; - uint16_t hint = (uint16_t)this_instr->operand; - _LOAD_ATTR_NOT_NULL - (void)hint; - (void)owner; - stack_pointer[-1] = attr; - if (oparg & 1) stack_pointer[0] = null; - stack_pointer += (oparg & 1); - break; - } - - case _LOAD_ATTR_SLOT: { - _Py_UOpsSymType *owner; - _Py_UOpsSymType *attr; - _Py_UOpsSymType *null = NULL; - owner = stack_pointer[-1]; - uint16_t index = (uint16_t)this_instr->operand; - _LOAD_ATTR_NOT_NULL - (void)index; - (void)owner; - stack_pointer[-1] = attr; - if (oparg & 1) stack_pointer[0] = null; - stack_pointer += (oparg & 1); - break; - } - - case _CHECK_ATTR_CLASS: { - break; - } - - case _LOAD_ATTR_CLASS: { - _Py_UOpsSymType *owner; - _Py_UOpsSymType *attr; - _Py_UOpsSymType *null = NULL; - owner = stack_pointer[-1]; - PyObject *descr = (PyObject *)this_instr->operand; - _LOAD_ATTR_NOT_NULL - (void)descr; - (void)owner; - stack_pointer[-1] = attr; - if (oparg & 1) stack_pointer[0] = null; - stack_pointer += (oparg & 1); - break; - } - - /* _LOAD_ATTR_PROPERTY is not a viable micro-op for tier 2 */ - - /* _LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN is not a viable micro-op for tier 2 */ - - case _GUARD_DORV_VALUES: { - break; - } - - case _STORE_ATTR_INSTANCE_VALUE: { - stack_pointer += -2; - break; - } - - /* _STORE_ATTR_WITH_HINT is not a viable micro-op for tier 2 */ - - case _STORE_ATTR_SLOT: { - stack_pointer += -2; - break; - } - - case _COMPARE_OP: { - _Py_UOpsSymType *res; - res = sym_new_unknown(ctx); - if (res == NULL) goto out_of_space; - stack_pointer[-2] = res; - stack_pointer += -1; - break; - } - - case _COMPARE_OP_FLOAT: { - _Py_UOpsSymType *res; - res = sym_new_unknown(ctx); - if (res == NULL) goto out_of_space; - stack_pointer[-2] = res; - stack_pointer += -1; - break; - } - - case _COMPARE_OP_INT: { - _Py_UOpsSymType *res; - res = sym_new_unknown(ctx); - if (res == NULL) goto out_of_space; - stack_pointer[-2] = res; - stack_pointer += -1; - break; - } - - case _COMPARE_OP_STR: { - _Py_UOpsSymType *res; - res = sym_new_unknown(ctx); - if (res == NULL) goto out_of_space; - stack_pointer[-2] = res; - stack_pointer += -1; - break; - } - - case _IS_OP: { - _Py_UOpsSymType *b; - b = sym_new_unknown(ctx); - if (b == NULL) goto out_of_space; - stack_pointer[-2] = b; - stack_pointer += -1; - break; - } - - case _CONTAINS_OP: { - _Py_UOpsSymType *b; - b = sym_new_unknown(ctx); - if (b == NULL) goto out_of_space; - stack_pointer[-2] = b; - stack_pointer += -1; - break; - } - - case _CHECK_EG_MATCH: { - _Py_UOpsSymType *rest; - _Py_UOpsSymType *match; - rest = sym_new_unknown(ctx); - if (rest == NULL) goto out_of_space; - match = sym_new_unknown(ctx); - if (match == NULL) goto out_of_space; - stack_pointer[-2] = rest; - stack_pointer[-1] = match; - break; - } - - case _CHECK_EXC_MATCH: { - _Py_UOpsSymType *b; - b = sym_new_unknown(ctx); - if (b == NULL) goto out_of_space; - stack_pointer[-1] = b; - break; - } - - /* _POP_JUMP_IF_FALSE is not a viable micro-op for tier 2 */ - - /* _POP_JUMP_IF_TRUE is not a viable micro-op for tier 2 */ - - case _IS_NONE: { - _Py_UOpsSymType *b; - b = sym_new_unknown(ctx); - if (b == NULL) goto out_of_space; - stack_pointer[-1] = b; - break; - } - - case _GET_LEN: { - _Py_UOpsSymType *len_o; - len_o = sym_new_unknown(ctx); - if (len_o == NULL) goto out_of_space; - stack_pointer[0] = len_o; - stack_pointer += 1; - break; - } - - case _MATCH_CLASS: { - _Py_UOpsSymType *attrs; - attrs = sym_new_unknown(ctx); - if (attrs == NULL) goto out_of_space; - stack_pointer[-3] = attrs; - stack_pointer += -2; - break; - } - - case _MATCH_MAPPING: { - _Py_UOpsSymType *res; - res = sym_new_unknown(ctx); - if (res == NULL) goto out_of_space; - stack_pointer[0] = res; - stack_pointer += 1; - break; - } - - case _MATCH_SEQUENCE: { - _Py_UOpsSymType *res; - res = sym_new_unknown(ctx); - if (res == NULL) goto out_of_space; - stack_pointer[0] = res; - stack_pointer += 1; - break; - } - - case _MATCH_KEYS: { - _Py_UOpsSymType *values_or_none; - values_or_none = sym_new_unknown(ctx); - if (values_or_none == NULL) goto out_of_space; - stack_pointer[0] = values_or_none; - stack_pointer += 1; - break; - } - - case _GET_ITER: { - _Py_UOpsSymType *iter; - iter = sym_new_unknown(ctx); - if (iter == NULL) goto out_of_space; - stack_pointer[-1] = iter; - break; - } - - case _GET_YIELD_FROM_ITER: { - _Py_UOpsSymType *iter; - iter = sym_new_unknown(ctx); - if (iter == NULL) goto out_of_space; - stack_pointer[-1] = iter; - break; - } - - /* _FOR_ITER is not a viable micro-op for tier 2 */ - - case _FOR_ITER_TIER_TWO: { - _Py_UOpsSymType *next; - next = sym_new_unknown(ctx); - if (next == NULL) goto out_of_space; - stack_pointer[0] = next; - stack_pointer += 1; - break; - } - - /* _INSTRUMENTED_FOR_ITER is not a viable micro-op for tier 2 */ - - case _ITER_CHECK_LIST: { - break; - } - - /* _ITER_JUMP_LIST is not a viable micro-op for tier 2 */ - - case _GUARD_NOT_EXHAUSTED_LIST: { - break; - } - - case _ITER_NEXT_LIST: { - _Py_UOpsSymType *next; - next = sym_new_unknown(ctx); - if (next == NULL) goto out_of_space; - stack_pointer[0] = next; - stack_pointer += 1; - break; - } - - case _ITER_CHECK_TUPLE: { - break; - } - - /* _ITER_JUMP_TUPLE is not a viable micro-op for tier 2 */ - - case _GUARD_NOT_EXHAUSTED_TUPLE: { - break; - } - - case _ITER_NEXT_TUPLE: { - _Py_UOpsSymType *next; - next = sym_new_unknown(ctx); - if (next == NULL) goto out_of_space; - stack_pointer[0] = next; - stack_pointer += 1; - break; - } - - case _ITER_CHECK_RANGE: { - break; - } - - /* _ITER_JUMP_RANGE is not a viable micro-op for tier 2 */ - - case _GUARD_NOT_EXHAUSTED_RANGE: { - break; - } - - case _ITER_NEXT_RANGE: { - _Py_UOpsSymType *iter; - _Py_UOpsSymType *next; - iter = stack_pointer[-1]; - OUT_OF_SPACE_IF_NULL(next = sym_new_known_type(ctx, &PyLong_Type)); - (void)iter; - stack_pointer[0] = next; - stack_pointer += 1; - break; - } - - /* _FOR_ITER_GEN is not a viable micro-op for tier 2 */ - - case _BEFORE_ASYNC_WITH: { - _Py_UOpsSymType *exit; - _Py_UOpsSymType *res; - exit = sym_new_unknown(ctx); - if (exit == NULL) goto out_of_space; - res = sym_new_unknown(ctx); - if (res == NULL) goto out_of_space; - stack_pointer[-1] = exit; - stack_pointer[0] = res; - stack_pointer += 1; - break; - } - - case _BEFORE_WITH: { - _Py_UOpsSymType *exit; - _Py_UOpsSymType *res; - exit = sym_new_unknown(ctx); - if (exit == NULL) goto out_of_space; - res = sym_new_unknown(ctx); - if (res == NULL) goto out_of_space; - stack_pointer[-1] = exit; - stack_pointer[0] = res; - stack_pointer += 1; - break; - } - - case _WITH_EXCEPT_START: { - _Py_UOpsSymType *res; - res = sym_new_unknown(ctx); - if (res == NULL) goto out_of_space; - stack_pointer[0] = res; - stack_pointer += 1; - break; - } - - case _PUSH_EXC_INFO: { - _Py_UOpsSymType *prev_exc; - _Py_UOpsSymType *new_exc; - prev_exc = sym_new_unknown(ctx); - if (prev_exc == NULL) goto out_of_space; - new_exc = sym_new_unknown(ctx); - if (new_exc == NULL) goto out_of_space; - stack_pointer[-1] = prev_exc; - stack_pointer[0] = new_exc; - stack_pointer += 1; - break; - } - - case _GUARD_DORV_VALUES_INST_ATTR_FROM_DICT: { - break; - } - - case _GUARD_KEYS_VERSION: { - break; - } - - case _LOAD_ATTR_METHOD_WITH_VALUES: { - _Py_UOpsSymType *owner; - _Py_UOpsSymType *attr; - _Py_UOpsSymType *self = NULL; - owner = stack_pointer[-1]; - PyObject *descr = (PyObject *)this_instr->operand; - (void)descr; - OUT_OF_SPACE_IF_NULL(attr = sym_new_known_notnull(ctx)); - self = owner; - stack_pointer[-1] = attr; - stack_pointer[0] = self; - stack_pointer += 1; - break; - } - - case _LOAD_ATTR_METHOD_NO_DICT: { - _Py_UOpsSymType *owner; - _Py_UOpsSymType *attr; - _Py_UOpsSymType *self = NULL; - owner = stack_pointer[-1]; - PyObject *descr = (PyObject *)this_instr->operand; - (void)descr; - OUT_OF_SPACE_IF_NULL(attr = sym_new_known_notnull(ctx)); - self = owner; - stack_pointer[-1] = attr; - stack_pointer[0] = self; - stack_pointer += 1; - break; - } - - case _LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES: { - _Py_UOpsSymType *attr; - attr = sym_new_unknown(ctx); - if (attr == NULL) goto out_of_space; - stack_pointer[-1] = attr; - break; - } - - case _LOAD_ATTR_NONDESCRIPTOR_NO_DICT: { - _Py_UOpsSymType *attr; - attr = sym_new_unknown(ctx); - if (attr == NULL) goto out_of_space; - stack_pointer[-1] = attr; - break; - } - - case _CHECK_ATTR_METHOD_LAZY_DICT: { - break; - } - - case _LOAD_ATTR_METHOD_LAZY_DICT: { - _Py_UOpsSymType *owner; - _Py_UOpsSymType *attr; - _Py_UOpsSymType *self = NULL; - owner = stack_pointer[-1]; - PyObject *descr = (PyObject *)this_instr->operand; - (void)descr; - OUT_OF_SPACE_IF_NULL(attr = sym_new_known_notnull(ctx)); - self = owner; - stack_pointer[-1] = attr; - stack_pointer[0] = self; - stack_pointer += 1; - break; - } - - /* _INSTRUMENTED_CALL is not a viable micro-op for tier 2 */ - - /* _CALL is not a viable micro-op for tier 2 */ - - case _CHECK_CALL_BOUND_METHOD_EXACT_ARGS: { - _Py_UOpsSymType *null; - _Py_UOpsSymType *callable; - null = stack_pointer[-1 - oparg]; - callable = stack_pointer[-2 - oparg]; - sym_set_null(null); - sym_set_type(callable, &PyMethod_Type); - break; - } - - case _INIT_CALL_BOUND_METHOD_EXACT_ARGS: { - _Py_UOpsSymType *callable; - _Py_UOpsSymType *func; - _Py_UOpsSymType *self; - callable = stack_pointer[-2 - oparg]; - (void)callable; - OUT_OF_SPACE_IF_NULL(func = sym_new_known_notnull(ctx)); - OUT_OF_SPACE_IF_NULL(self = sym_new_known_notnull(ctx)); - stack_pointer[-2 - oparg] = func; - stack_pointer[-1 - oparg] = self; - break; - } - - case _CHECK_PEP_523: { - break; - } - - case _CHECK_FUNCTION_EXACT_ARGS: { - _Py_UOpsSymType *self_or_null; - _Py_UOpsSymType *callable; - self_or_null = stack_pointer[-1 - oparg]; - callable = stack_pointer[-2 - oparg]; - uint32_t func_version = (uint32_t)this_instr->operand; - sym_set_type(callable, &PyFunction_Type); - (void)self_or_null; - (void)func_version; - break; - } - - case _CHECK_STACK_SPACE: { - break; - } - - case _INIT_CALL_PY_EXACT_ARGS: { - _Py_UOpsSymType **args; - _Py_UOpsSymType *self_or_null; - _Py_UOpsSymType *callable; - _Py_UOpsAbstractFrame *new_frame; - args = &stack_pointer[-oparg]; - self_or_null = stack_pointer[-1 - oparg]; - callable = stack_pointer[-2 - oparg]; - int argcount = oparg; - (void)callable; - PyFunctionObject *func = (PyFunctionObject *)(this_instr + 2)->operand; - if (func == NULL) { - goto error; - } - PyCodeObject *co = (PyCodeObject *)func->func_code; - assert(self_or_null != NULL); - assert(args != NULL); - if (sym_is_not_null(self_or_null)) { - // Bound method fiddling, same as _INIT_CALL_PY_EXACT_ARGS in VM - args--; - argcount++; - } - _Py_UOpsSymType **localsplus_start = ctx->n_consumed; - int n_locals_already_filled = 0; - // Can determine statically, so we interleave the new locals - // and make the current stack the new locals. - // This also sets up for true call inlining. - if (sym_is_known(self_or_null)) { - localsplus_start = args; - n_locals_already_filled = argcount; - } - OUT_OF_SPACE_IF_NULL(new_frame = - ctx_frame_new(ctx, co, localsplus_start, n_locals_already_filled, 0)); - stack_pointer[-2 - oparg] = (_Py_UOpsSymType *)new_frame; - stack_pointer += -1 - oparg; - break; - } - - case _PUSH_FRAME: { - _Py_UOpsAbstractFrame *new_frame; - new_frame = (_Py_UOpsAbstractFrame *)stack_pointer[-1]; - stack_pointer += -1; - ctx->frame->stack_pointer = stack_pointer; - ctx->frame = new_frame; - ctx->curr_frame_depth++; - stack_pointer = new_frame->stack_pointer; - break; - } - - /* _CALL_PY_WITH_DEFAULTS is not a viable micro-op for tier 2 */ - - case _CALL_TYPE_1: { - _Py_UOpsSymType *res; - res = sym_new_unknown(ctx); - if (res == NULL) goto out_of_space; - stack_pointer[-2 - oparg] = res; - stack_pointer += -1 - oparg; - break; - } - - case _CALL_STR_1: { - _Py_UOpsSymType *res; - res = sym_new_unknown(ctx); - if (res == NULL) goto out_of_space; - stack_pointer[-2 - oparg] = res; - stack_pointer += -1 - oparg; - break; - } - - case _CALL_TUPLE_1: { - _Py_UOpsSymType *res; - res = sym_new_unknown(ctx); - if (res == NULL) goto out_of_space; - stack_pointer[-2 - oparg] = res; - stack_pointer += -1 - oparg; - break; - } - - /* _CALL_ALLOC_AND_ENTER_INIT is not a viable micro-op for tier 2 */ - - case _EXIT_INIT_CHECK: { - stack_pointer += -1; - break; - } - - case _CALL_BUILTIN_CLASS: { - _Py_UOpsSymType *res; - res = sym_new_unknown(ctx); - if (res == NULL) goto out_of_space; - stack_pointer[-2 - oparg] = res; - stack_pointer += -1 - oparg; - break; - } - - case _CALL_BUILTIN_O: { - _Py_UOpsSymType *res; - res = sym_new_unknown(ctx); - if (res == NULL) goto out_of_space; - stack_pointer[-2 - oparg] = res; - stack_pointer += -1 - oparg; - break; - } - - case _CALL_BUILTIN_FAST: { - _Py_UOpsSymType *res; - res = sym_new_unknown(ctx); - if (res == NULL) goto out_of_space; - stack_pointer[-2 - oparg] = res; - stack_pointer += -1 - oparg; - break; - } - - case _CALL_BUILTIN_FAST_WITH_KEYWORDS: { - _Py_UOpsSymType *res; - res = sym_new_unknown(ctx); - if (res == NULL) goto out_of_space; - stack_pointer[-2 - oparg] = res; - stack_pointer += -1 - oparg; - break; - } - - case _CALL_LEN: { - _Py_UOpsSymType *res; - res = sym_new_unknown(ctx); - if (res == NULL) goto out_of_space; - stack_pointer[-2 - oparg] = res; - stack_pointer += -1 - oparg; - break; - } - - case _CALL_ISINSTANCE: { - _Py_UOpsSymType *res; - res = sym_new_unknown(ctx); - if (res == NULL) goto out_of_space; - stack_pointer[-2 - oparg] = res; - stack_pointer += -1 - oparg; - break; - } - - case _CALL_METHOD_DESCRIPTOR_O: { - _Py_UOpsSymType *res; - res = sym_new_unknown(ctx); - if (res == NULL) goto out_of_space; - stack_pointer[-2 - oparg] = res; - stack_pointer += -1 - oparg; - break; - } - - case _CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS: { - _Py_UOpsSymType *res; - res = sym_new_unknown(ctx); - if (res == NULL) goto out_of_space; - stack_pointer[-2 - oparg] = res; - stack_pointer += -1 - oparg; - break; - } - - case _CALL_METHOD_DESCRIPTOR_NOARGS: { - _Py_UOpsSymType *res; - res = sym_new_unknown(ctx); - if (res == NULL) goto out_of_space; - stack_pointer[-2 - oparg] = res; - stack_pointer += -1 - oparg; - break; - } - - case _CALL_METHOD_DESCRIPTOR_FAST: { - _Py_UOpsSymType *res; - res = sym_new_unknown(ctx); - if (res == NULL) goto out_of_space; - stack_pointer[-2 - oparg] = res; - stack_pointer += -1 - oparg; - break; - } - - /* _INSTRUMENTED_CALL_KW is not a viable micro-op for tier 2 */ - - /* _CALL_KW is not a viable micro-op for tier 2 */ - - /* _INSTRUMENTED_CALL_FUNCTION_EX is not a viable micro-op for tier 2 */ - - /* _CALL_FUNCTION_EX is not a viable micro-op for tier 2 */ - - case _MAKE_FUNCTION: { - _Py_UOpsSymType *func; - func = sym_new_unknown(ctx); - if (func == NULL) goto out_of_space; - stack_pointer[-1] = func; - break; - } - - case _SET_FUNCTION_ATTRIBUTE: { - _Py_UOpsSymType *func; - func = sym_new_unknown(ctx); - if (func == NULL) goto out_of_space; - stack_pointer[-2] = func; - stack_pointer += -1; - break; - } - - case _BUILD_SLICE: { - _Py_UOpsSymType *slice; - slice = sym_new_unknown(ctx); - if (slice == NULL) goto out_of_space; - stack_pointer[-2 - ((oparg == 3) ? 1 : 0)] = slice; - stack_pointer += -1 - ((oparg == 3) ? 1 : 0); - break; - } - - case _CONVERT_VALUE: { - _Py_UOpsSymType *result; - result = sym_new_unknown(ctx); - if (result == NULL) goto out_of_space; - stack_pointer[-1] = result; - break; - } - - case _FORMAT_SIMPLE: { - _Py_UOpsSymType *res; - res = sym_new_unknown(ctx); - if (res == NULL) goto out_of_space; - stack_pointer[-1] = res; - break; - } - - case _FORMAT_WITH_SPEC: { - _Py_UOpsSymType *res; - res = sym_new_unknown(ctx); - if (res == NULL) goto out_of_space; - stack_pointer[-2] = res; - stack_pointer += -1; - break; - } - - case _COPY: { - _Py_UOpsSymType *bottom; - _Py_UOpsSymType *top; - bottom = stack_pointer[-1 - (oparg-1)]; - assert(oparg > 0); - top = bottom; - stack_pointer[0] = top; - stack_pointer += 1; - break; - } - - case _BINARY_OP: { - _Py_UOpsSymType *res; - res = sym_new_unknown(ctx); - if (res == NULL) goto out_of_space; - stack_pointer[-2] = res; - stack_pointer += -1; - break; - } - - case _SWAP: { - _Py_UOpsSymType *top; - _Py_UOpsSymType *bottom; - top = stack_pointer[-1]; - bottom = stack_pointer[-2 - (oparg-2)]; - stack_pointer[-2 - (oparg-2)] = top; - stack_pointer[-1] = bottom; - break; - } - - /* _INSTRUMENTED_INSTRUCTION is not a viable micro-op for tier 2 */ - - /* _INSTRUMENTED_JUMP_FORWARD is not a viable micro-op for tier 2 */ - - /* _INSTRUMENTED_JUMP_BACKWARD is not a viable micro-op for tier 2 */ - - /* _INSTRUMENTED_POP_JUMP_IF_TRUE is not a viable micro-op for tier 2 */ - - /* _INSTRUMENTED_POP_JUMP_IF_FALSE is not a viable micro-op for tier 2 */ - - /* _INSTRUMENTED_POP_JUMP_IF_NONE is not a viable micro-op for tier 2 */ - - /* _INSTRUMENTED_POP_JUMP_IF_NOT_NONE is not a viable micro-op for tier 2 */ - - case _GUARD_IS_TRUE_POP: { - stack_pointer += -1; - break; - } - - case _GUARD_IS_FALSE_POP: { - stack_pointer += -1; - break; - } - - case _GUARD_IS_NONE_POP: { - stack_pointer += -1; - break; - } - - case _GUARD_IS_NOT_NONE_POP: { - stack_pointer += -1; - break; - } - - case _JUMP_TO_TOP: { - break; - } - - case _SET_IP: { - break; - } - - case _SAVE_RETURN_OFFSET: { - break; - } - - case _EXIT_TRACE: { - break; - } - - case _CHECK_VALIDITY: { - break; - } - - case _LOAD_CONST_INLINE: { - _Py_UOpsSymType *value; - PyObject *ptr = (PyObject *)this_instr->operand; - OUT_OF_SPACE_IF_NULL(value = sym_new_const(ctx, ptr)); - stack_pointer[0] = value; - stack_pointer += 1; - break; - } - - case _LOAD_CONST_INLINE_BORROW: { - _Py_UOpsSymType *value; - PyObject *ptr = (PyObject *)this_instr->operand; - OUT_OF_SPACE_IF_NULL(value = sym_new_const(ctx, ptr)); - stack_pointer[0] = value; - stack_pointer += 1; - break; - } - - case _LOAD_CONST_INLINE_WITH_NULL: { - _Py_UOpsSymType *value; - _Py_UOpsSymType *null; - PyObject *ptr = (PyObject *)this_instr->operand; - OUT_OF_SPACE_IF_NULL(value = sym_new_const(ctx, ptr)); - OUT_OF_SPACE_IF_NULL(null = sym_new_null(ctx)); - stack_pointer[0] = value; - stack_pointer[1] = null; - stack_pointer += 2; - break; - } - - case _LOAD_CONST_INLINE_BORROW_WITH_NULL: { - _Py_UOpsSymType *value; - _Py_UOpsSymType *null; - PyObject *ptr = (PyObject *)this_instr->operand; - OUT_OF_SPACE_IF_NULL(value = sym_new_const(ctx, ptr)); - OUT_OF_SPACE_IF_NULL(null = sym_new_null(ctx)); - stack_pointer[0] = value; - stack_pointer[1] = null; - stack_pointer += 2; - break; - } - - case _CHECK_GLOBALS: { - break; - } - - case _CHECK_BUILTINS: { - break; - } - - case _INTERNAL_INCREMENT_OPT_COUNTER: { - stack_pointer += -1; - break; - } - - case _COLD_EXIT: { - break; - } - - case _START_EXECUTOR: { - break; - } - - case _FATAL_ERROR: { - break; - } - - case _CHECK_VALIDITY_AND_SET_IP: { - break; - } - diff --git a/Tools/c-analyzer/cpython/_parser.py b/Tools/c-analyzer/cpython/_parser.py index 8482bf8..12010f0 100644 --- a/Tools/c-analyzer/cpython/_parser.py +++ b/Tools/c-analyzer/cpython/_parser.py @@ -83,11 +83,11 @@ Python/deepfreeze/*.c Python/frozen_modules/*.h Python/generated_cases.c.h Python/executor_cases.c.h -Python/tier2_redundancy_eliminator_cases.c.h +Python/optimizer_cases.c.h # not actually source Python/bytecodes.c -Python/tier2_redundancy_eliminator_bytecodes.c +Python/optimizer_bytecodes.c # mimalloc Objects/mimalloc/*.c diff --git a/Tools/cases_generator/README.md b/Tools/cases_generator/README.md index d35a868..fb512c4 100644 --- a/Tools/cases_generator/README.md +++ b/Tools/cases_generator/README.md @@ -13,9 +13,9 @@ What's currently here: - `parser.py` helper for interactions with `parsing.py` - `tierN_generator.py`: a couple of driver scripts to read `Python/bytecodes.c` and write `Python/generated_cases.c.h` (and several other files) -- `tier2_abstract_generator.py`: reads `Python/bytecodes.c` and - `Python/tier2_redundancy_eliminator_bytecodes.c` and writes - `Python/tier2_redundancy_eliminator_cases.c.h` +- `optimizer_generator.py`: reads `Python/bytecodes.c` and + `Python/optimizer_bytecodes.c` and writes + `Python/optimizer_cases.c.h` - `stack.py`: code to handle generalized stack effects - `cwriter.py`: code which understands tokens and how to format C code; main class: `CWriter` diff --git a/Tools/cases_generator/optimizer_generator.py b/Tools/cases_generator/optimizer_generator.py new file mode 100644 index 0000000..aa3f4ec --- /dev/null +++ b/Tools/cases_generator/optimizer_generator.py @@ -0,0 +1,237 @@ +"""Generate the cases for the tier 2 optimizer. +Reads the instruction definitions from bytecodes.c and optimizer_bytecodes.c +Writes the cases to optimizer_cases.c.h, which is #included in Python/optimizer_analysis.c. +""" + +import argparse +import os.path +import sys + +from analyzer import ( + Analysis, + Instruction, + Uop, + Part, + analyze_files, + Skip, + StackItem, + analysis_error, +) +from generators_common import ( + DEFAULT_INPUT, + ROOT, + write_header, + emit_tokens, + emit_to, + replace_sync_sp, +) +from cwriter import CWriter +from typing import TextIO, Iterator +from lexer import Token +from stack import StackOffset, Stack, SizeMismatch, UNUSED + +DEFAULT_OUTPUT = ROOT / "Python/optimizer_cases.c.h" +DEFAULT_ABSTRACT_INPUT = ROOT / "Python/optimizer_bytecodes.c" + + +def validate_uop(override: Uop, uop: Uop) -> None: + # To do + pass + + +def type_name(var: StackItem) -> str: + if var.is_array(): + return f"_Py_UOpsSymType **" + if var.type: + return var.type + return f"_Py_UOpsSymType *" + + +def declare_variables(uop: Uop, out: CWriter, skip_inputs: bool) -> None: + variables = {"unused"} + if not skip_inputs: + for var in reversed(uop.stack.inputs): + if var.name not in variables: + variables.add(var.name) + if var.condition: + out.emit(f"{type_name(var)}{var.name} = NULL;\n") + else: + out.emit(f"{type_name(var)}{var.name};\n") + for var in uop.stack.outputs: + if var.peek: + continue + if var.name not in variables: + variables.add(var.name) + if var.condition: + out.emit(f"{type_name(var)}{var.name} = NULL;\n") + else: + out.emit(f"{type_name(var)}{var.name};\n") + + +def decref_inputs( + out: CWriter, + tkn: Token, + tkn_iter: Iterator[Token], + uop: Uop, + stack: Stack, + inst: Instruction | None, +) -> None: + next(tkn_iter) + next(tkn_iter) + next(tkn_iter) + out.emit_at("", tkn) + + +def emit_default(out: CWriter, uop: Uop) -> None: + for i, var in enumerate(uop.stack.outputs): + if var.name != "unused" and not var.peek: + if var.is_array(): + out.emit(f"for (int _i = {var.size}; --_i >= 0;) {{\n") + out.emit(f"{var.name}[_i] = sym_new_unknown(ctx);\n") + out.emit(f"if ({var.name}[_i] == NULL) goto out_of_space;\n") + out.emit("}\n") + elif var.name == "null": + out.emit(f"{var.name} = sym_new_null(ctx);\n") + out.emit(f"if ({var.name} == NULL) goto out_of_space;\n") + else: + out.emit(f"{var.name} = sym_new_unknown(ctx);\n") + out.emit(f"if ({var.name} == NULL) goto out_of_space;\n") + + +def write_uop( + override: Uop | None, + uop: Uop, + out: CWriter, + stack: Stack, + debug: bool, + skip_inputs: bool, +) -> None: + try: + prototype = override if override else uop + is_override = override is not None + out.start_line() + for var in reversed(prototype.stack.inputs): + res = stack.pop(var) + if not skip_inputs: + out.emit(res) + if not prototype.properties.stores_sp: + for i, var in enumerate(prototype.stack.outputs): + res = stack.push(var) + if not var.peek or is_override: + out.emit(res) + if debug: + args = [] + for var in prototype.stack.inputs: + if not var.peek or is_override: + args.append(var.name) + out.emit(f'DEBUG_PRINTF({", ".join(args)});\n') + if override: + for cache in uop.caches: + if cache.name != "unused": + if cache.size == 4: + type = cast = "PyObject *" + else: + type = f"uint{cache.size*16}_t " + cast = f"uint{cache.size*16}_t" + out.emit(f"{type}{cache.name} = ({cast})this_instr->operand;\n") + if override: + replacement_funcs = { + "DECREF_INPUTS": decref_inputs, + "SYNC_SP": replace_sync_sp, + } + emit_tokens(out, override, stack, None, replacement_funcs) + else: + emit_default(out, uop) + + if prototype.properties.stores_sp: + for i, var in enumerate(prototype.stack.outputs): + if not var.peek or is_override: + out.emit(stack.push(var)) + out.start_line() + stack.flush(out, cast_type="_Py_UOpsSymType *") + except SizeMismatch as ex: + raise analysis_error(ex.args[0], uop.body[0]) + + +SKIPS = ("_EXTENDED_ARG",) + + +def generate_abstract_interpreter( + filenames: list[str], + abstract: Analysis, + base: Analysis, + outfile: TextIO, + debug: bool, +) -> None: + write_header(__file__, filenames, outfile) + out = CWriter(outfile, 2, False) + out.emit("\n") + base_uop_names = set([uop.name for uop in base.uops.values()]) + for abstract_uop_name in abstract.uops: + assert abstract_uop_name in base_uop_names,\ + f"All abstract uops should override base uops, but {abstract_uop_name} is not." + + for uop in base.uops.values(): + override: Uop | None = None + if uop.name in abstract.uops: + override = abstract.uops[uop.name] + validate_uop(override, uop) + if uop.properties.tier == 1: + continue + if uop.replicates: + continue + if uop.is_super(): + continue + if not uop.is_viable(): + out.emit(f"/* {uop.name} is not a viable micro-op for tier 2 */\n\n") + continue + out.emit(f"case {uop.name}: {{\n") + if override: + declare_variables(override, out, skip_inputs=False) + else: + declare_variables(uop, out, skip_inputs=True) + stack = Stack() + write_uop(override, uop, out, stack, debug, skip_inputs=(override is None)) + out.start_line() + out.emit("break;\n") + out.emit("}") + out.emit("\n\n") + + +def generate_tier2_abstract_from_files( + filenames: list[str], outfilename: str, debug: bool=False +) -> None: + assert len(filenames) == 2, "Need a base file and an abstract cases file." + base = analyze_files([filenames[0]]) + abstract = analyze_files([filenames[1]]) + with open(outfilename, "w") as outfile: + generate_abstract_interpreter(filenames, abstract, base, outfile, debug) + + +arg_parser = argparse.ArgumentParser( + description="Generate the code for the tier 2 interpreter.", + formatter_class=argparse.ArgumentDefaultsHelpFormatter, +) + +arg_parser.add_argument( + "-o", "--output", type=str, help="Generated code", default=DEFAULT_OUTPUT +) + + +arg_parser.add_argument("input", nargs=1, help="Abstract interpreter definition file") + +arg_parser.add_argument( + "base", nargs=argparse.REMAINDER, help="The base instruction definition file(s)" +) + +arg_parser.add_argument("-d", "--debug", help="Insert debug calls", action="store_true") + +if __name__ == "__main__": + args = arg_parser.parse_args() + if len(args.base) == 0: + args.input.append(DEFAULT_INPUT) + args.input.append(DEFAULT_ABSTRACT_INPUT) + abstract = analyze_files(args.input) + base = analyze_files(args.base) + with open(args.output, "w") as outfile: + generate_abstract_interpreter(args.input, abstract, base, outfile, args.debug) diff --git a/Tools/cases_generator/tier2_abstract_generator.py b/Tools/cases_generator/tier2_abstract_generator.py deleted file mode 100644 index 58c3110..0000000 --- a/Tools/cases_generator/tier2_abstract_generator.py +++ /dev/null @@ -1,237 +0,0 @@ -"""Generate the cases for the tier 2 redundancy eliminator/abstract interpreter. -Reads the instruction definitions from bytecodes.c. and tier2_redundancy_eliminator.bytecodes.c -Writes the cases to tier2_redundancy_eliminator_cases.c.h, which is #included in Python/optimizer_analysis.c. -""" - -import argparse -import os.path -import sys - -from analyzer import ( - Analysis, - Instruction, - Uop, - Part, - analyze_files, - Skip, - StackItem, - analysis_error, -) -from generators_common import ( - DEFAULT_INPUT, - ROOT, - write_header, - emit_tokens, - emit_to, - replace_sync_sp, -) -from cwriter import CWriter -from typing import TextIO, Iterator -from lexer import Token -from stack import StackOffset, Stack, SizeMismatch, UNUSED - -DEFAULT_OUTPUT = ROOT / "Python/tier2_redundancy_eliminator_cases.c.h" -DEFAULT_ABSTRACT_INPUT = ROOT / "Python/tier2_redundancy_eliminator_bytecodes.c" - - -def validate_uop(override: Uop, uop: Uop) -> None: - # To do - pass - - -def type_name(var: StackItem) -> str: - if var.is_array(): - return f"_Py_UOpsSymType **" - if var.type: - return var.type - return f"_Py_UOpsSymType *" - - -def declare_variables(uop: Uop, out: CWriter, skip_inputs: bool) -> None: - variables = {"unused"} - if not skip_inputs: - for var in reversed(uop.stack.inputs): - if var.name not in variables: - variables.add(var.name) - if var.condition: - out.emit(f"{type_name(var)}{var.name} = NULL;\n") - else: - out.emit(f"{type_name(var)}{var.name};\n") - for var in uop.stack.outputs: - if var.peek: - continue - if var.name not in variables: - variables.add(var.name) - if var.condition: - out.emit(f"{type_name(var)}{var.name} = NULL;\n") - else: - out.emit(f"{type_name(var)}{var.name};\n") - - -def decref_inputs( - out: CWriter, - tkn: Token, - tkn_iter: Iterator[Token], - uop: Uop, - stack: Stack, - inst: Instruction | None, -) -> None: - next(tkn_iter) - next(tkn_iter) - next(tkn_iter) - out.emit_at("", tkn) - - -def emit_default(out: CWriter, uop: Uop) -> None: - for i, var in enumerate(uop.stack.outputs): - if var.name != "unused" and not var.peek: - if var.is_array(): - out.emit(f"for (int _i = {var.size}; --_i >= 0;) {{\n") - out.emit(f"{var.name}[_i] = sym_new_unknown(ctx);\n") - out.emit(f"if ({var.name}[_i] == NULL) goto out_of_space;\n") - out.emit("}\n") - elif var.name == "null": - out.emit(f"{var.name} = sym_new_null(ctx);\n") - out.emit(f"if ({var.name} == NULL) goto out_of_space;\n") - else: - out.emit(f"{var.name} = sym_new_unknown(ctx);\n") - out.emit(f"if ({var.name} == NULL) goto out_of_space;\n") - - -def write_uop( - override: Uop | None, - uop: Uop, - out: CWriter, - stack: Stack, - debug: bool, - skip_inputs: bool, -) -> None: - try: - prototype = override if override else uop - is_override = override is not None - out.start_line() - for var in reversed(prototype.stack.inputs): - res = stack.pop(var) - if not skip_inputs: - out.emit(res) - if not prototype.properties.stores_sp: - for i, var in enumerate(prototype.stack.outputs): - res = stack.push(var) - if not var.peek or is_override: - out.emit(res) - if debug: - args = [] - for var in prototype.stack.inputs: - if not var.peek or is_override: - args.append(var.name) - out.emit(f'DEBUG_PRINTF({", ".join(args)});\n') - if override: - for cache in uop.caches: - if cache.name != "unused": - if cache.size == 4: - type = cast = "PyObject *" - else: - type = f"uint{cache.size*16}_t " - cast = f"uint{cache.size*16}_t" - out.emit(f"{type}{cache.name} = ({cast})this_instr->operand;\n") - if override: - replacement_funcs = { - "DECREF_INPUTS": decref_inputs, - "SYNC_SP": replace_sync_sp, - } - emit_tokens(out, override, stack, None, replacement_funcs) - else: - emit_default(out, uop) - - if prototype.properties.stores_sp: - for i, var in enumerate(prototype.stack.outputs): - if not var.peek or is_override: - out.emit(stack.push(var)) - out.start_line() - stack.flush(out, cast_type="_Py_UOpsSymType *") - except SizeMismatch as ex: - raise analysis_error(ex.args[0], uop.body[0]) - - -SKIPS = ("_EXTENDED_ARG",) - - -def generate_abstract_interpreter( - filenames: list[str], - abstract: Analysis, - base: Analysis, - outfile: TextIO, - debug: bool, -) -> None: - write_header(__file__, filenames, outfile) - out = CWriter(outfile, 2, False) - out.emit("\n") - base_uop_names = set([uop.name for uop in base.uops.values()]) - for abstract_uop_name in abstract.uops: - assert abstract_uop_name in base_uop_names,\ - f"All abstract uops should override base uops, but {abstract_uop_name} is not." - - for uop in base.uops.values(): - override: Uop | None = None - if uop.name in abstract.uops: - override = abstract.uops[uop.name] - validate_uop(override, uop) - if uop.properties.tier == 1: - continue - if uop.replicates: - continue - if uop.is_super(): - continue - if not uop.is_viable(): - out.emit(f"/* {uop.name} is not a viable micro-op for tier 2 */\n\n") - continue - out.emit(f"case {uop.name}: {{\n") - if override: - declare_variables(override, out, skip_inputs=False) - else: - declare_variables(uop, out, skip_inputs=True) - stack = Stack() - write_uop(override, uop, out, stack, debug, skip_inputs=(override is None)) - out.start_line() - out.emit("break;\n") - out.emit("}") - out.emit("\n\n") - - -def generate_tier2_abstract_from_files( - filenames: list[str], outfilename: str, debug: bool=False -) -> None: - assert len(filenames) == 2, "Need a base file and an abstract cases file." - base = analyze_files([filenames[0]]) - abstract = analyze_files([filenames[1]]) - with open(outfilename, "w") as outfile: - generate_abstract_interpreter(filenames, abstract, base, outfile, debug) - - -arg_parser = argparse.ArgumentParser( - description="Generate the code for the tier 2 interpreter.", - formatter_class=argparse.ArgumentDefaultsHelpFormatter, -) - -arg_parser.add_argument( - "-o", "--output", type=str, help="Generated code", default=DEFAULT_OUTPUT -) - - -arg_parser.add_argument("input", nargs=1, help="Abstract interpreter definition file") - -arg_parser.add_argument( - "base", nargs=argparse.REMAINDER, help="The base instruction definition file(s)" -) - -arg_parser.add_argument("-d", "--debug", help="Insert debug calls", action="store_true") - -if __name__ == "__main__": - args = arg_parser.parse_args() - if len(args.base) == 0: - args.input.append(DEFAULT_INPUT) - args.input.append(DEFAULT_ABSTRACT_INPUT) - abstract = analyze_files(args.input) - base = analyze_files(args.base) - with open(args.output, "w") as outfile: - generate_abstract_interpreter(args.input, abstract, base, outfile, args.debug) -- cgit v0.12