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-101907: Stop using _Py_OPCODE and _Py_OPARG macros #101912

Merged
merged 8 commits into from
Feb 20, 2023
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 22 additions & 8 deletions Include/cpython/code.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,21 +19,35 @@ extern "C" {
typedef union {
uint16_t cache;
struct {
uint8_t opcode;
uint8_t oparg;
};
uint8_t code;
uint8_t arg;
} op;
} _Py_CODEUNIT;

#define _Py_OPCODE(word) ((word).opcode)
#define _Py_OPARG(word) ((word).oparg)

/* These macros only remain defined for compatibility. */
#define _Py_OPCODE(word) ((word).op.code)
#define _Py_OPARG(word) ((word).op.arg)

static inline uint16_t
_py_make_codeunit(uint8_t opcode, uint8_t oparg)
{
// No designated initialisers because of C++ compat
_Py_CODEUNIT word;
word.op.code = opcode;
word.op.arg = oparg;
return word.cache;
}

static inline void
_py_set_opcode(_Py_CODEUNIT *word, uint8_t opcode)
_py_set_opcode(_Py_CODEUNIT *word, uint16_t packed_opcode)
{
word->opcode = opcode;
word->cache = packed_opcode;
zooba marked this conversation as resolved.
Show resolved Hide resolved
}

#define _Py_SET_OPCODE(word, opcode) _py_set_opocde(&(word), opcode)
#define _Py_MAKE_CODEUNIT(opcode, oparg) _py_make_codeunit((opcode), (oparg))
#define _Py_SET_OPCODE(word, opcode) _py_set_opcode(&(word), opcode)


typedef struct {
PyObject *_co_code;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Removes use of non-standard C++ extension in public header files.
20 changes: 10 additions & 10 deletions Objects/codeobject.c
Original file line number Diff line number Diff line change
Expand Up @@ -413,7 +413,7 @@ init_code(PyCodeObject *co, struct _PyCodeConstructor *con)
PyBytes_GET_SIZE(con->code));
int entry_point = 0;
while (entry_point < Py_SIZE(co) &&
_Py_OPCODE(_PyCode_CODE(co)[entry_point]) != RESUME) {
_PyCode_CODE(co)[entry_point].op.code != RESUME) {
entry_point++;
}
co->_co_firsttraceable = entry_point;
Expand Down Expand Up @@ -1505,12 +1505,12 @@ deopt_code(_Py_CODEUNIT *instructions, Py_ssize_t len)
{
for (int i = 0; i < len; i++) {
_Py_CODEUNIT instruction = instructions[i];
int opcode = _PyOpcode_Deopt[_Py_OPCODE(instruction)];
int opcode = _PyOpcode_Deopt[instruction.op.code];
int caches = _PyOpcode_Caches[opcode];
instructions[i].opcode = opcode;
instructions[i].op.code = opcode;
while (caches--) {
instructions[++i].opcode = CACHE;
instructions[i].oparg = 0;
instructions[++i].op.code = CACHE;
instructions[i].op.arg = 0;
}
}
}
Expand Down Expand Up @@ -1763,13 +1763,13 @@ code_richcompare(PyObject *self, PyObject *other, int op)
for (int i = 0; i < Py_SIZE(co); i++) {
_Py_CODEUNIT co_instr = _PyCode_CODE(co)[i];
_Py_CODEUNIT cp_instr = _PyCode_CODE(cp)[i];
co_instr.opcode = _PyOpcode_Deopt[_Py_OPCODE(co_instr)];
cp_instr.opcode =_PyOpcode_Deopt[_Py_OPCODE(cp_instr)];
co_instr.op.code = _PyOpcode_Deopt[co_instr.op.code];
cp_instr.op.code = _PyOpcode_Deopt[cp_instr.op.code];
eq = co_instr.cache == cp_instr.cache;
if (!eq) {
goto unequal;
}
i += _PyOpcode_Caches[_Py_OPCODE(co_instr)];
i += _PyOpcode_Caches[co_instr.op.code];
}

/* compare constants */
Expand Down Expand Up @@ -1848,9 +1848,9 @@ code_hash(PyCodeObject *co)
SCRAMBLE_IN(co->co_firstlineno);
SCRAMBLE_IN(Py_SIZE(co));
for (int i = 0; i < Py_SIZE(co); i++) {
int deop = _PyOpcode_Deopt[_Py_OPCODE(_PyCode_CODE(co)[i])];
int deop = _PyOpcode_Deopt[_PyCode_CODE(co)[i].op.code];
SCRAMBLE_IN(deop);
SCRAMBLE_IN(_Py_OPARG(_PyCode_CODE(co)[i]));
SCRAMBLE_IN(_PyCode_CODE(co)[i].op.arg);
i += _PyOpcode_Caches[deop];
}
if ((Py_hash_t)uhash == -1) {
Expand Down
24 changes: 12 additions & 12 deletions Objects/frameobject.c
Original file line number Diff line number Diff line change
Expand Up @@ -111,13 +111,13 @@ static unsigned int
get_arg(const _Py_CODEUNIT *codestr, Py_ssize_t i)
{
_Py_CODEUNIT word;
unsigned int oparg = _Py_OPARG(codestr[i]);
if (i >= 1 && _Py_OPCODE(word = codestr[i-1]) == EXTENDED_ARG) {
oparg |= _Py_OPARG(word) << 8;
if (i >= 2 && _Py_OPCODE(word = codestr[i-2]) == EXTENDED_ARG) {
oparg |= _Py_OPARG(word) << 16;
if (i >= 3 && _Py_OPCODE(word = codestr[i-3]) == EXTENDED_ARG) {
oparg |= _Py_OPARG(word) << 24;
unsigned int oparg = codestr[i].op.arg;
if (i >= 1 && (word = codestr[i-1]).op.code == EXTENDED_ARG) {
oparg |= word.op.arg << 8;
if (i >= 2 && (word = codestr[i-2]).op.code == EXTENDED_ARG) {
oparg |= word.op.arg << 16;
if (i >= 3 && (word = codestr[i-3]).op.code == EXTENDED_ARG) {
oparg |= word.op.arg << 24;
}
}
}
Expand Down Expand Up @@ -304,7 +304,7 @@ mark_stacks(PyCodeObject *code_obj, int len)
if (next_stack == UNINITIALIZED) {
continue;
}
opcode = _Py_OPCODE(code[i]);
opcode = code[i].op.code;
switch (opcode) {
case JUMP_IF_FALSE_OR_POP:
case JUMP_IF_TRUE_OR_POP:
Expand Down Expand Up @@ -610,7 +610,7 @@ _PyFrame_GetState(PyFrameObject *frame)
if (_PyInterpreterFrame_LASTI(frame->f_frame) < 0) {
return FRAME_CREATED;
}
switch (_Py_OPCODE(*frame->f_frame->prev_instr))
switch (frame->f_frame->prev_instr->op.code)
{
case COPY_FREE_VARS:
case MAKE_CELL:
Expand Down Expand Up @@ -1092,8 +1092,8 @@ _PyFrame_OpAlreadyRan(_PyInterpreterFrame *frame, int opcode, int oparg)
for (_Py_CODEUNIT *instruction = _PyCode_CODE(frame->f_code);
instruction < frame->prev_instr; instruction++)
{
int check_opcode = _PyOpcode_Deopt[_Py_OPCODE(*instruction)];
check_oparg |= _Py_OPARG(*instruction);
int check_opcode = _PyOpcode_Deopt[instruction->op.code];
check_oparg |= instruction->op.arg;
if (check_opcode == opcode && check_oparg == oparg) {
return 1;
}
Expand All @@ -1117,7 +1117,7 @@ frame_init_get_vars(_PyInterpreterFrame *frame)
// here:
PyCodeObject *co = frame->f_code;
int lasti = _PyInterpreterFrame_LASTI(frame);
if (!(lasti < 0 && _Py_OPCODE(_PyCode_CODE(co)[0]) == COPY_FREE_VARS
if (!(lasti < 0 && _PyCode_CODE(co)->op.code == COPY_FREE_VARS
&& PyFunction_Check(frame->f_funcobj)))
{
/* Free vars are initialized */
Expand Down
10 changes: 5 additions & 5 deletions Objects/genobject.c
Original file line number Diff line number Diff line change
Expand Up @@ -332,11 +332,11 @@ _PyGen_yf(PyGenObject *gen)
/* Return immediately if the frame didn't start yet. SEND
always come after LOAD_CONST: a code object should not start
with SEND */
assert(_Py_OPCODE(_PyCode_CODE(gen->gi_code)[0]) != SEND);
assert(_PyCode_CODE(gen->gi_code)[0].op.code != SEND);
return NULL;
}
_Py_CODEUNIT next = frame->prev_instr[1];
if (_Py_OPCODE(next) != RESUME || _Py_OPARG(next) < 2)
if (next.op.code != RESUME || next.op.arg < 2)
{
/* Not in a yield from */
return NULL;
Expand Down Expand Up @@ -371,9 +371,9 @@ gen_close(PyGenObject *gen, PyObject *args)
_PyInterpreterFrame *frame = (_PyInterpreterFrame *)gen->gi_iframe;
/* It is possible for the previous instruction to not be a
* YIELD_VALUE if the debugger has changed the lineno. */
if (err == 0 && frame->prev_instr->opcode == YIELD_VALUE) {
assert(frame->prev_instr[1].opcode == RESUME);
int exception_handler_depth = frame->prev_instr->oparg;
if (err == 0 && frame->prev_instr[0].op.code == YIELD_VALUE) {
assert(frame->prev_instr[1].op.code == RESUME);
int exception_handler_depth = frame->prev_instr[0].op.code;
assert(exception_handler_depth > 0);
/* We can safely ignore the outermost try block
* as it automatically generated to handle
Expand Down
4 changes: 2 additions & 2 deletions Objects/typeobject.c
Original file line number Diff line number Diff line change
Expand Up @@ -9507,8 +9507,8 @@ super_init_without_args(_PyInterpreterFrame *cframe, PyCodeObject *co,
if (_PyInterpreterFrame_LASTI(cframe) >= 0) {
// MAKE_CELL and COPY_FREE_VARS have no quickened forms, so no need
// to use _PyOpcode_Deopt here:
assert(_Py_OPCODE(_PyCode_CODE(co)[0]) == MAKE_CELL ||
_Py_OPCODE(_PyCode_CODE(co)[0]) == COPY_FREE_VARS);
assert(_PyCode_CODE(co)[0].op.code == MAKE_CELL ||
_PyCode_CODE(co)[0].op.code == COPY_FREE_VARS);
assert(PyCell_Check(firstarg));
firstarg = PyCell_GET(firstarg);
}
Expand Down
34 changes: 17 additions & 17 deletions Python/bytecodes.c
Original file line number Diff line number Diff line change
Expand Up @@ -246,9 +246,9 @@ dummy_func(
DEOPT_IF(!PyUnicode_CheckExact(left), BINARY_OP);
DEOPT_IF(Py_TYPE(right) != Py_TYPE(left), BINARY_OP);
_Py_CODEUNIT true_next = next_instr[INLINE_CACHE_ENTRIES_BINARY_OP];
assert(_Py_OPCODE(true_next) == STORE_FAST ||
_Py_OPCODE(true_next) == STORE_FAST__LOAD_FAST);
PyObject **target_local = &GETLOCAL(_Py_OPARG(true_next));
assert(true_next.op.code == STORE_FAST ||
true_next.op.code == STORE_FAST__LOAD_FAST);
PyObject **target_local = &GETLOCAL(true_next.op.arg);
DEOPT_IF(*target_local != left, BINARY_OP);
STAT_INC(BINARY_OP, hit);
/* Handle `left = left + right` or `left += right` for str.
Expand Down Expand Up @@ -1745,10 +1745,10 @@ dummy_func(
Py_DECREF(left);
Py_DECREF(right);
ERROR_IF(cond == NULL, error);
assert(_Py_OPCODE(next_instr[1]) == POP_JUMP_IF_FALSE ||
_Py_OPCODE(next_instr[1]) == POP_JUMP_IF_TRUE);
bool jump_on_true = _Py_OPCODE(next_instr[1]) == POP_JUMP_IF_TRUE;
int offset = _Py_OPARG(next_instr[1]);
assert(next_instr[1].op.code == POP_JUMP_IF_FALSE ||
next_instr[1].op.code == POP_JUMP_IF_TRUE);
bool jump_on_true = next_instr[1].op.code == POP_JUMP_IF_TRUE;
int offset = next_instr[1].op.arg;
int err = PyObject_IsTrue(cond);
Py_DECREF(cond);
if (err < 0) {
Expand All @@ -1771,7 +1771,7 @@ dummy_func(
_Py_DECREF_SPECIALIZED(left, _PyFloat_ExactDealloc);
_Py_DECREF_SPECIALIZED(right, _PyFloat_ExactDealloc);
if (sign_ish & oparg) {
int offset = _Py_OPARG(next_instr[1]);
int offset = next_instr[1].op.arg;
JUMPBY(offset);
}
}
Expand All @@ -1792,7 +1792,7 @@ dummy_func(
_Py_DECREF_SPECIALIZED(left, (destructor)PyObject_Free);
_Py_DECREF_SPECIALIZED(right, (destructor)PyObject_Free);
if (sign_ish & oparg) {
int offset = _Py_OPARG(next_instr[1]);
int offset = next_instr[1].op.arg;
JUMPBY(offset);
}
}
Expand All @@ -1811,7 +1811,7 @@ dummy_func(
assert((oparg & 0xf) == COMPARISON_NOT_EQUALS || (oparg & 0xf) == COMPARISON_EQUALS);
assert(COMPARISON_NOT_EQUALS + 1 == COMPARISON_EQUALS);
if ((res + COMPARISON_NOT_EQUALS) & oparg) {
int offset = _Py_OPARG(next_instr[1]);
int offset = next_instr[1].op.arg;
JUMPBY(offset);
}
}
Expand Down Expand Up @@ -2119,7 +2119,7 @@ dummy_func(
_PyErr_Clear(tstate);
}
/* iterator ended normally */
assert(_Py_OPCODE(next_instr[INLINE_CACHE_ENTRIES_FOR_ITER + oparg]) == END_FOR);
assert(next_instr[INLINE_CACHE_ENTRIES_FOR_ITER + oparg].op.code == END_FOR);
Py_DECREF(iter);
STACK_SHRINK(1);
/* Jump forward oparg, then skip following END_FOR instruction */
Expand Down Expand Up @@ -2183,7 +2183,7 @@ dummy_func(
DEOPT_IF(Py_TYPE(r) != &PyRangeIter_Type, FOR_ITER);
STAT_INC(FOR_ITER, hit);
_Py_CODEUNIT next = next_instr[INLINE_CACHE_ENTRIES_FOR_ITER];
assert(_PyOpcode_Deopt[_Py_OPCODE(next)] == STORE_FAST);
assert(_PyOpcode_Deopt[next.op.code] == STORE_FAST);
if (r->len <= 0) {
STACK_SHRINK(1);
Py_DECREF(r);
Expand All @@ -2194,7 +2194,7 @@ dummy_func(
long value = r->start;
r->start = value + r->step;
r->len--;
if (_PyLong_AssignValue(&GETLOCAL(_Py_OPARG(next)), value) < 0) {
if (_PyLong_AssignValue(&GETLOCAL(next.op.arg), value) < 0) {
goto error;
}
// The STORE_FAST is already done.
Expand All @@ -2217,7 +2217,7 @@ dummy_func(
gen->gi_exc_state.previous_item = tstate->exc_info;
tstate->exc_info = &gen->gi_exc_state;
JUMPBY(INLINE_CACHE_ENTRIES_FOR_ITER + oparg);
assert(_Py_OPCODE(*next_instr) == END_FOR);
assert(next_instr->op.code == END_FOR);
DISPATCH_INLINED(gen_frame);
}

Expand Down Expand Up @@ -2806,7 +2806,7 @@ dummy_func(
STACK_SHRINK(3);
// CALL + POP_TOP
JUMPBY(INLINE_CACHE_ENTRIES_CALL + 1);
assert(_Py_OPCODE(next_instr[-1]) == POP_TOP);
assert(next_instr[-1].op.code == POP_TOP);
DISPATCH();
}

Expand Down Expand Up @@ -3115,8 +3115,8 @@ dummy_func(
inst(EXTENDED_ARG, (--)) {
assert(oparg);
assert(cframe.use_tracing == 0);
opcode = _Py_OPCODE(*next_instr);
oparg = oparg << 8 | _Py_OPARG(*next_instr);
opcode = next_instr->op.code;
oparg = oparg << 8 | next_instr->op.arg;
PRE_DISPATCH_GOTO();
DISPATCH_GOTO();
}
Expand Down
12 changes: 6 additions & 6 deletions Python/ceval.c
Original file line number Diff line number Diff line change
Expand Up @@ -132,8 +132,8 @@ lltrace_instruction(_PyInterpreterFrame *frame,
objects enters the interpreter recursively. It is also slow.
So you might want to comment it out. */
dump_stack(frame, stack_pointer);
int oparg = _Py_OPARG(*next_instr);
int opcode = _Py_OPCODE(*next_instr);
int oparg = next_instr->op.arg;
int opcode = next_instr->op.code;
const char *opname = _PyOpcode_OpName[opcode];
assert(opname != NULL);
int offset = (int)(next_instr - _PyCode_CODE(frame->f_code));
Expand Down Expand Up @@ -920,8 +920,8 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int
// CPython hasn't ever traced the instruction after an EXTENDED_ARG.
// Inline the EXTENDED_ARG here, so we can avoid branching there:
INSTRUCTION_START(EXTENDED_ARG);
opcode = _Py_OPCODE(*next_instr);
oparg = oparg << 8 | _Py_OPARG(*next_instr);
opcode = next_instr->op.code;
oparg = oparg << 8 | next_instr->op.arg;
// Make sure the next instruction isn't a RESUME, since that needs
// to trace properly (and shouldn't have an EXTENDED_ARG, anyways):
assert(opcode != RESUME);
Expand All @@ -946,7 +946,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int
#endif
/* Tell C compilers not to hold the opcode variable in the loop.
next_instr points the current instruction without TARGET(). */
opcode = _Py_OPCODE(*next_instr);
opcode = next_instr->op.code;
_PyErr_Format(tstate, PyExc_SystemError,
"%U:%d: unknown opcode %d",
frame->f_code->co_filename,
Expand Down Expand Up @@ -2194,7 +2194,7 @@ maybe_call_line_trace(Py_tracefunc func, PyObject *obj,
(_PyInterpreterFrame_LASTI(frame) < instr_prev &&
// SEND has no quickened forms, so no need to use _PyOpcode_Deopt
// here:
_Py_OPCODE(*frame->prev_instr) != SEND);
frame->prev_instr->op.code != SEND);
if (trace) {
result = call_trace(func, obj, tstate, frame, PyTrace_LINE, Py_None);
}
Expand Down
18 changes: 9 additions & 9 deletions Python/ceval_macros.h
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@

#define DISPATCH_SAME_OPARG() \
{ \
opcode = _Py_OPCODE(*next_instr); \
opcode = next_instr->op.code; \
PRE_DISPATCH_GOTO(); \
opcode |= cframe.use_tracing OR_DTRACE_LINE; \
DISPATCH_GOTO(); \
Expand Down Expand Up @@ -143,8 +143,8 @@ GETITEM(PyObject *v, Py_ssize_t i) {
#define INSTR_OFFSET() ((int)(next_instr - _PyCode_CODE(frame->f_code)))
#define NEXTOPARG() do { \
_Py_CODEUNIT word = *next_instr; \
opcode = _Py_OPCODE(word); \
oparg = _Py_OPARG(word); \
opcode = word.op.code; \
oparg = word.op.arg; \
} while (0)
#define JUMPTO(x) (next_instr = _PyCode_CODE(frame->f_code) + (x))
#define JUMPBY(x) (next_instr += (x))
Expand Down Expand Up @@ -180,14 +180,14 @@ GETITEM(PyObject *v, Py_ssize_t i) {
#if USE_COMPUTED_GOTOS
#define PREDICT(op) if (0) goto PREDICT_ID(op)
#else
#define PREDICT(op) \
#define PREDICT(next_op) \
do { \
_Py_CODEUNIT word = *next_instr; \
opcode = _Py_OPCODE(word) | cframe.use_tracing OR_DTRACE_LINE; \
if (opcode == op) { \
oparg = _Py_OPARG(word); \
INSTRUCTION_START(op); \
goto PREDICT_ID(op); \
opcode = word.op.code | cframe.use_tracing OR_DTRACE_LINE; \
if (opcode == next_op) { \
oparg = word.op.arg; \
INSTRUCTION_START(next_op); \
goto PREDICT_ID(next_op); \
} \
} while(0)
#endif
Expand Down
Loading