Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

gh-105481: remove HAS_ARG, HAS_CONST, IS_JUMP_OPCODE, IS_PSEUDO_OPCODE and replace by their new versions #105865

Merged
merged 7 commits into from
Jun 17, 2023
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
13 changes: 0 additions & 13 deletions Include/internal/pycore_opcode.h

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

26 changes: 1 addition & 25 deletions Include/internal/pycore_opcode_utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,7 @@ extern "C" {

#define IS_WITHIN_OPCODE_RANGE(opcode) \
(((opcode) >= 0 && (opcode) <= MAX_REAL_OPCODE) || \
IS_PSEUDO_OPCODE(opcode))

#define IS_JUMP_OPCODE(opcode) \
is_bit_set_in_table(_PyOpcode_Jump, opcode)
IS_PSEUDO_INSTR(opcode))

#define IS_BLOCK_PUSH_OPCODE(opcode) \
((opcode) == SETUP_FINALLY || \
Expand Down Expand Up @@ -55,27 +52,6 @@ extern "C" {
(opcode) == RAISE_VARARGS || \
(opcode) == RERAISE)

#define LOG_BITS_PER_INT 5
#define MASK_LOW_LOG_BITS 31

static inline int
is_bit_set_in_table(const uint32_t *table, int bitindex) {
/* Is the relevant bit set in the relevant word? */
/* 512 bits fit into 9 32-bits words.
* Word is indexed by (bitindex>>ln(size of int in bits)).
* Bit within word is the low bits of bitindex.
*/
if (bitindex >= 0 && bitindex < 512) {
uint32_t word = table[bitindex >> LOG_BITS_PER_INT];
return (word >> (bitindex & MASK_LOW_LOG_BITS)) & 1;
}
else {
return 0;
}
}

#undef LOG_BITS_PER_INT
#undef MASK_LOW_LOG_BITS

/* Flags used in the oparg for MAKE_FUNCTION */
#define MAKE_FUNCTION_DEFAULTS 0x01
Expand Down
19 changes: 0 additions & 19 deletions Include/opcode.h

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

10 changes: 2 additions & 8 deletions Lib/test/test__opcode.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,20 +15,14 @@ def test_stack_effect(self):
self.assertEqual(stack_effect(dis.opmap['BUILD_SLICE'], 1), -1)
self.assertEqual(stack_effect(dis.opmap['BUILD_SLICE'], 3), -2)
self.assertRaises(ValueError, stack_effect, 30000)
self.assertRaises(ValueError, stack_effect, dis.opmap['BUILD_SLICE'])
self.assertRaises(ValueError, stack_effect, dis.opmap['POP_TOP'], 0)
# All defined opcodes
has_arg = dis.hasarg
for name, code in filter(lambda item: item[0] not in dis.deoptmap, dis.opmap.items()):
if code >= opcode.MIN_INSTRUMENTED_OPCODE:
continue
with self.subTest(opname=name):
if code not in has_arg:
stack_effect(code)
self.assertRaises(ValueError, stack_effect, code, 0)
else:
stack_effect(code, 0)
self.assertRaises(ValueError, stack_effect, code)
stack_effect(code)
stack_effect(code, 0)
# All not defined opcodes
for code in set(range(256)) - set(dis.opmap.values()):
with self.subTest(opcode=code):
Expand Down
22 changes: 6 additions & 16 deletions Modules/_opcode.c
Original file line number Diff line number Diff line change
Expand Up @@ -27,25 +27,16 @@ _opcode_stack_effect_impl(PyObject *module, int opcode, PyObject *oparg,
PyObject *jump)
/*[clinic end generated code: output=64a18f2ead954dbb input=461c9d4a44851898]*/
{
int effect;
int oparg_int = 0;
int jump_int;
if (HAS_ARG(opcode)) {
if (oparg == Py_None) {
PyErr_SetString(PyExc_ValueError,
"stack_effect: opcode requires oparg but oparg was not specified");
return -1;
}

if (oparg != Py_None) {
oparg_int = (int)PyLong_AsLong(oparg);
if ((oparg_int == -1) && PyErr_Occurred()) {
return -1;
}
}
else if (oparg != Py_None) {
PyErr_SetString(PyExc_ValueError,
"stack_effect: opcode does not permit oparg but oparg was specified");
return -1;
}

if (jump == Py_None) {
jump_int = -1;
}
Expand All @@ -60,11 +51,10 @@ _opcode_stack_effect_impl(PyObject *module, int opcode, PyObject *oparg,
"stack_effect: jump must be False, True or None");
return -1;
}
effect = PyCompile_OpcodeStackEffectWithJump(opcode, oparg_int, jump_int);
int effect = PyCompile_OpcodeStackEffectWithJump(opcode, oparg_int, jump_int);
if (effect == PY_INVALID_STACK_EFFECT) {
PyErr_SetString(PyExc_ValueError,
"invalid opcode or oparg");
return -1;
PyErr_SetString(PyExc_ValueError, "invalid opcode or oparg");
return -1;
}
return effect;
}
Expand Down
3 changes: 1 addition & 2 deletions Python/assemble.c
Original file line number Diff line number Diff line change
Expand Up @@ -339,10 +339,9 @@ static void
write_instr(_Py_CODEUNIT *codestr, instruction *instr, int ilen)
{
int opcode = instr->i_opcode;
assert(IS_PSEUDO_OPCODE(opcode) == IS_PSEUDO_INSTR(opcode));
assert(!IS_PSEUDO_INSTR(opcode));
int oparg = instr->i_oparg;
assert(HAS_ARG(opcode) || oparg == 0);
assert(OPCODE_HAS_ARG(opcode) || oparg == 0);
int caches = _PyOpcode_Caches[opcode];
switch (ilen - caches) {
case 4:
Expand Down
5 changes: 3 additions & 2 deletions Python/ceval.c
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
#include "pycore_frame.h"
#include "frameobject.h" // _PyInterpreterFrame_GetLine
#include "opcode.h"
#include "opcode_metadata.h"
#include "pydtrace.h"
#include "setobject.h"
#include "structmember.h" // struct PyMemberDef, T_OFFSET_EX
Expand Down Expand Up @@ -141,7 +142,7 @@ lltrace_instruction(_PyInterpreterFrame *frame,
const char *opname = _PyOpcode_OpName[opcode];
assert(opname != NULL);
int offset = (int)(next_instr - _PyCode_CODE(_PyFrame_GetCode(frame)));
if (HAS_ARG((int)_PyOpcode_Deopt[opcode])) {
if (OPCODE_HAS_ARG((int)_PyOpcode_Deopt[opcode])) {
printf("%d: %s %d\n", offset * 2, opname, oparg);
}
else {
Expand Down Expand Up @@ -882,7 +883,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int
#if USE_COMPUTED_GOTOS
_unknown_opcode:
#else
EXTRA_CASES // From opcode.h, a 'case' for each unused opcode
EXTRA_CASES // From pycore_opcode.h, a 'case' for each unused opcode
#endif
/* Tell C compilers not to hold the opcode variable in the loop.
next_instr points the current instruction without TARGET(). */
Expand Down
17 changes: 5 additions & 12 deletions Python/compile.c
Original file line number Diff line number Diff line change
Expand Up @@ -134,9 +134,8 @@ enum {
int
_PyCompile_InstrSize(int opcode, int oparg)
{
assert(IS_PSEUDO_OPCODE(opcode) == IS_PSEUDO_INSTR(opcode));
assert(!IS_PSEUDO_INSTR(opcode));
assert(HAS_ARG(opcode) || oparg == 0);
assert(OPCODE_HAS_ARG(opcode) || oparg == 0);
int extended_args = (0xFFFFFF < oparg) + (0xFFFF < oparg) + (0xFF < oparg);
int caches = _PyOpcode_Caches[opcode];
return extended_args + 1 + caches;
Expand Down Expand Up @@ -248,15 +247,9 @@ instr_sequence_use_label(instr_sequence *seq, int lbl) {
static int
instr_sequence_addop(instr_sequence *seq, int opcode, int oparg, location loc)
{
/* compare old and new opcode macros - use ! to compare as bools. */
assert(!HAS_ARG(opcode) == !OPCODE_HAS_ARG(opcode));
assert(!HAS_CONST(opcode) == !OPCODE_HAS_CONST(opcode));
assert(!OPCODE_HAS_JUMP(opcode) == !OPCODE_HAS_JUMP(opcode));

assert(0 <= opcode && opcode <= MAX_OPCODE);
assert(IS_PSEUDO_OPCODE(opcode) == IS_PSEUDO_INSTR(opcode));
assert(IS_WITHIN_OPCODE_RANGE(opcode));
assert(HAS_ARG(opcode) || HAS_TARGET(opcode) || oparg == 0);
assert(OPCODE_HAS_ARG(opcode) || HAS_TARGET(opcode) || oparg == 0);
assert(0 <= oparg && oparg < (1 << 30));

int idx = instr_sequence_next_inst(seq);
Expand Down Expand Up @@ -874,7 +867,7 @@ PyCompile_OpcodeStackEffect(int opcode, int oparg)
static int
codegen_addop_noarg(instr_sequence *seq, int opcode, location loc)
{
assert(!HAS_ARG(opcode));
assert(!OPCODE_HAS_ARG(opcode));
assert(!IS_ASSEMBLER_OPCODE(opcode));
return instr_sequence_addop(seq, opcode, 0, loc);
}
Expand Down Expand Up @@ -1151,7 +1144,7 @@ codegen_addop_j(instr_sequence *seq, location loc,
}

#define ADDOP_N(C, LOC, OP, O, TYPE) { \
assert(!HAS_CONST(OP)); /* use ADDOP_LOAD_CONST_NEW */ \
assert(!OPCODE_HAS_CONST(OP)); /* use ADDOP_LOAD_CONST_NEW */ \
if (compiler_addop_o((C)->u, (LOC), (OP), (C)->u->u_metadata.u_ ## TYPE, (O)) < 0) { \
Py_DECREF((O)); \
return ERROR; \
Expand Down Expand Up @@ -7798,7 +7791,7 @@ instructions_to_instr_sequence(PyObject *instructions, instr_sequence *seq)
goto error;
}
int oparg;
if (HAS_ARG(opcode)) {
if (OPCODE_HAS_ARG(opcode)) {
oparg = PyLong_AsLong(PyTuple_GET_ITEM(item, 1));
if (PyErr_Occurred()) {
goto error;
Expand Down
21 changes: 10 additions & 11 deletions Python/flowgraph.c
Original file line number Diff line number Diff line change
Expand Up @@ -45,14 +45,13 @@ is_block_push(cfg_instr *i)
static inline int
is_jump(cfg_instr *i)
{
assert(!OPCODE_HAS_JUMP(i->i_opcode) == !IS_JUMP_OPCODE(i->i_opcode));
return OPCODE_HAS_JUMP(i->i_opcode);
}

/* One arg*/
#define INSTR_SET_OP1(I, OP, ARG) \
do { \
assert(HAS_ARG(OP)); \
assert(OPCODE_HAS_ARG(OP)); \
_PyCfgInstruction *_instr__ptr_ = (I); \
_instr__ptr_->i_opcode = (OP); \
_instr__ptr_->i_oparg = (ARG); \
Expand All @@ -61,7 +60,7 @@ is_jump(cfg_instr *i)
/* No args*/
#define INSTR_SET_OP0(I, OP) \
do { \
assert(!HAS_ARG(OP)); \
assert(!OPCODE_HAS_ARG(OP)); \
_PyCfgInstruction *_instr__ptr_ = (I); \
_instr__ptr_->i_opcode = (OP); \
_instr__ptr_->i_oparg = 0; \
Expand Down Expand Up @@ -111,7 +110,7 @@ basicblock_addop(basicblock *b, int opcode, int oparg, location loc)
{
assert(IS_WITHIN_OPCODE_RANGE(opcode));
assert(!IS_ASSEMBLER_OPCODE(opcode));
assert(HAS_ARG(opcode) || HAS_TARGET(opcode) || oparg == 0);
assert(OPCODE_HAS_ARG(opcode) || HAS_TARGET(opcode) || oparg == 0);
assert(0 <= oparg && oparg < (1 << 30));

int off = basicblock_next_instr(b);
Expand Down Expand Up @@ -193,7 +192,7 @@ dump_instr(cfg_instr *i)
char arg[128];

*arg = '\0';
if (HAS_ARG(i->i_opcode)) {
if (OPCODE_HAS_ARG(i->i_opcode)) {
sprintf(arg, "arg: %d ", i->i_oparg);
}
if (HAS_TARGET(i->i_opcode)) {
Expand Down Expand Up @@ -1108,7 +1107,7 @@ static PyObject*
get_const_value(int opcode, int oparg, PyObject *co_consts)
{
PyObject *constant = NULL;
assert(HAS_CONST(opcode));
assert(OPCODE_HAS_CONST(opcode));
if (opcode == LOAD_CONST) {
constant = PyList_GET_ITEM(co_consts, oparg);
}
Expand Down Expand Up @@ -1139,7 +1138,7 @@ fold_tuple_on_constants(PyObject *const_cache,
assert(inst[n].i_oparg == n);

for (int i = 0; i < n; i++) {
if (!HAS_CONST(inst[i].i_opcode)) {
if (!OPCODE_HAS_CONST(inst[i].i_opcode)) {
return SUCCESS;
}
}
Expand Down Expand Up @@ -1542,8 +1541,8 @@ optimize_basic_block(PyObject *const_cache, basicblock *bb, PyObject *consts)
}
break;
default:
/* All HAS_CONST opcodes should be handled with LOAD_CONST */
assert (!HAS_CONST(inst->i_opcode));
/* All OPCODE_HAS_CONST opcodes should be handled with LOAD_CONST */
assert (!OPCODE_HAS_CONST(inst->i_opcode));
}
}

Expand Down Expand Up @@ -1793,7 +1792,7 @@ remove_unused_consts(basicblock *entryblock, PyObject *consts)
/* mark used consts */
for (basicblock *b = entryblock; b != NULL; b = b->b_next) {
for (int i = 0; i < b->b_iused; i++) {
if (HAS_CONST(b->b_instr[i].i_opcode)) {
if (OPCODE_HAS_CONST(b->b_instr[i].i_opcode)) {
int index = b->b_instr[i].i_oparg;
index_map[index] = index;
}
Expand Down Expand Up @@ -1846,7 +1845,7 @@ remove_unused_consts(basicblock *entryblock, PyObject *consts)

for (basicblock *b = entryblock; b != NULL; b = b->b_next) {
for (int i = 0; i < b->b_iused; i++) {
if (HAS_CONST(b->b_instr[i].i_opcode)) {
if (OPCODE_HAS_CONST(b->b_instr[i].i_opcode)) {
int index = b->b_instr[i].i_oparg;
assert(reverse_index_map[index] >= 0);
assert(reverse_index_map[index] < n_used_consts);
Expand Down