8000 gh-105481: remove HAS_ARG, HAS_CONST, IS_JUMP_OPCODE, IS_PSEUDO_OPCOD… · python/cpython@14d0126 · GitHub
[go: up one dir, main page]

Skip to content

Commit 14d0126

Browse files
authored
gh-105481: remove HAS_ARG, HAS_CONST, IS_JUMP_OPCODE, IS_PSEUDO_OPCODE and replace by their new versions (#105865)
1 parent 34e93d3 commit 14d0126

File tree

12 files changed

+38
-138
lines changed

12 files changed

+38
-138
lines changed

Doc/library/dis.rst

+6
Original file line numberDiff line numberDiff line change
@@ -318,6 +318,12 @@ operation is being performed, so the intermediate analysis object isn't useful:
318318
.. versionchanged:: 3.8
319319
Added *jump* parameter.
320320

321+
.. versionchanged:: 3.13
322+
If ``oparg`` is omitted (or ``None``), the stack effect is now returned
323+
for ``oparg=0``. Previously this was an error for opcodes that use their
324+
arg. It is also no longer an error to pass an integer ``oparg`` when
325+
the ``opcode`` does not use it; the ``oparg`` in this case is ignored.
326+
321327

322328
.. _bytecodes:
323329

Include/internal/pycore_opcode.h

-13
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Include/internal/pycore_opcode_utils.h

+1-25
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,7 @@ extern "C" {
1515

1616
#define IS_WITHIN_OPCODE_RANGE(opcode) \
1717
(((opcode) >= 0 && (opcode) <= MAX_REAL_OPCODE) || \
18-
IS_PSEUDO_OPCODE(opcode))
19-
20-
#define IS_JUMP_OPCODE(opcode) \
21-
is_bit_set_in_table(_PyOpcode_Jump, opcode)
18+
IS_PSEUDO_INSTR(opcode))
2219

2320
#define IS_BLOCK_PUSH_OPCODE(opcode) \
2421
((opcode) == SETUP_FINALLY || \
@@ -55,27 +52,6 @@ extern "C" {
5552
(opcode) == RAISE_VARARGS || \
5653
(opcode) == RERAISE)
5754

58-
#define LOG_BITS_PER_INT 5
59-
#define MASK_LOW_LOG_BITS 31
60-
61-
static inline int
62-
is_bit_set_in_table(const uint32_t *table, int bitindex) {
63-
/* Is the relevant bit set in the relevant word? */
64-
/* 512 bits fit into 9 32-bits words.
65-
* Word is indexed by (bitindex>>ln(size of int in bits)).
66-
* Bit within word is the low bits of bitindex.
67-
*/
68-
if (bitindex >= 0 && bitindex < 512) {
69-
uint32_t word = table[bitindex >> LOG_BITS_PER_INT];
70-
return (word >> (bitindex & MASK_LOW_LOG_BITS)) & 1;
71-
}
72-
else {
73-
return 0;
74-
}
75-
}
76-
77-
#undef LOG_BITS_PER_INT
78-
#undef MASK_LOW_LOG_BITS
7955

8056
/* Flags used in the oparg for MAKE_FUNCTION */
8157
#define MAKE_FUNCTION_DEFAULTS 0x01

Include/opcode.h

-19
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Lib/test/test__opcode.py

+2-8
< F438 /div>
Original file line numberDiff line numberDiff line change
@@ -15,20 +15,14 @@ def test_stack_effect(self):
1515
self.assertEqual(stack_effect(dis.opmap['BUILD_SLICE'], 1), -1)
1616
self.assertEqual(stack_effect(dis.opmap['BUILD_SLICE'], 3), -2)
1717
self.assertRaises(ValueError, stack_effect, 30000)
18-
self.assertRaises(ValueError, stack_effect, dis.opmap['BUILD_SLICE'])
19-
self.assertRaises(ValueError, stack_effect, dis.opmap['POP_TOP'], 0)
2018
# All defined opcodes
2119
has_arg = dis.hasarg
2220
for name, code in filter(lambda item: item[0] not in dis.deoptmap, dis.opmap.items()):
2321
if code >= opcode.MIN_INSTRUMENTED_OPCODE:
2422
continue
2523
with self.subTest(opname=name):
26-
if code not in has_arg:
27-
stack_effect(code)
28-
self.assertRaises(ValueError, stack_effect, code, 0)
29-
else:
30-
stack_effect(code, 0)
31-
self.assertRaises(ValueError, stack_effect, code)
24+
stack_effect(code)
25+
stack_effect(code, 0)
3226
# All not defined opcodes
3327
for code in set(range(256)) - set(dis.opmap.values()):
3428
with self.subTest(opcode=code):
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
:func:`~dis.stack_effect` no longer raises an exception if an ``oparg`` is
2+
provided for an ``opcode`` that doesn't use its arg, or when it is not
3+
provided for an ``opcode`` that does use it. In the latter case, the stack
4+
effect is returned for ``oparg=0``.

Modules/_opcode.c

+6-16
Original file line numberDiff line numberDiff line change
@@ -27,25 +27,16 @@ _opcode_stack_effect_impl(PyObject *module, int opcode, PyObject *oparg,
2727
PyObject *jump)
2828
/*[clinic end generated code: output=64a18f2ead954dbb input=461c9d4a44851898]*/
2929
{
30-
int effect;
3130
int oparg_int = 0;
3231
int jump_int;
33-
if (HAS_ARG(opcode)) {
34-
if (oparg == Py_None) {
35-
PyErr_SetString(PyExc_ValueError,
36-
"stack_effect: opcode requires oparg but oparg was not specified");
37-
return -1;
38-
}
32+
33+
if (oparg != Py_None) {
3934
oparg_int = (int)PyLong_AsLong(oparg);
4035
if ((oparg_int == -1) && PyErr_Occurred()) {
4136
return -1;
4237
}
4338
}
44-
else if (oparg != Py_None) {
45-
PyErr_SetString(PyExc_ValueError,
46-
"stack_effect: opcode does not permit oparg but oparg was specified");
47-
return -1;
48-
}
39+
4940
if (jump == Py_None) {
5041
jump_int = -1;
5142
}
@@ -60,11 +51,10 @@ _opcode_stack_effect_impl(PyObject *module, int opcode, PyObject *oparg,
6051
"stack_effect: jump must be False, True or None");
6152
return -1;
6253
}
63-
effect = PyCompile_OpcodeStackEffectWithJump(opcode, oparg_int, jump_int);
54+
int effect = PyCompile_OpcodeStackEffectWithJump(opcode, oparg_int, jump_int);
6455
if (effect == PY_INVALID_STACK_EFFECT) {
65-
PyErr_SetString(PyExc_ValueError,
66-
"invalid opcode or oparg");
67-
return -1;
56+
PyErr_SetString(PyExc_ValueError, "invalid opcode or oparg");
57+
return -1;
6858
}
6959
return effect;
7060
}

Python/assemble.c

+1-2
Original file line numberDiff line numberDiff line change
@@ -339,10 +339,9 @@ static void
339339
write_instr(_Py_CODEUNIT *codestr, instruction *instr, int ilen)
340340
{
341341
int opcode = instr->i_opcode;
342-
assert(IS_PSEUDO_OPCODE(opcode) == IS_PSEUDO_INSTR(opcode));
343342
assert(!IS_PSEUDO_INSTR(opcode));
344343
int oparg = instr->i_oparg;
345-
assert(HAS_ARG(opcode) || oparg == 0);
344+
assert(OPCODE_HAS_ARG(opcode) || oparg == 0);
346345
int caches = _PyOpcode_Caches[opcode];
347346
switch (ilen - caches) {
348347
case 4:

Python/ceval.c

+3-2
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
#include "pycore_frame.h"
3030
#include "frameobject.h" // _PyInterpreterFrame_GetLine
3131
#include "opcode.h"
32+
#include "opcode_metadata.h"
3233
#include "pydtrace.h"
3334
#include "setobject.h"
3435
#include "structmember.h" // struct PyMemberDef, T_OFFSET_EX
@@ -141,7 +142,7 @@ lltrace_instruction(_PyInterpreterFrame *frame,
141142
const char *opname = _PyOpcode_OpName[opcode];
142143
assert(opname != NULL);
143144
int offset = (int)(next_instr - _PyCode_CODE(_PyFrame_GetCode(frame)));
144-
if (HAS_ARG((int)_PyOpcode_Deopt[opcode])) {
145+
if (OPCODE_HAS_ARG((int)_PyOpcode_Deopt[opcode])) {
145146
printf("%d: %s %d\n", offset * 2, opname, oparg);
146147
}
147148
else {
@@ -882,7 +883,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int
882883
#if USE_COMPUTED_GOTOS
883884
_unknown_opcode:
884885
#else
885-
EXTRA_CASES // From opcode.h, a 'case' for each unused opcode
886+
EXTRA_CASES // From pycore_opcode.h, a 'case' for each unused opcode
886887
#endif
887888
/* Tell C compilers not to hold the opcode variable in the loop.
888889
next_instr points the current instruction without TARGET(). */

Python/compile.c

+5-12
Original file line numberDiff line numberDiff line change
@@ -134,9 +134,8 @@ enum {
134134
int
135135
_PyCompile_InstrSize(int opcode, int oparg)
136136
{
137-
assert(IS_PSEUDO_OPCODE(opcode) == IS_PSEUDO_INSTR(opcode));
138137
assert(!IS_PSEUDO_INSTR(opcode));
139-
assert(HAS_ARG(opcode) || oparg == 0);
138+
assert(OPCODE_HAS_ARG(opcode) || oparg == 0);
140139
int extended_args = (0xFFFFFF < oparg) + (0xFFFF < oparg) + (0xFF < oparg);
141140
int caches = _PyOpcode_Caches[opcode];
142141
return extended_args + 1 + caches;
@@ -248,15 +247,9 @@ instr_sequence_use_label(instr_sequence *seq, int lbl) {
248247
static int
249248
instr_sequence_addop(instr_sequence *seq, int opcode, int oparg, location loc)
250249
{
251-
/* compare old and new opcode macros - use ! to compare as bools. */
252-
assert(!HAS_ARG(opcode) == !OPCODE_HAS_ARG(opcode));
253-
assert(!HAS_CONST(opcode) == !OPCODE_HAS_CONST(opcode));
254-
assert(!OPCODE_HAS_JUMP(opcode) == !OPCODE_HAS_JUMP(opcode));
255-
256250
assert(0 <= opcode && opcode <= MAX_OPCODE);
257-
assert(IS_PSEUDO_OPCODE(opcode) == IS_PSEUDO_INSTR(opcode));
258251
assert(IS_WITHIN_OPCODE_RANGE(opcode));
259-
assert(HAS_ARG(opcode) || HAS_TARGET(opcode) || oparg == 0);
252+
assert(OPCODE_HAS_ARG(opcode) || HAS_TARGET(opcode) || oparg == 0);
260253
assert(0 <= oparg && oparg < (1 << 30));
261254

262255
int idx = instr_sequence_next_inst(seq);
@@ -874,7 +867,7 @@ PyCompile_OpcodeStackEffect(int opcode, int oparg)
874867
static int
875868
codegen_addop_noarg(instr_sequence *seq, int opcode, location loc)
876869
{
877-
assert(!HAS_ARG(opcode));
870+
assert(!OPCODE_HAS_ARG(opcode));
878871
assert(!IS_ASSEMBLER_OPCODE(opcode));
879872
return instr_sequence_addop(seq, opcode, 0, loc);
880873
}
@@ -1151,7 +1144,7 @@ codegen_addop_j(instr_sequence *seq, location loc,
11511144
}
11521145

11531146
#define ADDOP_N(C, LOC, OP, O, TYPE) { \
1154-
assert(!HAS_CONST(OP)); /* use ADDOP_LOAD_CONST_NEW */ \
1147+
assert(!OPCODE_HAS_CONST(OP)); /* use ADDOP_LOAD_CONST_NEW */ \
11551148
if (compiler_addop_o((C)->u, (LOC), (OP), (C)->u->u_metadata.u_ ## TYPE, (O)) < 0) { \
11561149
Py_DECREF((O)); \
11571150
return ERROR; \
@@ -7798,7 +7791,7 @@ instructions_to_instr_sequence(PyObject *instructions, instr_sequence *seq)
77987791
goto error;
77997792
}
78007793
int oparg;
7801-
if (HAS_ARG(opcode)) {
7794+
if (OPCODE_HAS_ARG(opcode)) {
78027795
oparg = PyLong_AsLong(PyTuple_GET_ITEM(item, 1));
78037796
if (PyErr_Occurred()) {
78047797
goto error;

Python/flowgraph.c

+10-11
Original file line numberDiff line numberDiff line change
@@ -45,14 +45,13 @@ is_block_push(cfg_instr *i)
4545
static inline int
4646
is_jump(cfg_instr *i)
4747
{
48-
assert(!OPCODE_HAS_JUMP(i->i_opcode) == !IS_JUMP_OPCODE(i->i_opcode));
4948
return OPCODE_HAS_JUMP(i->i_opcode);
5049
}
5150

5251
/* One arg*/
5352
#define INSTR_SET_OP1(I, OP, ARG) \
5453
do { \
55-
assert(HAS_ARG(OP)); \
54+
assert(OPCODE_HAS_ARG(OP)); \
5655
_PyCfgInstruction *_instr__ptr_ = (I); \
5756
_instr__ptr_->i_opcode = (OP); \
5857
_instr__ptr_->i_oparg = (ARG); \
@@ -61,7 +60,7 @@ is_jump(cfg_instr *i)
6160
/* No args*/
6261
#define INSTR_SET_OP0(I, OP) \
6362
do { \
64-
assert(!HAS_ARG(OP)); \
63+
assert(!OPCODE_HAS_ARG(OP)); \
6564
_PyCfgInstruction *_instr__ptr_ = (I); \
6665
_instr__ptr_->i_opcode = (OP); \
6766
_instr__ptr_->i_oparg = 0; \
@@ -111,7 +110,7 @@ basicblock_addop(basicblock *b, int opcode, int oparg, location loc)
111110
{
112111
assert(IS_WITHIN_OPCODE_RANGE(opcode));
113112
assert(!IS_ASSEMBLER_OPCODE(opcode));
114-
assert(HAS_ARG(opcode) || HAS_TARGET(opcode) || oparg == 0);
113+
assert(OPCODE_HAS_ARG(opcode) || HAS_TARGET(opcode) || oparg == 0);
115114
assert(0 <= oparg && oparg < (1 << 30));
116115

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

195194
*arg = '\0';
196-
if (HAS_ARG(i->i_opcode)) {
195+
if (OPCODE_HAS_ARG(i->i_opcode)) {
197196
sprintf(arg, "arg: %d ", i->i_oparg);
198197
}
199198
if (HAS_TARGET(i->i_opcode)) {
@@ -1108,7 +1107,7 @@ static PyObject*
11081107
get_const_value(int opcode, int oparg, PyObject *co_consts)
11091108
{
11101109
PyObject *constant = NULL;
1111-
assert(HAS_CONST(opcode));
1110+
assert(OPCODE_HAS_CONST(opcode));
11121111
if (opcode == LOAD_CONST) {
11131112
constant = PyList_GET_ITEM(co_consts, oparg);
11141113
}
@@ -1139,7 +1138,7 @@ fold_tuple_on_constants(PyObject *const_cache,
11391138
assert(inst[n].i_oparg == n);
11401139

11411140
for (int i = 0; i < n; i++) {
1142-
if (!HAS_CONST(inst[i].i_opcode)) {
1141+
if (!OPCODE_HAS_CONST(inst[i].i_opcode)) {
11431142
return SUCCESS;
11441143
}
11451144
}
@@ -1542,8 +1541,8 @@ optimize_basic_block(PyObject *const_cache, basicblock *bb, PyObject *consts)
15421541
}
15431542
break;
15441543
default:
1545-
/* All HAS_CONST opcodes should be handled with LOAD_CONST */
1546-
assert (!HAS_CONST(inst->i_opcode));
1544+
/* All OPCODE_HAS_CONST opcodes should be handled with LOAD_CONST */
1545+
assert (!OPCODE_HAS_CONST(inst->i_opcode));
15471546
}
15481547
}
15491548

@@ -1793,7 +1792,7 @@ remove_unused_consts(basicblock *entryblock, PyObject *consts)
17931792
/* mark used consts */
17941793
for (basicblock *b = entryblock; b != NULL; b = b->b_next) {
17951794
for (int i = 0; i < b->b_iused; i++) {
1796-
if (HAS_CONST(b->b_instr[i].i_opcode)) {
1795+
if (OPCODE_HAS_CONST(b->b_instr[i].i_opcode)) {
17971796
int index = b->b_instr[i].i_oparg;
17981797
index_map[index] = index;
17991798
}
@@ -1846,7 +1845,7 @@ remove_unused_consts(basicblock *entryblock, PyObject *consts)
18461845

18471846
for (basicblock *b = entryblock; b != NULL; b = b->b_next) {
18481847
for (int i = 0; i < b->b_iused; i++) {
1849-
if (HAS_CONST(b->b_instr[i].i_opcode)) {
1848+
if (OPCODE_HAS_CONST(b->b_instr[i].i_opcode)) {
18501849
int index = b->b_instr[i].i_oparg;
18511850
assert(reverse_index_map[index] >= 0);
18521851
assert(reverse_index_map[index] < n_used_consts);

0 commit comments

Comments
 (0)
0