Commit ab874005 authored by Serhiy Storchaka's avatar Serhiy Storchaka

Issue #27129: Replaced wordcode related magic constants with macros.

parent bdb847ae
...@@ -7,6 +7,16 @@ ...@@ -7,6 +7,16 @@
extern "C" { extern "C" {
#endif #endif
typedef uint16_t _Py_CODEUNIT;
#ifdef WORDS_BIGENDIAN
# define _Py_OPCODE(word) ((word) >> 8)
# define _Py_OPARG(word) ((word) & 255)
#else
# define _Py_OPCODE(word) ((word) & 255)
# define _Py_OPARG(word) ((word) >> 8)
#endif
/* Bytecode object */ /* Bytecode object */
typedef struct { typedef struct {
PyObject_HEAD PyObject_HEAD
......
...@@ -189,7 +189,7 @@ frame_setlineno(PyFrameObject *f, PyObject* p_new_lineno) ...@@ -189,7 +189,7 @@ frame_setlineno(PyFrameObject *f, PyObject* p_new_lineno)
memset(blockstack, '\0', sizeof(blockstack)); memset(blockstack, '\0', sizeof(blockstack));
memset(in_finally, '\0', sizeof(in_finally)); memset(in_finally, '\0', sizeof(in_finally));
blockstack_top = 0; blockstack_top = 0;
for (addr = 0; addr < code_len; addr += 2) { for (addr = 0; addr < code_len; addr += sizeof(_Py_CODEUNIT)) {
unsigned char op = code[addr]; unsigned char op = code[addr];
switch (op) { switch (op) {
case SETUP_LOOP: case SETUP_LOOP:
...@@ -273,7 +273,7 @@ frame_setlineno(PyFrameObject *f, PyObject* p_new_lineno) ...@@ -273,7 +273,7 @@ frame_setlineno(PyFrameObject *f, PyObject* p_new_lineno)
* can tell whether the jump goes into any blocks without coming out * can tell whether the jump goes into any blocks without coming out
* again - in that case we raise an exception below. */ * again - in that case we raise an exception below. */
delta_iblock = 0; delta_iblock = 0;
for (addr = min_addr; addr < max_addr; addr += 2) { for (addr = min_addr; addr < max_addr; addr += sizeof(_Py_CODEUNIT)) {
unsigned char op = code[addr]; unsigned char op = code[addr];
switch (op) { switch (op) {
case SETUP_LOOP: case SETUP_LOOP:
......
...@@ -390,7 +390,7 @@ _PyGen_yf(PyGenObject *gen) ...@@ -390,7 +390,7 @@ _PyGen_yf(PyGenObject *gen)
PyObject *bytecode = f->f_code->co_code; PyObject *bytecode = f->f_code->co_code;
unsigned char *code = (unsigned char *)PyBytes_AS_STRING(bytecode); unsigned char *code = (unsigned char *)PyBytes_AS_STRING(bytecode);
if (code[f->f_lasti + 2] != YIELD_FROM) if (code[f->f_lasti + sizeof(_Py_CODEUNIT)] != YIELD_FROM)
return NULL; return NULL;
yf = f->f_stacktop[-1]; yf = f->f_stacktop[-1];
Py_INCREF(yf); Py_INCREF(yf);
...@@ -498,7 +498,7 @@ _gen_throw(PyGenObject *gen, int close_on_genexit, ...@@ -498,7 +498,7 @@ _gen_throw(PyGenObject *gen, int close_on_genexit,
assert(ret == yf); assert(ret == yf);
Py_DECREF(ret); Py_DECREF(ret);
/* Termination repetition of YIELD_FROM */ /* Termination repetition of YIELD_FROM */
gen->gi_frame->f_lasti += 2; gen->gi_frame->f_lasti += sizeof(_Py_CODEUNIT);
if (_PyGen_FetchStopIterationValue(&val) == 0) { if (_PyGen_FetchStopIterationValue(&val) == 0) {
ret = gen_send_ex(gen, val, 0, 0); ret = gen_send_ex(gen, val, 0, 0);
Py_DECREF(val); Py_DECREF(val);
......
...@@ -62,7 +62,7 @@ static int import_all_from(PyObject *, PyObject *); ...@@ -62,7 +62,7 @@ static int import_all_from(PyObject *, PyObject *);
static void format_exc_check_arg(PyObject *, const char *, PyObject *); static void format_exc_check_arg(PyObject *, const char *, PyObject *);
static void format_exc_unbound(PyCodeObject *co, int oparg); static void format_exc_unbound(PyCodeObject *co, int oparg);
static PyObject * unicode_concatenate(PyObject *, PyObject *, static PyObject * unicode_concatenate(PyObject *, PyObject *,
PyFrameObject *, const unsigned short *); PyFrameObject *, const _Py_CODEUNIT *);
static PyObject * special_lookup(PyObject *, _Py_Identifier *); static PyObject * special_lookup(PyObject *, _Py_Identifier *);
#define NAME_ERROR_MSG \ #define NAME_ERROR_MSG \
...@@ -725,7 +725,7 @@ _PyEval_EvalFrameDefault(PyFrameObject *f, int throwflag) ...@@ -725,7 +725,7 @@ _PyEval_EvalFrameDefault(PyFrameObject *f, int throwflag)
int lastopcode = 0; int lastopcode = 0;
#endif #endif
PyObject **stack_pointer; /* Next free slot in value stack */ PyObject **stack_pointer; /* Next free slot in value stack */
const unsigned short *next_instr; const _Py_CODEUNIT *next_instr;
int opcode; /* Current opcode */ int opcode; /* Current opcode */
int oparg; /* Current opcode argument, if any */ int oparg; /* Current opcode argument, if any */
enum why_code why; /* Reason for block stack unwind */ enum why_code why; /* Reason for block stack unwind */
...@@ -743,7 +743,7 @@ _PyEval_EvalFrameDefault(PyFrameObject *f, int throwflag) ...@@ -743,7 +743,7 @@ _PyEval_EvalFrameDefault(PyFrameObject *f, int throwflag)
time it is tested. */ time it is tested. */
int instr_ub = -1, instr_lb = 0, instr_prev = -1; int instr_ub = -1, instr_lb = 0, instr_prev = -1;
const unsigned short *first_instr; const _Py_CODEUNIT *first_instr;
PyObject *names; PyObject *names;
PyObject *consts; PyObject *consts;
...@@ -864,23 +864,16 @@ _PyEval_EvalFrameDefault(PyFrameObject *f, int throwflag) ...@@ -864,23 +864,16 @@ _PyEval_EvalFrameDefault(PyFrameObject *f, int throwflag)
/* Code access macros */ /* Code access macros */
#ifdef WORDS_BIGENDIAN
#define OPCODE(word) ((word) >> 8)
#define OPARG(word) ((word) & 255)
#else
#define OPCODE(word) ((word) & 255)
#define OPARG(word) ((word) >> 8)
#endif
/* The integer overflow is checked by an assertion below. */ /* The integer overflow is checked by an assertion below. */
#define INSTR_OFFSET() (2*(int)(next_instr - first_instr)) #define INSTR_OFFSET() (sizeof(_Py_CODEUNIT) * (int)(next_instr - first_instr))
#define NEXTOPARG() do { \ #define NEXTOPARG() do { \
unsigned short word = *next_instr; \ _Py_CODEUNIT word = *next_instr; \
opcode = OPCODE(word); \ opcode = _Py_OPCODE(word); \
oparg = OPARG(word); \ oparg = _Py_OPARG(word); \
next_instr++; \ next_instr++; \
} while (0) } while (0)
#define JUMPTO(x) (next_instr = first_instr + (x)/2) #define JUMPTO(x) (next_instr = first_instr + (x) / sizeof(_Py_CODEUNIT))
#define JUMPBY(x) (next_instr += (x)/2) #define JUMPBY(x) (next_instr += (x) / sizeof(_Py_CODEUNIT))
/* OpCode prediction macros /* OpCode prediction macros
Some opcodes tend to come in pairs thus making it possible to Some opcodes tend to come in pairs thus making it possible to
...@@ -913,10 +906,10 @@ _PyEval_EvalFrameDefault(PyFrameObject *f, int throwflag) ...@@ -913,10 +906,10 @@ _PyEval_EvalFrameDefault(PyFrameObject *f, int throwflag)
#else #else
#define PREDICT(op) \ #define PREDICT(op) \
do{ \ do{ \
unsigned short word = *next_instr; \ _Py_CODEUNIT word = *next_instr; \
opcode = OPCODE(word); \ opcode = _Py_OPCODE(word); \
if (opcode == op){ \ if (opcode == op){ \
oparg = OPARG(word); \ oparg = _Py_OPARG(word); \
next_instr++; \ next_instr++; \
goto PRED_##op; \ goto PRED_##op; \
} \ } \
...@@ -1056,9 +1049,9 @@ _PyEval_EvalFrameDefault(PyFrameObject *f, int throwflag) ...@@ -1056,9 +1049,9 @@ _PyEval_EvalFrameDefault(PyFrameObject *f, int throwflag)
freevars = f->f_localsplus + co->co_nlocals; freevars = f->f_localsplus + co->co_nlocals;
assert(PyBytes_Check(co->co_code)); assert(PyBytes_Check(co->co_code));
assert(PyBytes_GET_SIZE(co->co_code) <= INT_MAX); assert(PyBytes_GET_SIZE(co->co_code) <= INT_MAX);
assert(PyBytes_GET_SIZE(co->co_code) % 2 == 0); assert(PyBytes_GET_SIZE(co->co_code) % sizeof(_Py_CODEUNIT) == 0);
assert(_Py_IS_ALIGNED(PyBytes_AS_STRING(co->co_code), 2)); assert(_Py_IS_ALIGNED(PyBytes_AS_STRING(co->co_code), sizeof(_Py_CODEUNIT)));
first_instr = (unsigned short*) PyBytes_AS_STRING(co->co_code); first_instr = (_Py_CODEUNIT *) PyBytes_AS_STRING(co->co_code);
/* /*
f->f_lasti refers to the index of the last instruction, f->f_lasti refers to the index of the last instruction,
unless it's -1 in which case next_instr should be first_instr. unless it's -1 in which case next_instr should be first_instr.
...@@ -1074,10 +1067,11 @@ _PyEval_EvalFrameDefault(PyFrameObject *f, int throwflag) ...@@ -1074,10 +1067,11 @@ _PyEval_EvalFrameDefault(PyFrameObject *f, int throwflag)
FOR_ITER is effectively a single opcode and f->f_lasti will point FOR_ITER is effectively a single opcode and f->f_lasti will point
to the beginning of the combined pair.) to the beginning of the combined pair.)
*/ */
assert(f->f_lasti >= -1);
next_instr = first_instr; next_instr = first_instr;
if (f->f_lasti >= 0) { if (f->f_lasti >= 0) {
assert(f->f_lasti % 2 == 0); assert(f->f_lasti % sizeof(_Py_CODEUNIT) == 0);
next_instr += f->f_lasti/2 + 1; next_instr += f->f_lasti / sizeof(_Py_CODEUNIT) + 1;
} }
stack_pointer = f->f_stacktop; stack_pointer = f->f_stacktop;
assert(stack_pointer != NULL); assert(stack_pointer != NULL);
...@@ -1125,7 +1119,7 @@ _PyEval_EvalFrameDefault(PyFrameObject *f, int throwflag) ...@@ -1125,7 +1119,7 @@ _PyEval_EvalFrameDefault(PyFrameObject *f, int throwflag)
Py_MakePendingCalls() above. */ Py_MakePendingCalls() above. */
if (_Py_atomic_load_relaxed(&eval_breaker)) { if (_Py_atomic_load_relaxed(&eval_breaker)) {
if (OPCODE(*next_instr) == SETUP_FINALLY) { if (_Py_OPCODE(*next_instr) == SETUP_FINALLY) {
/* Make the last opcode before /* Make the last opcode before
a try: finally: block uninterruptible. */ a try: finally: block uninterruptible. */
goto fast_next_opcode; goto fast_next_opcode;
...@@ -2049,7 +2043,7 @@ _PyEval_EvalFrameDefault(PyFrameObject *f, int throwflag) ...@@ -2049,7 +2043,7 @@ _PyEval_EvalFrameDefault(PyFrameObject *f, int throwflag)
f->f_stacktop = stack_pointer; f->f_stacktop = stack_pointer;
why = WHY_YIELD; why = WHY_YIELD;
/* and repeat... */ /* and repeat... */
f->f_lasti -= 2; f->f_lasti -= sizeof(_Py_CODEUNIT);
goto fast_yield; goto fast_yield;
} }
...@@ -5321,7 +5315,7 @@ format_exc_unbound(PyCodeObject *co, int oparg) ...@@ -5321,7 +5315,7 @@ format_exc_unbound(PyCodeObject *co, int oparg)
static PyObject * static PyObject *
unicode_concatenate(PyObject *v, PyObject *w, unicode_concatenate(PyObject *v, PyObject *w,
PyFrameObject *f, const unsigned short *next_instr) PyFrameObject *f, const _Py_CODEUNIT *next_instr)
{ {
PyObject *res; PyObject *res;
if (Py_REFCNT(v) == 2) { if (Py_REFCNT(v) == 2) {
......
...@@ -4948,7 +4948,7 @@ assemble_lnotab(struct assembler *a, struct instr *i) ...@@ -4948,7 +4948,7 @@ assemble_lnotab(struct assembler *a, struct instr *i)
Py_ssize_t len; Py_ssize_t len;
unsigned char *lnotab; unsigned char *lnotab;
d_bytecode = a->a_offset - a->a_lineno_off; d_bytecode = (a->a_offset - a->a_lineno_off) * sizeof(_Py_CODEUNIT);
d_lineno = i->i_lineno - a->a_lineno; d_lineno = i->i_lineno - a->a_lineno;
assert(d_bytecode >= 0); assert(d_bytecode >= 0);
...@@ -5055,21 +5055,21 @@ assemble_emit(struct assembler *a, struct instr *i) ...@@ -5055,21 +5055,21 @@ assemble_emit(struct assembler *a, struct instr *i)
{ {
int size, arg = 0; int size, arg = 0;
Py_ssize_t len = PyBytes_GET_SIZE(a->a_bytecode); Py_ssize_t len = PyBytes_GET_SIZE(a->a_bytecode);
char *code; _Py_CODEUNIT *code;
arg = i->i_oparg; arg = i->i_oparg;
size = instrsize(arg); size = instrsize(arg);
if (i->i_lineno && !assemble_lnotab(a, i)) if (i->i_lineno && !assemble_lnotab(a, i))
return 0; return 0;
if (a->a_offset + size >= len) { if (a->a_offset + size >= len / (int)sizeof(_Py_CODEUNIT)) {
if (len > PY_SSIZE_T_MAX / 2) if (len > PY_SSIZE_T_MAX / 2)
return 0; return 0;
if (_PyBytes_Resize(&a->a_bytecode, len * 2) < 0) if (_PyBytes_Resize(&a->a_bytecode, len * 2) < 0)
return 0; return 0;
} }
code = PyBytes_AS_STRING(a->a_bytecode) + a->a_offset; code = (_Py_CODEUNIT *)PyBytes_AS_STRING(a->a_bytecode) + a->a_offset;
a->a_offset += size; a->a_offset += size;
write_op_arg((unsigned char*)code, i->i_opcode, arg, size); write_op_arg(code, i->i_opcode, arg, size);
return 1; return 1;
} }
...@@ -5106,6 +5106,7 @@ assemble_jump_offsets(struct assembler *a, struct compiler *c) ...@@ -5106,6 +5106,7 @@ assemble_jump_offsets(struct assembler *a, struct compiler *c)
if (instr->i_jrel) { if (instr->i_jrel) {
instr->i_oparg -= bsize; instr->i_oparg -= bsize;
} }
instr->i_oparg *= sizeof(_Py_CODEUNIT);
if (instrsize(instr->i_oparg) != isize) { if (instrsize(instr->i_oparg) != isize) {
extended_arg_recompile = 1; extended_arg_recompile = 1;
} }
...@@ -5351,7 +5352,7 @@ assemble(struct compiler *c, int addNone) ...@@ -5351,7 +5352,7 @@ assemble(struct compiler *c, int addNone)
if (_PyBytes_Resize(&a.a_lnotab, a.a_lnotab_off) < 0) if (_PyBytes_Resize(&a.a_lnotab, a.a_lnotab_off) < 0)
goto error; goto error;
if (_PyBytes_Resize(&a.a_bytecode, a.a_offset) < 0) if (_PyBytes_Resize(&a.a_bytecode, a.a_offset * sizeof(_Py_CODEUNIT)) < 0)
goto error; goto error;
co = makecode(c, &a); co = makecode(c, &a);
......
This diff is collapsed.
...@@ -2,35 +2,38 @@ ...@@ -2,35 +2,38 @@
optimizer. optimizer.
*/ */
/* Minimum number of bytes necessary to encode instruction with EXTENDED_ARGs */ #ifdef WORDS_BIGENDIAN
# define PACKOPARG(opcode, oparg) ((_Py_CODEUNIT)(((opcode) << 8) | (oparg)))
#else
# define PACKOPARG(opcode, oparg) ((_Py_CODEUNIT)(((oparg) << 8) | (opcode)))
#endif
/* Minimum number of code units necessary to encode instruction with
EXTENDED_ARGs */
static int static int
instrsize(unsigned int oparg) instrsize(unsigned int oparg)
{ {
return oparg <= 0xff ? 2 : return oparg <= 0xff ? 1 :
oparg <= 0xffff ? 4 : oparg <= 0xffff ? 2 :
oparg <= 0xffffff ? 6 : oparg <= 0xffffff ? 3 :
8; 4;
} }
/* Spits out op/oparg pair using ilen bytes. codestr should be pointed at the /* Spits out op/oparg pair using ilen bytes. codestr should be pointed at the
desired location of the first EXTENDED_ARG */ desired location of the first EXTENDED_ARG */
static void static void
write_op_arg(unsigned char *codestr, unsigned char opcode, write_op_arg(_Py_CODEUNIT *codestr, unsigned char opcode,
unsigned int oparg, int ilen) unsigned int oparg, int ilen)
{ {
switch (ilen) { switch (ilen) {
case 8:
*codestr++ = EXTENDED_ARG;
*codestr++ = (oparg >> 24) & 0xff;
case 6:
*codestr++ = EXTENDED_ARG;
*codestr++ = (oparg >> 16) & 0xff;
case 4: case 4:
*codestr++ = EXTENDED_ARG; *codestr++ = PACKOPARG(EXTENDED_ARG, (oparg >> 24) & 0xff);
*codestr++ = (oparg >> 8) & 0xff; case 3:
*codestr++ = PACKOPARG(EXTENDED_ARG, (oparg >> 16) & 0xff);
case 2: case 2:
*codestr++ = opcode; *codestr++ = PACKOPARG(EXTENDED_ARG, (oparg >> 8) & 0xff);
*codestr++ = oparg & 0xff; case 1:
*codestr++ = PACKOPARG(opcode, oparg & 0xff);
break; break;
default: default:
assert(0); assert(0);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment