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

This commit is contained in:
Irit Katriel 2021-09-14 09:53:32 +01:00 committed by GitHub
parent 9f93018b69
commit c2f1e95337
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 53 additions and 7 deletions

4
Include/opcode.h generated
View File

@ -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.

View File

@ -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;

View File

@ -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)