]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
gh-148211: refactor bool to explicit uops in JIT (GH-148258)
authorNeko Asakura <neko.asakura@outlook.com>
Thu, 9 Apr 2026 05:20:31 +0000 (13:20 +0800)
committerGitHub <noreply@github.com>
Thu, 9 Apr 2026 05:20:31 +0000 (13:20 +0800)
Python/optimizer_analysis.c
Python/optimizer_bytecodes.c
Python/optimizer_cases.c.h

index ed1619df2a188b447c2a9ebaa017d63ced46d0b3..a3c6efeb2f1177248b3d6d9c65e6226a0722522c 100644 (file)
@@ -155,7 +155,8 @@ type_watcher_callback(PyTypeObject* type)
 }
 
 static PyObject *
-convert_global_to_const(_PyUOpInstruction *inst, PyObject *obj, bool insert)
+convert_global_to_const(_PyUOpInstruction *inst, PyObject *obj,
+                        uint16_t immortal_op, uint16_t mortal_op)
 {
     assert(inst->opcode == _LOAD_GLOBAL_MODULE || inst->opcode == _LOAD_GLOBAL_BUILTINS || inst->opcode == _LOAD_ATTR_MODULE);
     assert(PyDict_CheckExact(obj));
@@ -175,18 +176,12 @@ convert_global_to_const(_PyUOpInstruction *inst, PyObject *obj, bool insert)
     if (res == NULL) {
         return NULL;
     }
-    if (insert) {
-        if (_Py_IsImmortal(res)) {
-            inst->opcode = _INSERT_1_LOAD_CONST_INLINE_BORROW;
-        } else {
-            inst->opcode = _INSERT_1_LOAD_CONST_INLINE;
-        }
+    if (_Py_IsImmortal(res)) {
+        inst->opcode = immortal_op;
     } else {
-        if (_Py_IsImmortal(res)) {
-            inst->opcode = _LOAD_CONST_INLINE_BORROW;
-        } else {
-            inst->opcode = _LOAD_CONST_INLINE;
-        }
+        inst->opcode = mortal_op;
+    }
+    if (inst->opcode == _LOAD_CONST_INLINE_BORROW || inst->opcode == _LOAD_CONST_INLINE) {
         if (inst->oparg & 1) {
             assert(inst[1].opcode == _PUSH_NULL_CONDITIONAL);
             assert(inst[1].oparg & 1);
@@ -330,7 +325,7 @@ optimize_to_bool(
     JitOptContext *ctx,
     JitOptRef value,
     JitOptRef *result_ptr,
-    bool insert_mode)
+    uint16_t prefix, uint16_t load_op)
 {
     if (sym_matches_type(value, &PyBool_Type)) {
         ADD_OP(_NOP, 0, 0);
@@ -340,12 +335,10 @@ optimize_to_bool(
     int truthiness = sym_truthiness(ctx, value);
     if (truthiness >= 0) {
         PyObject *load = truthiness ? Py_True : Py_False;
-        if (insert_mode) {
-            ADD_OP(_INSERT_1_LOAD_CONST_INLINE_BORROW, 0, (uintptr_t)load);
-        } else {
-            ADD_OP(_POP_TOP, 0, 0);
-            ADD_OP(_LOAD_CONST_INLINE_BORROW, 0, (uintptr_t)load);
+        if (prefix != _NOP) {
+            ADD_OP(prefix, 0, 0);
         }
+        ADD_OP(load_op, 0, (uintptr_t)load);
         *result_ptr = sym_new_const(ctx, load);
         return 1;
     }
@@ -391,22 +384,18 @@ eliminate_pop_guard(_PyUOpInstruction *this_instr, JitOptContext *ctx, bool exit
 
 static JitOptRef
 lookup_attr(JitOptContext *ctx, _PyBloomFilter *dependencies, _PyUOpInstruction *this_instr,
-            PyTypeObject *type, PyObject *name, bool pop)
+            PyTypeObject *type, PyObject *name,
+            uint16_t prefix, uint16_t immortal_op, uint16_t mortal_op)
 {
     // The cached value may be dead, so we need to do the lookup again... :(
     if (type && PyType_Check(type)) {
         PyObject *lookup = _PyType_Lookup(type, name);
         if (lookup) {
             bool immortal = _Py_IsImmortal(lookup) || (type->tp_flags & Py_TPFLAGS_IMMUTABLETYPE);
-            if (pop) {
-                ADD_OP(_POP_TOP, 0, 0);
-                ADD_OP(immortal ? _LOAD_CONST_INLINE_BORROW : _LOAD_CONST_INLINE,
-                       0, (uintptr_t)lookup);
-            }
-            else {
-                ADD_OP(immortal ? _INSERT_1_LOAD_CONST_INLINE_BORROW : _INSERT_1_LOAD_CONST_INLINE,
-                       0, (uintptr_t)lookup);
+            if (prefix != _NOP) {
+                ADD_OP(prefix, 0, 0);
             }
+            ADD_OP(immortal ? immortal_op : mortal_op, 0, (uintptr_t)lookup);
             PyType_Watch(TYPE_WATCHER_ID, (PyObject *)type);
             _Py_BloomFilter_Add(dependencies, type);
             return sym_new_const(ctx, lookup);
index 3ba404b81ea043aafb06a8c1ddbb265edcf75bbc..7dc763db71b34b3e2a9c9766510f7ca074204618 100644 (file)
@@ -536,21 +536,24 @@ dummy_func(void) {
     }
 
     op(_TO_BOOL, (value -- res)) {
-        int already_bool = optimize_to_bool(this_instr, ctx, value, &res, false);
+        int already_bool = optimize_to_bool(this_instr, ctx, value, &res,
+                                            _POP_TOP, _LOAD_CONST_INLINE_BORROW);
         if (!already_bool) {
             res = sym_new_truthiness(ctx, value, true);
         }
     }
 
     op(_TO_BOOL_BOOL, (value -- value)) {
-        int already_bool = optimize_to_bool(this_instr, ctx, value, &value, false);
+        int already_bool = optimize_to_bool(this_instr, ctx, value, &value,
+                                            _POP_TOP, _LOAD_CONST_INLINE_BORROW);
         if (!already_bool) {
             sym_set_type(value, &PyBool_Type);
         }
     }
 
     op(_TO_BOOL_INT, (value -- res, v)) {
-        int already_bool = optimize_to_bool(this_instr, ctx, value, &res, true);
+        int already_bool = optimize_to_bool(this_instr, ctx, value, &res,
+                                            _NOP, _INSERT_1_LOAD_CONST_INLINE_BORROW);
         if (!already_bool) {
             sym_set_type(value, &PyLong_Type);
             res = sym_new_truthiness(ctx, value, true);
@@ -559,7 +562,8 @@ dummy_func(void) {
     }
 
     op(_TO_BOOL_LIST, (value -- res, v)) {
-        int already_bool = optimize_to_bool(this_instr, ctx, value, &res, true);
+        int already_bool = optimize_to_bool(this_instr, ctx, value, &res,
+                                            _NOP, _INSERT_1_LOAD_CONST_INLINE_BORROW);
         if (!already_bool) {
             res = sym_new_type(ctx, &PyBool_Type);
         }
@@ -567,7 +571,8 @@ dummy_func(void) {
     }
 
     op(_TO_BOOL_NONE, (value -- res)) {
-        int already_bool = optimize_to_bool(this_instr, ctx, value, &res, false);
+        int already_bool = optimize_to_bool(this_instr, ctx, value, &res,
+                                            _POP_TOP, _LOAD_CONST_INLINE_BORROW);
         if (!already_bool) {
             sym_set_const(value, Py_None);
             res = sym_new_const(ctx, Py_False);
@@ -593,7 +598,8 @@ dummy_func(void) {
     }
 
     op(_TO_BOOL_STR, (value -- res, v)) {
-        int already_bool = optimize_to_bool(this_instr, ctx, value, &res, true);
+        int already_bool = optimize_to_bool(this_instr, ctx, value, &res,
+                                            _NOP, _INSERT_1_LOAD_CONST_INLINE_BORROW);
         v = value;
         if (!already_bool) {
             res = sym_new_truthiness(ctx, value, true);
@@ -837,7 +843,8 @@ dummy_func(void) {
                 if (watched_mutations < _Py_MAX_ALLOWED_GLOBALS_MODIFICATIONS) {
                     PyDict_Watch(GLOBALS_WATCHER_ID, dict);
                     _Py_BloomFilter_Add(dependencies, dict);
-                    PyObject *res = convert_global_to_const(this_instr, dict, true);
+                    PyObject *res = convert_global_to_const(this_instr, dict,
+                        _INSERT_1_LOAD_CONST_INLINE_BORROW, _INSERT_1_LOAD_CONST_INLINE);
                     if (res == NULL) {
                         attr = sym_new_not_null(ctx);
                     }
@@ -890,7 +897,7 @@ dummy_func(void) {
         PyTypeObject *type = (PyTypeObject *)sym_get_const(ctx, owner);
         PyObject *name = get_co_name(ctx, oparg >> 1);
         attr = lookup_attr(ctx, dependencies, this_instr, type, name,
-                           true);
+                           _POP_TOP, _LOAD_CONST_INLINE_BORROW, _LOAD_CONST_INLINE);
     }
 
     op(_LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES, (descr/4, owner -- attr)) {
@@ -898,7 +905,7 @@ dummy_func(void) {
         PyTypeObject *type = sym_get_type(owner);
         PyObject *name = get_co_name(ctx, oparg >> 1);
         attr = lookup_attr(ctx, dependencies, this_instr, type, name,
-                           true);
+                           _POP_TOP, _LOAD_CONST_INLINE_BORROW, _LOAD_CONST_INLINE);
     }
 
     op(_LOAD_ATTR_NONDESCRIPTOR_NO_DICT, (descr/4, owner -- attr)) {
@@ -906,7 +913,7 @@ dummy_func(void) {
         PyTypeObject *type = sym_get_type(owner);
         PyObject *name = get_co_name(ctx, oparg >> 1);
         attr = lookup_attr(ctx, dependencies, this_instr, type, name,
-                           true);
+                           _POP_TOP, _LOAD_CONST_INLINE_BORROW, _LOAD_CONST_INLINE);
     }
 
     op(_LOAD_ATTR_METHOD_WITH_VALUES, (descr/4, owner -- attr, self)) {
@@ -914,7 +921,7 @@ dummy_func(void) {
         PyTypeObject *type = sym_get_type(owner);
         PyObject *name = get_co_name(ctx, oparg >> 1);
         attr = lookup_attr(ctx, dependencies, this_instr, type, name,
-                           false);
+                           _NOP, _INSERT_1_LOAD_CONST_INLINE_BORROW, _INSERT_1_LOAD_CONST_INLINE);
         self = owner;
     }
 
@@ -923,7 +930,7 @@ dummy_func(void) {
         PyTypeObject *type = sym_get_type(owner);
         PyObject *name = get_co_name(ctx, oparg >> 1);
         attr = lookup_attr(ctx, dependencies, this_instr, type, name,
-                           false);
+                           _NOP, _INSERT_1_LOAD_CONST_INLINE_BORROW, _INSERT_1_LOAD_CONST_INLINE);
         self = owner;
     }
 
@@ -932,7 +939,7 @@ dummy_func(void) {
         PyTypeObject *type = sym_get_type(owner);
         PyObject *name = get_co_name(ctx, oparg >> 1);
         attr = lookup_attr(ctx, dependencies, this_instr, type, name,
-                           false);
+                           _NOP, _INSERT_1_LOAD_CONST_INLINE_BORROW, _INSERT_1_LOAD_CONST_INLINE);
         self = owner;
     }
 
@@ -2007,7 +2014,8 @@ dummy_func(void) {
                 ctx->builtins_watched = true;
             }
             if (ctx->frame->globals_checked_version != 0 && ctx->frame->globals_watched) {
-                cnst = convert_global_to_const(this_instr, builtins, false);
+                cnst = convert_global_to_const(this_instr, builtins,
+                    _LOAD_CONST_INLINE_BORROW, _LOAD_CONST_INLINE);
             }
         }
         if (cnst == NULL) {
@@ -2046,7 +2054,8 @@ dummy_func(void) {
                     ctx->frame->globals_checked_version = version;
                 }
                 if (ctx->frame->globals_checked_version == version) {
-                    cnst = convert_global_to_const(this_instr, globals, false);
+                    cnst = convert_global_to_const(this_instr, globals,
+                    _LOAD_CONST_INLINE_BORROW, _LOAD_CONST_INLINE);
                 }
             }
         }
index 2c8a0bff13ce3520f947d9ed305f25c9be218c31..2462959ace83a3a4c6cdbd4d54952b01f1411aa3 100644 (file)
             JitOptRef value;
             JitOptRef res;
             value = stack_pointer[-1];
-            int already_bool = optimize_to_bool(this_instr, ctx, value, &res, false);
+            int already_bool = optimize_to_bool(this_instr, ctx, value, &res,
+                _POP_TOP, _LOAD_CONST_INLINE_BORROW);
             if (!already_bool) {
                 res = sym_new_truthiness(ctx, value, true);
             }
         case _TO_BOOL_BOOL: {
             JitOptRef value;
             value = stack_pointer[-1];
-            int already_bool = optimize_to_bool(this_instr, ctx, value, &value, false);
+            int already_bool = optimize_to_bool(this_instr, ctx, value, &value,
+                _POP_TOP, _LOAD_CONST_INLINE_BORROW);
             if (!already_bool) {
                 sym_set_type(value, &PyBool_Type);
             }
             JitOptRef res;
             JitOptRef v;
             value = stack_pointer[-1];
-            int already_bool = optimize_to_bool(this_instr, ctx, value, &res, true);
+            int already_bool = optimize_to_bool(this_instr, ctx, value, &res,
+                _NOP, _INSERT_1_LOAD_CONST_INLINE_BORROW);
             if (!already_bool) {
                 sym_set_type(value, &PyLong_Type);
                 res = sym_new_truthiness(ctx, value, true);
             JitOptRef res;
             JitOptRef v;
             value = stack_pointer[-1];
-            int already_bool = optimize_to_bool(this_instr, ctx, value, &res, true);
+            int already_bool = optimize_to_bool(this_instr, ctx, value, &res,
+                _NOP, _INSERT_1_LOAD_CONST_INLINE_BORROW);
             if (!already_bool) {
                 res = sym_new_type(ctx, &PyBool_Type);
             }
             JitOptRef value;
             JitOptRef res;
             value = stack_pointer[-1];
-            int already_bool = optimize_to_bool(this_instr, ctx, value, &res, false);
+            int already_bool = optimize_to_bool(this_instr, ctx, value, &res,
+                _POP_TOP, _LOAD_CONST_INLINE_BORROW);
             if (!already_bool) {
                 sym_set_const(value, Py_None);
                 res = sym_new_const(ctx, Py_False);
             JitOptRef res;
             JitOptRef v;
             value = stack_pointer[-1];
-            int already_bool = optimize_to_bool(this_instr, ctx, value, &res, true);
+            int already_bool = optimize_to_bool(this_instr, ctx, value, &res,
+                _NOP, _INSERT_1_LOAD_CONST_INLINE_BORROW);
             v = value;
             if (!already_bool) {
                 res = sym_new_truthiness(ctx, value, true);
                         ctx->frame->globals_checked_version = version;
                     }
                     if (ctx->frame->globals_checked_version == version) {
-                        cnst = convert_global_to_const(this_instr, globals, false);
+                        cnst = convert_global_to_const(this_instr, globals,
+                            _LOAD_CONST_INLINE_BORROW, _LOAD_CONST_INLINE);
                     }
                 }
             }
                     ctx->builtins_watched = true;
                 }
                 if (ctx->frame->globals_checked_version != 0 && ctx->frame->globals_watched) {
-                    cnst = convert_global_to_const(this_instr, builtins, false);
+                    cnst = convert_global_to_const(this_instr, builtins,
+                        _LOAD_CONST_INLINE_BORROW, _LOAD_CONST_INLINE);
                 }
             }
             if (cnst == NULL) {
                     if (watched_mutations < _Py_MAX_ALLOWED_GLOBALS_MODIFICATIONS) {
                         PyDict_Watch(GLOBALS_WATCHER_ID, dict);
                         _Py_BloomFilter_Add(dependencies, dict);
-                        PyObject *res = convert_global_to_const(this_instr, dict, true);
+                        PyObject *res = convert_global_to_const(this_instr, dict,
+                            _INSERT_1_LOAD_CONST_INLINE_BORROW, _INSERT_1_LOAD_CONST_INLINE);
                         if (res == NULL) {
                             attr = sym_new_not_null(ctx);
                         }
             PyTypeObject *type = (PyTypeObject *)sym_get_const(ctx, owner);
             PyObject *name = get_co_name(ctx, oparg >> 1);
             attr = lookup_attr(ctx, dependencies, this_instr, type, name,
-                           true);
+                           _POP_TOP, _LOAD_CONST_INLINE_BORROW, _LOAD_CONST_INLINE);
             stack_pointer[-1] = attr;
             break;
         }
             PyTypeObject *type = sym_get_type(owner);
             PyObject *name = get_co_name(ctx, oparg >> 1);
             attr = lookup_attr(ctx, dependencies, this_instr, type, name,
-                           false);
+                           _NOP, _INSERT_1_LOAD_CONST_INLINE_BORROW, _INSERT_1_LOAD_CONST_INLINE);
             self = owner;
             CHECK_STACK_BOUNDS(1);
             stack_pointer[-1] = attr;
             PyTypeObject *type = sym_get_type(owner);
             PyObject *name = get_co_name(ctx, oparg >> 1);
             attr = lookup_attr(ctx, dependencies, this_instr, type, name,
-                           false);
+                           _NOP, _INSERT_1_LOAD_CONST_INLINE_BORROW, _INSERT_1_LOAD_CONST_INLINE);
             self = owner;
             CHECK_STACK_BOUNDS(1);
             stack_pointer[-1] = attr;
             PyTypeObject *type = sym_get_type(owner);
             PyObject *name = get_co_name(ctx, oparg >> 1);
             attr = lookup_attr(ctx, dependencies, this_instr, type, name,
-                           true);
+                           _POP_TOP, _LOAD_CONST_INLINE_BORROW, _LOAD_CONST_INLINE);
             stack_pointer[-1] = attr;
             break;
         }
             PyTypeObject *type = sym_get_type(owner);
             PyObject *name = get_co_name(ctx, oparg >> 1);
             attr = lookup_attr(ctx, dependencies, this_instr, type, name,
-                           true);
+                           _POP_TOP, _LOAD_CONST_INLINE_BORROW, _LOAD_CONST_INLINE);
             stack_pointer[-1] = attr;
             break;
         }
             PyTypeObject *type = sym_get_type(owner);
             PyObject *name = get_co_name(ctx, oparg >> 1);
             attr = lookup_attr(ctx, dependencies, this_instr, type, name,
-                           false);
+                           _NOP, _INSERT_1_LOAD_CONST_INLINE_BORROW, _INSERT_1_LOAD_CONST_INLINE);
             self = owner;
             CHECK_STACK_BOUNDS(1);
             stack_pointer[-1] = attr;