| 
									
										
										
										
											2024-04-30 18:26:34 -07:00
										 |  |  | #ifdef _Py_TIER2
 | 
					
						
							| 
									
										
										
										
											2024-02-27 10:51:26 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | #include "Python.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "pycore_code.h"
 | 
					
						
							|  |  |  | #include "pycore_frame.h"
 | 
					
						
							| 
									
										
										
										
											2024-03-05 11:23:46 +00:00
										 |  |  | #include "pycore_long.h"
 | 
					
						
							| 
									
										
										
										
											2024-02-27 10:51:26 +00:00
										 |  |  | #include "pycore_optimizer.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include <stdbool.h>
 | 
					
						
							|  |  |  | #include <stdint.h>
 | 
					
						
							|  |  |  | #include <stddef.h>
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-02-28 09:55:56 -08:00
										 |  |  | /* Symbols
 | 
					
						
							|  |  |  |    ======= | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |    See the diagram at | 
					
						
							|  |  |  |    https://github.com/faster-cpython/ideas/blob/main/3.13/redundancy_eliminator.md
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |    We represent the nodes in the diagram as follows | 
					
						
							|  |  |  |    (the flag bits are only defined in optimizer_symbols.c): | 
					
						
							|  |  |  |    - Top: no flag bits, typ and const_val are NULL. | 
					
						
							|  |  |  |    - NULL: IS_NULL flag set, type and const_val NULL. | 
					
						
							|  |  |  |    - Not NULL: NOT_NULL flag set, type and const_val NULL. | 
					
						
							|  |  |  |    - None/not None: not used. (None could be represented as any other constant.) | 
					
						
							|  |  |  |    - Known type: NOT_NULL flag set and typ set; const_val is NULL. | 
					
						
							|  |  |  |    - Known constant: NOT_NULL flag set, type set, const_val set. | 
					
						
							|  |  |  |    - Bottom: IS_NULL and NOT_NULL flags set, type and const_val NULL. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-02-27 10:51:26 +00:00
										 |  |  | #ifdef Py_DEBUG
 | 
					
						
							|  |  |  | static inline int get_lltrace(void) { | 
					
						
							|  |  |  |     char *uop_debug = Py_GETENV("PYTHON_OPT_DEBUG"); | 
					
						
							|  |  |  |     int lltrace = 0; | 
					
						
							|  |  |  |     if (uop_debug != NULL && *uop_debug >= '0') { | 
					
						
							|  |  |  |         lltrace = *uop_debug - '0';  // TODO: Parse an int and all that
 | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return lltrace; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | #define DPRINTF(level, ...) \
 | 
					
						
							|  |  |  |     if (get_lltrace() >= (level)) { printf(__VA_ARGS__); } | 
					
						
							|  |  |  | #else
 | 
					
						
							|  |  |  | #define DPRINTF(level, ...)
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-01-20 15:49:15 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | static JitOptSymbol NO_SPACE_SYMBOL = { | 
					
						
							|  |  |  |     .tag = JIT_SYM_BOTTOM_TAG | 
					
						
							| 
									
										
										
										
											2024-05-10 17:43:23 +01:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-01-20 15:49:15 +00:00
										 |  |  | JitOptSymbol * | 
					
						
							|  |  |  | out_of_space(JitOptContext *ctx) | 
					
						
							| 
									
										
										
										
											2024-05-10 17:43:23 +01:00
										 |  |  | { | 
					
						
							|  |  |  |     ctx->done = true; | 
					
						
							|  |  |  |     ctx->out_of_space = true; | 
					
						
							|  |  |  |     return &NO_SPACE_SYMBOL; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-01-20 15:49:15 +00:00
										 |  |  | static JitOptSymbol * | 
					
						
							|  |  |  | sym_new(JitOptContext *ctx) | 
					
						
							| 
									
										
										
										
											2024-02-27 10:51:26 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2025-01-20 15:49:15 +00:00
										 |  |  |     JitOptSymbol *self = &ctx->t_arena.arena[ctx->t_arena.ty_curr_number]; | 
					
						
							| 
									
										
										
										
											2024-02-27 10:51:26 +00:00
										 |  |  |     if (ctx->t_arena.ty_curr_number >= ctx->t_arena.ty_max_number) { | 
					
						
							|  |  |  |         OPT_STAT_INC(optimizer_failure_reason_no_memory); | 
					
						
							|  |  |  |         DPRINTF(1, "out of space for symbolic expression type\n"); | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     ctx->t_arena.ty_curr_number++; | 
					
						
							| 
									
										
										
										
											2025-01-20 15:49:15 +00:00
										 |  |  |     self->tag = JIT_SYM_UNKNOWN_TAG; | 
					
						
							| 
									
										
										
										
											2024-02-27 10:51:26 +00:00
										 |  |  |     return self; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static inline void | 
					
						
							| 
									
										
										
										
											2025-01-20 15:49:15 +00:00
										 |  |  | sym_set_bottom(JitOptContext *ctx, JitOptSymbol *sym) | 
					
						
							| 
									
										
										
										
											2024-02-28 09:55:56 -08:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2025-01-20 15:49:15 +00:00
										 |  |  |     sym->tag = JIT_SYM_BOTTOM_TAG; | 
					
						
							| 
									
										
										
										
											2024-05-10 17:43:23 +01:00
										 |  |  |     ctx->done = true; | 
					
						
							|  |  |  |     ctx->contradiction = true; | 
					
						
							| 
									
										
										
										
											2024-02-28 09:55:56 -08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-02-28 14:38:01 -08:00
										 |  |  | bool | 
					
						
							| 
									
										
										
										
											2025-01-20 15:49:15 +00:00
										 |  |  | _Py_uop_sym_is_bottom(JitOptSymbol *sym) | 
					
						
							| 
									
										
										
										
											2024-02-27 10:51:26 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2025-01-20 15:49:15 +00:00
										 |  |  |     return sym->tag == JIT_SYM_BOTTOM_TAG; | 
					
						
							| 
									
										
										
										
											2024-02-27 10:51:26 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | bool | 
					
						
							| 
									
										
										
										
											2025-01-20 15:49:15 +00:00
										 |  |  | _Py_uop_sym_is_not_null(JitOptSymbol *sym) { | 
					
						
							|  |  |  |     return sym->tag == JIT_SYM_NON_NULL_TAG || sym->tag > JIT_SYM_BOTTOM_TAG; | 
					
						
							| 
									
										
										
										
											2024-02-27 10:51:26 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | bool | 
					
						
							| 
									
										
										
										
											2025-01-20 15:49:15 +00:00
										 |  |  | _Py_uop_sym_is_const(JitOptSymbol *sym) | 
					
						
							| 
									
										
										
										
											2024-02-27 10:51:26 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2025-01-20 15:49:15 +00:00
										 |  |  |     return sym->tag == JIT_SYM_KNOWN_VALUE_TAG; | 
					
						
							| 
									
										
										
										
											2024-02-27 10:51:26 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | bool | 
					
						
							| 
									
										
										
										
											2025-01-20 15:49:15 +00:00
										 |  |  | _Py_uop_sym_is_null(JitOptSymbol *sym) | 
					
						
							| 
									
										
										
										
											2024-02-27 10:51:26 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2025-01-20 15:49:15 +00:00
										 |  |  |     return sym->tag == JIT_SYM_NULL_TAG; | 
					
						
							| 
									
										
										
										
											2024-02-27 10:51:26 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-01-20 15:49:15 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-02-27 10:51:26 +00:00
										 |  |  | PyObject * | 
					
						
							| 
									
										
										
										
											2025-01-20 15:49:15 +00:00
										 |  |  | _Py_uop_sym_get_const(JitOptSymbol *sym) | 
					
						
							| 
									
										
										
										
											2024-02-27 10:51:26 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2025-01-20 15:49:15 +00:00
										 |  |  |     if (sym->tag == JIT_SYM_KNOWN_VALUE_TAG) { | 
					
						
							|  |  |  |         return sym->value.value; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return NULL; | 
					
						
							| 
									
										
										
										
											2024-02-27 10:51:26 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-05-10 17:43:23 +01:00
										 |  |  | void | 
					
						
							| 
									
										
										
										
											2025-01-20 15:49:15 +00:00
										 |  |  | _Py_uop_sym_set_type(JitOptContext *ctx, JitOptSymbol *sym, PyTypeObject *typ) | 
					
						
							| 
									
										
										
										
											2024-02-27 10:51:26 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2025-01-20 15:49:15 +00:00
										 |  |  |     JitSymType tag = sym->tag; | 
					
						
							|  |  |  |     switch(tag) { | 
					
						
							|  |  |  |         case JIT_SYM_NULL_TAG: | 
					
						
							| 
									
										
										
										
											2024-05-10 17:43:23 +01:00
										 |  |  |             sym_set_bottom(ctx, sym); | 
					
						
							|  |  |  |             return; | 
					
						
							| 
									
										
										
										
											2025-01-20 15:49:15 +00:00
										 |  |  |         case JIT_SYM_KNOWN_CLASS_TAG: | 
					
						
							|  |  |  |             if (sym->cls.type != typ) { | 
					
						
							|  |  |  |                 sym_set_bottom(ctx, sym); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             return; | 
					
						
							|  |  |  |         case JIT_SYM_TYPE_VERSION_TAG: | 
					
						
							|  |  |  |             if (sym->version.version == typ->tp_version_tag) { | 
					
						
							|  |  |  |                 sym->tag = JIT_SYM_KNOWN_CLASS_TAG; | 
					
						
							|  |  |  |                 sym->cls.type = typ; | 
					
						
							|  |  |  |                 sym->cls.version = typ->tp_version_tag; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             else { | 
					
						
							|  |  |  |                 sym_set_bottom(ctx, sym); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             return; | 
					
						
							|  |  |  |         case JIT_SYM_KNOWN_VALUE_TAG: | 
					
						
							|  |  |  |             if (Py_TYPE(sym->value.value) != typ) { | 
					
						
							|  |  |  |                 Py_CLEAR(sym->value.value); | 
					
						
							|  |  |  |                 sym_set_bottom(ctx, sym); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             return; | 
					
						
							|  |  |  |         case JIT_SYM_TUPLE_TAG: | 
					
						
							|  |  |  |             if (typ != &PyTuple_Type) { | 
					
						
							|  |  |  |                 sym_set_bottom(ctx, sym); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             return; | 
					
						
							|  |  |  |         case JIT_SYM_BOTTOM_TAG: | 
					
						
							|  |  |  |             return; | 
					
						
							|  |  |  |         case JIT_SYM_NON_NULL_TAG: | 
					
						
							|  |  |  |         case JIT_SYM_UNKNOWN_TAG: | 
					
						
							|  |  |  |             sym->tag = JIT_SYM_KNOWN_CLASS_TAG; | 
					
						
							|  |  |  |             sym->cls.version = 0; | 
					
						
							|  |  |  |             sym->cls.type = typ; | 
					
						
							|  |  |  |             return; | 
					
						
							| 
									
										
										
										
											2024-02-29 10:55:29 -08:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2024-02-28 09:55:56 -08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-06-08 05:41:45 -04:00
										 |  |  | bool | 
					
						
							| 
									
										
										
										
											2025-01-20 15:49:15 +00:00
										 |  |  | _Py_uop_sym_set_type_version(JitOptContext *ctx, JitOptSymbol *sym, unsigned int version) | 
					
						
							| 
									
										
										
										
											2024-06-08 05:41:45 -04:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2025-01-20 15:49:15 +00:00
										 |  |  |     JitSymType tag = sym->tag; | 
					
						
							|  |  |  |     switch(tag) { | 
					
						
							|  |  |  |         case JIT_SYM_NULL_TAG: | 
					
						
							|  |  |  |             sym_set_bottom(ctx, sym); | 
					
						
							|  |  |  |             return false; | 
					
						
							|  |  |  |         case JIT_SYM_KNOWN_CLASS_TAG: | 
					
						
							|  |  |  |             if (sym->cls.type->tp_version_tag != version) { | 
					
						
							|  |  |  |                 sym_set_bottom(ctx, sym); | 
					
						
							|  |  |  |                 return false; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             else { | 
					
						
							|  |  |  |                 sym->cls.version = version; | 
					
						
							|  |  |  |                 return true; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         case JIT_SYM_KNOWN_VALUE_TAG: | 
					
						
							|  |  |  |             Py_CLEAR(sym->value.value); | 
					
						
							|  |  |  |             sym_set_bottom(ctx, sym); | 
					
						
							|  |  |  |             return false; | 
					
						
							|  |  |  |         case JIT_SYM_TUPLE_TAG: | 
					
						
							|  |  |  |             sym_set_bottom(ctx, sym); | 
					
						
							|  |  |  |             return false; | 
					
						
							|  |  |  |         case JIT_SYM_TYPE_VERSION_TAG: | 
					
						
							|  |  |  |             if (sym->version.version == version) { | 
					
						
							|  |  |  |                 return true; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             sym_set_bottom(ctx, sym); | 
					
						
							|  |  |  |             return false; | 
					
						
							|  |  |  |         case JIT_SYM_BOTTOM_TAG: | 
					
						
							|  |  |  |             return false; | 
					
						
							|  |  |  |         case JIT_SYM_NON_NULL_TAG: | 
					
						
							|  |  |  |         case JIT_SYM_UNKNOWN_TAG: | 
					
						
							|  |  |  |             sym->tag = JIT_SYM_TYPE_VERSION_TAG; | 
					
						
							|  |  |  |             sym->version.version = version; | 
					
						
							|  |  |  |             return true; | 
					
						
							| 
									
										
										
										
											2024-06-08 05:41:45 -04:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2025-01-20 15:49:15 +00:00
										 |  |  |     Py_UNREACHABLE(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void make_const(JitOptSymbol *sym, PyObject *val) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     sym->tag = JIT_SYM_KNOWN_VALUE_TAG; | 
					
						
							|  |  |  |     sym->value.value = Py_NewRef(val); | 
					
						
							| 
									
										
										
										
											2024-06-08 05:41:45 -04:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-05-10 17:43:23 +01:00
										 |  |  | void | 
					
						
							| 
									
										
										
										
											2025-01-20 15:49:15 +00:00
										 |  |  | _Py_uop_sym_set_const(JitOptContext *ctx, JitOptSymbol *sym, PyObject *const_val) | 
					
						
							| 
									
										
										
										
											2024-02-28 09:55:56 -08:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2025-01-20 15:49:15 +00:00
										 |  |  |     JitSymType tag = sym->tag; | 
					
						
							|  |  |  |     switch(tag) { | 
					
						
							|  |  |  |         case JIT_SYM_NULL_TAG: | 
					
						
							| 
									
										
										
										
											2024-05-10 17:43:23 +01:00
										 |  |  |             sym_set_bottom(ctx, sym); | 
					
						
							| 
									
										
										
										
											2025-01-20 15:49:15 +00:00
										 |  |  |             return; | 
					
						
							|  |  |  |         case JIT_SYM_KNOWN_CLASS_TAG: | 
					
						
							|  |  |  |             if (sym->cls.type != Py_TYPE(const_val)) { | 
					
						
							|  |  |  |                 sym_set_bottom(ctx, sym); | 
					
						
							|  |  |  |                 return; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             make_const(sym, const_val); | 
					
						
							|  |  |  |             return; | 
					
						
							|  |  |  |         case JIT_SYM_KNOWN_VALUE_TAG: | 
					
						
							|  |  |  |             if (sym->value.value != const_val) { | 
					
						
							|  |  |  |                 Py_CLEAR(sym->value.value); | 
					
						
							|  |  |  |                 sym_set_bottom(ctx, sym); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             return; | 
					
						
							|  |  |  |         case JIT_SYM_TUPLE_TAG: | 
					
						
							|  |  |  |             sym_set_bottom(ctx, sym); | 
					
						
							|  |  |  |             return; | 
					
						
							|  |  |  |         case JIT_SYM_TYPE_VERSION_TAG: | 
					
						
							|  |  |  |             if (sym->version.version != Py_TYPE(const_val)->tp_version_tag) { | 
					
						
							|  |  |  |                 sym_set_bottom(ctx, sym); | 
					
						
							|  |  |  |                 return; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             make_const(sym, const_val); | 
					
						
							|  |  |  |             return; | 
					
						
							|  |  |  |         case JIT_SYM_BOTTOM_TAG: | 
					
						
							|  |  |  |             return; | 
					
						
							|  |  |  |         case JIT_SYM_NON_NULL_TAG: | 
					
						
							|  |  |  |         case JIT_SYM_UNKNOWN_TAG: | 
					
						
							|  |  |  |             make_const(sym, const_val); | 
					
						
							|  |  |  |             return; | 
					
						
							| 
									
										
										
										
											2024-02-29 10:55:29 -08:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2024-02-27 10:51:26 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-05-10 17:43:23 +01:00
										 |  |  | void | 
					
						
							| 
									
										
										
										
											2025-01-20 15:49:15 +00:00
										 |  |  | _Py_uop_sym_set_null(JitOptContext *ctx, JitOptSymbol *sym) | 
					
						
							| 
									
										
										
										
											2024-02-27 10:51:26 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2025-01-20 15:49:15 +00:00
										 |  |  |     if (sym->tag == JIT_SYM_UNKNOWN_TAG) { | 
					
						
							|  |  |  |         sym->tag = JIT_SYM_NULL_TAG; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     else if (sym->tag > JIT_SYM_NULL_TAG) { | 
					
						
							| 
									
										
										
										
											2024-05-10 17:43:23 +01:00
										 |  |  |         sym_set_bottom(ctx, sym); | 
					
						
							| 
									
										
										
										
											2024-05-02 16:17:59 +01:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2024-02-28 09:55:56 -08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-05-10 17:43:23 +01:00
										 |  |  | void | 
					
						
							| 
									
										
										
										
											2025-01-20 15:49:15 +00:00
										 |  |  | _Py_uop_sym_set_non_null(JitOptContext *ctx, JitOptSymbol *sym) | 
					
						
							| 
									
										
										
										
											2024-02-28 09:55:56 -08:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2025-01-20 15:49:15 +00:00
										 |  |  |     if (sym->tag == JIT_SYM_UNKNOWN_TAG) { | 
					
						
							|  |  |  |         sym->tag = JIT_SYM_NON_NULL_TAG; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     else if (sym->tag == JIT_SYM_NULL_TAG) { | 
					
						
							| 
									
										
										
										
											2024-05-10 17:43:23 +01:00
										 |  |  |         sym_set_bottom(ctx, sym); | 
					
						
							| 
									
										
										
										
											2024-05-02 16:17:59 +01:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2024-02-27 10:51:26 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-01-20 15:49:15 +00:00
										 |  |  | JitOptSymbol * | 
					
						
							|  |  |  | _Py_uop_sym_new_unknown(JitOptContext *ctx) | 
					
						
							| 
									
										
										
										
											2024-02-27 10:51:26 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2025-01-20 15:49:15 +00:00
										 |  |  |     JitOptSymbol *res = sym_new(ctx); | 
					
						
							|  |  |  |     if (res == NULL) { | 
					
						
							|  |  |  |         return out_of_space(ctx); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return res; | 
					
						
							| 
									
										
										
										
											2024-02-27 10:51:26 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-01-20 15:49:15 +00:00
										 |  |  | JitOptSymbol * | 
					
						
							|  |  |  | _Py_uop_sym_new_not_null(JitOptContext *ctx) | 
					
						
							| 
									
										
										
										
											2024-02-27 10:51:26 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2025-01-20 15:49:15 +00:00
										 |  |  |     JitOptSymbol *res = sym_new(ctx); | 
					
						
							| 
									
										
										
										
											2024-02-27 10:51:26 +00:00
										 |  |  |     if (res == NULL) { | 
					
						
							| 
									
										
										
										
											2024-05-10 17:43:23 +01:00
										 |  |  |         return out_of_space(ctx); | 
					
						
							| 
									
										
										
										
											2024-02-27 10:51:26 +00:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2025-01-20 15:49:15 +00:00
										 |  |  |     res->tag = JIT_SYM_NON_NULL_TAG; | 
					
						
							| 
									
										
										
										
											2024-02-27 10:51:26 +00:00
										 |  |  |     return res; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-01-20 15:49:15 +00:00
										 |  |  | JitOptSymbol * | 
					
						
							|  |  |  | _Py_uop_sym_new_type(JitOptContext *ctx, PyTypeObject *typ) | 
					
						
							| 
									
										
										
										
											2024-02-27 10:51:26 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2025-01-20 15:49:15 +00:00
										 |  |  |     JitOptSymbol *res = sym_new(ctx); | 
					
						
							| 
									
										
										
										
											2024-02-27 10:51:26 +00:00
										 |  |  |     if (res == NULL) { | 
					
						
							| 
									
										
										
										
											2024-05-10 17:43:23 +01:00
										 |  |  |         return out_of_space(ctx); | 
					
						
							| 
									
										
										
										
											2024-02-27 10:51:26 +00:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2024-05-10 17:43:23 +01:00
										 |  |  |     _Py_uop_sym_set_type(ctx, res, typ); | 
					
						
							| 
									
										
										
										
											2024-02-27 10:51:26 +00:00
										 |  |  |     return res; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-02-28 09:55:56 -08:00
										 |  |  | // Adds a new reference to const_val, owned by the symbol.
 | 
					
						
							| 
									
										
										
										
											2025-01-20 15:49:15 +00:00
										 |  |  | JitOptSymbol * | 
					
						
							|  |  |  | _Py_uop_sym_new_const(JitOptContext *ctx, PyObject *const_val) | 
					
						
							| 
									
										
										
										
											2024-02-27 10:51:26 +00:00
										 |  |  | { | 
					
						
							|  |  |  |     assert(const_val != NULL); | 
					
						
							| 
									
										
										
										
											2025-01-20 15:49:15 +00:00
										 |  |  |     JitOptSymbol *res = sym_new(ctx); | 
					
						
							| 
									
										
										
										
											2024-02-28 09:55:56 -08:00
										 |  |  |     if (res == NULL) { | 
					
						
							| 
									
										
										
										
											2024-05-10 17:43:23 +01:00
										 |  |  |         return out_of_space(ctx); | 
					
						
							| 
									
										
										
										
											2024-02-27 10:51:26 +00:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2024-05-10 17:43:23 +01:00
										 |  |  |     _Py_uop_sym_set_const(ctx, res, const_val); | 
					
						
							| 
									
										
										
										
											2024-02-28 09:55:56 -08:00
										 |  |  |     return res; | 
					
						
							| 
									
										
										
										
											2024-02-27 10:51:26 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-01-20 15:49:15 +00:00
										 |  |  | JitOptSymbol * | 
					
						
							|  |  |  | _Py_uop_sym_new_null(JitOptContext *ctx) | 
					
						
							| 
									
										
										
										
											2024-02-27 10:51:26 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2025-01-20 15:49:15 +00:00
										 |  |  |     JitOptSymbol *null_sym = sym_new(ctx); | 
					
						
							| 
									
										
										
										
											2024-02-27 10:51:26 +00:00
										 |  |  |     if (null_sym == NULL) { | 
					
						
							| 
									
										
										
										
											2024-05-10 17:43:23 +01:00
										 |  |  |         return out_of_space(ctx); | 
					
						
							| 
									
										
										
										
											2024-02-27 10:51:26 +00:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2024-05-10 17:43:23 +01:00
										 |  |  |     _Py_uop_sym_set_null(ctx, null_sym); | 
					
						
							| 
									
										
										
										
											2024-02-27 10:51:26 +00:00
										 |  |  |     return null_sym; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-04-22 13:34:06 +01:00
										 |  |  | PyTypeObject * | 
					
						
							| 
									
										
										
										
											2025-01-20 15:49:15 +00:00
										 |  |  | _Py_uop_sym_get_type(JitOptSymbol *sym) | 
					
						
							| 
									
										
										
										
											2024-04-22 13:34:06 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2025-01-20 15:49:15 +00:00
										 |  |  |     JitSymType tag = sym->tag; | 
					
						
							|  |  |  |     switch(tag) { | 
					
						
							|  |  |  |         case JIT_SYM_NULL_TAG: | 
					
						
							|  |  |  |         case JIT_SYM_TYPE_VERSION_TAG: | 
					
						
							|  |  |  |         case JIT_SYM_BOTTOM_TAG: | 
					
						
							|  |  |  |         case JIT_SYM_NON_NULL_TAG: | 
					
						
							|  |  |  |         case JIT_SYM_UNKNOWN_TAG: | 
					
						
							|  |  |  |             return NULL; | 
					
						
							|  |  |  |         case JIT_SYM_KNOWN_CLASS_TAG: | 
					
						
							|  |  |  |             return sym->cls.type; | 
					
						
							|  |  |  |         case JIT_SYM_KNOWN_VALUE_TAG: | 
					
						
							|  |  |  |             return Py_TYPE(sym->value.value); | 
					
						
							|  |  |  |         case JIT_SYM_TUPLE_TAG: | 
					
						
							|  |  |  |             return &PyTuple_Type; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     Py_UNREACHABLE(); | 
					
						
							| 
									
										
										
										
											2024-04-22 13:34:06 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-06-08 05:41:45 -04:00
										 |  |  | unsigned int | 
					
						
							| 
									
										
										
										
											2025-01-20 15:49:15 +00:00
										 |  |  | _Py_uop_sym_get_type_version(JitOptSymbol *sym) | 
					
						
							| 
									
										
										
										
											2024-06-08 05:41:45 -04:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2025-01-20 15:49:15 +00:00
										 |  |  |     JitSymType tag = sym->tag; | 
					
						
							|  |  |  |     switch(tag) { | 
					
						
							|  |  |  |         case JIT_SYM_NULL_TAG: | 
					
						
							|  |  |  |         case JIT_SYM_BOTTOM_TAG: | 
					
						
							|  |  |  |         case JIT_SYM_NON_NULL_TAG: | 
					
						
							|  |  |  |         case JIT_SYM_UNKNOWN_TAG: | 
					
						
							|  |  |  |             return 0; | 
					
						
							|  |  |  |         case JIT_SYM_TYPE_VERSION_TAG: | 
					
						
							|  |  |  |             return sym->version.version; | 
					
						
							|  |  |  |         case JIT_SYM_KNOWN_CLASS_TAG: | 
					
						
							|  |  |  |             return sym->cls.version; | 
					
						
							|  |  |  |         case JIT_SYM_KNOWN_VALUE_TAG: | 
					
						
							|  |  |  |             return Py_TYPE(sym->value.value)->tp_version_tag; | 
					
						
							|  |  |  |         case JIT_SYM_TUPLE_TAG: | 
					
						
							|  |  |  |             return PyTuple_Type.tp_version_tag; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     Py_UNREACHABLE(); | 
					
						
							| 
									
										
										
										
											2024-06-08 05:41:45 -04:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-03-05 15:06:00 +00:00
										 |  |  | bool | 
					
						
							| 
									
										
										
										
											2025-01-20 15:49:15 +00:00
										 |  |  | _Py_uop_sym_has_type(JitOptSymbol *sym) | 
					
						
							| 
									
										
										
										
											2024-03-05 15:06:00 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2025-01-20 15:49:15 +00:00
										 |  |  |     JitSymType tag = sym->tag; | 
					
						
							|  |  |  |     switch(tag) { | 
					
						
							|  |  |  |         case JIT_SYM_NULL_TAG: | 
					
						
							|  |  |  |         case JIT_SYM_TYPE_VERSION_TAG: | 
					
						
							|  |  |  |         case JIT_SYM_BOTTOM_TAG: | 
					
						
							|  |  |  |         case JIT_SYM_NON_NULL_TAG: | 
					
						
							|  |  |  |         case JIT_SYM_UNKNOWN_TAG: | 
					
						
							|  |  |  |             return false; | 
					
						
							|  |  |  |         case JIT_SYM_KNOWN_CLASS_TAG: | 
					
						
							|  |  |  |         case JIT_SYM_KNOWN_VALUE_TAG: | 
					
						
							|  |  |  |         case JIT_SYM_TUPLE_TAG: | 
					
						
							|  |  |  |             return true; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     Py_UNREACHABLE(); | 
					
						
							| 
									
										
										
										
											2024-03-05 15:06:00 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-02-27 10:51:26 +00:00
										 |  |  | bool | 
					
						
							| 
									
										
										
										
											2025-01-20 15:49:15 +00:00
										 |  |  | _Py_uop_sym_matches_type(JitOptSymbol *sym, PyTypeObject *typ) | 
					
						
							| 
									
										
										
										
											2024-02-27 10:51:26 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2024-02-28 09:55:56 -08:00
										 |  |  |     assert(typ != NULL && PyType_Check(typ)); | 
					
						
							| 
									
										
										
										
											2024-04-22 13:34:06 +01:00
										 |  |  |     return _Py_uop_sym_get_type(sym) == typ; | 
					
						
							| 
									
										
										
										
											2024-02-27 10:51:26 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-06-08 05:41:45 -04:00
										 |  |  | bool | 
					
						
							| 
									
										
										
										
											2025-01-20 15:49:15 +00:00
										 |  |  | _Py_uop_sym_matches_type_version(JitOptSymbol *sym, unsigned int version) | 
					
						
							| 
									
										
										
										
											2024-06-08 05:41:45 -04:00
										 |  |  | { | 
					
						
							|  |  |  |     return _Py_uop_sym_get_type_version(sym) == version; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-03-05 11:23:46 +00:00
										 |  |  | int | 
					
						
							| 
									
										
										
										
											2025-01-20 15:49:15 +00:00
										 |  |  | _Py_uop_sym_truthiness(JitOptSymbol *sym) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     switch(sym->tag) { | 
					
						
							|  |  |  |         case JIT_SYM_NULL_TAG: | 
					
						
							|  |  |  |         case JIT_SYM_TYPE_VERSION_TAG: | 
					
						
							|  |  |  |         case JIT_SYM_BOTTOM_TAG: | 
					
						
							|  |  |  |         case JIT_SYM_NON_NULL_TAG: | 
					
						
							|  |  |  |         case JIT_SYM_UNKNOWN_TAG: | 
					
						
							|  |  |  |             return -1; | 
					
						
							|  |  |  |         case JIT_SYM_KNOWN_CLASS_TAG: | 
					
						
							|  |  |  |             /* TODO :
 | 
					
						
							|  |  |  |              * Instances of some classes are always | 
					
						
							|  |  |  |              * true. We should return 1 in those cases */ | 
					
						
							|  |  |  |             return -1; | 
					
						
							|  |  |  |         case JIT_SYM_KNOWN_VALUE_TAG: | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |         case JIT_SYM_TUPLE_TAG: | 
					
						
							|  |  |  |             return sym->tuple.length != 0; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     PyObject *value = sym->value.value; | 
					
						
							|  |  |  |     /* Only handle a few known safe types */ | 
					
						
							| 
									
										
										
										
											2024-03-05 11:23:46 +00:00
										 |  |  |     if (value == Py_None) { | 
					
						
							|  |  |  |         return 0; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     PyTypeObject *tp = Py_TYPE(value); | 
					
						
							|  |  |  |     if (tp == &PyLong_Type) { | 
					
						
							|  |  |  |         return !_PyLong_IsZero((PyLongObject *)value); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if (tp == &PyUnicode_Type) { | 
					
						
							|  |  |  |         return value != &_Py_STR(empty); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if (tp == &PyBool_Type) { | 
					
						
							|  |  |  |         return value == Py_True; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return -1; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-01-20 15:49:15 +00:00
										 |  |  | static JitOptSymbol * | 
					
						
							|  |  |  | allocation_base(JitOptContext *ctx) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     return ctx->t_arena.arena; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | JitOptSymbol * | 
					
						
							|  |  |  | _Py_uop_sym_new_tuple(JitOptContext *ctx, int size, JitOptSymbol **args) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     JitOptSymbol *res = sym_new(ctx); | 
					
						
							|  |  |  |     if (res == NULL) { | 
					
						
							|  |  |  |         return out_of_space(ctx); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if (size > MAX_SYMBOLIC_TUPLE_SIZE) { | 
					
						
							|  |  |  |         res->tag = JIT_SYM_KNOWN_CLASS_TAG; | 
					
						
							|  |  |  |         res->cls.type = &PyTuple_Type; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     else { | 
					
						
							|  |  |  |         res->tag = JIT_SYM_TUPLE_TAG; | 
					
						
							|  |  |  |         res->tuple.length = size; | 
					
						
							|  |  |  |         for (int i = 0; i < size; i++) { | 
					
						
							|  |  |  |             res->tuple.items[i] = (uint16_t)(args[i] - allocation_base(ctx)); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return res; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | JitOptSymbol * | 
					
						
							|  |  |  | _Py_uop_sym_tuple_getitem(JitOptContext *ctx, JitOptSymbol *sym, int item) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     assert(item >= 0); | 
					
						
							|  |  |  |     if (sym->tag == JIT_SYM_KNOWN_VALUE_TAG) { | 
					
						
							|  |  |  |         PyObject *tuple = sym->value.value; | 
					
						
							|  |  |  |         if (PyTuple_CheckExact(tuple) && item < PyTuple_GET_SIZE(tuple)) { | 
					
						
							|  |  |  |             return _Py_uop_sym_new_const(ctx, PyTuple_GET_ITEM(tuple, item)); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     else if (sym->tag == JIT_SYM_TUPLE_TAG && item < sym->tuple.length) { | 
					
						
							|  |  |  |         return allocation_base(ctx) + sym->tuple.items[item]; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return _Py_uop_sym_new_unknown(ctx); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int | 
					
						
							|  |  |  | _Py_uop_sym_tuple_length(JitOptSymbol *sym) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (sym->tag == JIT_SYM_KNOWN_VALUE_TAG) { | 
					
						
							|  |  |  |         PyObject *tuple = sym->value.value; | 
					
						
							|  |  |  |         if (PyTuple_CheckExact(tuple)) { | 
					
						
							|  |  |  |             return PyTuple_GET_SIZE(tuple); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     else if (sym->tag == JIT_SYM_TUPLE_TAG) { | 
					
						
							|  |  |  |         return sym->tuple.length; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return -1; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Return true if known to be immortal.
 | 
					
						
							|  |  |  | bool | 
					
						
							|  |  |  | _Py_uop_sym_is_immortal(JitOptSymbol *sym) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (sym->tag == JIT_SYM_KNOWN_VALUE_TAG) { | 
					
						
							|  |  |  |         return _Py_IsImmortal(sym->value.value); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if (sym->tag == JIT_SYM_KNOWN_CLASS_TAG) { | 
					
						
							|  |  |  |         return sym->cls.type == &PyBool_Type; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return false; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-02-27 10:51:26 +00:00
										 |  |  | // 0 on success, -1 on error.
 | 
					
						
							|  |  |  | _Py_UOpsAbstractFrame * | 
					
						
							| 
									
										
										
										
											2024-02-27 13:25:02 +00:00
										 |  |  | _Py_uop_frame_new( | 
					
						
							| 
									
										
										
										
											2025-01-20 15:49:15 +00:00
										 |  |  |     JitOptContext *ctx, | 
					
						
							| 
									
										
										
										
											2024-02-27 10:51:26 +00:00
										 |  |  |     PyCodeObject *co, | 
					
						
							| 
									
										
										
										
											2024-06-08 05:41:45 -04:00
										 |  |  |     int curr_stackentries, | 
					
						
							| 
									
										
										
										
											2025-01-20 15:49:15 +00:00
										 |  |  |     JitOptSymbol **args, | 
					
						
							| 
									
										
										
										
											2024-06-08 05:41:45 -04:00
										 |  |  |     int arg_len) | 
					
						
							| 
									
										
										
										
											2024-02-27 10:51:26 +00:00
										 |  |  | { | 
					
						
							|  |  |  |     assert(ctx->curr_frame_depth < MAX_ABSTRACT_FRAME_DEPTH); | 
					
						
							|  |  |  |     _Py_UOpsAbstractFrame *frame = &ctx->frames[ctx->curr_frame_depth]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     frame->stack_len = co->co_stacksize; | 
					
						
							|  |  |  |     frame->locals_len = co->co_nlocalsplus; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-06-08 05:41:45 -04:00
										 |  |  |     frame->locals = ctx->n_consumed; | 
					
						
							| 
									
										
										
										
											2024-02-27 10:51:26 +00:00
										 |  |  |     frame->stack = frame->locals + co->co_nlocalsplus; | 
					
						
							|  |  |  |     frame->stack_pointer = frame->stack + curr_stackentries; | 
					
						
							| 
									
										
										
										
											2024-06-08 05:41:45 -04:00
										 |  |  |     ctx->n_consumed = ctx->n_consumed + (co->co_nlocalsplus + co->co_stacksize); | 
					
						
							| 
									
										
										
										
											2024-02-27 10:51:26 +00:00
										 |  |  |     if (ctx->n_consumed >= ctx->limit) { | 
					
						
							| 
									
										
										
										
											2024-05-10 17:43:23 +01:00
										 |  |  |         ctx->done = true; | 
					
						
							|  |  |  |         ctx->out_of_space = true; | 
					
						
							| 
									
										
										
										
											2024-02-27 10:51:26 +00:00
										 |  |  |         return NULL; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // Initialize with the initial state of all local variables
 | 
					
						
							| 
									
										
										
										
											2024-06-08 05:41:45 -04:00
										 |  |  |     for (int i = 0; i < arg_len; i++) { | 
					
						
							|  |  |  |         frame->locals[i] = args[i]; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     for (int i = arg_len; i < co->co_nlocalsplus; i++) { | 
					
						
							| 
									
										
										
										
											2025-01-20 15:49:15 +00:00
										 |  |  |         JitOptSymbol *local = _Py_uop_sym_new_unknown(ctx); | 
					
						
							| 
									
										
										
										
											2024-02-27 10:51:26 +00:00
										 |  |  |         frame->locals[i] = local; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // Initialize the stack as well
 | 
					
						
							|  |  |  |     for (int i = 0; i < curr_stackentries; i++) { | 
					
						
							| 
									
										
										
										
											2025-01-20 15:49:15 +00:00
										 |  |  |         JitOptSymbol *stackvar = _Py_uop_sym_new_unknown(ctx); | 
					
						
							| 
									
										
										
										
											2024-02-27 10:51:26 +00:00
										 |  |  |         frame->stack[i] = stackvar; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return frame; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void | 
					
						
							| 
									
										
										
										
											2025-01-20 15:49:15 +00:00
										 |  |  | _Py_uop_abstractcontext_fini(JitOptContext *ctx) | 
					
						
							| 
									
										
										
										
											2024-02-27 10:51:26 +00:00
										 |  |  | { | 
					
						
							|  |  |  |     if (ctx == NULL) { | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     ctx->curr_frame_depth = 0; | 
					
						
							|  |  |  |     int tys = ctx->t_arena.ty_curr_number; | 
					
						
							|  |  |  |     for (int i = 0; i < tys; i++) { | 
					
						
							| 
									
										
										
										
											2025-01-20 15:49:15 +00:00
										 |  |  |         JitOptSymbol *sym = &ctx->t_arena.arena[i]; | 
					
						
							|  |  |  |         if (sym->tag == JIT_SYM_KNOWN_VALUE_TAG) { | 
					
						
							|  |  |  |             Py_CLEAR(sym->value.value); | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2024-02-27 10:51:26 +00:00
										 |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-05-10 17:43:23 +01:00
										 |  |  | void | 
					
						
							| 
									
										
										
										
											2025-01-20 15:49:15 +00:00
										 |  |  | _Py_uop_abstractcontext_init(JitOptContext *ctx) | 
					
						
							| 
									
										
										
										
											2024-02-27 10:51:26 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2025-01-20 15:49:15 +00:00
										 |  |  |     static_assert(sizeof(JitOptSymbol) <= 2*sizeof(uint64_t)); | 
					
						
							| 
									
										
										
										
											2024-02-27 10:51:26 +00:00
										 |  |  |     ctx->limit = ctx->locals_and_stack + MAX_ABSTRACT_INTERP_SIZE; | 
					
						
							|  |  |  |     ctx->n_consumed = ctx->locals_and_stack; | 
					
						
							|  |  |  | #ifdef Py_DEBUG // Aids debugging a little. There should never be NULL in the abstract interpreter.
 | 
					
						
							|  |  |  |     for (int i = 0 ; i < MAX_ABSTRACT_INTERP_SIZE; i++) { | 
					
						
							|  |  |  |         ctx->locals_and_stack[i] = NULL; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // Setup the arena for sym expressions.
 | 
					
						
							|  |  |  |     ctx->t_arena.ty_curr_number = 0; | 
					
						
							|  |  |  |     ctx->t_arena.ty_max_number = TY_ARENA_SIZE; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // Frame setup
 | 
					
						
							|  |  |  |     ctx->curr_frame_depth = 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int | 
					
						
							| 
									
										
										
										
											2025-01-20 15:49:15 +00:00
										 |  |  | _Py_uop_frame_pop(JitOptContext *ctx) | 
					
						
							| 
									
										
										
										
											2024-02-27 10:51:26 +00:00
										 |  |  | { | 
					
						
							|  |  |  |     _Py_UOpsAbstractFrame *frame = ctx->frame; | 
					
						
							|  |  |  |     ctx->n_consumed = frame->locals; | 
					
						
							|  |  |  |     ctx->curr_frame_depth--; | 
					
						
							|  |  |  |     assert(ctx->curr_frame_depth >= 1); | 
					
						
							|  |  |  |     ctx->frame = &ctx->frames[ctx->curr_frame_depth - 1]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #define TEST_PREDICATE(PRED, MSG) \
 | 
					
						
							|  |  |  | do { \ | 
					
						
							|  |  |  |     if (!(PRED)) { \ | 
					
						
							|  |  |  |         PyErr_SetString( \ | 
					
						
							|  |  |  |             PyExc_AssertionError, \ | 
					
						
							|  |  |  |             (MSG)); \ | 
					
						
							|  |  |  |         goto fail; \ | 
					
						
							|  |  |  |     } \ | 
					
						
							|  |  |  | } while (0) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-01-20 15:49:15 +00:00
										 |  |  | static JitOptSymbol * | 
					
						
							|  |  |  | make_bottom(JitOptContext *ctx) | 
					
						
							| 
									
										
										
										
											2024-02-27 10:51:26 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2025-01-20 15:49:15 +00:00
										 |  |  |     JitOptSymbol *sym = sym_new(ctx); | 
					
						
							|  |  |  |     sym->tag = JIT_SYM_BOTTOM_TAG; | 
					
						
							| 
									
										
										
										
											2024-02-27 10:51:26 +00:00
										 |  |  |     return sym; | 
					
						
							| 
									
										
										
										
											2024-02-28 09:55:56 -08:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2024-02-27 10:51:26 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | PyObject * | 
					
						
							|  |  |  | _Py_uop_symbols_test(PyObject *Py_UNUSED(self), PyObject *Py_UNUSED(ignored)) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2025-01-20 15:49:15 +00:00
										 |  |  |     JitOptContext context; | 
					
						
							|  |  |  |     JitOptContext *ctx = &context; | 
					
						
							| 
									
										
										
										
											2024-02-27 10:51:26 +00:00
										 |  |  |     _Py_uop_abstractcontext_init(ctx); | 
					
						
							| 
									
										
										
										
											2024-02-28 09:55:56 -08:00
										 |  |  |     PyObject *val_42 = NULL; | 
					
						
							|  |  |  |     PyObject *val_43 = NULL; | 
					
						
							| 
									
										
										
										
											2024-02-27 10:51:26 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-02-28 09:55:56 -08:00
										 |  |  |     // Use a single 'sym' variable so copy-pasting tests is easier.
 | 
					
						
							| 
									
										
										
										
											2025-01-20 15:49:15 +00:00
										 |  |  |     JitOptSymbol *sym = _Py_uop_sym_new_unknown(ctx); | 
					
						
							| 
									
										
										
										
											2024-02-28 09:55:56 -08:00
										 |  |  |     if (sym == NULL) { | 
					
						
							|  |  |  |         goto fail; | 
					
						
							| 
									
										
										
										
											2024-02-27 10:51:26 +00:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2024-02-28 09:55:56 -08:00
										 |  |  |     TEST_PREDICATE(!_Py_uop_sym_is_null(sym), "top is NULL"); | 
					
						
							|  |  |  |     TEST_PREDICATE(!_Py_uop_sym_is_not_null(sym), "top is not NULL"); | 
					
						
							|  |  |  |     TEST_PREDICATE(!_Py_uop_sym_matches_type(sym, &PyLong_Type), "top matches a type"); | 
					
						
							|  |  |  |     TEST_PREDICATE(!_Py_uop_sym_is_const(sym), "top is a constant"); | 
					
						
							|  |  |  |     TEST_PREDICATE(_Py_uop_sym_get_const(sym) == NULL, "top as constant is not NULL"); | 
					
						
							|  |  |  |     TEST_PREDICATE(!_Py_uop_sym_is_bottom(sym), "top is bottom"); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     sym = make_bottom(ctx); | 
					
						
							|  |  |  |     if (sym == NULL) { | 
					
						
							|  |  |  |         goto fail; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     TEST_PREDICATE(!_Py_uop_sym_is_null(sym), "bottom is NULL is not false"); | 
					
						
							|  |  |  |     TEST_PREDICATE(!_Py_uop_sym_is_not_null(sym), "bottom is not NULL is not false"); | 
					
						
							|  |  |  |     TEST_PREDICATE(!_Py_uop_sym_matches_type(sym, &PyLong_Type), "bottom matches a type"); | 
					
						
							|  |  |  |     TEST_PREDICATE(!_Py_uop_sym_is_const(sym), "bottom is a constant is not false"); | 
					
						
							|  |  |  |     TEST_PREDICATE(_Py_uop_sym_get_const(sym) == NULL, "bottom as constant is not NULL"); | 
					
						
							|  |  |  |     TEST_PREDICATE(_Py_uop_sym_is_bottom(sym), "bottom isn't bottom"); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     sym = _Py_uop_sym_new_type(ctx, &PyLong_Type); | 
					
						
							|  |  |  |     if (sym == NULL) { | 
					
						
							|  |  |  |         goto fail; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     TEST_PREDICATE(!_Py_uop_sym_is_null(sym), "int is NULL"); | 
					
						
							|  |  |  |     TEST_PREDICATE(_Py_uop_sym_is_not_null(sym), "int isn't not NULL"); | 
					
						
							|  |  |  |     TEST_PREDICATE(_Py_uop_sym_matches_type(sym, &PyLong_Type), "int isn't int"); | 
					
						
							|  |  |  |     TEST_PREDICATE(!_Py_uop_sym_matches_type(sym, &PyFloat_Type), "int matches float"); | 
					
						
							|  |  |  |     TEST_PREDICATE(!_Py_uop_sym_is_const(sym), "int is a constant"); | 
					
						
							|  |  |  |     TEST_PREDICATE(_Py_uop_sym_get_const(sym) == NULL, "int as constant is not NULL"); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-05-10 17:43:23 +01:00
										 |  |  |     _Py_uop_sym_set_type(ctx, sym, &PyLong_Type);  // Should be a no-op
 | 
					
						
							| 
									
										
										
										
											2024-02-28 09:55:56 -08:00
										 |  |  |     TEST_PREDICATE(_Py_uop_sym_matches_type(sym, &PyLong_Type), "(int and int) isn't int"); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-05-10 17:43:23 +01:00
										 |  |  |     _Py_uop_sym_set_type(ctx, sym, &PyFloat_Type);  // Should make it bottom
 | 
					
						
							| 
									
										
										
										
											2024-02-28 09:55:56 -08:00
										 |  |  |     TEST_PREDICATE(_Py_uop_sym_is_bottom(sym), "(int and float) isn't bottom"); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     val_42 = PyLong_FromLong(42); | 
					
						
							|  |  |  |     assert(val_42 != NULL); | 
					
						
							|  |  |  |     assert(_Py_IsImmortal(val_42)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     val_43 = PyLong_FromLong(43); | 
					
						
							|  |  |  |     assert(val_43 != NULL); | 
					
						
							|  |  |  |     assert(_Py_IsImmortal(val_43)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     sym = _Py_uop_sym_new_type(ctx, &PyLong_Type); | 
					
						
							|  |  |  |     if (sym == NULL) { | 
					
						
							|  |  |  |         goto fail; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2024-05-10 17:43:23 +01:00
										 |  |  |     _Py_uop_sym_set_const(ctx, sym, val_42); | 
					
						
							| 
									
										
										
										
											2024-03-05 11:23:46 +00:00
										 |  |  |     TEST_PREDICATE(_Py_uop_sym_truthiness(sym) == 1, "bool(42) is not True"); | 
					
						
							| 
									
										
										
										
											2024-02-28 09:55:56 -08:00
										 |  |  |     TEST_PREDICATE(!_Py_uop_sym_is_null(sym), "42 is NULL"); | 
					
						
							|  |  |  |     TEST_PREDICATE(_Py_uop_sym_is_not_null(sym), "42 isn't not NULL"); | 
					
						
							|  |  |  |     TEST_PREDICATE(_Py_uop_sym_matches_type(sym, &PyLong_Type), "42 isn't an int"); | 
					
						
							|  |  |  |     TEST_PREDICATE(!_Py_uop_sym_matches_type(sym, &PyFloat_Type), "42 matches float"); | 
					
						
							|  |  |  |     TEST_PREDICATE(_Py_uop_sym_is_const(sym), "42 is not a constant"); | 
					
						
							|  |  |  |     TEST_PREDICATE(_Py_uop_sym_get_const(sym) != NULL, "42 as constant is NULL"); | 
					
						
							|  |  |  |     TEST_PREDICATE(_Py_uop_sym_get_const(sym) == val_42, "42 as constant isn't 42"); | 
					
						
							| 
									
										
										
										
											2025-01-20 15:49:15 +00:00
										 |  |  |     TEST_PREDICATE(_Py_uop_sym_is_immortal(sym), "42 is not immortal"); | 
					
						
							| 
									
										
										
										
											2024-02-28 09:55:56 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-05-10 17:43:23 +01:00
										 |  |  |     _Py_uop_sym_set_type(ctx, sym, &PyLong_Type);  // Should be a no-op
 | 
					
						
							| 
									
										
										
										
											2024-02-28 09:55:56 -08:00
										 |  |  |     TEST_PREDICATE(_Py_uop_sym_matches_type(sym, &PyLong_Type), "(42 and 42) isn't an int"); | 
					
						
							|  |  |  |     TEST_PREDICATE(_Py_uop_sym_get_const(sym) == val_42, "(42 and 42) as constant isn't 42"); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-05-10 17:43:23 +01:00
										 |  |  |     _Py_uop_sym_set_type(ctx, sym, &PyFloat_Type);  // Should make it bottom
 | 
					
						
							| 
									
										
										
										
											2024-02-28 09:55:56 -08:00
										 |  |  |     TEST_PREDICATE(_Py_uop_sym_is_bottom(sym), "(42 and float) isn't bottom"); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-01-20 15:49:15 +00:00
										 |  |  |     sym = _Py_uop_sym_new_type(ctx, &PyBool_Type); | 
					
						
							|  |  |  |     TEST_PREDICATE(_Py_uop_sym_is_immortal(sym), "a bool is not immortal"); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-02-28 09:55:56 -08:00
										 |  |  |     sym = _Py_uop_sym_new_type(ctx, &PyLong_Type); | 
					
						
							|  |  |  |     if (sym == NULL) { | 
					
						
							|  |  |  |         goto fail; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2024-05-10 17:43:23 +01:00
										 |  |  |     _Py_uop_sym_set_const(ctx, sym, val_42); | 
					
						
							|  |  |  |     _Py_uop_sym_set_const(ctx, sym, val_43);  // Should make it bottom
 | 
					
						
							| 
									
										
										
										
											2024-02-28 09:55:56 -08:00
										 |  |  |     TEST_PREDICATE(_Py_uop_sym_is_bottom(sym), "(42 and 43) isn't bottom"); | 
					
						
							| 
									
										
										
										
											2024-02-27 10:51:26 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-03-05 11:23:46 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     sym = _Py_uop_sym_new_const(ctx, Py_None); | 
					
						
							|  |  |  |     TEST_PREDICATE(_Py_uop_sym_truthiness(sym) == 0, "bool(None) is not False"); | 
					
						
							|  |  |  |     sym = _Py_uop_sym_new_const(ctx, Py_False); | 
					
						
							|  |  |  |     TEST_PREDICATE(_Py_uop_sym_truthiness(sym) == 0, "bool(False) is not False"); | 
					
						
							|  |  |  |     sym = _Py_uop_sym_new_const(ctx, PyLong_FromLong(0)); | 
					
						
							|  |  |  |     TEST_PREDICATE(_Py_uop_sym_truthiness(sym) == 0, "bool(0) is not False"); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-01-20 15:49:15 +00:00
										 |  |  |     JitOptSymbol *i1 = _Py_uop_sym_new_type(ctx, &PyFloat_Type); | 
					
						
							|  |  |  |     JitOptSymbol *i2 = _Py_uop_sym_new_const(ctx, val_43); | 
					
						
							|  |  |  |     JitOptSymbol *array[2] = { i1, i2 }; | 
					
						
							|  |  |  |     sym = _Py_uop_sym_new_tuple(ctx, 2, array); | 
					
						
							|  |  |  |     TEST_PREDICATE( | 
					
						
							|  |  |  |         _Py_uop_sym_matches_type(_Py_uop_sym_tuple_getitem(ctx, sym, 0), &PyFloat_Type), | 
					
						
							|  |  |  |         "tuple item does not match value used to create tuple" | 
					
						
							|  |  |  |     ); | 
					
						
							|  |  |  |     TEST_PREDICATE( | 
					
						
							|  |  |  |         _Py_uop_sym_get_const(_Py_uop_sym_tuple_getitem(ctx, sym, 1)) == val_43, | 
					
						
							|  |  |  |         "tuple item does not match value used to create tuple" | 
					
						
							|  |  |  |     ); | 
					
						
							|  |  |  |     PyObject *pair[2] = { val_42, val_43 }; | 
					
						
							|  |  |  |     PyObject *tuple = _PyTuple_FromArray(pair, 2); | 
					
						
							|  |  |  |     sym = _Py_uop_sym_new_const(ctx, tuple); | 
					
						
							|  |  |  |     TEST_PREDICATE( | 
					
						
							|  |  |  |         _Py_uop_sym_get_const(_Py_uop_sym_tuple_getitem(ctx, sym, 1)) == val_43, | 
					
						
							|  |  |  |         "tuple item does not match value used to create tuple" | 
					
						
							|  |  |  |     ); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-02-27 10:51:26 +00:00
										 |  |  |     _Py_uop_abstractcontext_fini(ctx); | 
					
						
							| 
									
										
										
										
											2024-02-28 09:55:56 -08:00
										 |  |  |     Py_DECREF(val_42); | 
					
						
							|  |  |  |     Py_DECREF(val_43); | 
					
						
							| 
									
										
										
										
											2025-01-20 15:49:15 +00:00
										 |  |  |     Py_DECREF(tuple); | 
					
						
							| 
									
										
										
										
											2024-02-27 10:51:26 +00:00
										 |  |  |     Py_RETURN_NONE; | 
					
						
							| 
									
										
										
										
											2024-02-28 09:55:56 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-02-27 10:51:26 +00:00
										 |  |  | fail: | 
					
						
							|  |  |  |     _Py_uop_abstractcontext_fini(ctx); | 
					
						
							| 
									
										
										
										
											2024-02-28 09:55:56 -08:00
										 |  |  |     Py_XDECREF(val_42); | 
					
						
							|  |  |  |     Py_XDECREF(val_43); | 
					
						
							| 
									
										
										
										
											2025-01-20 15:49:15 +00:00
										 |  |  |     Py_DECREF(tuple); | 
					
						
							| 
									
										
										
										
											2024-02-27 10:51:26 +00:00
										 |  |  |     return NULL; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2024-04-30 18:26:34 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | #endif /* _Py_TIER2 */
 |