[Python-checkins] bpo-45152: Add HAS_CONST macro and get_const_value() function and use… (#28262)

markshannon webhook-mailer at python.org
Tue Sep 14 04:53:37 EDT 2021


https://github.com/python/cpython/commit/c2f1e953371c25f6c42b599ba3d8797effbb503e
commit: c2f1e953371c25f6c42b599ba3d8797effbb503e
branch: main
author: Irit Katriel <1055913+iritkatriel at users.noreply.github.com>
committer: markshannon <mark at hotpy.org>
date: 2021-09-14T09:53:32+01:00
summary:

bpo-45152: Add HAS_CONST macro and get_const_value() function and use… (#28262)

files:
M Include/opcode.h
M Python/compile.c
M Tools/scripts/generate_opcode_h.py

diff --git a/Include/opcode.h b/Include/opcode.h
index 0043cc2d209aa..2789525594783 100644
--- a/Include/opcode.h
+++ b/Include/opcode.h
@@ -190,6 +190,10 @@ static uint32_t _PyOpcode_Jump[8] = {
 };
 #endif /* OPCODE_TABLES */
 
+#define HAS_CONST(op) (false\
+    || ((op) == 100) \
+    )
+
 #define HAS_ARG(op) ((op) >= HAVE_ARGUMENT)
 
 /* Reserve some bytecodes for internal use in the compiler.
diff --git a/Python/compile.c b/Python/compile.c
index 389b3e0d723ee..fdc2ce61a8e03 100644
--- a/Python/compile.c
+++ b/Python/compile.c
@@ -1638,14 +1638,14 @@ compiler_addop_j_noline(struct compiler *c, int opcode, basicblock *b)
 }
 
 #define ADDOP_O(C, OP, O, TYPE) { \
-    assert((OP) != LOAD_CONST); /* use ADDOP_LOAD_CONST */ \
+    assert(!HAS_CONST(OP)); /* use ADDOP_LOAD_CONST */ \
     if (!compiler_addop_o((C), (OP), (C)->u->u_ ## TYPE, (O))) \
         return 0; \
 }
 
 /* Same as ADDOP_O, but steals a reference. */
 #define ADDOP_N(C, OP, O, TYPE) { \
-    assert((OP) != LOAD_CONST); /* use ADDOP_LOAD_CONST_NEW */ \
+    assert(!HAS_CONST(OP)); /* use ADDOP_LOAD_CONST_NEW */ \
     if (!compiler_addop_o((C), (OP), (C)->u->u_ ## TYPE, (O))) { \
         Py_DECREF((O)); \
         return 0; \
@@ -7951,6 +7951,24 @@ assemble(struct compiler *c, int addNone)
     return co;
 }
 
+static PyObject*
+get_const_value(int opcode, int oparg, PyObject *co_consts)
+{
+    PyObject *constant = NULL;
+    assert(HAS_CONST(opcode));
+    if (opcode == LOAD_CONST) {
+        constant = PyList_GET_ITEM(co_consts, oparg);
+    }
+
+    if (constant == NULL) {
+        PyErr_SetString(PyExc_SystemError,
+                        "Internal error: failed to get value of a constant");
+        return NULL;
+    }
+    Py_INCREF(constant);
+    return constant;
+}
+
 /* Replace LOAD_CONST c1, LOAD_CONST c2 ... LOAD_CONST cn, BUILD_TUPLE n
    with    LOAD_CONST (c1, c2, ... cn).
    The consts table must still be in list form so that the
@@ -7968,7 +7986,7 @@ fold_tuple_on_constants(struct compiler *c,
     assert(inst[n].i_oparg == n);
 
     for (int i = 0; i < n; i++) {
-        if (inst[i].i_opcode != LOAD_CONST) {
+        if (!HAS_CONST(inst[i].i_opcode)) {
             return 0;
         }
     }
@@ -7979,9 +7997,12 @@ fold_tuple_on_constants(struct compiler *c,
         return -1;
     }
     for (int i = 0; i < n; i++) {
+        int op = inst[i].i_opcode;
         int arg = inst[i].i_oparg;
-        PyObject *constant = PyList_GET_ITEM(consts, arg);
-        Py_INCREF(constant);
+        PyObject *constant = get_const_value(op, arg, consts);
+        if (constant == NULL) {
+            return -1;
+        }
         PyTuple_SET_ITEM(newconst, i, constant);
     }
     if (merge_const_one(c, &newconst) == 0) {
@@ -8107,8 +8128,12 @@ optimize_basic_block(struct compiler *c, basicblock *bb, PyObject *consts)
                 switch(nextop) {
                     case POP_JUMP_IF_FALSE:
                     case POP_JUMP_IF_TRUE:
-                        cnt = PyList_GET_ITEM(consts, oparg);
+                        cnt = get_const_value(inst->i_opcode, oparg, consts);
+                        if (cnt == NULL) {
+                            goto error;
+                        }
                         is_true = PyObject_IsTrue(cnt);
+                        Py_DECREF(cnt);
                         if (is_true == -1) {
                             goto error;
                         }
@@ -8124,8 +8149,12 @@ optimize_basic_block(struct compiler *c, basicblock *bb, PyObject *consts)
                         break;
                     case JUMP_IF_FALSE_OR_POP:
                     case JUMP_IF_TRUE_OR_POP:
-                        cnt = PyList_GET_ITEM(consts, oparg);
+                        cnt = get_const_value(inst->i_opcode, oparg, consts);
+                        if (cnt == NULL) {
+                            goto error;
+                        }
                         is_true = PyObject_IsTrue(cnt);
+                        Py_DECREF(cnt);
                         if (is_true == -1) {
                             goto error;
                         }
@@ -8310,6 +8339,9 @@ optimize_basic_block(struct compiler *c, basicblock *bb, PyObject *consts)
                     fold_rotations(inst - oparg + 1, oparg);
                 }
                 break;
+            default:
+                /* All HAS_CONST opcodes should be handled with LOAD_CONST */
+                assert (!HAS_CONST(inst->i_opcode));
         }
     }
     return 0;
diff --git a/Tools/scripts/generate_opcode_h.py b/Tools/scripts/generate_opcode_h.py
index 41ae3fe6e5368..48875d2a9dd39 100644
--- a/Tools/scripts/generate_opcode_h.py
+++ b/Tools/scripts/generate_opcode_h.py
@@ -51,6 +51,7 @@ def main(opcode_py, outfile='Include/opcode.h'):
         code = fp.read()
     exec(code, opcode)
     opmap = opcode['opmap']
+    hasconst = opcode['hasconst']
     hasjrel = opcode['hasjrel']
     hasjabs = opcode['hasjabs']
     used = [ False ] * 256
@@ -65,15 +66,24 @@ def main(opcode_py, outfile='Include/opcode.h'):
             if name == 'POP_EXCEPT': # Special entry for HAVE_ARGUMENT
                 fobj.write("#define %-23s %3d\n" %
                             ('HAVE_ARGUMENT', opcode['HAVE_ARGUMENT']))
+
         for name in opcode['_specialized_instructions']:
             while used[next_op]:
                 next_op += 1
             fobj.write("#define %-23s %3s\n" % (name, next_op))
             used[next_op] = True
+
         fobj.write("#ifdef NEED_OPCODE_JUMP_TABLES\n")
         write_int_array_from_ops("_PyOpcode_RelativeJump", opcode['hasjrel'], fobj)
         write_int_array_from_ops("_PyOpcode_Jump", opcode['hasjrel'] + opcode['hasjabs'], fobj)
         fobj.write("#endif /* OPCODE_TABLES */\n")
+
+        fobj.write("\n")
+        fobj.write("#define HAS_CONST(op) (false\\")
+        for op in hasconst:
+            fobj.write(f"\n    || ((op) == {op}) \\")
+        fobj.write("\n    )\n")
+
         fobj.write(footer)
 
 



More information about the Python-checkins mailing list