(blocks[start]==blocks[end])
-#define CONST_STACK_CREATE() { \
- const_stack_size = 256; \
- const_stack = PyMem_New(PyObject *, const_stack_size); \
- if (!const_stack) { \
- PyErr_NoMemory(); \
- goto exitError; \
- } \
- }
-
-#define CONST_STACK_DELETE() do { \
- if (const_stack) \
- PyMem_Free(const_stack); \
- } while(0)
-
-#define CONST_STACK_LEN() ((unsigned)(const_stack_top + 1))
-
-#define CONST_STACK_PUSH_OP(i) do { \
- PyObject *_x; \
- assert(_Py_OPCODE(codestr[i]) == LOAD_CONST); \
- assert(PyList_GET_SIZE(consts) > (Py_ssize_t)get_arg(codestr, i)); \
- _x = PyList_GET_ITEM(consts, get_arg(codestr, i)); \
- if (++const_stack_top >= const_stack_size) { \
- const_stack_size *= 2; \
- PyMem_Resize(const_stack, PyObject *, const_stack_size); \
- if (!const_stack) { \
- PyErr_NoMemory(); \
- goto exitError; \
- } \
- } \
- const_stack[const_stack_top] = _x; \
- in_consts = 1; \
- } while(0)
-
-#define CONST_STACK_RESET() do { \
- const_stack_top = -1; \
- } while(0)
-
-#define CONST_STACK_LASTN(i) \
- &const_stack[CONST_STACK_LEN() - i]
-
-#define CONST_STACK_POP(i) do { \
- assert(CONST_STACK_LEN() >= i); \
- const_stack_top -= i; \
- } while(0)
-
/* Scans back N consecutive LOAD_CONST instructions, skipping NOPs,
returns index of the Nth last's LOAD_CONST's EXTENDED_ARG prefix.
Callers are responsible to check CONST_STACK_LEN beforehand.
}
}
else {
- assert(_Py_OPCODE(codestr[i]) == NOP ||
- _Py_OPCODE(codestr[i]) == EXTENDED_ARG);
+ assert(_Py_OPCODE(codestr[i]) == EXTENDED_ARG);
}
}
}
The consts table must still be in list form so that the
new constant (c1, c2, ... cn) can be appended.
Called with codestr pointing to the first LOAD_CONST.
- Bails out with no change if one or more of the LOAD_CONSTs is missing.
*/
static Py_ssize_t
fold_tuple_on_constants(_Py_CODEUNIT *codestr, Py_ssize_t c_start,
- Py_ssize_t opcode_end, unsigned char opcode,
- PyObject *consts, PyObject **objs, int n)
+ Py_ssize_t opcode_end, PyObject *consts, int n)
{
- PyObject *newconst, *constant;
- Py_ssize_t i, len_consts;
-
/* Pre-conditions */
assert(PyList_CheckExact(consts));
/* Buildup new tuple of constants */
- newconst = PyTuple_New(n);
+ PyObject *newconst = PyTuple_New(n);
if (newconst == NULL) {
return -1;
}
- for (i=0 ; i<n ; i++) {
- constant = objs[i];
+
+ for (Py_ssize_t i = 0, pos = c_start; i < n; i++, pos++) {
+ assert(pos < opcode_end);
+ pos = find_op(codestr, pos);
+ assert(_Py_OPCODE(codestr[pos]) == LOAD_CONST);
+
+ unsigned int arg = get_arg(codestr, pos);
+ PyObject *constant = PyList_GET_ITEM(consts, arg);
Py_INCREF(constant);
PyTuple_SET_ITEM(newconst, i, constant);
}
/* Append folded constant onto consts */
- len_consts = PyList_GET_SIZE(consts);
if (PyList_Append(consts, newconst)) {
Py_DECREF(newconst);
return -1;
}
Py_DECREF(newconst);
- return copy_op_arg(codestr, c_start, LOAD_CONST, len_consts, opcode_end);
+ return copy_op_arg(codestr, c_start, LOAD_CONST,
+ PyList_GET_SIZE(consts)-1, opcode_end);
}
static unsigned int *
unsigned char *lnotab;
unsigned int cum_orig_offset, last_offset;
Py_ssize_t tabsiz;
- PyObject **const_stack = NULL;
- Py_ssize_t const_stack_top = -1;
- Py_ssize_t const_stack_size = 0;
- int in_consts = 0; /* whether we are in a LOAD_CONST sequence */
+ // Count runs of consecutive LOAD_CONSTs
+ unsigned int cumlc = 0, lastlc = 0;
unsigned int *blocks = NULL;
/* Bail out if an exception is set */
goto exitError;
assert(PyList_Check(consts));
- CONST_STACK_CREATE();
-
for (i=find_op(codestr, 0) ; i<codelen ; i=nexti) {
opcode = _Py_OPCODE(codestr[i]);
op_start = i;
nexti++;
nextop = nexti < codelen ? _Py_OPCODE(codestr[nexti]) : 0;
- if (!in_consts) {
- CONST_STACK_RESET();
- }
- in_consts = 0;
+ lastlc = cumlc;
+ cumlc = 0;
switch (opcode) {
/* Skip over LOAD_CONST trueconst
POP_JUMP_IF_FALSE xx. This improves
"while 1" performance. */
case LOAD_CONST:
- CONST_STACK_PUSH_OP(i);
+ cumlc = lastlc + 1;
if (nextop != POP_JUMP_IF_FALSE ||
!ISBASICBLOCK(blocks, op_start, i + 1) ||
!PyObject_IsTrue(PyList_GET_ITEM(consts, get_arg(codestr, i))))
break;
fill_nops(codestr, op_start, nexti + 1);
- CONST_STACK_POP(1);
+ cumlc = 0;
break;
/* Try to fold tuples of constants.
Replace BUILD_SEQN 3 UNPACK_SEQN 3 with ROT3 ROT2. */
case BUILD_TUPLE:
j = get_arg(codestr, i);
- if (j > 0 && CONST_STACK_LEN() >= j) {
+ if (j > 0 && lastlc >= j) {
h = lastn_const_start(codestr, op_start, j);
if (ISBASICBLOCK(blocks, h, op_start)) {
- h = fold_tuple_on_constants(codestr, h, i + 1, opcode,
- consts, CONST_STACK_LASTN(j), j);
- if (h >= 0) {
- CONST_STACK_POP(j);
- CONST_STACK_PUSH_OP(h);
- }
+ h = fold_tuple_on_constants(codestr, h, i+1, consts, j);
break;
}
}
} else if (j == 2) {
codestr[op_start] = PACKOPARG(ROT_TWO, 0);
fill_nops(codestr, op_start + 1, nexti + 1);
- CONST_STACK_RESET();
} else if (j == 3) {
codestr[op_start] = PACKOPARG(ROT_THREE, 0);
codestr[op_start + 1] = PACKOPARG(ROT_TWO, 0);
fill_nops(codestr, op_start + 2, nexti + 1);
- CONST_STACK_RESET();
}
break;
}
assert(h + (Py_ssize_t)nops == codelen);
- CONST_STACK_DELETE();
PyMem_Free(blocks);
code = PyBytes_FromStringAndSize((char *)codestr, h * sizeof(_Py_CODEUNIT));
PyMem_Free(codestr);
exitUnchanged:
Py_XINCREF(code);
- CONST_STACK_DELETE();
PyMem_Free(blocks);
PyMem_Free(codestr);
return code;