Python/Python-ast.c generated
Python/executor_cases.c.h generated
Python/generated_cases.c.h generated
+Python/abstract_interp_cases.c.h generated
Python/opcode_targets.h generated
Python/stdlib_module_names.h generated
Tools/peg_generator/pegen/grammar_parser.py generated
typedef struct _PyOptimizerObject _PyOptimizerObject;
/* Should return > 0 if a new executor is created. O if no executor is produced and < 0 if an error occurred. */
-typedef int (*optimize_func)(_PyOptimizerObject* self, PyCodeObject *code, _Py_CODEUNIT *instr, _PyExecutorObject **);
+typedef int (*optimize_func)(_PyOptimizerObject* self, PyCodeObject *code, _Py_CODEUNIT *instr, _PyExecutorObject **, int curr_stackentries);
typedef struct _PyOptimizerObject {
PyObject_HEAD
#define _POP_JUMP_IF_FALSE 331
#define _POP_JUMP_IF_TRUE 332
#define JUMP_TO_TOP 333
+#define INSERT 334
extern int _PyOpcode_num_popped(int opcode, int oparg, bool jump);
#ifdef NEED_OPCODE_METADATA
return 1;
case UNARY_INVERT:
return 1;
+ case _GUARD_BOTH_INT:
+ return 2;
+ case _BINARY_OP_MULTIPLY_INT:
+ return 2;
+ case _BINARY_OP_ADD_INT:
+ return 2;
+ case _BINARY_OP_SUBTRACT_INT:
+ return 2;
case BINARY_OP_MULTIPLY_INT:
return 2;
case BINARY_OP_ADD_INT:
return 2;
case BINARY_OP_SUBTRACT_INT:
return 2;
+ case _GUARD_BOTH_FLOAT:
+ return 2;
+ case _BINARY_OP_MULTIPLY_FLOAT:
+ return 2;
+ case _BINARY_OP_ADD_FLOAT:
+ return 2;
+ case _BINARY_OP_SUBTRACT_FLOAT:
+ return 2;
case BINARY_OP_MULTIPLY_FLOAT:
return 2;
case BINARY_OP_ADD_FLOAT:
return 2;
case BINARY_OP_SUBTRACT_FLOAT:
return 2;
+ case _GUARD_BOTH_UNICODE:
+ return 2;
+ case _BINARY_OP_ADD_UNICODE:
+ return 2;
case BINARY_OP_ADD_UNICODE:
return 2;
case BINARY_OP_INPLACE_ADD_UNICODE:
return 1;
case DELETE_GLOBAL:
return 0;
+ case _LOAD_LOCALS:
+ return 0;
case LOAD_LOCALS:
return 0;
+ case _LOAD_FROM_DICT_OR_GLOBALS:
+ return 1;
case LOAD_NAME:
return 0;
case LOAD_FROM_DICT_OR_GLOBALS:
return 1;
case LOAD_GLOBAL:
return 0;
+ case _GUARD_GLOBALS_VERSION:
+ return 0;
+ case _GUARD_BUILTINS_VERSION:
+ return 0;
+ case _LOAD_GLOBAL_MODULE:
+ return 0;
+ case _LOAD_GLOBAL_BUILTINS:
+ return 0;
case LOAD_GLOBAL_MODULE:
return 0;
case LOAD_GLOBAL_BUILTIN:
return 1;
case LOAD_METHOD:
return 1;
+ case _GUARD_TYPE_VERSION:
+ return 1;
+ case _CHECK_MANAGED_OBJECT_HAS_VALUES:
+ return 1;
+ case _LOAD_ATTR_INSTANCE_VALUE:
+ return 1;
case LOAD_ATTR_INSTANCE_VALUE:
return 1;
case LOAD_ATTR_MODULE:
return 1;
case POP_JUMP_IF_TRUE:
return 1;
+ case IS_NONE:
+ return 1;
case POP_JUMP_IF_NONE:
return 1;
case POP_JUMP_IF_NOT_NONE:
return 1;
case INSTRUMENTED_FOR_ITER:
return 0;
+ case _ITER_CHECK_LIST:
+ return 1;
+ case _IS_ITER_EXHAUSTED_LIST:
+ return 1;
+ case _ITER_NEXT_LIST:
+ return 1;
case FOR_ITER_LIST:
return 1;
+ case _ITER_CHECK_TUPLE:
+ return 1;
+ case _IS_ITER_EXHAUSTED_TUPLE:
+ return 1;
+ case _ITER_NEXT_TUPLE:
+ return 1;
case FOR_ITER_TUPLE:
return 1;
+ case _ITER_CHECK_RANGE:
+ return 1;
+ case _IS_ITER_EXHAUSTED_RANGE:
+ return 1;
+ case _ITER_NEXT_RANGE:
+ return 1;
case FOR_ITER_RANGE:
return 1;
case FOR_ITER_GEN:
return 0;
case RESERVED:
return 0;
+ case _POP_JUMP_IF_FALSE:
+ return 1;
+ case _POP_JUMP_IF_TRUE:
+ return 1;
+ case JUMP_TO_TOP:
+ return 0;
+ case SAVE_IP:
+ return 0;
+ case EXIT_TRACE:
+ return 0;
+ case INSERT:
+ return oparg + 1;
default:
return -1;
}
return 1;
case UNARY_INVERT:
return 1;
+ case _GUARD_BOTH_INT:
+ return 2;
+ case _BINARY_OP_MULTIPLY_INT:
+ return 1;
+ case _BINARY_OP_ADD_INT:
+ return 1;
+ case _BINARY_OP_SUBTRACT_INT:
+ return 1;
case BINARY_OP_MULTIPLY_INT:
return 1;
case BINARY_OP_ADD_INT:
return 1;
case BINARY_OP_SUBTRACT_INT:
return 1;
+ case _GUARD_BOTH_FLOAT:
+ return 2;
+ case _BINARY_OP_MULTIPLY_FLOAT:
+ return 1;
+ case _BINARY_OP_ADD_FLOAT:
+ return 1;
+ case _BINARY_OP_SUBTRACT_FLOAT:
+ return 1;
case BINARY_OP_MULTIPLY_FLOAT:
return 1;
case BINARY_OP_ADD_FLOAT:
return 1;
case BINARY_OP_SUBTRACT_FLOAT:
return 1;
+ case _GUARD_BOTH_UNICODE:
+ return 2;
+ case _BINARY_OP_ADD_UNICODE:
+ return 1;
case BINARY_OP_ADD_UNICODE:
return 1;
case BINARY_OP_INPLACE_ADD_UNICODE:
return 0;
case DELETE_GLOBAL:
return 0;
+ case _LOAD_LOCALS:
+ return 1;
case LOAD_LOCALS:
return 1;
+ case _LOAD_FROM_DICT_OR_GLOBALS:
+ return 1;
case LOAD_NAME:
return 1;
case LOAD_FROM_DICT_OR_GLOBALS:
return 1;
case LOAD_GLOBAL:
return ((oparg & 1) ? 1 : 0) + 1;
+ case _GUARD_GLOBALS_VERSION:
+ return 0;
+ case _GUARD_BUILTINS_VERSION:
+ return 0;
+ case _LOAD_GLOBAL_MODULE:
+ return ((oparg & 1) ? 1 : 0) + 1;
+ case _LOAD_GLOBAL_BUILTINS:
+ return ((oparg & 1) ? 1 : 0) + 1;
case LOAD_GLOBAL_MODULE:
return (oparg & 1 ? 1 : 0) + 1;
case LOAD_GLOBAL_BUILTIN:
return ((oparg & 1) ? 1 : 0) + 1;
case LOAD_METHOD:
return ((oparg & 1) ? 1 : 0) + 1;
+ case _GUARD_TYPE_VERSION:
+ return 1;
+ case _CHECK_MANAGED_OBJECT_HAS_VALUES:
+ return 1;
+ case _LOAD_ATTR_INSTANCE_VALUE:
+ return ((oparg & 1) ? 1 : 0) + 1;
case LOAD_ATTR_INSTANCE_VALUE:
return (oparg & 1 ? 1 : 0) + 1;
case LOAD_ATTR_MODULE:
return 0;
case POP_JUMP_IF_TRUE:
return 0;
+ case IS_NONE:
+ return 1;
case POP_JUMP_IF_NONE:
return 0;
case POP_JUMP_IF_NOT_NONE:
return 2;
case INSTRUMENTED_FOR_ITER:
return 0;
+ case _ITER_CHECK_LIST:
+ return 1;
+ case _IS_ITER_EXHAUSTED_LIST:
+ return 2;
+ case _ITER_NEXT_LIST:
+ return 2;
case FOR_ITER_LIST:
return 2;
+ case _ITER_CHECK_TUPLE:
+ return 1;
+ case _IS_ITER_EXHAUSTED_TUPLE:
+ return 2;
+ case _ITER_NEXT_TUPLE:
+ return 2;
case FOR_ITER_TUPLE:
return 2;
+ case _ITER_CHECK_RANGE:
+ return 1;
+ case _IS_ITER_EXHAUSTED_RANGE:
+ return 2;
+ case _ITER_NEXT_RANGE:
+ return 2;
case FOR_ITER_RANGE:
return 2;
case FOR_ITER_GEN:
return 0;
case RESERVED:
return 0;
+ case _POP_JUMP_IF_FALSE:
+ return 0;
+ case _POP_JUMP_IF_TRUE:
+ return 0;
+ case JUMP_TO_TOP:
+ return 0;
+ case SAVE_IP:
+ return 0;
+ case EXIT_TRACE:
+ return 0;
+ case INSERT:
+ return oparg + 1;
default:
return -1;
}
[_POP_JUMP_IF_FALSE] = "_POP_JUMP_IF_FALSE",
[_POP_JUMP_IF_TRUE] = "_POP_JUMP_IF_TRUE",
[JUMP_TO_TOP] = "JUMP_TO_TOP",
+ [INSERT] = "INSERT",
};
#endif // NEED_OPCODE_METADATA
--- /dev/null
+#ifndef Py_INTERNAL_OPTIMIZER_H
+#define Py_INTERNAL_OPTIMIZER_H
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef Py_BUILD_CORE
+# error "this header requires Py_BUILD_CORE define"
+#endif
+
+#include "pycore_uops.h"
+
+int _Py_uop_analyze_and_optimize(PyCodeObject *code,
+ _PyUOpInstruction *trace, int trace_len, int curr_stackentries);
+
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* !Py_INTERNAL_OPTIMIZER_H */
# error "this header requires Py_BUILD_CORE define"
#endif
-#define _Py_UOP_MAX_TRACE_LENGTH 32
+#define _Py_UOP_MAX_TRACE_LENGTH 64
typedef struct {
uint32_t opcode;
Python/mysnprintf.o \
Python/mystrtoul.o \
Python/optimizer.o \
+ Python/optimizer_analysis.o \
Python/pathconfig.o \
Python/preconfig.o \
Python/pyarena.o \
-m $(srcdir)/Include/internal/pycore_opcode_metadata.h.new \
-e $(srcdir)/Python/executor_cases.c.h.new \
-p $(srcdir)/Lib/_opcode_metadata.py.new \
+ -a $(srcdir)/Python/abstract_interp_cases.c.h.new \
$(srcdir)/Python/bytecodes.c
$(UPDATE_FILE) $(srcdir)/Python/generated_cases.c.h $(srcdir)/Python/generated_cases.c.h.new
$(UPDATE_FILE) $(srcdir)/Include/internal/pycore_opcode_metadata.h $(srcdir)/Include/internal/pycore_opcode_metadata.h.new
$(UPDATE_FILE) $(srcdir)/Python/executor_cases.c.h $(srcdir)/Python/executor_cases.c.h.new
+ $(UPDATE_FILE) $(srcdir)/Python/abstract_interp_cases.c.h $(srcdir)/Python/abstract_interp_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
Python/executor.o: \
$(srcdir)/Include/internal/pycore_opcode_metadata.h \
+ $(srcdir)/Include/internal/pycore_optimizer.h \
$(srcdir)/Python/ceval_macros.h \
$(srcdir)/Python/executor_cases.c.h
Python/optimizer.o: \
$(srcdir)/Python/executor_cases.c.h \
- $(srcdir)/Include/internal/pycore_opcode_metadata.h
+ $(srcdir)/Include/internal/pycore_opcode_metadata.h \
+ $(srcdir)/Include/internal/pycore_optimizer.h
+
+Python/optimizer_analysis.o: \
+ $(srcdir)/Include/internal/pycore_opcode_metadata.h \
+ $(srcdir)/Include/internal/pycore_optimizer.h
Python/frozen.o: $(FROZEN_FILES_OUT)
$(srcdir)/Include/internal/pycore_obmalloc_init.h \
$(srcdir)/Include/internal/pycore_opcode.h \
$(srcdir)/Include/internal/pycore_opcode_utils.h \
+ $(srcdir)/Include/internal/pycore_optimizer.h \
$(srcdir)/Include/internal/pycore_pathconfig.h \
$(srcdir)/Include/internal/pycore_pyarena.h \
$(srcdir)/Include/internal/pycore_pyerrors.h \
--- /dev/null
+Generate the cases needed for the barebones tier 2 abstract interpreter for optimization passes in CPython.
<ClCompile Include="..\Python\mysnprintf.c" />
<ClCompile Include="..\Python\mystrtoul.c" />
<ClCompile Include="..\Python\optimizer.c" />
+ <ClCompile Include="..\Python\optimizer_analysis.c" />
<ClCompile Include="..\Python\pathconfig.c" />
<ClCompile Include="..\Python\perf_trampoline.c" />
<ClCompile Include="..\Python\preconfig.c" />
<ClCompile Include="..\Python\optimizer.c">
<Filter>Source Files</Filter>
</ClCompile>
+ <ClCompile Include="..\Python\optimizer_analysis.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
<ClCompile Include="..\Parser\parser.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClInclude Include="..\Include\internal\pycore_object_state.h" />
<ClInclude Include="..\Include\internal\pycore_obmalloc.h" />
<ClInclude Include="..\Include\internal\pycore_obmalloc_init.h" />
+ <ClInclude Include="..\Include\internal\pycore_optimizer.h" />
<ClInclude Include="..\Include\internal\pycore_pathconfig.h" />
<ClInclude Include="..\Include\internal\pycore_pyarena.h" />
<ClInclude Include="..\Include\internal\pycore_pyerrors.h" />
<ClInclude Include="..\Include\internal\pycore_unionobject.h" />
<ClInclude Include="..\Include\internal\pycore_unicodeobject.h" />
<ClInclude Include="..\Include\internal\pycore_unicodeobject_generated.h" />
+ <ClInclude Include="..\Include\internal\pycore_uops.h" />
<ClInclude Include="..\Include\internal\pycore_warnings.h" />
<ClInclude Include="..\Include\internal\pycore_weakref.h" />
<ClInclude Include="..\Include\interpreteridobject.h" />
<ClCompile Include="..\Python\mysnprintf.c" />
<ClCompile Include="..\Python\mystrtoul.c" />
<ClCompile Include="..\Python\optimizer.c" />
+ <ClCompile Include="..\Python\optimizer_analysis.c" />
<ClCompile Include="..\Python\pathconfig.c" />
<ClCompile Include="..\Python\perf_trampoline.c" />
<ClCompile Include="..\Python\preconfig.c" />
<ClInclude Include="..\Include\internal\pycore_obmalloc_init.h">
<Filter>Include\internal</Filter>
</ClInclude>
+ <ClInclude Include="..\Include\internal\pycore_optimizer.h">
+ <Filter>Include\internal</Filter>
+ </ClInclude>
<ClInclude Include="..\Include\internal\pycore_pathconfig.h">
<Filter>Include\internal</Filter>
</ClInclude>
<ClInclude Include="..\Include\internal\pycore_unionobject.h">
<Filter>Include\internal</Filter>
</ClInclude>
+ <ClInclude Include="..\Include\internal\pycore_uops.h">
+ <Filter>Include\internal</Filter>
+ </ClInclude>
<ClInclude Include="$(zlibDir)\crc32.h">
<Filter>Modules\zlib</Filter>
</ClInclude>
<ClCompile Include="..\Python\optimizer.c">
<Filter>Python</Filter>
</ClCompile>
+ <ClCompile Include="..\Python\optimizer_analysis.c">
+ <Filter>Python</Filter>
+ </ClCompile>
<ClCompile Include="..\Python\pathconfig.c">
<Filter>Python</Filter>
</ClCompile>
--- /dev/null
+// This file is generated by Tools/cases_generator/generate_cases.py
+// from:
+// Python/bytecodes.c
+// Do not edit!
+
+ case NOP: {
+ break;
+ }
+
+ case POP_TOP: {
+ STACK_SHRINK(1);
+ break;
+ }
+
+ case PUSH_NULL: {
+ STACK_GROW(1);
+ PARTITIONNODE_OVERWRITE((_Py_PARTITIONNODE_t *)PARTITIONNODE_NULLROOT, PEEK(-(-1)), true);
+ break;
+ }
+
+ case END_SEND: {
+ STACK_SHRINK(1);
+ PARTITIONNODE_OVERWRITE((_Py_PARTITIONNODE_t *)PARTITIONNODE_NULLROOT, PEEK(-(-1)), true);
+ break;
+ }
+
+ case UNARY_NEGATIVE: {
+ PARTITIONNODE_OVERWRITE((_Py_PARTITIONNODE_t *)PARTITIONNODE_NULLROOT, PEEK(-(-1)), true);
+ break;
+ }
+
+ case UNARY_NOT: {
+ PARTITIONNODE_OVERWRITE((_Py_PARTITIONNODE_t *)PARTITIONNODE_NULLROOT, PEEK(-(-1)), true);
+ break;
+ }
+
+ case TO_BOOL: {
+ PARTITIONNODE_OVERWRITE((_Py_PARTITIONNODE_t *)PARTITIONNODE_NULLROOT, PEEK(-(-1)), true);
+ break;
+ }
+
+ case TO_BOOL_BOOL: {
+ break;
+ }
+
+ case TO_BOOL_INT: {
+ PARTITIONNODE_OVERWRITE((_Py_PARTITIONNODE_t *)PARTITIONNODE_NULLROOT, PEEK(-(-1)), true);
+ break;
+ }
+
+ case TO_BOOL_LIST: {
+ PARTITIONNODE_OVERWRITE((_Py_PARTITIONNODE_t *)PARTITIONNODE_NULLROOT, PEEK(-(-1)), true);
+ break;
+ }
+
+ case TO_BOOL_NONE: {
+ PARTITIONNODE_OVERWRITE((_Py_PARTITIONNODE_t *)PARTITIONNODE_NULLROOT, PEEK(-(-1)), true);
+ break;
+ }
+
+ case TO_BOOL_STR: {
+ PARTITIONNODE_OVERWRITE((_Py_PARTITIONNODE_t *)PARTITIONNODE_NULLROOT, PEEK(-(-1)), true);
+ break;
+ }
+
+ case TO_BOOL_ALWAYS_TRUE: {
+ PARTITIONNODE_OVERWRITE((_Py_PARTITIONNODE_t *)PARTITIONNODE_NULLROOT, PEEK(-(-1)), true);
+ break;
+ }
+
+ case UNARY_INVERT: {
+ PARTITIONNODE_OVERWRITE((_Py_PARTITIONNODE_t *)PARTITIONNODE_NULLROOT, PEEK(-(-1)), true);
+ break;
+ }
+
+ case _GUARD_BOTH_INT: {
+ break;
+ }
+
+ case _GUARD_BOTH_FLOAT: {
+ break;
+ }
+
+ case _BINARY_OP_MULTIPLY_FLOAT: {
+ STACK_SHRINK(1);
+ PARTITIONNODE_OVERWRITE((_Py_PARTITIONNODE_t *)PARTITIONNODE_NULLROOT, PEEK(-(-1)), true);
+ break;
+ }
+
+ case _BINARY_OP_ADD_FLOAT: {
+ STACK_SHRINK(1);
+ PARTITIONNODE_OVERWRITE((_Py_PARTITIONNODE_t *)PARTITIONNODE_NULLROOT, PEEK(-(-1)), true);
+ break;
+ }
+
+ case _BINARY_OP_SUBTRACT_FLOAT: {
+ STACK_SHRINK(1);
+ PARTITIONNODE_OVERWRITE((_Py_PARTITIONNODE_t *)PARTITIONNODE_NULLROOT, PEEK(-(-1)), true);
+ break;
+ }
+
+ case _GUARD_BOTH_UNICODE: {
+ break;
+ }
+
+ case _BINARY_OP_ADD_UNICODE: {
+ STACK_SHRINK(1);
+ PARTITIONNODE_OVERWRITE((_Py_PARTITIONNODE_t *)PARTITIONNODE_NULLROOT, PEEK(-(-1)), true);
+ break;
+ }
+
+ case BINARY_SUBSCR: {
+ STACK_SHRINK(1);
+ PARTITIONNODE_OVERWRITE((_Py_PARTITIONNODE_t *)PARTITIONNODE_NULLROOT, PEEK(-(-1)), true);
+ break;
+ }
+
+ case BINARY_SLICE: {
+ STACK_SHRINK(2);
+ PARTITIONNODE_OVERWRITE((_Py_PARTITIONNODE_t *)PARTITIONNODE_NULLROOT, PEEK(-(-1)), true);
+ break;
+ }
+
+ case STORE_SLICE: {
+ STACK_SHRINK(4);
+ break;
+ }
+
+ case BINARY_SUBSCR_LIST_INT: {
+ STACK_SHRINK(1);
+ PARTITIONNODE_OVERWRITE((_Py_PARTITIONNODE_t *)PARTITIONNODE_NULLROOT, PEEK(-(-1)), true);
+ break;
+ }
+
+ case BINARY_SUBSCR_STR_INT: {
+ STACK_SHRINK(1);
+ PARTITIONNODE_OVERWRITE((_Py_PARTITIONNODE_t *)PARTITIONNODE_NULLROOT, PEEK(-(-1)), true);
+ break;
+ }
+
+ case BINARY_SUBSCR_TUPLE_INT: {
+ STACK_SHRINK(1);
+ PARTITIONNODE_OVERWRITE((_Py_PARTITIONNODE_t *)PARTITIONNODE_NULLROOT, PEEK(-(-1)), true);
+ break;
+ }
+
+ case BINARY_SUBSCR_DICT: {
+ STACK_SHRINK(1);
+ PARTITIONNODE_OVERWRITE((_Py_PARTITIONNODE_t *)PARTITIONNODE_NULLROOT, PEEK(-(-1)), true);
+ break;
+ }
+
+ case LIST_APPEND: {
+ STACK_SHRINK(1);
+ break;
+ }
+
+ case SET_ADD: {
+ STACK_SHRINK(1);
+ break;
+ }
+
+ case STORE_SUBSCR: {
+ STACK_SHRINK(3);
+ break;
+ }
+
+ case STORE_SUBSCR_LIST_INT: {
+ STACK_SHRINK(3);
+ break;
+ }
+
+ case STORE_SUBSCR_DICT: {
+ STACK_SHRINK(3);
+ break;
+ }
+
+ case DELETE_SUBSCR: {
+ STACK_SHRINK(2);
+ break;
+ }
+
+ case CALL_INTRINSIC_1: {
+ PARTITIONNODE_OVERWRITE((_Py_PARTITIONNODE_t *)PARTITIONNODE_NULLROOT, PEEK(-(-1)), true);
+ break;
+ }
+
+ case CALL_INTRINSIC_2: {
+ STACK_SHRINK(1);
+ PARTITIONNODE_OVERWRITE((_Py_PARTITIONNODE_t *)PARTITIONNODE_NULLROOT, PEEK(-(-1)), true);
+ break;
+ }
+
+ case GET_AITER: {
+ PARTITIONNODE_OVERWRITE((_Py_PARTITIONNODE_t *)PARTITIONNODE_NULLROOT, PEEK(-(-1)), true);
+ break;
+ }
+
+ case GET_ANEXT: {
+ STACK_GROW(1);
+ PARTITIONNODE_OVERWRITE((_Py_PARTITIONNODE_t *)PARTITIONNODE_NULLROOT, PEEK(-(-1)), true);
+ break;
+ }
+
+ case GET_AWAITABLE: {
+ PARTITIONNODE_OVERWRITE((_Py_PARTITIONNODE_t *)PARTITIONNODE_NULLROOT, PEEK(-(-1)), true);
+ break;
+ }
+
+ case POP_EXCEPT: {
+ STACK_SHRINK(1);
+ break;
+ }
+
+ case LOAD_ASSERTION_ERROR: {
+ STACK_GROW(1);
+ PARTITIONNODE_OVERWRITE((_Py_PARTITIONNODE_t *)PARTITIONNODE_NULLROOT, PEEK(-(-1)), true);
+ break;
+ }
+
+ case LOAD_BUILD_CLASS: {
+ STACK_GROW(1);
+ PARTITIONNODE_OVERWRITE((_Py_PARTITIONNODE_t *)PARTITIONNODE_NULLROOT, PEEK(-(-1)), true);
+ break;
+ }
+
+ case STORE_NAME: {
+ STACK_SHRINK(1);
+ break;
+ }
+
+ case DELETE_NAME: {
+ break;
+ }
+
+ case UNPACK_SEQUENCE: {
+ STACK_SHRINK(1);
+ STACK_GROW(oparg);
+ break;
+ }
+
+ case UNPACK_SEQUENCE_TWO_TUPLE: {
+ STACK_SHRINK(1);
+ STACK_GROW(oparg);
+ break;
+ }
+
+ case UNPACK_SEQUENCE_TUPLE: {
+ STACK_SHRINK(1);
+ STACK_GROW(oparg);
+ break;
+ }
+
+ case UNPACK_SEQUENCE_LIST: {
+ STACK_SHRINK(1);
+ STACK_GROW(oparg);
+ break;
+ }
+
+ case UNPACK_EX: {
+ STACK_GROW((oparg & 0xFF) + (oparg >> 8));
+ PARTITIONNODE_OVERWRITE((_Py_PARTITIONNODE_t *)PARTITIONNODE_NULLROOT, PEEK(-(-1 - (oparg >> 8))), true);
+ break;
+ }
+
+ case STORE_ATTR: {
+ STACK_SHRINK(2);
+ break;
+ }
+
+ case DELETE_ATTR: {
+ STACK_SHRINK(1);
+ break;
+ }
+
+ case STORE_GLOBAL: {
+ STACK_SHRINK(1);
+ break;
+ }
+
+ case DELETE_GLOBAL: {
+ break;
+ }
+
+ case _LOAD_LOCALS: {
+ STACK_GROW(1);
+ PARTITIONNODE_OVERWRITE((_Py_PARTITIONNODE_t *)PARTITIONNODE_NULLROOT, PEEK(-(-1)), true);
+ break;
+ }
+
+ case _LOAD_FROM_DICT_OR_GLOBALS: {
+ PARTITIONNODE_OVERWRITE((_Py_PARTITIONNODE_t *)PARTITIONNODE_NULLROOT, PEEK(-(-1)), true);
+ break;
+ }
+
+ case LOAD_GLOBAL: {
+ STACK_GROW(1);
+ STACK_GROW(((oparg & 1) ? 1 : 0));
+ PARTITIONNODE_OVERWRITE((_Py_PARTITIONNODE_t *)PARTITIONNODE_NULLROOT, PEEK(-(-1 - (oparg & 1 ? 1 : 0))), true);
+ PARTITIONNODE_OVERWRITE((_Py_PARTITIONNODE_t *)PARTITIONNODE_NULLROOT, PEEK(-(-(oparg & 1 ? 1 : 0))), true);
+ break;
+ }
+
+ case _GUARD_GLOBALS_VERSION: {
+ break;
+ }
+
+ case _GUARD_BUILTINS_VERSION: {
+ break;
+ }
+
+ case _LOAD_GLOBAL_MODULE: {
+ STACK_GROW(1);
+ STACK_GROW(((oparg & 1) ? 1 : 0));
+ PARTITIONNODE_OVERWRITE((_Py_PARTITIONNODE_t *)PARTITIONNODE_NULLROOT, PEEK(-(-1 - (oparg & 1 ? 1 : 0))), true);
+ PARTITIONNODE_OVERWRITE((_Py_PARTITIONNODE_t *)PARTITIONNODE_NULLROOT, PEEK(-(-(oparg & 1 ? 1 : 0))), true);
+ break;
+ }
+
+ case _LOAD_GLOBAL_BUILTINS: {
+ STACK_GROW(1);
+ STACK_GROW(((oparg & 1) ? 1 : 0));
+ PARTITIONNODE_OVERWRITE((_Py_PARTITIONNODE_t *)PARTITIONNODE_NULLROOT, PEEK(-(-1 - (oparg & 1 ? 1 : 0))), true);
+ PARTITIONNODE_OVERWRITE((_Py_PARTITIONNODE_t *)PARTITIONNODE_NULLROOT, PEEK(-(-(oparg & 1 ? 1 : 0))), true);
+ break;
+ }
+
+ case DELETE_FAST: {
+ break;
+ }
+
+ case DELETE_DEREF: {
+ break;
+ }
+
+ case LOAD_FROM_DICT_OR_DEREF: {
+ PARTITIONNODE_OVERWRITE((_Py_PARTITIONNODE_t *)PARTITIONNODE_NULLROOT, PEEK(-(-1)), true);
+ break;
+ }
+
+ case LOAD_DEREF: {
+ STACK_GROW(1);
+ PARTITIONNODE_OVERWRITE((_Py_PARTITIONNODE_t *)PARTITIONNODE_NULLROOT, PEEK(-(-1)), true);
+ break;
+ }
+
+ case STORE_DEREF: {
+ STACK_SHRINK(1);
+ break;
+ }
+
+ case COPY_FREE_VARS: {
+ break;
+ }
+
+ case BUILD_STRING: {
+ STACK_SHRINK(oparg);
+ STACK_GROW(1);
+ PARTITIONNODE_OVERWRITE((_Py_PARTITIONNODE_t *)PARTITIONNODE_NULLROOT, PEEK(-(-1)), true);
+ break;
+ }
+
+ case BUILD_TUPLE: {
+ STACK_SHRINK(oparg);
+ STACK_GROW(1);
+ PARTITIONNODE_OVERWRITE((_Py_PARTITIONNODE_t *)PARTITIONNODE_NULLROOT, PEEK(-(-1)), true);
+ break;
+ }
+
+ case BUILD_LIST: {
+ STACK_SHRINK(oparg);
+ STACK_GROW(1);
+ PARTITIONNODE_OVERWRITE((_Py_PARTITIONNODE_t *)PARTITIONNODE_NULLROOT, PEEK(-(-1)), true);
+ break;
+ }
+
+ case LIST_EXTEND: {
+ STACK_SHRINK(1);
+ break;
+ }
+
+ case SET_UPDATE: {
+ STACK_SHRINK(1);
+ break;
+ }
+
+ case BUILD_SET: {
+ STACK_SHRINK(oparg);
+ STACK_GROW(1);
+ PARTITIONNODE_OVERWRITE((_Py_PARTITIONNODE_t *)PARTITIONNODE_NULLROOT, PEEK(-(-1)), true);
+ break;
+ }
+
+ case BUILD_MAP: {
+ STACK_SHRINK(oparg*2);
+ STACK_GROW(1);
+ PARTITIONNODE_OVERWRITE((_Py_PARTITIONNODE_t *)PARTITIONNODE_NULLROOT, PEEK(-(-1)), true);
+ break;
+ }
+
+ case SETUP_ANNOTATIONS: {
+ break;
+ }
+
+ case BUILD_CONST_KEY_MAP: {
+ STACK_SHRINK(oparg);
+ PARTITIONNODE_OVERWRITE((_Py_PARTITIONNODE_t *)PARTITIONNODE_NULLROOT, PEEK(-(-1)), true);
+ break;
+ }
+
+ case DICT_UPDATE: {
+ STACK_SHRINK(1);
+ break;
+ }
+
+ case DICT_MERGE: {
+ STACK_SHRINK(1);
+ break;
+ }
+
+ case MAP_ADD: {
+ STACK_SHRINK(2);
+ break;
+ }
+
+ case LOAD_SUPER_ATTR_ATTR: {
+ STACK_SHRINK(2);
+ PARTITIONNODE_OVERWRITE((_Py_PARTITIONNODE_t *)PARTITIONNODE_NULLROOT, PEEK(-(-1)), true);
+ PARTITIONNODE_OVERWRITE((_Py_PARTITIONNODE_t *)PARTITIONNODE_NULLROOT, PEEK(-(0)), true);
+ break;
+ }
+
+ case LOAD_SUPER_ATTR_METHOD: {
+ STACK_SHRINK(1);
+ PARTITIONNODE_OVERWRITE((_Py_PARTITIONNODE_t *)PARTITIONNODE_NULLROOT, PEEK(-(-2)), true);
+ PARTITIONNODE_OVERWRITE((_Py_PARTITIONNODE_t *)PARTITIONNODE_NULLROOT, PEEK(-(-1)), true);
+ break;
+ }
+
+ case LOAD_ATTR: {
+ STACK_GROW(((oparg & 1) ? 1 : 0));
+ PARTITIONNODE_OVERWRITE((_Py_PARTITIONNODE_t *)PARTITIONNODE_NULLROOT, PEEK(-(-1 - (oparg & 1 ? 1 : 0))), true);
+ PARTITIONNODE_OVERWRITE((_Py_PARTITIONNODE_t *)PARTITIONNODE_NULLROOT, PEEK(-(-(oparg & 1 ? 1 : 0))), true);
+ break;
+ }
+
+ case _GUARD_TYPE_VERSION: {
+ break;
+ }
+
+ case _CHECK_MANAGED_OBJECT_HAS_VALUES: {
+ break;
+ }
+
+ case _LOAD_ATTR_INSTANCE_VALUE: {
+ STACK_GROW(((oparg & 1) ? 1 : 0));
+ PARTITIONNODE_OVERWRITE((_Py_PARTITIONNODE_t *)PARTITIONNODE_NULLROOT, PEEK(-(-1 - (oparg & 1 ? 1 : 0))), true);
+ PARTITIONNODE_OVERWRITE((_Py_PARTITIONNODE_t *)PARTITIONNODE_NULLROOT, PEEK(-(-(oparg & 1 ? 1 : 0))), true);
+ break;
+ }
+
+ case COMPARE_OP: {
+ STACK_SHRINK(1);
+ PARTITIONNODE_OVERWRITE((_Py_PARTITIONNODE_t *)PARTITIONNODE_NULLROOT, PEEK(-(-1)), true);
+ break;
+ }
+
+ case COMPARE_OP_FLOAT: {
+ STACK_SHRINK(1);
+ PARTITIONNODE_OVERWRITE((_Py_PARTITIONNODE_t *)PARTITIONNODE_NULLROOT, PEEK(-(-1)), true);
+ break;
+ }
+
+ case COMPARE_OP_INT: {
+ STACK_SHRINK(1);
+ PARTITIONNODE_OVERWRITE((_Py_PARTITIONNODE_t *)PARTITIONNODE_NULLROOT, PEEK(-(-1)), true);
+ break;
+ }
+
+ case COMPARE_OP_STR: {
+ STACK_SHRINK(1);
+ PARTITIONNODE_OVERWRITE((_Py_PARTITIONNODE_t *)PARTITIONNODE_NULLROOT, PEEK(-(-1)), true);
+ break;
+ }
+
+ case IS_OP: {
+ STACK_SHRINK(1);
+ PARTITIONNODE_OVERWRITE((_Py_PARTITIONNODE_t *)PARTITIONNODE_NULLROOT, PEEK(-(-1)), true);
+ break;
+ }
+
+ case CONTAINS_OP: {
+ STACK_SHRINK(1);
+ PARTITIONNODE_OVERWRITE((_Py_PARTITIONNODE_t *)PARTITIONNODE_NULLROOT, PEEK(-(-1)), true);
+ break;
+ }
+
+ case CHECK_EG_MATCH: {
+ PARTITIONNODE_OVERWRITE((_Py_PARTITIONNODE_t *)PARTITIONNODE_NULLROOT, PEEK(-(-2)), true);
+ PARTITIONNODE_OVERWRITE((_Py_PARTITIONNODE_t *)PARTITIONNODE_NULLROOT, PEEK(-(-1)), true);
+ break;
+ }
+
+ case CHECK_EXC_MATCH: {
+ PARTITIONNODE_OVERWRITE((_Py_PARTITIONNODE_t *)PARTITIONNODE_NULLROOT, PEEK(-(-1)), true);
+ break;
+ }
+
+ case IS_NONE: {
+ PARTITIONNODE_OVERWRITE((_Py_PARTITIONNODE_t *)PARTITIONNODE_NULLROOT, PEEK(-(-1)), true);
+ break;
+ }
+
+ case GET_LEN: {
+ STACK_GROW(1);
+ PARTITIONNODE_OVERWRITE((_Py_PARTITIONNODE_t *)PARTITIONNODE_NULLROOT, PEEK(-(-1)), true);
+ break;
+ }
+
+ case MATCH_CLASS: {
+ STACK_SHRINK(2);
+ PARTITIONNODE_OVERWRITE((_Py_PARTITIONNODE_t *)PARTITIONNODE_NULLROOT, PEEK(-(-1)), true);
+ break;
+ }
+
+ case MATCH_MAPPING: {
+ STACK_GROW(1);
+ PARTITIONNODE_OVERWRITE((_Py_PARTITIONNODE_t *)PARTITIONNODE_NULLROOT, PEEK(-(-1)), true);
+ break;
+ }
+
+ case MATCH_SEQUENCE: {
+ STACK_GROW(1);
+ PARTITIONNODE_OVERWRITE((_Py_PARTITIONNODE_t *)PARTITIONNODE_NULLROOT, PEEK(-(-1)), true);
+ break;
+ }
+
+ case MATCH_KEYS: {
+ STACK_GROW(1);
+ PARTITIONNODE_OVERWRITE((_Py_PARTITIONNODE_t *)PARTITIONNODE_NULLROOT, PEEK(-(-1)), true);
+ break;
+ }
+
+ case GET_ITER: {
+ PARTITIONNODE_OVERWRITE((_Py_PARTITIONNODE_t *)PARTITIONNODE_NULLROOT, PEEK(-(-1)), true);
+ break;
+ }
+
+ case GET_YIELD_FROM_ITER: {
+ PARTITIONNODE_OVERWRITE((_Py_PARTITIONNODE_t *)PARTITIONNODE_NULLROOT, PEEK(-(-1)), true);
+ break;
+ }
+
+ case _ITER_CHECK_LIST: {
+ break;
+ }
+
+ case _IS_ITER_EXHAUSTED_LIST: {
+ STACK_GROW(1);
+ PARTITIONNODE_OVERWRITE((_Py_PARTITIONNODE_t *)PARTITIONNODE_NULLROOT, PEEK(-(-1)), true);
+ break;
+ }
+
+ case _ITER_NEXT_LIST: {
+ STACK_GROW(1);
+ PARTITIONNODE_OVERWRITE((_Py_PARTITIONNODE_t *)PARTITIONNODE_NULLROOT, PEEK(-(-1)), true);
+ break;
+ }
+
+ case _ITER_CHECK_TUPLE: {
+ break;
+ }
+
+ case _IS_ITER_EXHAUSTED_TUPLE: {
+ STACK_GROW(1);
+ PARTITIONNODE_OVERWRITE((_Py_PARTITIONNODE_t *)PARTITIONNODE_NULLROOT, PEEK(-(-1)), true);
+ break;
+ }
+
+ case _ITER_NEXT_TUPLE: {
+ STACK_GROW(1);
+ PARTITIONNODE_OVERWRITE((_Py_PARTITIONNODE_t *)PARTITIONNODE_NULLROOT, PEEK(-(-1)), true);
+ break;
+ }
+
+ case _ITER_CHECK_RANGE: {
+ break;
+ }
+
+ case _IS_ITER_EXHAUSTED_RANGE: {
+ STACK_GROW(1);
+ PARTITIONNODE_OVERWRITE((_Py_PARTITIONNODE_t *)PARTITIONNODE_NULLROOT, PEEK(-(-1)), true);
+ break;
+ }
+
+ case _ITER_NEXT_RANGE: {
+ STACK_GROW(1);
+ PARTITIONNODE_OVERWRITE((_Py_PARTITIONNODE_t *)PARTITIONNODE_NULLROOT, PEEK(-(-1)), true);
+ break;
+ }
+
+ case WITH_EXCEPT_START: {
+ STACK_GROW(1);
+ PARTITIONNODE_OVERWRITE((_Py_PARTITIONNODE_t *)PARTITIONNODE_NULLROOT, PEEK(-(-1)), true);
+ break;
+ }
+
+ case PUSH_EXC_INFO: {
+ STACK_GROW(1);
+ PARTITIONNODE_OVERWRITE((_Py_PARTITIONNODE_t *)PARTITIONNODE_NULLROOT, PEEK(-(-2)), true);
+ PARTITIONNODE_OVERWRITE((_Py_PARTITIONNODE_t *)PARTITIONNODE_NULLROOT, PEEK(-(-1)), true);
+ break;
+ }
+
+ case CALL_NO_KW_TYPE_1: {
+ STACK_SHRINK(oparg);
+ STACK_SHRINK(1);
+ PARTITIONNODE_OVERWRITE((_Py_PARTITIONNODE_t *)PARTITIONNODE_NULLROOT, PEEK(-(-1)), true);
+ break;
+ }
+
+ case CALL_NO_KW_STR_1: {
+ STACK_SHRINK(oparg);
+ STACK_SHRINK(1);
+ PARTITIONNODE_OVERWRITE((_Py_PARTITIONNODE_t *)PARTITIONNODE_NULLROOT, PEEK(-(-1)), true);
+ break;
+ }
+
+ case CALL_NO_KW_TUPLE_1: {
+ STACK_SHRINK(oparg);
+ STACK_SHRINK(1);
+ PARTITIONNODE_OVERWRITE((_Py_PARTITIONNODE_t *)PARTITIONNODE_NULLROOT, PEEK(-(-1)), true);
+ break;
+ }
+
+ case EXIT_INIT_CHECK: {
+ STACK_SHRINK(1);
+ break;
+ }
+
+ case CALL_NO_KW_BUILTIN_O: {
+ STACK_SHRINK(oparg);
+ STACK_SHRINK(1);
+ PARTITIONNODE_OVERWRITE((_Py_PARTITIONNODE_t *)PARTITIONNODE_NULLROOT, PEEK(-(-1)), true);
+ break;
+ }
+
+ case CALL_NO_KW_BUILTIN_FAST: {
+ STACK_SHRINK(oparg);
+ STACK_SHRINK(1);
+ PARTITIONNODE_OVERWRITE((_Py_PARTITIONNODE_t *)PARTITIONNODE_NULLROOT, PEEK(-(-1)), true);
+ break;
+ }
+
+ case CALL_NO_KW_LEN: {
+ STACK_SHRINK(oparg);
+ STACK_SHRINK(1);
+ PARTITIONNODE_OVERWRITE((_Py_PARTITIONNODE_t *)PARTITIONNODE_NULLROOT, PEEK(-(-1)), true);
+ break;
+ }
+
+ case CALL_NO_KW_ISINSTANCE: {
+ STACK_SHRINK(oparg);
+ STACK_SHRINK(1);
+ PARTITIONNODE_OVERWRITE((_Py_PARTITIONNODE_t *)PARTITIONNODE_NULLROOT, PEEK(-(-1)), true);
+ break;
+ }
+
+ case CALL_NO_KW_METHOD_DESCRIPTOR_O: {
+ STACK_SHRINK(oparg);
+ STACK_SHRINK(1);
+ PARTITIONNODE_OVERWRITE((_Py_PARTITIONNODE_t *)PARTITIONNODE_NULLROOT, PEEK(-(-1)), true);
+ break;
+ }
+
+ case CALL_NO_KW_METHOD_DESCRIPTOR_NOARGS: {
+ STACK_SHRINK(oparg);
+ STACK_SHRINK(1);
+ PARTITIONNODE_OVERWRITE((_Py_PARTITIONNODE_t *)PARTITIONNODE_NULLROOT, PEEK(-(-1)), true);
+ break;
+ }
+
+ case CALL_NO_KW_METHOD_DESCRIPTOR_FAST: {
+ STACK_SHRINK(oparg);
+ STACK_SHRINK(1);
+ PARTITIONNODE_OVERWRITE((_Py_PARTITIONNODE_t *)PARTITIONNODE_NULLROOT, PEEK(-(-1)), true);
+ break;
+ }
+
+ case MAKE_FUNCTION: {
+ PARTITIONNODE_OVERWRITE((_Py_PARTITIONNODE_t *)PARTITIONNODE_NULLROOT, PEEK(-(-1)), true);
+ break;
+ }
+
+ case SET_FUNCTION_ATTRIBUTE: {
+ STACK_SHRINK(1);
+ PARTITIONNODE_OVERWRITE((_Py_PARTITIONNODE_t *)PARTITIONNODE_NULLROOT, PEEK(-(-1)), true);
+ break;
+ }
+
+ case BUILD_SLICE: {
+ STACK_SHRINK(((oparg == 3) ? 1 : 0));
+ STACK_SHRINK(1);
+ PARTITIONNODE_OVERWRITE((_Py_PARTITIONNODE_t *)PARTITIONNODE_NULLROOT, PEEK(-(-1)), true);
+ break;
+ }
+
+ case CONVERT_VALUE: {
+ PARTITIONNODE_OVERWRITE((_Py_PARTITIONNODE_t *)PARTITIONNODE_NULLROOT, PEEK(-(-1)), true);
+ break;
+ }
+
+ case FORMAT_SIMPLE: {
+ PARTITIONNODE_OVERWRITE((_Py_PARTITIONNODE_t *)PARTITIONNODE_NULLROOT, PEEK(-(-1)), true);
+ break;
+ }
+
+ case FORMAT_WITH_SPEC: {
+ STACK_SHRINK(1);
+ PARTITIONNODE_OVERWRITE((_Py_PARTITIONNODE_t *)PARTITIONNODE_NULLROOT, PEEK(-(-1)), true);
+ break;
+ }
+
+ case BINARY_OP: {
+ STACK_SHRINK(1);
+ PARTITIONNODE_OVERWRITE((_Py_PARTITIONNODE_t *)PARTITIONNODE_NULLROOT, PEEK(-(-1)), true);
+ break;
+ }
+
+ case SWAP: {
+ PARTITIONNODE_OVERWRITE((_Py_PARTITIONNODE_t *)PARTITIONNODE_NULLROOT, PEEK(-(-2 - (oparg-2))), true);
+ PARTITIONNODE_OVERWRITE((_Py_PARTITIONNODE_t *)PARTITIONNODE_NULLROOT, PEEK(-(-1)), true);
+ break;
+ }
+
+ case _POP_JUMP_IF_FALSE: {
+ STACK_SHRINK(1);
+ break;
+ }
+
+ case _POP_JUMP_IF_TRUE: {
+ STACK_SHRINK(1);
+ break;
+ }
+
+ case JUMP_TO_TOP: {
+ break;
+ }
+
+ case SAVE_IP: {
+ break;
+ }
+
+ case EXIT_TRACE: {
+ break;
+ }
+
+ case INSERT: {
+ PARTITIONNODE_OVERWRITE((_Py_PARTITIONNODE_t *)PARTITIONNODE_NULLROOT, PEEK(-(-1 - oparg)), true);
+ break;
+ }
return frame;
}
+ op(INSERT, (unused[oparg], top -- top, unused[oparg])) {
+ // Inserts TOS at position specified by oparg;
+ memmove(&stack_pointer[-1 - oparg], &stack_pointer[-oparg], oparg * sizeof(stack_pointer[0]));
+ }
+
// END BYTECODES //
return frame;
break;
}
+
+ case INSERT: {
+ PyObject *top;
+ top = stack_pointer[-1];
+ // Inserts TOS at position specified by oparg;
+ memmove(&stack_pointer[-1 - oparg], &stack_pointer[-oparg], oparg * sizeof(stack_pointer[0]));
+ stack_pointer[-1 - oparg] = top;
+ break;
+ }
#include "pycore_opcode.h"
#include "pycore_opcode_metadata.h"
#include "pycore_opcode_utils.h"
+#include "pycore_optimizer.h"
#include "pycore_pystate.h" // _PyInterpreterState_GET()
#include "pycore_uops.h"
#include "cpython/optimizer.h"
_PyOptimizerObject* self,
PyCodeObject *code,
_Py_CODEUNIT *instr,
- _PyExecutorObject **exec)
+ _PyExecutorObject **exec,
+ int Py_UNUSED(stack_entries))
{
PyErr_Format(PyExc_SystemError, "Should never call error_optimize");
return -1;
}
_PyOptimizerObject *opt = interp->optimizer;
_PyExecutorObject *executor = NULL;
- int err = opt->optimize(opt, code, dest, &executor);
+ int err = opt->optimize(opt, code, dest, &executor, (int)(stack_pointer - _PyFrame_Stackbase(frame)));
if (err <= 0) {
assert(executor == NULL);
if (err < 0) {
_PyOptimizerObject* self,
PyCodeObject *code,
_Py_CODEUNIT *instr,
- _PyExecutorObject **exec_ptr)
+ _PyExecutorObject **exec_ptr,
+ int Py_UNUSED(curr_stackentries)
+)
{
_PyCounterExecutorObject *executor = (_PyCounterExecutorObject *)_PyObject_New(&CounterExecutor_Type);
if (executor == NULL) {
_PyOptimizerObject *self,
PyCodeObject *code,
_Py_CODEUNIT *instr,
- _PyExecutorObject **exec_ptr)
+ _PyExecutorObject **exec_ptr,
+ int curr_stackentries)
{
_PyUOpInstruction trace[_Py_UOP_MAX_TRACE_LENGTH];
int trace_length = translate_bytecode_to_trace(code, instr, trace, _Py_UOP_MAX_TRACE_LENGTH);
return trace_length;
}
OBJECT_STAT_INC(optimization_traces_created);
+ char *uop_optimize = Py_GETENV("PYTHONUOPSOPTIMIZE");
+ if (uop_optimize != NULL && *uop_optimize > '0') {
+ trace_length = _Py_uop_analyze_and_optimize(code, trace, trace_length, curr_stackentries);
+ }
_PyUOpExecutorObject *executor = PyObject_NewVar(_PyUOpExecutorObject, &UOpExecutor_Type, trace_length);
if (executor == NULL) {
return -1;
--- /dev/null
+#include "Python.h"
+#include "opcode.h"
+#include "pycore_interp.h"
+#include "pycore_opcode.h"
+#include "pycore_opcode_metadata.h"
+#include "pycore_opcode_utils.h"
+#include "pycore_pystate.h" // _PyInterpreterState_GET()
+#include "pycore_uops.h"
+#include "pycore_long.h"
+#include "cpython/optimizer.h"
+#include <stdbool.h>
+#include <stdint.h>
+#include <stddef.h>
+#include "pycore_optimizer.h"
+
+
+int
+_Py_uop_analyze_and_optimize(
+ PyCodeObject *co,
+ _PyUOpInstruction *trace,
+ int trace_len,
+ int curr_stacklen
+)
+{
+ return trace_len;
+}
Python/frozen_modules/*.h
Python/generated_cases.c.h
Python/executor_cases.c.h
+Python/abstract_interp_cases.c.h
# not actually source
Python/bytecodes.c
## other
Modules/_io/_iomodule.c - _PyIO_Module -
Modules/_sqlite/module.c - _sqlite3module -
+Python/optimizer_analysis.c - _Py_PartitionRootNode_Type -
+Python/optimizer_analysis.c - _Py_UOpsAbstractInterpContext_Type -
from flags import InstructionFlags, variable_used
from instructions import (
AnyInstruction,
+ AbstractInstruction,
Component,
Instruction,
MacroInstruction,
DEFAULT_EXECUTOR_OUTPUT = os.path.relpath(
os.path.join(ROOT, "Python/executor_cases.c.h")
)
+DEFAULT_ABSTRACT_INTERPRETER_OUTPUT = os.path.relpath(
+ os.path.join(ROOT, "Python/abstract_interp_cases.c.h")
+)
# Constants used instead of size for macro expansions.
# Note: 1, 2, 4 must match actual cache entry sizes.
INSTR_FMT_PREFIX = "INSTR_FMT_"
+# TODO: generate all these after updating the DSL
+SPECIALLY_HANDLED_ABSTRACT_INSTR = {
+ "LOAD_FAST",
+ "LOAD_FAST_CHECK",
+ "LOAD_FAST_AND_CLEAR",
+ "LOAD_CONST",
+ "STORE_FAST",
+ "STORE_FAST_MAYBE_NULL",
+ "COPY",
+
+ # Arithmetic
+ "_BINARY_OP_MULTIPLY_INT",
+ "_BINARY_OP_ADD_INT",
+ "_BINARY_OP_SUBTRACT_INT",
+
+}
+
arg_parser = argparse.ArgumentParser(
description="Generate the code for the interpreter switch.",
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
help="Write executor cases to this file",
default=DEFAULT_EXECUTOR_OUTPUT,
)
-
+arg_parser.add_argument(
+ "-a",
+ "--abstract-interpreter-cases",
+ type=str,
+ help="Write abstract interpreter cases to this file",
+ default=DEFAULT_ABSTRACT_INTERPRETER_OUTPUT,
+)
class Generator(Analyzer):
def get_stack_effect_info(
pushed: str | None
match thing:
case parsing.InstDef():
- if thing.kind != "op":
+ if thing.kind != "op" or self.instrs[thing.name].is_viable_uop():
instr = self.instrs[thing.name]
popped = effect_str(instr.input_effects)
pushed = effect_str(instr.output_effects)
file=sys.stderr,
)
+ def write_abstract_interpreter_instructions(
+ self, abstract_interpreter_filename: str, emit_line_directives: bool
+ ) -> None:
+ """Generate cases for the Tier 2 abstract interpreter/analzyer."""
+ with open(abstract_interpreter_filename, "w") as f:
+ self.out = Formatter(f, 8, emit_line_directives)
+ self.write_provenance_header()
+ for thing in self.everything:
+ match thing:
+ case OverriddenInstructionPlaceHolder():
+ pass
+ case parsing.InstDef():
+ instr = AbstractInstruction(self.instrs[thing.name].inst)
+ if instr.is_viable_uop() and instr.name not in SPECIALLY_HANDLED_ABSTRACT_INSTR:
+ self.out.emit("")
+ with self.out.block(f"case {thing.name}:"):
+ instr.write(self.out, tier=TIER_TWO)
+ self.out.emit("break;")
+ case parsing.Macro():
+ pass
+ case parsing.Pseudo():
+ pass
+ case _:
+ typing.assert_never(thing)
+ print(
+ f"Wrote some stuff to {abstract_interpreter_filename}",
+ file=sys.stderr,
+ )
+
def write_overridden_instr_place_holder(
self, place_holder: OverriddenInstructionPlaceHolder
) -> None:
a.write_instructions(args.output, args.emit_line_directives)
a.write_metadata(args.metadata, args.pymetadata)
a.write_executor_instructions(args.executor_cases, args.emit_line_directives)
+ a.write_abstract_interpreter_instructions(args.abstract_interpreter_cases,
+ args.emit_line_directives)
if __name__ == "__main__":
InstructionOrCacheEffect = Instruction | parsing.CacheEffect
+# Instruction used for abstract interpretation.
+class AbstractInstruction(Instruction):
+ def __init__(self, inst: parsing.InstDef):
+ super().__init__(inst)
+
+ def write(self, out: Formatter, tier: Tiers = TIER_ONE) -> None:
+ """Write one abstract instruction, sans prologue and epilogue."""
+ stacking.write_single_instr_for_abstract_interp(self, out)
+
+ def write_body(
+ self,
+ out: Formatter,
+ dedent: int,
+ active_caches: list[ActiveCacheEffect],
+ tier: Tiers = TIER_ONE,
+ ) -> None:
+ pass
+
+
@dataclasses.dataclass
class Component:
instr: Instruction
poke.as_stack_effect(),
poke.effect,
)
+
+
+def write_single_instr_for_abstract_interp(
+ instr: Instruction, out: Formatter
+):
+ try:
+ _write_components_for_abstract_interp(
+ [Component(instr, instr.active_caches)],
+ out,
+ )
+ except AssertionError as err:
+ raise AssertionError(f"Error writing abstract instruction {instr.name}") from err
+
+
+def _write_components_for_abstract_interp(
+ parts: list[Component],
+ out: Formatter,
+):
+ managers = get_managers(parts)
+ for mgr in managers:
+ if mgr is managers[-1]:
+ out.stack_adjust(mgr.final_offset.deep, mgr.final_offset.high)
+ # Use clone() since adjust_inverse() mutates final_offset
+ mgr.adjust_inverse(mgr.final_offset.clone())
+ # NULL out the output stack effects
+ for poke in mgr.pokes:
+ if not poke.effect.size and poke.effect.name not in mgr.instr.unmoved_names:
+ out.emit(f"PARTITIONNODE_OVERWRITE((_Py_PARTITIONNODE_t *)"
+ f"PARTITIONNODE_NULLROOT, PEEK(-({poke.offset.as_index()})), true);")