| 
									
										
										
										
											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"
 | 
					
						
							| 
									
										
										
										
											2025-03-20 15:39:38 +00:00
										 |  |  | #include "pycore_stats.h"
 | 
					
						
							| 
									
										
										
										
											2025-03-17 14:41:05 +00:00
										 |  |  | #include "pycore_tuple.h"         // _PyTuple_FromArray()
 | 
					
						
							| 
									
										
										
										
											2024-02-27 10:51:26 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | #include <stdbool.h>
 | 
					
						
							|  |  |  | #include <stdint.h>
 | 
					
						
							|  |  |  | #include <stddef.h>
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-05-22 11:15:03 -04:00
										 |  |  | /*
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Symbols | 
					
						
							|  |  |  | ======= | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | https://github.com/faster-cpython/ideas/blob/main/3.13/redundancy_eliminator.md
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Logically, all symbols begin as UNKNOWN, and can transition downwards along the | 
					
						
							|  |  |  | edges of the lattice, but *never* upwards (see the diagram below). The UNKNOWN | 
					
						
							|  |  |  | state represents no information, and the BOTTOM state represents contradictory | 
					
						
							|  |  |  | information. Though symbols logically progress through all intermediate nodes, | 
					
						
							|  |  |  | we often skip in-between states for convenience: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |    UNKNOWN | 
					
						
							|  |  |  |    |     | | 
					
						
							|  |  |  | NULL     | | 
					
						
							|  |  |  | |        |                <- Anything below this level is an object. | 
					
						
							| 
									
										
										
										
											2025-06-19 11:10:29 +01:00
										 |  |  | |        NON_NULL-+ | 
					
						
							|  |  |  | |          |      |       <- Anything below this level has a known type version. | 
					
						
							|  |  |  | |    TYPE_VERSION | | 
					
						
							|  |  |  | |    |            |       <- Anything below this level has a known type. | 
					
						
							|  |  |  | |    KNOWN_CLASS  | | 
					
						
							|  |  |  | |    |  |  |   |  | | 
					
						
							|  |  |  | |    |  | INT* |  | | 
					
						
							|  |  |  | |    |  |  |   |  |       <- Anything below this level has a known truthiness. | 
					
						
							|  |  |  | |    |  |  |   |  TRUTHINESS | 
					
						
							|  |  |  | |    |  |  |   |  | | 
					
						
							|  |  |  | | TUPLE |  |   |  | | 
					
						
							|  |  |  | |    |  |  |   |  |       <- Anything below this level is a known constant. | 
					
						
							|  |  |  | |    KNOWN_VALUE--+ | 
					
						
							| 
									
										
										
										
											2025-05-22 11:15:03 -04:00
										 |  |  | |    |                    <- Anything below this level is unreachable. | 
					
						
							|  |  |  | BOTTOM | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | For example, after guarding that the type of an UNKNOWN local is int, we can | 
					
						
							|  |  |  | narrow the symbol to KNOWN_CLASS (logically progressing though NON_NULL and | 
					
						
							|  |  |  | TYPE_VERSION to get there). Later, we may learn that it is falsey based on the | 
					
						
							|  |  |  | result of a truth test, which would allow us to narrow the symbol to KNOWN_VALUE | 
					
						
							|  |  |  | (with a value of integer zero). If at any point we encounter a float guard on | 
					
						
							|  |  |  | the same symbol, that would be a contradiction, and the symbol would be set to | 
					
						
							|  |  |  | BOTTOM (indicating that the code is unreachable). | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-06-19 11:10:29 +01:00
										 |  |  | INT* is a limited range int, currently a "compact" int. | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-05-22 11:15:03 -04:00
										 |  |  | */ | 
					
						
							| 
									
										
										
										
											2024-02-28 09:55:56 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											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-03-02 13:21:34 -08:00
										 |  |  | static JitOptSymbol * | 
					
						
							|  |  |  | allocation_base(JitOptContext *ctx) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     return ctx->t_arena.arena; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											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-06-17 23:25:53 +08:00
										 |  |  | JitOptRef | 
					
						
							|  |  |  | out_of_space_ref(JitOptContext *ctx) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     return PyJitRef_Wrap(out_of_space(ctx)); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											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-06-17 23:25:53 +08:00
										 |  |  |     self->tag = JIT_SYM_UNKNOWN_TAG;; | 
					
						
							| 
									
										
										
										
											2024-02-27 10:51:26 +00:00
										 |  |  |     return self; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-03-02 13:21:34 -08:00
										 |  |  | static void make_const(JitOptSymbol *sym, PyObject *val) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     sym->tag = JIT_SYM_KNOWN_VALUE_TAG; | 
					
						
							|  |  |  |     sym->value.value = Py_NewRef(val); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-02-27 10:51:26 +00:00
										 |  |  | 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-06-17 23:25:53 +08:00
										 |  |  | _Py_uop_sym_is_bottom(JitOptRef ref) | 
					
						
							| 
									
										
										
										
											2024-02-27 10:51:26 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2025-06-17 23:25:53 +08:00
										 |  |  |     JitOptSymbol *sym = PyJitRef_Unwrap(ref); | 
					
						
							| 
									
										
										
										
											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-06-17 23:25:53 +08:00
										 |  |  | _Py_uop_sym_is_not_null(JitOptRef ref) { | 
					
						
							|  |  |  |     JitOptSymbol *sym = PyJitRef_Unwrap(ref); | 
					
						
							| 
									
										
										
										
											2025-01-20 15:49:15 +00:00
										 |  |  |     return sym->tag == JIT_SYM_NON_NULL_TAG || sym->tag > JIT_SYM_BOTTOM_TAG; | 
					
						
							| 
									
										
										
										
											2024-02-27 10:51:26 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | bool | 
					
						
							| 
									
										
										
										
											2025-06-17 23:25:53 +08:00
										 |  |  | _Py_uop_sym_is_const(JitOptContext *ctx, JitOptRef ref) | 
					
						
							| 
									
										
										
										
											2024-02-27 10:51:26 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2025-06-17 23:25:53 +08:00
										 |  |  |     JitOptSymbol *sym = PyJitRef_Unwrap(ref); | 
					
						
							| 
									
										
										
										
											2025-03-02 13:21:34 -08:00
										 |  |  |     if (sym->tag == JIT_SYM_KNOWN_VALUE_TAG) { | 
					
						
							|  |  |  |         return true; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if (sym->tag == JIT_SYM_TRUTHINESS_TAG) { | 
					
						
							|  |  |  |         JitOptSymbol *value = allocation_base(ctx) + sym->truthiness.value; | 
					
						
							| 
									
										
										
										
											2025-06-17 23:25:53 +08:00
										 |  |  |         int truthiness = _Py_uop_sym_truthiness(ctx, PyJitRef_Wrap(value)); | 
					
						
							| 
									
										
										
										
											2025-03-02 13:21:34 -08:00
										 |  |  |         if (truthiness < 0) { | 
					
						
							|  |  |  |             return false; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2025-03-21 00:59:41 +01:00
										 |  |  |         make_const(sym, (truthiness ^ sym->truthiness.invert) ? Py_True : Py_False); | 
					
						
							| 
									
										
										
										
											2025-03-02 13:21:34 -08:00
										 |  |  |         return true; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return false; | 
					
						
							| 
									
										
										
										
											2024-02-27 10:51:26 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | bool | 
					
						
							| 
									
										
										
										
											2025-06-17 23:25:53 +08:00
										 |  |  | _Py_uop_sym_is_null(JitOptRef ref) | 
					
						
							| 
									
										
										
										
											2024-02-27 10:51:26 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2025-06-17 23:25:53 +08:00
										 |  |  |     return PyJitRef_Unwrap(ref)->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-06-17 23:25:53 +08:00
										 |  |  | _Py_uop_sym_get_const(JitOptContext *ctx, JitOptRef ref) | 
					
						
							| 
									
										
										
										
											2024-02-27 10:51:26 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2025-06-17 23:25:53 +08:00
										 |  |  |     JitOptSymbol *sym = PyJitRef_Unwrap(ref); | 
					
						
							| 
									
										
										
										
											2025-01-20 15:49:15 +00:00
										 |  |  |     if (sym->tag == JIT_SYM_KNOWN_VALUE_TAG) { | 
					
						
							|  |  |  |         return sym->value.value; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2025-03-02 13:21:34 -08:00
										 |  |  |     if (sym->tag == JIT_SYM_TRUTHINESS_TAG) { | 
					
						
							|  |  |  |         JitOptSymbol *value = allocation_base(ctx) + sym->truthiness.value; | 
					
						
							| 
									
										
										
										
											2025-06-17 23:25:53 +08:00
										 |  |  |         int truthiness = _Py_uop_sym_truthiness(ctx, PyJitRef_Wrap(value)); | 
					
						
							| 
									
										
										
										
											2025-03-02 13:21:34 -08:00
										 |  |  |         if (truthiness < 0) { | 
					
						
							|  |  |  |             return NULL; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2025-03-21 00:59:41 +01:00
										 |  |  |         PyObject *res = (truthiness ^ sym->truthiness.invert) ? Py_True : Py_False; | 
					
						
							| 
									
										
										
										
											2025-03-02 13:21:34 -08:00
										 |  |  |         make_const(sym, res); | 
					
						
							|  |  |  |         return res; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2025-01-20 15:49:15 +00:00
										 |  |  |     return NULL; | 
					
						
							| 
									
										
										
										
											2024-02-27 10:51:26 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-06-27 19:37:44 +08:00
										 |  |  | _PyStackRef | 
					
						
							|  |  |  | _Py_uop_sym_get_const_as_stackref(JitOptContext *ctx, JitOptRef sym) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     PyObject *const_val = _Py_uop_sym_get_const(ctx, sym); | 
					
						
							|  |  |  |     if (const_val == NULL) { | 
					
						
							|  |  |  |         return PyStackRef_NULL; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return PyStackRef_FromPyObjectBorrow(const_val); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*
 | 
					
						
							|  |  |  |  Indicates whether the constant is safe to constant evaluate | 
					
						
							|  |  |  |  (without side effects). | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | bool | 
					
						
							|  |  |  | _Py_uop_sym_is_safe_const(JitOptContext *ctx, JitOptRef sym) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     PyObject *const_val = _Py_uop_sym_get_const(ctx, sym); | 
					
						
							|  |  |  |     if (const_val == NULL) { | 
					
						
							|  |  |  |         return false; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2025-06-28 00:18:44 +08:00
										 |  |  |     if (_PyLong_CheckExactAndCompact(const_val)) { | 
					
						
							|  |  |  |         return true; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2025-06-27 19:37:44 +08:00
										 |  |  |     PyTypeObject *typ = Py_TYPE(const_val); | 
					
						
							| 
									
										
										
										
											2025-06-28 00:18:44 +08:00
										 |  |  |     return (typ == &PyUnicode_Type) || | 
					
						
							| 
									
										
										
										
											2025-06-27 19:37:44 +08:00
										 |  |  |            (typ == &PyFloat_Type) || | 
					
						
							| 
									
										
										
										
											2025-06-28 18:30:30 +08:00
										 |  |  |            (typ == &_PyNone_Type) || | 
					
						
							| 
									
										
										
										
											2025-06-27 19:37:44 +08:00
										 |  |  |            (typ == &PyBool_Type); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-05-10 17:43:23 +01:00
										 |  |  | void | 
					
						
							| 
									
										
										
										
											2025-06-17 23:25:53 +08:00
										 |  |  | _Py_uop_sym_set_type(JitOptContext *ctx, JitOptRef ref, PyTypeObject *typ) | 
					
						
							| 
									
										
										
										
											2024-02-27 10:51:26 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2025-06-17 23:25:53 +08:00
										 |  |  |     JitOptSymbol *sym = PyJitRef_Unwrap(ref); | 
					
						
							| 
									
										
										
										
											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; | 
					
						
							| 
									
										
										
										
											2025-03-02 13:21:34 -08:00
										 |  |  |         case JIT_SYM_TRUTHINESS_TAG: | 
					
						
							|  |  |  |             if (typ != &PyBool_Type) { | 
					
						
							|  |  |  |                 sym_set_bottom(ctx, sym); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             return; | 
					
						
							| 
									
										
										
										
											2025-06-19 11:10:29 +01:00
										 |  |  |         case JIT_SYM_COMPACT_INT: | 
					
						
							|  |  |  |             if (typ != &PyLong_Type) { | 
					
						
							|  |  |  |                 sym_set_bottom(ctx, sym); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             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-06-17 23:25:53 +08:00
										 |  |  | _Py_uop_sym_set_type_version(JitOptContext *ctx, JitOptRef ref, unsigned int version) | 
					
						
							| 
									
										
										
										
											2024-06-08 05:41:45 -04:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2025-06-17 23:25:53 +08:00
										 |  |  |     JitOptSymbol *sym = PyJitRef_Unwrap(ref); | 
					
						
							| 
									
										
										
										
											2025-05-20 18:09:51 -04:00
										 |  |  |     PyTypeObject *type = _PyType_LookupByVersion(version); | 
					
						
							|  |  |  |     if (type) { | 
					
						
							| 
									
										
										
										
											2025-06-17 23:25:53 +08:00
										 |  |  |         _Py_uop_sym_set_type(ctx, ref, type); | 
					
						
							| 
									
										
										
										
											2025-05-20 18:09:51 -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: | 
					
						
							| 
									
										
										
										
											2025-05-20 18:09:51 -04:00
										 |  |  |             if (Py_TYPE(sym->value.value)->tp_version_tag != version) { | 
					
						
							|  |  |  |                 Py_CLEAR(sym->value.value); | 
					
						
							|  |  |  |                 sym_set_bottom(ctx, sym); | 
					
						
							|  |  |  |                 return false; | 
					
						
							|  |  |  |             }; | 
					
						
							|  |  |  |             return true; | 
					
						
							| 
									
										
										
										
											2025-01-20 15:49:15 +00:00
										 |  |  |         case JIT_SYM_TUPLE_TAG: | 
					
						
							| 
									
										
										
										
											2025-05-20 18:09:51 -04:00
										 |  |  |             if (PyTuple_Type.tp_version_tag != version) { | 
					
						
							|  |  |  |                 sym_set_bottom(ctx, sym); | 
					
						
							|  |  |  |                 return false; | 
					
						
							|  |  |  |             }; | 
					
						
							|  |  |  |             return true; | 
					
						
							| 
									
										
										
										
											2025-01-20 15:49:15 +00:00
										 |  |  |         case JIT_SYM_TYPE_VERSION_TAG: | 
					
						
							| 
									
										
										
										
											2025-05-20 18:09:51 -04:00
										 |  |  |             if (sym->version.version != version) { | 
					
						
							|  |  |  |                 sym_set_bottom(ctx, sym); | 
					
						
							|  |  |  |                 return false; | 
					
						
							| 
									
										
										
										
											2025-01-20 15:49:15 +00:00
										 |  |  |             } | 
					
						
							| 
									
										
										
										
											2025-05-20 18:09:51 -04:00
										 |  |  |             return true; | 
					
						
							| 
									
										
										
										
											2025-01-20 15:49:15 +00:00
										 |  |  |         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; | 
					
						
							| 
									
										
										
										
											2025-03-02 13:21:34 -08:00
										 |  |  |         case JIT_SYM_TRUTHINESS_TAG: | 
					
						
							|  |  |  |             if (version != PyBool_Type.tp_version_tag) { | 
					
						
							|  |  |  |                 sym_set_bottom(ctx, sym); | 
					
						
							|  |  |  |                 return false; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             return true; | 
					
						
							| 
									
										
										
										
											2025-06-19 11:10:29 +01:00
										 |  |  |         case JIT_SYM_COMPACT_INT: | 
					
						
							|  |  |  |             if (version != PyLong_Type.tp_version_tag) { | 
					
						
							|  |  |  |                 sym_set_bottom(ctx, sym); | 
					
						
							|  |  |  |                 return false; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             return true; | 
					
						
							| 
									
										
										
										
											2024-06-08 05:41:45 -04:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2025-01-20 15:49:15 +00:00
										 |  |  |     Py_UNREACHABLE(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-05-10 17:43:23 +01:00
										 |  |  | void | 
					
						
							| 
									
										
										
										
											2025-06-17 23:25:53 +08:00
										 |  |  | _Py_uop_sym_set_const(JitOptContext *ctx, JitOptRef ref, PyObject *const_val) | 
					
						
							| 
									
										
										
										
											2024-02-28 09:55:56 -08:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2025-06-17 23:25:53 +08:00
										 |  |  |     JitOptSymbol *sym = PyJitRef_Unwrap(ref); | 
					
						
							| 
									
										
										
										
											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: | 
					
						
							| 
									
										
										
										
											2025-05-20 18:09:51 -04:00
										 |  |  |             if (PyTuple_CheckExact(const_val)) { | 
					
						
							| 
									
										
										
										
											2025-06-17 23:25:53 +08:00
										 |  |  |                 Py_ssize_t len = _Py_uop_sym_tuple_length(ref); | 
					
						
							| 
									
										
										
										
											2025-05-20 18:09:51 -04:00
										 |  |  |                 if (len == PyTuple_GET_SIZE(const_val)) { | 
					
						
							|  |  |  |                     for (Py_ssize_t i = 0; i < len; i++) { | 
					
						
							| 
									
										
										
										
											2025-06-17 23:25:53 +08:00
										 |  |  |                         JitOptRef sym_item = _Py_uop_sym_tuple_getitem(ctx, ref, i); | 
					
						
							| 
									
										
										
										
											2025-05-20 18:09:51 -04:00
										 |  |  |                         PyObject *item = PyTuple_GET_ITEM(const_val, i); | 
					
						
							|  |  |  |                         _Py_uop_sym_set_const(ctx, sym_item, item); | 
					
						
							|  |  |  |                     } | 
					
						
							|  |  |  |                     make_const(sym, const_val); | 
					
						
							|  |  |  |                     return; | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |             } | 
					
						
							| 
									
										
										
										
											2025-01-20 15:49:15 +00:00
										 |  |  |             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; | 
					
						
							| 
									
										
										
										
											2025-03-02 13:21:34 -08:00
										 |  |  |         case JIT_SYM_TRUTHINESS_TAG: | 
					
						
							|  |  |  |             if (!PyBool_Check(const_val) || | 
					
						
							| 
									
										
										
										
											2025-06-17 23:25:53 +08:00
										 |  |  |                 (_Py_uop_sym_is_const(ctx, ref) && | 
					
						
							|  |  |  |                  _Py_uop_sym_get_const(ctx, ref) != const_val)) | 
					
						
							| 
									
										
										
										
											2025-03-02 13:21:34 -08:00
										 |  |  |             { | 
					
						
							|  |  |  |                 sym_set_bottom(ctx, sym); | 
					
						
							|  |  |  |                 return; | 
					
						
							|  |  |  |             } | 
					
						
							| 
									
										
										
										
											2025-06-17 23:25:53 +08:00
										 |  |  |             JitOptRef value = PyJitRef_Wrap( | 
					
						
							|  |  |  |                 allocation_base(ctx) + sym->truthiness.value); | 
					
						
							| 
									
										
										
										
											2025-03-02 13:21:34 -08:00
										 |  |  |             PyTypeObject *type = _Py_uop_sym_get_type(value); | 
					
						
							| 
									
										
										
										
											2025-03-21 00:59:41 +01:00
										 |  |  |             if (const_val == (sym->truthiness.invert ? Py_False : Py_True)) { | 
					
						
							| 
									
										
										
										
											2025-03-02 13:21:34 -08:00
										 |  |  |                 // value is truthy. This is only useful for bool:
 | 
					
						
							|  |  |  |                 if (type == &PyBool_Type) { | 
					
						
							|  |  |  |                     _Py_uop_sym_set_const(ctx, value, Py_True); | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             // value is falsey:
 | 
					
						
							|  |  |  |             else if (type == &PyBool_Type) { | 
					
						
							|  |  |  |                 _Py_uop_sym_set_const(ctx, value, Py_False); | 
					
						
							|  |  |  |             } | 
					
						
							| 
									
										
										
										
											2025-03-04 12:44:09 -08:00
										 |  |  |             else if (type == &PyLong_Type) { | 
					
						
							|  |  |  |                 _Py_uop_sym_set_const(ctx, value, Py_GetConstant(Py_CONSTANT_ZERO)); | 
					
						
							|  |  |  |             } | 
					
						
							| 
									
										
										
										
											2025-03-04 13:20:17 -08:00
										 |  |  |             else if (type == &PyUnicode_Type) { | 
					
						
							|  |  |  |                 _Py_uop_sym_set_const(ctx, value, Py_GetConstant(Py_CONSTANT_EMPTY_STR)); | 
					
						
							|  |  |  |             } | 
					
						
							| 
									
										
										
										
											2025-03-02 13:21:34 -08:00
										 |  |  |             // TODO: More types (GH-130415)!
 | 
					
						
							|  |  |  |             make_const(sym, const_val); | 
					
						
							|  |  |  |             return; | 
					
						
							| 
									
										
										
										
											2025-06-19 11:10:29 +01:00
										 |  |  |         case JIT_SYM_COMPACT_INT: | 
					
						
							| 
									
										
										
										
											2025-06-19 21:09:09 +08:00
										 |  |  |             if (_PyLong_CheckExactAndCompact(const_val)) { | 
					
						
							| 
									
										
										
										
											2025-06-19 11:10:29 +01:00
										 |  |  |                 make_const(sym, const_val); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             else { | 
					
						
							|  |  |  |                 sym_set_bottom(ctx, sym); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             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-06-17 23:25:53 +08:00
										 |  |  | _Py_uop_sym_set_null(JitOptContext *ctx, JitOptRef ref) | 
					
						
							| 
									
										
										
										
											2024-02-27 10:51:26 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2025-06-17 23:25:53 +08:00
										 |  |  |     JitOptSymbol *sym = PyJitRef_Unwrap(ref); | 
					
						
							| 
									
										
										
										
											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-06-17 23:25:53 +08:00
										 |  |  | _Py_uop_sym_set_non_null(JitOptContext *ctx, JitOptRef ref) | 
					
						
							| 
									
										
										
										
											2024-02-28 09:55:56 -08:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2025-06-17 23:25:53 +08:00
										 |  |  |     JitOptSymbol *sym = PyJitRef_Unwrap(ref); | 
					
						
							| 
									
										
										
										
											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-06-17 23:25:53 +08:00
										 |  |  | JitOptRef | 
					
						
							| 
									
										
										
										
											2025-01-20 15:49:15 +00:00
										 |  |  | _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) { | 
					
						
							| 
									
										
										
										
											2025-06-17 23:25:53 +08:00
										 |  |  |         return out_of_space_ref(ctx); | 
					
						
							| 
									
										
										
										
											2025-01-20 15:49:15 +00:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2025-06-17 23:25:53 +08:00
										 |  |  |     return PyJitRef_Wrap(res); | 
					
						
							| 
									
										
										
										
											2024-02-27 10:51:26 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-06-17 23:25:53 +08:00
										 |  |  | JitOptRef | 
					
						
							| 
									
										
										
										
											2025-01-20 15:49:15 +00:00
										 |  |  | _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) { | 
					
						
							| 
									
										
										
										
											2025-06-17 23:25:53 +08:00
										 |  |  |         return out_of_space_ref(ctx); | 
					
						
							| 
									
										
										
										
											2024-02-27 10:51:26 +00:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2025-01-20 15:49:15 +00:00
										 |  |  |     res->tag = JIT_SYM_NON_NULL_TAG; | 
					
						
							| 
									
										
										
										
											2025-06-17 23:25:53 +08:00
										 |  |  |     return PyJitRef_Wrap(res); | 
					
						
							| 
									
										
										
										
											2024-02-27 10:51:26 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-06-17 23:25:53 +08:00
										 |  |  | JitOptRef | 
					
						
							| 
									
										
										
										
											2025-01-20 15:49:15 +00:00
										 |  |  | _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) { | 
					
						
							| 
									
										
										
										
											2025-06-17 23:25:53 +08:00
										 |  |  |         return out_of_space_ref(ctx); | 
					
						
							| 
									
										
										
										
											2024-02-27 10:51:26 +00:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2025-06-17 23:25:53 +08:00
										 |  |  |     JitOptRef ref = PyJitRef_Wrap(res); | 
					
						
							|  |  |  |     _Py_uop_sym_set_type(ctx, ref, typ); | 
					
						
							|  |  |  |     return ref; | 
					
						
							| 
									
										
										
										
											2024-02-27 10:51:26 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-02-28 09:55:56 -08:00
										 |  |  | // Adds a new reference to const_val, owned by the symbol.
 | 
					
						
							| 
									
										
										
										
											2025-06-17 23:25:53 +08:00
										 |  |  | JitOptRef | 
					
						
							| 
									
										
										
										
											2025-01-20 15:49:15 +00:00
										 |  |  | _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) { | 
					
						
							| 
									
										
										
										
											2025-06-17 23:25:53 +08:00
										 |  |  |         return out_of_space_ref(ctx); | 
					
						
							| 
									
										
										
										
											2024-02-27 10:51:26 +00:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2025-06-17 23:25:53 +08:00
										 |  |  |     JitOptRef ref = PyJitRef_Wrap(res); | 
					
						
							|  |  |  |     _Py_uop_sym_set_const(ctx, ref, const_val); | 
					
						
							|  |  |  |     return ref; | 
					
						
							| 
									
										
										
										
											2024-02-27 10:51:26 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-06-27 19:37:44 +08:00
										 |  |  | JitOptRef | 
					
						
							|  |  |  | _Py_uop_sym_new_const_steal(JitOptContext *ctx, PyObject *const_val) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     assert(const_val != NULL); | 
					
						
							|  |  |  |     JitOptRef res = _Py_uop_sym_new_const(ctx, const_val); | 
					
						
							|  |  |  |     // Decref once because sym_new_const increfs it.
 | 
					
						
							|  |  |  |     Py_DECREF(const_val); | 
					
						
							|  |  |  |     return res; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-06-17 23:25:53 +08:00
										 |  |  | JitOptRef | 
					
						
							| 
									
										
										
										
											2025-01-20 15:49:15 +00:00
										 |  |  | _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) { | 
					
						
							| 
									
										
										
										
											2025-06-17 23:25:53 +08:00
										 |  |  |         return out_of_space_ref(ctx); | 
					
						
							| 
									
										
										
										
											2024-02-27 10:51:26 +00:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2025-06-17 23:25:53 +08:00
										 |  |  |     JitOptRef ref = PyJitRef_Wrap(null_sym); | 
					
						
							|  |  |  |     _Py_uop_sym_set_null(ctx, ref); | 
					
						
							|  |  |  |     return ref; | 
					
						
							| 
									
										
										
										
											2024-02-27 10:51:26 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-04-22 13:34:06 +01:00
										 |  |  | PyTypeObject * | 
					
						
							| 
									
										
										
										
											2025-06-17 23:25:53 +08:00
										 |  |  | _Py_uop_sym_get_type(JitOptRef ref) | 
					
						
							| 
									
										
										
										
											2024-04-22 13:34:06 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2025-06-17 23:25:53 +08:00
										 |  |  |     JitOptSymbol *sym = PyJitRef_Unwrap(ref); | 
					
						
							| 
									
										
										
										
											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 NULL; | 
					
						
							|  |  |  |         case JIT_SYM_KNOWN_CLASS_TAG: | 
					
						
							|  |  |  |             return sym->cls.type; | 
					
						
							|  |  |  |         case JIT_SYM_KNOWN_VALUE_TAG: | 
					
						
							|  |  |  |             return Py_TYPE(sym->value.value); | 
					
						
							| 
									
										
										
										
											2025-05-22 11:15:03 -04:00
										 |  |  |         case JIT_SYM_TYPE_VERSION_TAG: | 
					
						
							|  |  |  |             return _PyType_LookupByVersion(sym->version.version); | 
					
						
							| 
									
										
										
										
											2025-01-20 15:49:15 +00:00
										 |  |  |         case JIT_SYM_TUPLE_TAG: | 
					
						
							|  |  |  |             return &PyTuple_Type; | 
					
						
							| 
									
										
										
										
											2025-03-02 13:21:34 -08:00
										 |  |  |         case JIT_SYM_TRUTHINESS_TAG: | 
					
						
							|  |  |  |             return &PyBool_Type; | 
					
						
							| 
									
										
										
										
											2025-06-19 11:10:29 +01:00
										 |  |  |         case JIT_SYM_COMPACT_INT: | 
					
						
							|  |  |  |             return &PyLong_Type; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-01-20 15:49:15 +00:00
										 |  |  |     } | 
					
						
							|  |  |  |     Py_UNREACHABLE(); | 
					
						
							| 
									
										
										
										
											2024-04-22 13:34:06 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-06-08 05:41:45 -04:00
										 |  |  | unsigned int | 
					
						
							| 
									
										
										
										
											2025-06-17 23:25:53 +08:00
										 |  |  | _Py_uop_sym_get_type_version(JitOptRef ref) | 
					
						
							| 
									
										
										
										
											2024-06-08 05:41:45 -04:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2025-06-17 23:25:53 +08:00
										 |  |  |     JitOptSymbol *sym = PyJitRef_Unwrap(ref); | 
					
						
							| 
									
										
										
										
											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; | 
					
						
							| 
									
										
										
										
											2025-03-02 13:21:34 -08:00
										 |  |  |         case JIT_SYM_TRUTHINESS_TAG: | 
					
						
							|  |  |  |             return PyBool_Type.tp_version_tag; | 
					
						
							| 
									
										
										
										
											2025-06-19 11:10:29 +01:00
										 |  |  |         case JIT_SYM_COMPACT_INT: | 
					
						
							|  |  |  |             return PyLong_Type.tp_version_tag; | 
					
						
							| 
									
										
										
										
											2025-01-20 15:49:15 +00:00
										 |  |  |     } | 
					
						
							|  |  |  |     Py_UNREACHABLE(); | 
					
						
							| 
									
										
										
										
											2024-06-08 05:41:45 -04:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-03-05 15:06:00 +00:00
										 |  |  | bool | 
					
						
							| 
									
										
										
										
											2025-06-17 23:25:53 +08:00
										 |  |  | _Py_uop_sym_has_type(JitOptRef sym) | 
					
						
							| 
									
										
										
										
											2024-03-05 15:06:00 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2025-05-22 11:15:03 -04:00
										 |  |  |     return _Py_uop_sym_get_type(sym) != NULL; | 
					
						
							| 
									
										
										
										
											2024-03-05 15:06:00 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-02-27 10:51:26 +00:00
										 |  |  | bool | 
					
						
							| 
									
										
										
										
											2025-06-17 23:25:53 +08:00
										 |  |  | _Py_uop_sym_matches_type(JitOptRef 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-06-17 23:25:53 +08:00
										 |  |  | _Py_uop_sym_matches_type_version(JitOptRef 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-06-17 23:25:53 +08:00
										 |  |  | _Py_uop_sym_truthiness(JitOptContext *ctx, JitOptRef ref) | 
					
						
							| 
									
										
										
										
											2025-01-20 15:49:15 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2025-06-17 23:25:53 +08:00
										 |  |  |     JitOptSymbol *sym = PyJitRef_Unwrap(ref); | 
					
						
							| 
									
										
										
										
											2025-01-20 15:49:15 +00:00
										 |  |  |     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: | 
					
						
							| 
									
										
										
										
											2025-06-19 11:10:29 +01:00
										 |  |  |         case JIT_SYM_COMPACT_INT: | 
					
						
							| 
									
										
										
										
											2025-01-20 15:49:15 +00:00
										 |  |  |             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; | 
					
						
							| 
									
										
										
										
											2025-03-02 13:21:34 -08:00
										 |  |  |         case JIT_SYM_TRUTHINESS_TAG: | 
					
						
							|  |  |  |             ; | 
					
						
							|  |  |  |             JitOptSymbol *value = allocation_base(ctx) + sym->truthiness.value; | 
					
						
							| 
									
										
										
										
											2025-06-17 23:25:53 +08:00
										 |  |  |             int truthiness = _Py_uop_sym_truthiness(ctx, | 
					
						
							|  |  |  |                                                     PyJitRef_Wrap(value)); | 
					
						
							| 
									
										
										
										
											2025-03-02 13:21:34 -08:00
										 |  |  |             if (truthiness < 0) { | 
					
						
							|  |  |  |                 return truthiness; | 
					
						
							|  |  |  |             } | 
					
						
							| 
									
										
										
										
											2025-03-21 00:59:41 +01:00
										 |  |  |             truthiness ^= sym->truthiness.invert; | 
					
						
							| 
									
										
										
										
											2025-03-02 13:21:34 -08:00
										 |  |  |             make_const(sym, truthiness ? Py_True : Py_False); | 
					
						
							|  |  |  |             return truthiness; | 
					
						
							| 
									
										
										
										
											2025-01-20 15:49:15 +00:00
										 |  |  |     } | 
					
						
							|  |  |  |     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-06-17 23:25:53 +08:00
										 |  |  | JitOptRef | 
					
						
							|  |  |  | _Py_uop_sym_new_tuple(JitOptContext *ctx, int size, JitOptRef *args) | 
					
						
							| 
									
										
										
										
											2025-01-20 15:49:15 +00:00
										 |  |  | { | 
					
						
							|  |  |  |     JitOptSymbol *res = sym_new(ctx); | 
					
						
							|  |  |  |     if (res == NULL) { | 
					
						
							| 
									
										
										
										
											2025-06-17 23:25:53 +08:00
										 |  |  |         return out_of_space_ref(ctx); | 
					
						
							| 
									
										
										
										
											2025-01-20 15:49:15 +00:00
										 |  |  |     } | 
					
						
							|  |  |  |     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++) { | 
					
						
							| 
									
										
										
										
											2025-06-17 23:25:53 +08:00
										 |  |  |             res->tuple.items[i] = (uint16_t)(PyJitRef_Unwrap(args[i]) - allocation_base(ctx)); | 
					
						
							| 
									
										
										
										
											2025-01-20 15:49:15 +00:00
										 |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2025-06-17 23:25:53 +08:00
										 |  |  |     return PyJitRef_Wrap(res); | 
					
						
							| 
									
										
										
										
											2025-01-20 15:49:15 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-06-17 23:25:53 +08:00
										 |  |  | JitOptRef | 
					
						
							|  |  |  | _Py_uop_sym_tuple_getitem(JitOptContext *ctx, JitOptRef ref, int item) | 
					
						
							| 
									
										
										
										
											2025-01-20 15:49:15 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2025-06-17 23:25:53 +08:00
										 |  |  |     JitOptSymbol *sym = PyJitRef_Unwrap(ref); | 
					
						
							| 
									
										
										
										
											2025-01-20 15:49:15 +00:00
										 |  |  |     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) { | 
					
						
							| 
									
										
										
										
											2025-06-17 23:25:53 +08:00
										 |  |  |         return PyJitRef_Wrap(allocation_base(ctx) + sym->tuple.items[item]); | 
					
						
							| 
									
										
										
										
											2025-01-20 15:49:15 +00:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2025-05-22 11:15:03 -04:00
										 |  |  |     return _Py_uop_sym_new_not_null(ctx); | 
					
						
							| 
									
										
										
										
											2025-01-20 15:49:15 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int | 
					
						
							| 
									
										
										
										
											2025-06-17 23:25:53 +08:00
										 |  |  | _Py_uop_sym_tuple_length(JitOptRef ref) | 
					
						
							| 
									
										
										
										
											2025-01-20 15:49:15 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2025-06-17 23:25:53 +08:00
										 |  |  |     JitOptSymbol *sym = PyJitRef_Unwrap(ref); | 
					
						
							| 
									
										
										
										
											2025-01-20 15:49:15 +00:00
										 |  |  |     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 | 
					
						
							| 
									
										
										
										
											2025-06-17 23:25:53 +08:00
										 |  |  | _Py_uop_symbol_is_immortal(JitOptSymbol *sym) | 
					
						
							| 
									
										
										
										
											2025-01-20 15:49:15 +00:00
										 |  |  | { | 
					
						
							|  |  |  |     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; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-06-19 11:10:29 +01:00
										 |  |  | bool | 
					
						
							|  |  |  | _Py_uop_sym_is_compact_int(JitOptRef ref) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     JitOptSymbol *sym = PyJitRef_Unwrap(ref); | 
					
						
							|  |  |  |     if (sym->tag == JIT_SYM_KNOWN_VALUE_TAG) { | 
					
						
							| 
									
										
										
										
											2025-06-19 21:09:09 +08:00
										 |  |  |         return (bool)_PyLong_CheckExactAndCompact(sym->value.value); | 
					
						
							| 
									
										
										
										
											2025-06-19 11:10:29 +01:00
										 |  |  |     } | 
					
						
							|  |  |  |     return sym->tag == JIT_SYM_COMPACT_INT; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-06-17 23:25:53 +08:00
										 |  |  | bool | 
					
						
							|  |  |  | _Py_uop_sym_is_immortal(JitOptRef ref) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     JitOptSymbol *sym = PyJitRef_Unwrap(ref); | 
					
						
							|  |  |  |     return _Py_uop_symbol_is_immortal(sym); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-06-19 11:10:29 +01:00
										 |  |  | void | 
					
						
							|  |  |  | _Py_uop_sym_set_compact_int(JitOptContext *ctx, JitOptRef ref) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     JitOptSymbol *sym = PyJitRef_Unwrap(ref); | 
					
						
							|  |  |  |     JitSymType tag = sym->tag; | 
					
						
							|  |  |  |     switch(tag) { | 
					
						
							|  |  |  |         case JIT_SYM_NULL_TAG: | 
					
						
							|  |  |  |             sym_set_bottom(ctx, sym); | 
					
						
							|  |  |  |             return; | 
					
						
							|  |  |  |         case JIT_SYM_KNOWN_CLASS_TAG: | 
					
						
							|  |  |  |             if (sym->cls.type == &PyLong_Type) { | 
					
						
							|  |  |  |                 sym->tag = JIT_SYM_COMPACT_INT; | 
					
						
							|  |  |  |             } else { | 
					
						
							|  |  |  |                 sym_set_bottom(ctx, sym); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             return; | 
					
						
							|  |  |  |         case JIT_SYM_TYPE_VERSION_TAG: | 
					
						
							|  |  |  |             if (sym->version.version == PyLong_Type.tp_version_tag) { | 
					
						
							|  |  |  |                 sym->tag = JIT_SYM_COMPACT_INT; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             else { | 
					
						
							|  |  |  |                 sym_set_bottom(ctx, sym); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             return; | 
					
						
							|  |  |  |         case JIT_SYM_KNOWN_VALUE_TAG: | 
					
						
							| 
									
										
										
										
											2025-06-19 21:09:09 +08:00
										 |  |  |             if (!_PyLong_CheckExactAndCompact(sym->value.value)) { | 
					
						
							| 
									
										
										
										
											2025-06-19 11:10:29 +01:00
										 |  |  |                 Py_CLEAR(sym->value.value); | 
					
						
							|  |  |  |                 sym_set_bottom(ctx, sym); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             return; | 
					
						
							|  |  |  |         case JIT_SYM_TUPLE_TAG: | 
					
						
							|  |  |  |         case JIT_SYM_TRUTHINESS_TAG: | 
					
						
							|  |  |  |             sym_set_bottom(ctx, sym); | 
					
						
							|  |  |  |             return; | 
					
						
							|  |  |  |         case JIT_SYM_BOTTOM_TAG: | 
					
						
							|  |  |  |         case JIT_SYM_COMPACT_INT: | 
					
						
							|  |  |  |             return; | 
					
						
							|  |  |  |         case JIT_SYM_NON_NULL_TAG: | 
					
						
							|  |  |  |         case JIT_SYM_UNKNOWN_TAG: | 
					
						
							|  |  |  |             sym->tag = JIT_SYM_COMPACT_INT; | 
					
						
							|  |  |  |             return; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-06-17 23:25:53 +08:00
										 |  |  | JitOptRef | 
					
						
							|  |  |  | _Py_uop_sym_new_truthiness(JitOptContext *ctx, JitOptRef ref, bool truthy) | 
					
						
							| 
									
										
										
										
											2025-03-02 13:21:34 -08:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2025-06-17 23:25:53 +08:00
										 |  |  |     JitOptSymbol *value = PyJitRef_Unwrap(ref); | 
					
						
							| 
									
										
										
										
											2025-03-02 13:21:34 -08:00
										 |  |  |     // It's clearer to invert this in the signature:
 | 
					
						
							| 
									
										
										
										
											2025-03-21 00:59:41 +01:00
										 |  |  |     bool invert = !truthy; | 
					
						
							|  |  |  |     if (value->tag == JIT_SYM_TRUTHINESS_TAG && value->truthiness.invert == invert) { | 
					
						
							| 
									
										
										
										
											2025-06-17 23:25:53 +08:00
										 |  |  |         return ref; | 
					
						
							| 
									
										
										
										
											2025-03-02 13:21:34 -08:00
										 |  |  |     } | 
					
						
							|  |  |  |     JitOptSymbol *res = sym_new(ctx); | 
					
						
							|  |  |  |     if (res == NULL) { | 
					
						
							| 
									
										
										
										
											2025-06-17 23:25:53 +08:00
										 |  |  |         return out_of_space_ref(ctx); | 
					
						
							| 
									
										
										
										
											2025-03-02 13:21:34 -08:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2025-06-17 23:25:53 +08:00
										 |  |  |     int truthiness = _Py_uop_sym_truthiness(ctx, ref); | 
					
						
							| 
									
										
										
										
											2025-03-02 13:21:34 -08:00
										 |  |  |     if (truthiness < 0) { | 
					
						
							|  |  |  |         res->tag = JIT_SYM_TRUTHINESS_TAG; | 
					
						
							| 
									
										
										
										
											2025-03-21 00:59:41 +01:00
										 |  |  |         res->truthiness.invert = invert; | 
					
						
							| 
									
										
										
										
											2025-03-02 13:21:34 -08:00
										 |  |  |         res->truthiness.value = (uint16_t)(value - allocation_base(ctx)); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     else { | 
					
						
							| 
									
										
										
										
											2025-03-21 00:59:41 +01:00
										 |  |  |         make_const(res, (truthiness ^ invert) ? Py_True : Py_False); | 
					
						
							| 
									
										
										
										
											2025-03-02 13:21:34 -08:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2025-06-17 23:25:53 +08:00
										 |  |  |     return PyJitRef_Wrap(res); | 
					
						
							| 
									
										
										
										
											2025-03-02 13:21:34 -08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-06-19 11:10:29 +01:00
										 |  |  | JitOptRef | 
					
						
							|  |  |  | _Py_uop_sym_new_compact_int(JitOptContext *ctx) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     JitOptSymbol *sym = sym_new(ctx); | 
					
						
							|  |  |  |     if (sym == NULL) { | 
					
						
							|  |  |  |         return out_of_space_ref(ctx); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     sym->tag = JIT_SYM_COMPACT_INT; | 
					
						
							|  |  |  |     return PyJitRef_Wrap(sym); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											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-06-17 23:25:53 +08:00
										 |  |  |     JitOptRef *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-06-17 23:25:53 +08:00
										 |  |  |         JitOptRef 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-06-17 23:25:53 +08:00
										 |  |  |         JitOptRef 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-06-17 23:25:53 +08:00
										 |  |  |     static_assert(sizeof(JitOptSymbol) <= 3 * sizeof(uint64_t), "JitOptSymbol has grown"); | 
					
						
							| 
									
										
										
										
											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++) { | 
					
						
							| 
									
										
										
										
											2025-06-17 23:25:53 +08:00
										 |  |  |         ctx->locals_and_stack[i] = PyJitRef_NULL; | 
					
						
							| 
									
										
										
										
											2024-02-27 10:51:26 +00:00
										 |  |  |     } | 
					
						
							|  |  |  | #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; | 
					
						
							| 
									
										
										
										
											2025-06-19 11:10:29 +01:00
										 |  |  |     PyObject *val_big = NULL; | 
					
						
							| 
									
										
										
										
											2025-03-02 13:21:34 -08:00
										 |  |  |     PyObject *tuple = 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-06-17 23:25:53 +08:00
										 |  |  |     JitOptRef ref = _Py_uop_sym_new_unknown(ctx); | 
					
						
							|  |  |  |     if (PyJitRef_IsNull(ref)) { | 
					
						
							| 
									
										
										
										
											2024-02-28 09:55:56 -08:00
										 |  |  |         goto fail; | 
					
						
							| 
									
										
										
										
											2024-02-27 10:51:26 +00:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2025-06-17 23:25:53 +08:00
										 |  |  |     TEST_PREDICATE(!_Py_uop_sym_is_null(ref), "top is NULL"); | 
					
						
							|  |  |  |     TEST_PREDICATE(!_Py_uop_sym_is_not_null(ref), "top is not NULL"); | 
					
						
							|  |  |  |     TEST_PREDICATE(!_Py_uop_sym_matches_type(ref, &PyLong_Type), "top matches a type"); | 
					
						
							|  |  |  |     TEST_PREDICATE(!_Py_uop_sym_is_const(ctx, ref), "top is a constant"); | 
					
						
							|  |  |  |     TEST_PREDICATE(_Py_uop_sym_get_const(ctx, ref) == NULL, "top as constant is not NULL"); | 
					
						
							|  |  |  |     TEST_PREDICATE(!_Py_uop_sym_is_bottom(ref), "top is bottom"); | 
					
						
							| 
									
										
										
										
											2024-02-28 09:55:56 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-06-17 23:25:53 +08:00
										 |  |  |     ref = PyJitRef_Wrap(make_bottom(ctx)); | 
					
						
							|  |  |  |     if (PyJitRef_IsNull(ref)) { | 
					
						
							| 
									
										
										
										
											2024-02-28 09:55:56 -08:00
										 |  |  |         goto fail; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2025-06-17 23:25:53 +08:00
										 |  |  |     TEST_PREDICATE(!_Py_uop_sym_is_null(ref), "bottom is NULL is not false"); | 
					
						
							|  |  |  |     TEST_PREDICATE(!_Py_uop_sym_is_not_null(ref), "bottom is not NULL is not false"); | 
					
						
							|  |  |  |     TEST_PREDICATE(!_Py_uop_sym_matches_type(ref, &PyLong_Type), "bottom matches a type"); | 
					
						
							|  |  |  |     TEST_PREDICATE(!_Py_uop_sym_is_const(ctx, ref), "bottom is a constant is not false"); | 
					
						
							|  |  |  |     TEST_PREDICATE(_Py_uop_sym_get_const(ctx, ref) == NULL, "bottom as constant is not NULL"); | 
					
						
							|  |  |  |     TEST_PREDICATE(_Py_uop_sym_is_bottom(ref), "bottom isn't bottom"); | 
					
						
							| 
									
										
										
										
											2024-02-28 09:55:56 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-06-17 23:25:53 +08:00
										 |  |  |     ref = _Py_uop_sym_new_type(ctx, &PyLong_Type); | 
					
						
							|  |  |  |     if (PyJitRef_IsNull(ref)) { | 
					
						
							| 
									
										
										
										
											2024-02-28 09:55:56 -08:00
										 |  |  |         goto fail; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2025-06-17 23:25:53 +08:00
										 |  |  |     TEST_PREDICATE(!_Py_uop_sym_is_null(ref), "int is NULL"); | 
					
						
							|  |  |  |     TEST_PREDICATE(_Py_uop_sym_is_not_null(ref), "int isn't not NULL"); | 
					
						
							|  |  |  |     TEST_PREDICATE(_Py_uop_sym_matches_type(ref, &PyLong_Type), "int isn't int"); | 
					
						
							|  |  |  |     TEST_PREDICATE(!_Py_uop_sym_matches_type(ref, &PyFloat_Type), "int matches float"); | 
					
						
							|  |  |  |     TEST_PREDICATE(!_Py_uop_sym_is_const(ctx, ref), "int is a constant"); | 
					
						
							|  |  |  |     TEST_PREDICATE(_Py_uop_sym_get_const(ctx, ref) == NULL, "int as constant is not NULL"); | 
					
						
							| 
									
										
										
										
											2024-02-28 09:55:56 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-06-17 23:25:53 +08:00
										 |  |  |     _Py_uop_sym_set_type(ctx, ref, &PyLong_Type);  // Should be a no-op
 | 
					
						
							|  |  |  |     TEST_PREDICATE(_Py_uop_sym_matches_type(ref, &PyLong_Type), "(int and int) isn't int"); | 
					
						
							| 
									
										
										
										
											2024-02-28 09:55:56 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-06-17 23:25:53 +08:00
										 |  |  |     _Py_uop_sym_set_type(ctx, ref, &PyFloat_Type);  // Should make it bottom
 | 
					
						
							|  |  |  |     TEST_PREDICATE(_Py_uop_sym_is_bottom(ref), "(int and float) isn't bottom"); | 
					
						
							| 
									
										
										
										
											2024-02-28 09:55:56 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     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)); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-06-17 23:25:53 +08:00
										 |  |  |     ref = _Py_uop_sym_new_type(ctx, &PyLong_Type); | 
					
						
							|  |  |  |     if (PyJitRef_IsNull(ref)) { | 
					
						
							| 
									
										
										
										
											2024-02-28 09:55:56 -08:00
										 |  |  |         goto fail; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2025-06-17 23:25:53 +08:00
										 |  |  |     _Py_uop_sym_set_const(ctx, ref, val_42); | 
					
						
							|  |  |  |     TEST_PREDICATE(_Py_uop_sym_truthiness(ctx, ref) == 1, "bool(42) is not True"); | 
					
						
							|  |  |  |     TEST_PREDICATE(!_Py_uop_sym_is_null(ref), "42 is NULL"); | 
					
						
							|  |  |  |     TEST_PREDICATE(_Py_uop_sym_is_not_null(ref), "42 isn't not NULL"); | 
					
						
							|  |  |  |     TEST_PREDICATE(_Py_uop_sym_matches_type(ref, &PyLong_Type), "42 isn't an int"); | 
					
						
							|  |  |  |     TEST_PREDICATE(!_Py_uop_sym_matches_type(ref, &PyFloat_Type), "42 matches float"); | 
					
						
							|  |  |  |     TEST_PREDICATE(_Py_uop_sym_is_const(ctx, ref), "42 is not a constant"); | 
					
						
							|  |  |  |     TEST_PREDICATE(_Py_uop_sym_get_const(ctx, ref) != NULL, "42 as constant is NULL"); | 
					
						
							|  |  |  |     TEST_PREDICATE(_Py_uop_sym_get_const(ctx, ref) == val_42, "42 as constant isn't 42"); | 
					
						
							|  |  |  |     TEST_PREDICATE(_Py_uop_sym_is_immortal(ref), "42 is not immortal"); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     _Py_uop_sym_set_type(ctx, ref, &PyLong_Type);  // Should be a no-op
 | 
					
						
							|  |  |  |     TEST_PREDICATE(_Py_uop_sym_matches_type(ref, &PyLong_Type), "(42 and 42) isn't an int"); | 
					
						
							|  |  |  |     TEST_PREDICATE(_Py_uop_sym_get_const(ctx, ref) == val_42, "(42 and 42) as constant isn't 42"); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     _Py_uop_sym_set_type(ctx, ref, &PyFloat_Type);  // Should make it bottom
 | 
					
						
							|  |  |  |     TEST_PREDICATE(_Py_uop_sym_is_bottom(ref), "(42 and float) isn't bottom"); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     ref = _Py_uop_sym_new_type(ctx, &PyBool_Type); | 
					
						
							|  |  |  |     TEST_PREDICATE(_Py_uop_sym_is_immortal(ref), "a bool is not immortal"); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     ref = _Py_uop_sym_new_type(ctx, &PyLong_Type); | 
					
						
							|  |  |  |     if (PyJitRef_IsNull(ref)) { | 
					
						
							| 
									
										
										
										
											2024-02-28 09:55:56 -08:00
										 |  |  |         goto fail; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2025-06-17 23:25:53 +08:00
										 |  |  |     _Py_uop_sym_set_const(ctx, ref, val_42); | 
					
						
							|  |  |  |     _Py_uop_sym_set_const(ctx, ref, val_43);  // Should make it bottom
 | 
					
						
							|  |  |  |     TEST_PREDICATE(_Py_uop_sym_is_bottom(ref), "(42 and 43) isn't bottom"); | 
					
						
							| 
									
										
										
										
											2024-02-27 10:51:26 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-03-05 11:23:46 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-06-17 23:25:53 +08:00
										 |  |  |     ref = _Py_uop_sym_new_const(ctx, Py_None); | 
					
						
							|  |  |  |     TEST_PREDICATE(_Py_uop_sym_truthiness(ctx, ref) == 0, "bool(None) is not False"); | 
					
						
							|  |  |  |     ref = _Py_uop_sym_new_const(ctx, Py_False); | 
					
						
							|  |  |  |     TEST_PREDICATE(_Py_uop_sym_truthiness(ctx, ref) == 0, "bool(False) is not False"); | 
					
						
							|  |  |  |     ref = _Py_uop_sym_new_const(ctx, PyLong_FromLong(0)); | 
					
						
							|  |  |  |     TEST_PREDICATE(_Py_uop_sym_truthiness(ctx, ref) == 0, "bool(0) is not False"); | 
					
						
							| 
									
										
										
										
											2024-03-05 11:23:46 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-06-17 23:25:53 +08:00
										 |  |  |     JitOptRef i1 = _Py_uop_sym_new_type(ctx, &PyFloat_Type); | 
					
						
							|  |  |  |     JitOptRef i2 = _Py_uop_sym_new_const(ctx, val_43); | 
					
						
							|  |  |  |     JitOptRef array[2] = { i1, i2 }; | 
					
						
							|  |  |  |     ref = _Py_uop_sym_new_tuple(ctx, 2, array); | 
					
						
							| 
									
										
										
										
											2025-01-20 15:49:15 +00:00
										 |  |  |     TEST_PREDICATE( | 
					
						
							| 
									
										
										
										
											2025-06-17 23:25:53 +08:00
										 |  |  |         _Py_uop_sym_matches_type(_Py_uop_sym_tuple_getitem(ctx, ref, 0), &PyFloat_Type), | 
					
						
							| 
									
										
										
										
											2025-01-20 15:49:15 +00:00
										 |  |  |         "tuple item does not match value used to create tuple" | 
					
						
							|  |  |  |     ); | 
					
						
							|  |  |  |     TEST_PREDICATE( | 
					
						
							| 
									
										
										
										
											2025-06-17 23:25:53 +08:00
										 |  |  |         _Py_uop_sym_get_const(ctx, _Py_uop_sym_tuple_getitem(ctx, ref, 1)) == val_43, | 
					
						
							| 
									
										
										
										
											2025-01-20 15:49:15 +00:00
										 |  |  |         "tuple item does not match value used to create tuple" | 
					
						
							|  |  |  |     ); | 
					
						
							|  |  |  |     PyObject *pair[2] = { val_42, val_43 }; | 
					
						
							| 
									
										
										
										
											2025-03-02 13:21:34 -08:00
										 |  |  |     tuple = _PyTuple_FromArray(pair, 2); | 
					
						
							| 
									
										
										
										
											2025-06-17 23:25:53 +08:00
										 |  |  |     ref = _Py_uop_sym_new_const(ctx, tuple); | 
					
						
							| 
									
										
										
										
											2025-01-20 15:49:15 +00:00
										 |  |  |     TEST_PREDICATE( | 
					
						
							| 
									
										
										
										
											2025-06-17 23:25:53 +08:00
										 |  |  |         _Py_uop_sym_get_const(ctx, _Py_uop_sym_tuple_getitem(ctx, ref, 1)) == val_43, | 
					
						
							| 
									
										
										
										
											2025-01-20 15:49:15 +00:00
										 |  |  |         "tuple item does not match value used to create tuple" | 
					
						
							|  |  |  |     ); | 
					
						
							| 
									
										
										
										
											2025-06-17 23:25:53 +08:00
										 |  |  |     ref = _Py_uop_sym_new_type(ctx, &PyTuple_Type); | 
					
						
							| 
									
										
										
										
											2025-05-22 11:15:03 -04:00
										 |  |  |     TEST_PREDICATE( | 
					
						
							| 
									
										
										
										
											2025-06-17 23:25:53 +08:00
										 |  |  |         _Py_uop_sym_is_not_null(_Py_uop_sym_tuple_getitem(ctx, ref, 42)), | 
					
						
							| 
									
										
										
										
											2025-05-22 11:15:03 -04:00
										 |  |  |         "Unknown tuple item is not narrowed to non-NULL" | 
					
						
							|  |  |  |     ); | 
					
						
							| 
									
										
										
										
											2025-06-17 23:25:53 +08:00
										 |  |  |     JitOptRef value = _Py_uop_sym_new_type(ctx, &PyBool_Type); | 
					
						
							|  |  |  |     ref = _Py_uop_sym_new_truthiness(ctx, value, false); | 
					
						
							|  |  |  |     TEST_PREDICATE(_Py_uop_sym_matches_type(ref, &PyBool_Type), "truthiness is not boolean"); | 
					
						
							|  |  |  |     TEST_PREDICATE(_Py_uop_sym_truthiness(ctx, ref) == -1, "truthiness is not unknown"); | 
					
						
							|  |  |  |     TEST_PREDICATE(_Py_uop_sym_is_const(ctx, ref) == false, "truthiness is constant"); | 
					
						
							|  |  |  |     TEST_PREDICATE(_Py_uop_sym_get_const(ctx, ref) == NULL, "truthiness is not NULL"); | 
					
						
							| 
									
										
										
										
											2025-03-02 13:21:34 -08:00
										 |  |  |     TEST_PREDICATE(_Py_uop_sym_is_const(ctx, value) == false, "value is constant"); | 
					
						
							|  |  |  |     TEST_PREDICATE(_Py_uop_sym_get_const(ctx, value) == NULL, "value is not NULL"); | 
					
						
							| 
									
										
										
										
											2025-06-17 23:25:53 +08:00
										 |  |  |     _Py_uop_sym_set_const(ctx, ref, Py_False); | 
					
						
							|  |  |  |     TEST_PREDICATE(_Py_uop_sym_matches_type(ref, &PyBool_Type), "truthiness is not boolean"); | 
					
						
							|  |  |  |     TEST_PREDICATE(_Py_uop_sym_truthiness(ctx, ref) == 0, "truthiness is not True"); | 
					
						
							|  |  |  |     TEST_PREDICATE(_Py_uop_sym_is_const(ctx, ref) == true, "truthiness is not constant"); | 
					
						
							|  |  |  |     TEST_PREDICATE(_Py_uop_sym_get_const(ctx, ref) == Py_False, "truthiness is not False"); | 
					
						
							| 
									
										
										
										
											2025-03-02 13:21:34 -08:00
										 |  |  |     TEST_PREDICATE(_Py_uop_sym_is_const(ctx, value) == true, "value is not constant"); | 
					
						
							|  |  |  |     TEST_PREDICATE(_Py_uop_sym_get_const(ctx, value) == Py_True, "value is not True"); | 
					
						
							| 
									
										
										
										
											2025-06-19 11:10:29 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     val_big = PyNumber_Lshift(_PyLong_GetOne(), PyLong_FromLong(66)); | 
					
						
							|  |  |  |     if (val_big == NULL) { | 
					
						
							|  |  |  |         goto fail; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     JitOptRef ref_42 = _Py_uop_sym_new_const(ctx, val_42); | 
					
						
							|  |  |  |     JitOptRef ref_big = _Py_uop_sym_new_const(ctx, val_big); | 
					
						
							|  |  |  |     JitOptRef ref_int = _Py_uop_sym_new_compact_int(ctx); | 
					
						
							|  |  |  |     TEST_PREDICATE(_Py_uop_sym_is_compact_int(ref_42), "42 is not a compact int"); | 
					
						
							|  |  |  |     TEST_PREDICATE(!_Py_uop_sym_is_compact_int(ref_big), "(1 << 66) is a compact int"); | 
					
						
							|  |  |  |     TEST_PREDICATE(_Py_uop_sym_is_compact_int(ref_int), "compact int is not a compact int"); | 
					
						
							|  |  |  |     TEST_PREDICATE(_Py_uop_sym_matches_type(ref_int, &PyLong_Type), "compact int is not an int"); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     _Py_uop_sym_set_type(ctx, ref_int, &PyLong_Type);  // Should have no effect
 | 
					
						
							|  |  |  |     TEST_PREDICATE(_Py_uop_sym_is_compact_int(ref_int), "compact int is not a compact int after cast"); | 
					
						
							|  |  |  |     TEST_PREDICATE(_Py_uop_sym_matches_type(ref_int, &PyLong_Type), "compact int is not an int after cast"); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     _Py_uop_sym_set_type(ctx, ref_int, &PyFloat_Type);  // Should make it bottom
 | 
					
						
							|  |  |  |     TEST_PREDICATE(_Py_uop_sym_is_bottom(ref_int), "compact int cast to float isn't bottom"); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     ref_int = _Py_uop_sym_new_compact_int(ctx); | 
					
						
							|  |  |  |     _Py_uop_sym_set_const(ctx, ref_int, val_43); | 
					
						
							|  |  |  |     TEST_PREDICATE(_Py_uop_sym_is_compact_int(ref_int), "43 is not a compact int"); | 
					
						
							|  |  |  |     TEST_PREDICATE(_Py_uop_sym_matches_type(ref_int, &PyLong_Type), "43 is not an int"); | 
					
						
							|  |  |  |     TEST_PREDICATE(_Py_uop_sym_get_const(ctx, ref_int) == val_43, "43 isn't 43"); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											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-06-19 11:10:29 +01:00
										 |  |  |     Py_DECREF(val_big); | 
					
						
							| 
									
										
										
										
											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-06-19 11:10:29 +01:00
										 |  |  |     Py_XDECREF(val_big); | 
					
						
							| 
									
										
										
										
											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 */
 |