Team Ai
Datasetpublic

codekingpro/portable-devtools

sourceHugging Faceupdated 5mo agoView on Hugging Face
1likes14kdownloads
pycore_optimizer.h319 linesDownload Raw Back to internal
1#ifndef Py_INTERNAL_OPTIMIZER_H2#define Py_INTERNAL_OPTIMIZER_H3#ifdef __cplusplus4extern "C" {5#endif6 7#ifndef Py_BUILD_CORE8#  error "this header requires Py_BUILD_CORE define"9#endif10 11#include "pycore_typedefs.h"      // _PyInterpreterFrame12#include "pycore_uop_ids.h"13#include <stdbool.h>14 15 16typedef struct _PyExecutorLinkListNode {17    struct _PyExecutorObject *next;18    struct _PyExecutorObject *previous;19} _PyExecutorLinkListNode;20 21 22/* Bloom filter with m = 25623 * https://en.wikipedia.org/wiki/Bloom_filter */24#define _Py_BLOOM_FILTER_WORDS 825 26typedef struct {27    uint32_t bits[_Py_BLOOM_FILTER_WORDS];28} _PyBloomFilter;29 30typedef struct {31    uint8_t opcode;32    uint8_t oparg;33    uint8_t valid:1;34    uint8_t linked:1;35    uint8_t chain_depth:6;  // Must be big enough for MAX_CHAIN_DEPTH - 1.36    bool warm;37    int index;           // Index of ENTER_EXECUTOR (if code isn't NULL, below).38    _PyBloomFilter bloom;39    _PyExecutorLinkListNode links;40    PyCodeObject *code;  // Weak (NULL if no corresponding ENTER_EXECUTOR).41} _PyVMData;42 43/* Depending on the format,44 * the 32 bits between the oparg and operand are:45 * UOP_FORMAT_TARGET:46 *    uint32_t target;47 * UOP_FORMAT_JUMP48 *    uint16_t jump_target;49 *    uint16_t error_target;50 */51typedef struct {52    uint16_t opcode:15;53    uint16_t format:1;54    uint16_t oparg;55    union {56        uint32_t target;57        struct {58            uint16_t jump_target;59            uint16_t error_target;60        };61    };62    uint64_t operand0;  // A cache entry63    uint64_t operand1;64#ifdef Py_STATS65    uint64_t execution_count;66#endif67} _PyUOpInstruction;68 69typedef struct {70    uint32_t target;71    _Py_BackoffCounter temperature;72    struct _PyExecutorObject *executor;73} _PyExitData;74 75typedef struct _PyExecutorObject {76    PyObject_VAR_HEAD77    const _PyUOpInstruction *trace;78    _PyVMData vm_data; /* Used by the VM, but opaque to the optimizer */79    uint32_t exit_count;80    uint32_t code_size;81    size_t jit_size;82    void *jit_code;83    void *jit_side_entry;84    _PyExitData exits[1];85} _PyExecutorObject;86 87/* If pending deletion list gets large enough, then scan,88 * and free any executors that aren't executing89 * i.e. any that aren't a thread's current_executor. */90#define EXECUTOR_DELETE_LIST_MAX 10091 92// Export for '_opcode' shared extension (JIT compiler).93PyAPI_FUNC(_PyExecutorObject*) _Py_GetExecutor(PyCodeObject *code, int offset);94 95void _Py_ExecutorInit(_PyExecutorObject *, const _PyBloomFilter *);96void _Py_ExecutorDetach(_PyExecutorObject *);97void _Py_BloomFilter_Init(_PyBloomFilter *);98void _Py_BloomFilter_Add(_PyBloomFilter *bloom, void *obj);99PyAPI_FUNC(void) _Py_Executor_DependsOn(_PyExecutorObject *executor, void *obj);100 101#define _Py_MAX_ALLOWED_BUILTINS_MODIFICATIONS 3102#define _Py_MAX_ALLOWED_GLOBALS_MODIFICATIONS 6103 104#ifdef _Py_TIER2105PyAPI_FUNC(void) _Py_Executors_InvalidateDependency(PyInterpreterState *interp, void *obj, int is_invalidation);106PyAPI_FUNC(void) _Py_Executors_InvalidateAll(PyInterpreterState *interp, int is_invalidation);107PyAPI_FUNC(void) _Py_Executors_InvalidateCold(PyInterpreterState *interp);108 109#else110#  define _Py_Executors_InvalidateDependency(A, B, C) ((void)0)111#  define _Py_Executors_InvalidateAll(A, B) ((void)0)112#  define _Py_Executors_InvalidateCold(A) ((void)0)113 114#endif115 116// Used as the threshold to trigger executor invalidation when117// trace_run_counter is greater than this value.118#define JIT_CLEANUP_THRESHOLD 100000119 120// This is the length of the trace we project initially.121#define UOP_MAX_TRACE_LENGTH 800122 123#define TRACE_STACK_SIZE 5124 125int _Py_uop_analyze_and_optimize(_PyInterpreterFrame *frame,126    _PyUOpInstruction *trace, int trace_len, int curr_stackentries,127    _PyBloomFilter *dependencies);128 129extern PyTypeObject _PyUOpExecutor_Type;130 131 132#define UOP_FORMAT_TARGET 0133#define UOP_FORMAT_JUMP 1134 135static inline uint32_t uop_get_target(const _PyUOpInstruction *inst)136{137    assert(inst->format == UOP_FORMAT_TARGET);138    return inst->target;139}140 141static inline uint16_t uop_get_jump_target(const _PyUOpInstruction *inst)142{143    assert(inst->format == UOP_FORMAT_JUMP);144    return inst->jump_target;145}146 147static inline uint16_t uop_get_error_target(const _PyUOpInstruction *inst)148{149    assert(inst->format != UOP_FORMAT_TARGET);150    return inst->error_target;151}152 153// Holds locals, stack, locals, stack ... co_consts (in that order)154#define MAX_ABSTRACT_INTERP_SIZE 4096155 156#define TY_ARENA_SIZE (UOP_MAX_TRACE_LENGTH * 5)157 158// Need extras for root frame and for overflow frame (see TRACE_STACK_PUSH())159#define MAX_ABSTRACT_FRAME_DEPTH (TRACE_STACK_SIZE + 2)160 161// The maximum number of side exits that we can take before requiring forward162// progress (and inserting a new ENTER_EXECUTOR instruction). In practice, this163// is the "maximum amount of polymorphism" that an isolated trace tree can164// handle before rejoining the rest of the program.165#define MAX_CHAIN_DEPTH 4166 167/* Symbols */168/* See explanation in optimizer_symbols.c */169 170 171typedef enum _JitSymType {172    JIT_SYM_UNKNOWN_TAG = 1,173    JIT_SYM_NULL_TAG = 2,174    JIT_SYM_NON_NULL_TAG = 3,175    JIT_SYM_BOTTOM_TAG = 4,176    JIT_SYM_TYPE_VERSION_TAG = 5,177    JIT_SYM_KNOWN_CLASS_TAG = 6,178    JIT_SYM_KNOWN_VALUE_TAG = 7,179    JIT_SYM_TUPLE_TAG = 8,180    JIT_SYM_TRUTHINESS_TAG = 9,181} JitSymType;182 183typedef struct _jit_opt_known_class {184    uint8_t tag;185    uint32_t version;186    PyTypeObject *type;187} JitOptKnownClass;188 189typedef struct _jit_opt_known_version {190    uint8_t tag;191    uint32_t version;192} JitOptKnownVersion;193 194typedef struct _jit_opt_known_value {195    uint8_t tag;196    PyObject *value;197} JitOptKnownValue;198 199#define MAX_SYMBOLIC_TUPLE_SIZE 7200 201typedef struct _jit_opt_tuple {202    uint8_t tag;203    uint8_t length;204    uint16_t items[MAX_SYMBOLIC_TUPLE_SIZE];205} JitOptTuple;206 207typedef struct {208    uint8_t tag;209    bool invert;210    uint16_t value;211} JitOptTruthiness;212 213typedef union _jit_opt_symbol {214    uint8_t tag;215    JitOptKnownClass cls;216    JitOptKnownValue value;217    JitOptKnownVersion version;218    JitOptTuple tuple;219    JitOptTruthiness truthiness;220} JitOptSymbol;221 222 223 224struct _Py_UOpsAbstractFrame {225    // Max stacklen226    int stack_len;227    int locals_len;228 229    JitOptSymbol **stack_pointer;230    JitOptSymbol **stack;231    JitOptSymbol **locals;232};233 234typedef struct _Py_UOpsAbstractFrame _Py_UOpsAbstractFrame;235 236typedef struct ty_arena {237    int ty_curr_number;238    int ty_max_number;239    JitOptSymbol arena[TY_ARENA_SIZE];240} ty_arena;241 242typedef struct _JitOptContext {243    char done;244    char out_of_space;245    bool contradiction;246    // The current "executing" frame.247    _Py_UOpsAbstractFrame *frame;248    _Py_UOpsAbstractFrame frames[MAX_ABSTRACT_FRAME_DEPTH];249    int curr_frame_depth;250 251    // Arena for the symbolic types.252    ty_arena t_arena;253 254    JitOptSymbol **n_consumed;255    JitOptSymbol **limit;256    JitOptSymbol *locals_and_stack[MAX_ABSTRACT_INTERP_SIZE];257} JitOptContext;258 259extern bool _Py_uop_sym_is_null(JitOptSymbol *sym);260extern bool _Py_uop_sym_is_not_null(JitOptSymbol *sym);261extern bool _Py_uop_sym_is_const(JitOptContext *ctx, JitOptSymbol *sym);262extern PyObject *_Py_uop_sym_get_const(JitOptContext *ctx, JitOptSymbol *sym);263extern JitOptSymbol *_Py_uop_sym_new_unknown(JitOptContext *ctx);264extern JitOptSymbol *_Py_uop_sym_new_not_null(JitOptContext *ctx);265extern JitOptSymbol *_Py_uop_sym_new_type(266    JitOptContext *ctx, PyTypeObject *typ);267extern JitOptSymbol *_Py_uop_sym_new_const(JitOptContext *ctx, PyObject *const_val);268extern JitOptSymbol *_Py_uop_sym_new_null(JitOptContext *ctx);269extern bool _Py_uop_sym_has_type(JitOptSymbol *sym);270extern bool _Py_uop_sym_matches_type(JitOptSymbol *sym, PyTypeObject *typ);271extern bool _Py_uop_sym_matches_type_version(JitOptSymbol *sym, unsigned int version);272extern void _Py_uop_sym_set_null(JitOptContext *ctx, JitOptSymbol *sym);273extern void _Py_uop_sym_set_non_null(JitOptContext *ctx, JitOptSymbol *sym);274extern void _Py_uop_sym_set_type(JitOptContext *ctx, JitOptSymbol *sym, PyTypeObject *typ);275extern bool _Py_uop_sym_set_type_version(JitOptContext *ctx, JitOptSymbol *sym, unsigned int version);276extern void _Py_uop_sym_set_const(JitOptContext *ctx, JitOptSymbol *sym, PyObject *const_val);277extern bool _Py_uop_sym_is_bottom(JitOptSymbol *sym);278extern int _Py_uop_sym_truthiness(JitOptContext *ctx, JitOptSymbol *sym);279extern PyTypeObject *_Py_uop_sym_get_type(JitOptSymbol *sym);280extern bool _Py_uop_sym_is_immortal(JitOptSymbol *sym);281extern JitOptSymbol *_Py_uop_sym_new_tuple(JitOptContext *ctx, int size, JitOptSymbol **args);282extern JitOptSymbol *_Py_uop_sym_tuple_getitem(JitOptContext *ctx, JitOptSymbol *sym, int item);283extern int _Py_uop_sym_tuple_length(JitOptSymbol *sym);284extern JitOptSymbol *_Py_uop_sym_new_truthiness(JitOptContext *ctx, JitOptSymbol *value, bool truthy);285 286extern void _Py_uop_abstractcontext_init(JitOptContext *ctx);287extern void _Py_uop_abstractcontext_fini(JitOptContext *ctx);288 289extern _Py_UOpsAbstractFrame *_Py_uop_frame_new(290    JitOptContext *ctx,291    PyCodeObject *co,292    int curr_stackentries,293    JitOptSymbol **args,294    int arg_len);295extern int _Py_uop_frame_pop(JitOptContext *ctx);296 297PyAPI_FUNC(PyObject *) _Py_uop_symbols_test(PyObject *self, PyObject *ignored);298 299PyAPI_FUNC(int) _PyOptimizer_Optimize(_PyInterpreterFrame *frame, _Py_CODEUNIT *start, _PyExecutorObject **exec_ptr, int chain_depth);300 301static inline int is_terminator(const _PyUOpInstruction *uop)302{303    int opcode = uop->opcode;304    return (305        opcode == _EXIT_TRACE ||306        opcode == _JUMP_TO_TOP307    );308}309 310PyAPI_FUNC(int) _PyDumpExecutors(FILE *out);311#ifdef _Py_TIER2312extern void _Py_ClearExecutorDeletionList(PyInterpreterState *interp);313#endif314 315#ifdef __cplusplus316}317#endif318#endif /* !Py_INTERNAL_OPTIMIZER_H */319 
codekingpro/portable-devtools · Team Ai