gh-107557: Setup abstract interpretation (#107847)

Co-authored-by: Guido van Rossum <gvanrossum@users.noreply.github.com>
Co-authored-by: Jules <57632293+juliapoo@users.noreply.github.com>
This commit is contained in:
Ken Jin 2023-08-16 02:04:17 +08:00 committed by GitHub
parent 34e1917912
commit e28b0dc86d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
21 changed files with 1118 additions and 9 deletions

1
.gitattributes vendored
View File

@ -90,6 +90,7 @@ Programs/test_frozenmain.h generated
Python/Python-ast.c generated Python/Python-ast.c generated
Python/executor_cases.c.h generated Python/executor_cases.c.h generated
Python/generated_cases.c.h generated Python/generated_cases.c.h generated
Python/abstract_interp_cases.c.h generated
Python/opcode_targets.h generated Python/opcode_targets.h generated
Python/stdlib_module_names.h generated Python/stdlib_module_names.h generated
Tools/peg_generator/pegen/grammar_parser.py generated Tools/peg_generator/pegen/grammar_parser.py generated

View File

@ -22,7 +22,7 @@ typedef struct _PyExecutorObject {
typedef struct _PyOptimizerObject _PyOptimizerObject; 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. */ /* 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 { typedef struct _PyOptimizerObject {
PyObject_HEAD PyObject_HEAD

View File

@ -55,6 +55,7 @@
#define _POP_JUMP_IF_FALSE 331 #define _POP_JUMP_IF_FALSE 331
#define _POP_JUMP_IF_TRUE 332 #define _POP_JUMP_IF_TRUE 332
#define JUMP_TO_TOP 333 #define JUMP_TO_TOP 333
#define INSERT 334
extern int _PyOpcode_num_popped(int opcode, int oparg, bool jump); extern int _PyOpcode_num_popped(int opcode, int oparg, bool jump);
#ifdef NEED_OPCODE_METADATA #ifdef NEED_OPCODE_METADATA
@ -118,18 +119,38 @@ int _PyOpcode_num_popped(int opcode, int oparg, bool jump) {
return 1; return 1;
case UNARY_INVERT: case UNARY_INVERT:
return 1; 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: case BINARY_OP_MULTIPLY_INT:
return 2; return 2;
case BINARY_OP_ADD_INT: case BINARY_OP_ADD_INT:
return 2; return 2;
case BINARY_OP_SUBTRACT_INT: case BINARY_OP_SUBTRACT_INT:
return 2; 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: case BINARY_OP_MULTIPLY_FLOAT:
return 2; return 2;
case BINARY_OP_ADD_FLOAT: case BINARY_OP_ADD_FLOAT:
return 2; return 2;
case BINARY_OP_SUBTRACT_FLOAT: case BINARY_OP_SUBTRACT_FLOAT:
return 2; return 2;
case _GUARD_BOTH_UNICODE:
return 2;
case _BINARY_OP_ADD_UNICODE:
return 2;
case BINARY_OP_ADD_UNICODE: case BINARY_OP_ADD_UNICODE:
return 2; return 2;
case BINARY_OP_INPLACE_ADD_UNICODE: case BINARY_OP_INPLACE_ADD_UNICODE:
@ -226,14 +247,26 @@ int _PyOpcode_num_popped(int opcode, int oparg, bool jump) {
return 1; return 1;
case DELETE_GLOBAL: case DELETE_GLOBAL:
return 0; return 0;
case _LOAD_LOCALS:
return 0;
case LOAD_LOCALS: case LOAD_LOCALS:
return 0; return 0;
case _LOAD_FROM_DICT_OR_GLOBALS:
return 1;
case LOAD_NAME: case LOAD_NAME:
return 0; return 0;
case LOAD_FROM_DICT_OR_GLOBALS: case LOAD_FROM_DICT_OR_GLOBALS:
return 1; return 1;
case LOAD_GLOBAL: case LOAD_GLOBAL:
return 0; 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: case LOAD_GLOBAL_MODULE:
return 0; return 0;
case LOAD_GLOBAL_BUILTIN: case LOAD_GLOBAL_BUILTIN:
@ -294,6 +327,12 @@ int _PyOpcode_num_popped(int opcode, int oparg, bool jump) {
return 1; return 1;
case LOAD_METHOD: case LOAD_METHOD:
return 1; 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: case LOAD_ATTR_INSTANCE_VALUE:
return 1; return 1;
case LOAD_ATTR_MODULE: case LOAD_ATTR_MODULE:
@ -348,6 +387,8 @@ int _PyOpcode_num_popped(int opcode, int oparg, bool jump) {
return 1; return 1;
case POP_JUMP_IF_TRUE: case POP_JUMP_IF_TRUE:
return 1; return 1;
case IS_NONE:
return 1;
case POP_JUMP_IF_NONE: case POP_JUMP_IF_NONE:
return 1; return 1;
case POP_JUMP_IF_NOT_NONE: case POP_JUMP_IF_NOT_NONE:
@ -372,10 +413,28 @@ int _PyOpcode_num_popped(int opcode, int oparg, bool jump) {
return 1; return 1;
case INSTRUMENTED_FOR_ITER: case INSTRUMENTED_FOR_ITER:
return 0; 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: case FOR_ITER_LIST:
return 1; 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: case FOR_ITER_TUPLE:
return 1; 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: case FOR_ITER_RANGE:
return 1; return 1;
case FOR_ITER_GEN: case FOR_ITER_GEN:
@ -494,6 +553,18 @@ int _PyOpcode_num_popped(int opcode, int oparg, bool jump) {
return 0; return 0;
case RESERVED: case RESERVED:
return 0; 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: default:
return -1; return -1;
} }
@ -562,18 +633,38 @@ int _PyOpcode_num_pushed(int opcode, int oparg, bool jump) {
return 1; return 1;
case UNARY_INVERT: case UNARY_INVERT:
return 1; 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: case BINARY_OP_MULTIPLY_INT:
return 1; return 1;
case BINARY_OP_ADD_INT: case BINARY_OP_ADD_INT:
return 1; return 1;
case BINARY_OP_SUBTRACT_INT: case BINARY_OP_SUBTRACT_INT:
return 1; 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: case BINARY_OP_MULTIPLY_FLOAT:
return 1; return 1;
case BINARY_OP_ADD_FLOAT: case BINARY_OP_ADD_FLOAT:
return 1; return 1;
case BINARY_OP_SUBTRACT_FLOAT: case BINARY_OP_SUBTRACT_FLOAT:
return 1; return 1;
case _GUARD_BOTH_UNICODE:
return 2;
case _BINARY_OP_ADD_UNICODE:
return 1;
case BINARY_OP_ADD_UNICODE: case BINARY_OP_ADD_UNICODE:
return 1; return 1;
case BINARY_OP_INPLACE_ADD_UNICODE: case BINARY_OP_INPLACE_ADD_UNICODE:
@ -670,14 +761,26 @@ int _PyOpcode_num_pushed(int opcode, int oparg, bool jump) {
return 0; return 0;
case DELETE_GLOBAL: case DELETE_GLOBAL:
return 0; return 0;
case _LOAD_LOCALS:
return 1;
case LOAD_LOCALS: case LOAD_LOCALS:
return 1; return 1;
case _LOAD_FROM_DICT_OR_GLOBALS:
return 1;
case LOAD_NAME: case LOAD_NAME:
return 1; return 1;
case LOAD_FROM_DICT_OR_GLOBALS: case LOAD_FROM_DICT_OR_GLOBALS:
return 1; return 1;
case LOAD_GLOBAL: case LOAD_GLOBAL:
return ((oparg & 1) ? 1 : 0) + 1; 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: case LOAD_GLOBAL_MODULE:
return (oparg & 1 ? 1 : 0) + 1; return (oparg & 1 ? 1 : 0) + 1;
case LOAD_GLOBAL_BUILTIN: case LOAD_GLOBAL_BUILTIN:
@ -738,6 +841,12 @@ int _PyOpcode_num_pushed(int opcode, int oparg, bool jump) {
return ((oparg & 1) ? 1 : 0) + 1; return ((oparg & 1) ? 1 : 0) + 1;
case LOAD_METHOD: case LOAD_METHOD:
return ((oparg & 1) ? 1 : 0) + 1; 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: case LOAD_ATTR_INSTANCE_VALUE:
return (oparg & 1 ? 1 : 0) + 1; return (oparg & 1 ? 1 : 0) + 1;
case LOAD_ATTR_MODULE: case LOAD_ATTR_MODULE:
@ -792,6 +901,8 @@ int _PyOpcode_num_pushed(int opcode, int oparg, bool jump) {
return 0; return 0;
case POP_JUMP_IF_TRUE: case POP_JUMP_IF_TRUE:
return 0; return 0;
case IS_NONE:
return 1;
case POP_JUMP_IF_NONE: case POP_JUMP_IF_NONE:
return 0; return 0;
case POP_JUMP_IF_NOT_NONE: case POP_JUMP_IF_NOT_NONE:
@ -816,10 +927,28 @@ int _PyOpcode_num_pushed(int opcode, int oparg, bool jump) {
return 2; return 2;
case INSTRUMENTED_FOR_ITER: case INSTRUMENTED_FOR_ITER:
return 0; 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: case FOR_ITER_LIST:
return 2; 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: case FOR_ITER_TUPLE:
return 2; 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: case FOR_ITER_RANGE:
return 2; return 2;
case FOR_ITER_GEN: case FOR_ITER_GEN:
@ -938,6 +1067,18 @@ int _PyOpcode_num_pushed(int opcode, int oparg, bool jump) {
return 0; return 0;
case RESERVED: case RESERVED:
return 0; 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: default:
return -1; return -1;
} }
@ -1393,5 +1534,6 @@ const char * const _PyOpcode_uop_name[OPCODE_UOP_NAME_SIZE] = {
[_POP_JUMP_IF_FALSE] = "_POP_JUMP_IF_FALSE", [_POP_JUMP_IF_FALSE] = "_POP_JUMP_IF_FALSE",
[_POP_JUMP_IF_TRUE] = "_POP_JUMP_IF_TRUE", [_POP_JUMP_IF_TRUE] = "_POP_JUMP_IF_TRUE",
[JUMP_TO_TOP] = "JUMP_TO_TOP", [JUMP_TO_TOP] = "JUMP_TO_TOP",
[INSERT] = "INSERT",
}; };
#endif // NEED_OPCODE_METADATA #endif // NEED_OPCODE_METADATA

View File

@ -0,0 +1,20 @@
#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 */

View File

@ -8,7 +8,7 @@ extern "C" {
# error "this header requires Py_BUILD_CORE define" # error "this header requires Py_BUILD_CORE define"
#endif #endif
#define _Py_UOP_MAX_TRACE_LENGTH 32 #define _Py_UOP_MAX_TRACE_LENGTH 64
typedef struct { typedef struct {
uint32_t opcode; uint32_t opcode;

View File

@ -405,6 +405,7 @@ PYTHON_OBJS= \
Python/mysnprintf.o \ Python/mysnprintf.o \
Python/mystrtoul.o \ Python/mystrtoul.o \
Python/optimizer.o \ Python/optimizer.o \
Python/optimizer_analysis.o \
Python/pathconfig.o \ Python/pathconfig.o \
Python/preconfig.o \ Python/preconfig.o \
Python/pyarena.o \ Python/pyarena.o \
@ -1552,10 +1553,12 @@ regen-cases:
-m $(srcdir)/Include/internal/pycore_opcode_metadata.h.new \ -m $(srcdir)/Include/internal/pycore_opcode_metadata.h.new \
-e $(srcdir)/Python/executor_cases.c.h.new \ -e $(srcdir)/Python/executor_cases.c.h.new \
-p $(srcdir)/Lib/_opcode_metadata.py.new \ -p $(srcdir)/Lib/_opcode_metadata.py.new \
-a $(srcdir)/Python/abstract_interp_cases.c.h.new \
$(srcdir)/Python/bytecodes.c $(srcdir)/Python/bytecodes.c
$(UPDATE_FILE) $(srcdir)/Python/generated_cases.c.h $(srcdir)/Python/generated_cases.c.h.new $(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)/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/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 $(UPDATE_FILE) $(srcdir)/Lib/_opcode_metadata.py $(srcdir)/Lib/_opcode_metadata.py.new
Python/compile.o: $(srcdir)/Include/internal/pycore_opcode_metadata.h Python/compile.o: $(srcdir)/Include/internal/pycore_opcode_metadata.h
@ -1568,6 +1571,7 @@ Python/ceval.o: \
Python/executor.o: \ Python/executor.o: \
$(srcdir)/Include/internal/pycore_opcode_metadata.h \ $(srcdir)/Include/internal/pycore_opcode_metadata.h \
$(srcdir)/Include/internal/pycore_optimizer.h \
$(srcdir)/Python/ceval_macros.h \ $(srcdir)/Python/ceval_macros.h \
$(srcdir)/Python/executor_cases.c.h $(srcdir)/Python/executor_cases.c.h
@ -1576,7 +1580,12 @@ Python/flowgraph.o: \
Python/optimizer.o: \ Python/optimizer.o: \
$(srcdir)/Python/executor_cases.c.h \ $(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) Python/frozen.o: $(FROZEN_FILES_OUT)
@ -1786,6 +1795,7 @@ PYTHON_HEADERS= \
$(srcdir)/Include/internal/pycore_obmalloc_init.h \ $(srcdir)/Include/internal/pycore_obmalloc_init.h \
$(srcdir)/Include/internal/pycore_opcode.h \ $(srcdir)/Include/internal/pycore_opcode.h \
$(srcdir)/Include/internal/pycore_opcode_utils.h \ $(srcdir)/Include/internal/pycore_opcode_utils.h \
$(srcdir)/Include/internal/pycore_optimizer.h \
$(srcdir)/Include/internal/pycore_pathconfig.h \ $(srcdir)/Include/internal/pycore_pathconfig.h \
$(srcdir)/Include/internal/pycore_pyarena.h \ $(srcdir)/Include/internal/pycore_pyarena.h \
$(srcdir)/Include/internal/pycore_pyerrors.h \ $(srcdir)/Include/internal/pycore_pyerrors.h \

View File

@ -0,0 +1 @@
Generate the cases needed for the barebones tier 2 abstract interpreter for optimization passes in CPython.

View File

@ -218,6 +218,7 @@
<ClCompile Include="..\Python\mysnprintf.c" /> <ClCompile Include="..\Python\mysnprintf.c" />
<ClCompile Include="..\Python\mystrtoul.c" /> <ClCompile Include="..\Python\mystrtoul.c" />
<ClCompile Include="..\Python\optimizer.c" /> <ClCompile Include="..\Python\optimizer.c" />
<ClCompile Include="..\Python\optimizer_analysis.c" />
<ClCompile Include="..\Python\pathconfig.c" /> <ClCompile Include="..\Python\pathconfig.c" />
<ClCompile Include="..\Python\perf_trampoline.c" /> <ClCompile Include="..\Python\perf_trampoline.c" />
<ClCompile Include="..\Python\preconfig.c" /> <ClCompile Include="..\Python\preconfig.c" />

View File

@ -283,6 +283,9 @@
<ClCompile Include="..\Python\optimizer.c"> <ClCompile Include="..\Python\optimizer.c">
<Filter>Source Files</Filter> <Filter>Source Files</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="..\Python\optimizer_analysis.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\Parser\parser.c"> <ClCompile Include="..\Parser\parser.c">
<Filter>Source Files</Filter> <Filter>Source Files</Filter>
</ClCompile> </ClCompile>

View File

@ -248,6 +248,7 @@
<ClInclude Include="..\Include\internal\pycore_object_state.h" /> <ClInclude Include="..\Include\internal\pycore_object_state.h" />
<ClInclude Include="..\Include\internal\pycore_obmalloc.h" /> <ClInclude Include="..\Include\internal\pycore_obmalloc.h" />
<ClInclude Include="..\Include\internal\pycore_obmalloc_init.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_pathconfig.h" />
<ClInclude Include="..\Include\internal\pycore_pyarena.h" /> <ClInclude Include="..\Include\internal\pycore_pyarena.h" />
<ClInclude Include="..\Include\internal\pycore_pyerrors.h" /> <ClInclude Include="..\Include\internal\pycore_pyerrors.h" />
@ -279,6 +280,7 @@
<ClInclude Include="..\Include\internal\pycore_unionobject.h" /> <ClInclude Include="..\Include\internal\pycore_unionobject.h" />
<ClInclude Include="..\Include\internal\pycore_unicodeobject.h" /> <ClInclude Include="..\Include\internal\pycore_unicodeobject.h" />
<ClInclude Include="..\Include\internal\pycore_unicodeobject_generated.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_warnings.h" />
<ClInclude Include="..\Include\internal\pycore_weakref.h" /> <ClInclude Include="..\Include\internal\pycore_weakref.h" />
<ClInclude Include="..\Include\interpreteridobject.h" /> <ClInclude Include="..\Include\interpreteridobject.h" />
@ -548,6 +550,7 @@
<ClCompile Include="..\Python\mysnprintf.c" /> <ClCompile Include="..\Python\mysnprintf.c" />
<ClCompile Include="..\Python\mystrtoul.c" /> <ClCompile Include="..\Python\mystrtoul.c" />
<ClCompile Include="..\Python\optimizer.c" /> <ClCompile Include="..\Python\optimizer.c" />
<ClCompile Include="..\Python\optimizer_analysis.c" />
<ClCompile Include="..\Python\pathconfig.c" /> <ClCompile Include="..\Python\pathconfig.c" />
<ClCompile Include="..\Python\perf_trampoline.c" /> <ClCompile Include="..\Python\perf_trampoline.c" />
<ClCompile Include="..\Python\preconfig.c" /> <ClCompile Include="..\Python\preconfig.c" />

View File

@ -648,6 +648,9 @@
<ClInclude Include="..\Include\internal\pycore_obmalloc_init.h"> <ClInclude Include="..\Include\internal\pycore_obmalloc_init.h">
<Filter>Include\internal</Filter> <Filter>Include\internal</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="..\Include\internal\pycore_optimizer.h">
<Filter>Include\internal</Filter>
</ClInclude>
<ClInclude Include="..\Include\internal\pycore_pathconfig.h"> <ClInclude Include="..\Include\internal\pycore_pathconfig.h">
<Filter>Include\internal</Filter> <Filter>Include\internal</Filter>
</ClInclude> </ClInclude>
@ -732,6 +735,9 @@
<ClInclude Include="..\Include\internal\pycore_unionobject.h"> <ClInclude Include="..\Include\internal\pycore_unionobject.h">
<Filter>Include\internal</Filter> <Filter>Include\internal</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="..\Include\internal\pycore_uops.h">
<Filter>Include\internal</Filter>
</ClInclude>
<ClInclude Include="$(zlibDir)\crc32.h"> <ClInclude Include="$(zlibDir)\crc32.h">
<Filter>Modules\zlib</Filter> <Filter>Modules\zlib</Filter>
</ClInclude> </ClInclude>
@ -1223,6 +1229,9 @@
<ClCompile Include="..\Python\optimizer.c"> <ClCompile Include="..\Python\optimizer.c">
<Filter>Python</Filter> <Filter>Python</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="..\Python\optimizer_analysis.c">
<Filter>Python</Filter>
</ClCompile>
<ClCompile Include="..\Python\pathconfig.c"> <ClCompile Include="..\Python\pathconfig.c">
<Filter>Python</Filter> <Filter>Python</Filter>
</ClCompile> </ClCompile>

761
Python/abstract_interp_cases.c.h generated Normal file
View File

@ -0,0 +1,761 @@
// 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;
}

View File

@ -3743,6 +3743,11 @@ dummy_func(
return frame; 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 // // END BYTECODES //

View File

@ -2733,3 +2733,12 @@
return frame; return frame;
break; 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;
}

View File

@ -4,6 +4,7 @@
#include "pycore_opcode.h" #include "pycore_opcode.h"
#include "pycore_opcode_metadata.h" #include "pycore_opcode_metadata.h"
#include "pycore_opcode_utils.h" #include "pycore_opcode_utils.h"
#include "pycore_optimizer.h"
#include "pycore_pystate.h" // _PyInterpreterState_GET() #include "pycore_pystate.h" // _PyInterpreterState_GET()
#include "pycore_uops.h" #include "pycore_uops.h"
#include "cpython/optimizer.h" #include "cpython/optimizer.h"
@ -103,7 +104,8 @@ error_optimize(
_PyOptimizerObject* self, _PyOptimizerObject* self,
PyCodeObject *code, PyCodeObject *code,
_Py_CODEUNIT *instr, _Py_CODEUNIT *instr,
_PyExecutorObject **exec) _PyExecutorObject **exec,
int Py_UNUSED(stack_entries))
{ {
PyErr_Format(PyExc_SystemError, "Should never call error_optimize"); PyErr_Format(PyExc_SystemError, "Should never call error_optimize");
return -1; return -1;
@ -164,7 +166,7 @@ _PyOptimizer_BackEdge(_PyInterpreterFrame *frame, _Py_CODEUNIT *src, _Py_CODEUNI
} }
_PyOptimizerObject *opt = interp->optimizer; _PyOptimizerObject *opt = interp->optimizer;
_PyExecutorObject *executor = NULL; _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) { if (err <= 0) {
assert(executor == NULL); assert(executor == NULL);
if (err < 0) { if (err < 0) {
@ -254,7 +256,9 @@ counter_optimize(
_PyOptimizerObject* self, _PyOptimizerObject* self,
PyCodeObject *code, PyCodeObject *code,
_Py_CODEUNIT *instr, _Py_CODEUNIT *instr,
_PyExecutorObject **exec_ptr) _PyExecutorObject **exec_ptr,
int Py_UNUSED(curr_stackentries)
)
{ {
_PyCounterExecutorObject *executor = (_PyCounterExecutorObject *)_PyObject_New(&CounterExecutor_Type); _PyCounterExecutorObject *executor = (_PyCounterExecutorObject *)_PyObject_New(&CounterExecutor_Type);
if (executor == NULL) { if (executor == NULL) {
@ -684,7 +688,8 @@ uop_optimize(
_PyOptimizerObject *self, _PyOptimizerObject *self,
PyCodeObject *code, PyCodeObject *code,
_Py_CODEUNIT *instr, _Py_CODEUNIT *instr,
_PyExecutorObject **exec_ptr) _PyExecutorObject **exec_ptr,
int curr_stackentries)
{ {
_PyUOpInstruction trace[_Py_UOP_MAX_TRACE_LENGTH]; _PyUOpInstruction trace[_Py_UOP_MAX_TRACE_LENGTH];
int trace_length = translate_bytecode_to_trace(code, instr, trace, _Py_UOP_MAX_TRACE_LENGTH); int trace_length = translate_bytecode_to_trace(code, instr, trace, _Py_UOP_MAX_TRACE_LENGTH);
@ -693,6 +698,10 @@ uop_optimize(
return trace_length; return trace_length;
} }
OBJECT_STAT_INC(optimization_traces_created); 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); _PyUOpExecutorObject *executor = PyObject_NewVar(_PyUOpExecutorObject, &UOpExecutor_Type, trace_length);
if (executor == NULL) { if (executor == NULL) {
return -1; return -1;

View File

@ -0,0 +1,26 @@
#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;
}

View File

@ -84,6 +84,7 @@ Python/deepfreeze/*.c
Python/frozen_modules/*.h Python/frozen_modules/*.h
Python/generated_cases.c.h Python/generated_cases.c.h
Python/executor_cases.c.h Python/executor_cases.c.h
Python/abstract_interp_cases.c.h
# not actually source # not actually source
Python/bytecodes.c Python/bytecodes.c

View File

@ -716,3 +716,5 @@ Modules/expat/xmlrole.c - error -
## other ## other
Modules/_io/_iomodule.c - _PyIO_Module - Modules/_io/_iomodule.c - _PyIO_Module -
Modules/_sqlite/module.c - _sqlite3module - Modules/_sqlite/module.c - _sqlite3module -
Python/optimizer_analysis.c - _Py_PartitionRootNode_Type -
Python/optimizer_analysis.c - _Py_UOpsAbstractInterpContext_Type -

Can't render this file because it has a wrong number of fields in line 4.

View File

@ -16,6 +16,7 @@ from formatting import Formatter, list_effect_size
from flags import InstructionFlags, variable_used from flags import InstructionFlags, variable_used
from instructions import ( from instructions import (
AnyInstruction, AnyInstruction,
AbstractInstruction,
Component, Component,
Instruction, Instruction,
MacroInstruction, MacroInstruction,
@ -44,6 +45,9 @@ DEFAULT_PYMETADATA_OUTPUT = os.path.relpath(
DEFAULT_EXECUTOR_OUTPUT = os.path.relpath( DEFAULT_EXECUTOR_OUTPUT = os.path.relpath(
os.path.join(ROOT, "Python/executor_cases.c.h") 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. # Constants used instead of size for macro expansions.
# Note: 1, 2, 4 must match actual cache entry sizes. # Note: 1, 2, 4 must match actual cache entry sizes.
@ -58,6 +62,23 @@ OPARG_SIZES = {
INSTR_FMT_PREFIX = "INSTR_FMT_" 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( arg_parser = argparse.ArgumentParser(
description="Generate the code for the interpreter switch.", description="Generate the code for the interpreter switch.",
formatter_class=argparse.ArgumentDefaultsHelpFormatter, formatter_class=argparse.ArgumentDefaultsHelpFormatter,
@ -92,7 +113,13 @@ arg_parser.add_argument(
help="Write executor cases to this file", help="Write executor cases to this file",
default=DEFAULT_EXECUTOR_OUTPUT, 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): class Generator(Analyzer):
def get_stack_effect_info( def get_stack_effect_info(
@ -109,7 +136,7 @@ class Generator(Analyzer):
pushed: str | None pushed: str | None
match thing: match thing:
case parsing.InstDef(): case parsing.InstDef():
if thing.kind != "op": if thing.kind != "op" or self.instrs[thing.name].is_viable_uop():
instr = self.instrs[thing.name] instr = self.instrs[thing.name]
popped = effect_str(instr.input_effects) popped = effect_str(instr.input_effects)
pushed = effect_str(instr.output_effects) pushed = effect_str(instr.output_effects)
@ -588,6 +615,35 @@ class Generator(Analyzer):
file=sys.stderr, 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( def write_overridden_instr_place_holder(
self, place_holder: OverriddenInstructionPlaceHolder self, place_holder: OverriddenInstructionPlaceHolder
) -> None: ) -> None:
@ -629,6 +685,8 @@ def main():
a.write_instructions(args.output, args.emit_line_directives) a.write_instructions(args.output, args.emit_line_directives)
a.write_metadata(args.metadata, args.pymetadata) a.write_metadata(args.metadata, args.pymetadata)
a.write_executor_instructions(args.executor_cases, args.emit_line_directives) 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__": if __name__ == "__main__":

View File

@ -248,6 +248,25 @@ class Instruction:
InstructionOrCacheEffect = Instruction | parsing.CacheEffect 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 @dataclasses.dataclass
class Component: class Component:
instr: Instruction instr: Instruction

View File

@ -391,3 +391,32 @@ def write_components(
poke.as_stack_effect(), poke.as_stack_effect(),
poke.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);")