Commit f4cf76dd authored by Raymond Hettinger's avatar Raymond Hettinger

Revert the previous enhancement to the bytecode optimizer.

The additional code complexity and new NOP opcode were not worth it.
parent 7d618c73
...@@ -14,8 +14,6 @@ extern "C" { ...@@ -14,8 +14,6 @@ extern "C" {
#define DUP_TOP 4 #define DUP_TOP 4
#define ROT_FOUR 5 #define ROT_FOUR 5
#define NOP 9
#define UNARY_POSITIVE 10 #define UNARY_POSITIVE 10
#define UNARY_NEGATIVE 11 #define UNARY_NEGATIVE 11
#define UNARY_NOT 12 #define UNARY_NOT 12
......
...@@ -49,8 +49,6 @@ def_op('ROT_THREE', 3) ...@@ -49,8 +49,6 @@ def_op('ROT_THREE', 3)
def_op('DUP_TOP', 4) def_op('DUP_TOP', 4)
def_op('ROT_FOUR', 5) def_op('ROT_FOUR', 5)
def_op('NOP', 9)
def_op('UNARY_POSITIVE', 10) def_op('UNARY_POSITIVE', 10)
def_op('UNARY_NEGATIVE', 11) def_op('UNARY_NEGATIVE', 11)
def_op('UNARY_NOT', 12) def_op('UNARY_NOT', 12)
......
...@@ -306,13 +306,6 @@ Core and builtins ...@@ -306,13 +306,6 @@ Core and builtins
value, but according to PEP 237 it really needs to be 1 now. This value, but according to PEP 237 it really needs to be 1 now. This
will be backported to Python 2.2.3 a well. (SF #660455) will be backported to Python 2.2.3 a well. (SF #660455)
- Added several bytecode optimizations. Provides speed-ups to
inverted in/is tests, inverted jumps, while 1 loops, and jumps to
unconditional jumps.
- Added a new opcode, NOP, which is used in some of the bytecode
transformations.
- int(s, base) sometimes sign-folds hex and oct constants; it only - int(s, base) sometimes sign-folds hex and oct constants; it only
does this when base is 0 and s.strip() starts with a '0'. When the does this when base is 0 and s.strip() starts with a '0'. When the
sign is actually folded, as in int("0xffffffff", 0) on a 32-bit sign is actually folded, as in int("0xffffffff", 0) on a 32-bit
......
...@@ -873,9 +873,6 @@ eval_frame(PyFrameObject *f) ...@@ -873,9 +873,6 @@ eval_frame(PyFrameObject *f)
/* case STOP_CODE: this is an error! */ /* case STOP_CODE: this is an error! */
case NOP:
goto fast_next_opcode;
case LOAD_FAST: case LOAD_FAST:
x = GETLOCAL(oparg); x = GETLOCAL(oparg);
if (x != NULL) { if (x != NULL) {
......
...@@ -328,43 +328,6 @@ intern_strings(PyObject *tuple) ...@@ -328,43 +328,6 @@ intern_strings(PyObject *tuple)
#define ABSOLUTE_JUMP(op) (op==JUMP_ABSOLUTE || op==CONTINUE_LOOP) #define ABSOLUTE_JUMP(op) (op==JUMP_ABSOLUTE || op==CONTINUE_LOOP)
#define GETJUMPTGT(arr, i) (GETARG(arr,i) + (ABSOLUTE_JUMP(arr[i]) ? 0 : i+3)) #define GETJUMPTGT(arr, i) (GETARG(arr,i) + (ABSOLUTE_JUMP(arr[i]) ? 0 : i+3))
#define SETARG(arr, i, val) arr[i+2] = val>>8; arr[i+1] = val & 255 #define SETARG(arr, i, val) arr[i+2] = val>>8; arr[i+1] = val & 255
#define CODESIZE(op) (HAS_ARG(op) ? 3 : 1)
#define ISBASICBLOCK(blocks, start, bytes) (blocks[start]==blocks[start+bytes-1])
static unsigned int *
markblocks(unsigned char *code, int len)
{
unsigned int *blocks = PyMem_Malloc(len*sizeof(int));
int i,j, opcode, oldblock, newblock, blockcnt = 0;
if (blocks == NULL)
return NULL;
memset(blocks, 0, len*sizeof(int));
for (i=0 ; i<len ; i+=CODESIZE(opcode)) {
opcode = code[i];
switch (opcode) {
case FOR_ITER:
case JUMP_FORWARD:
case JUMP_IF_FALSE:
case JUMP_IF_TRUE:
case JUMP_ABSOLUTE:
case CONTINUE_LOOP:
case SETUP_LOOP:
case SETUP_EXCEPT:
case SETUP_FINALLY:
j = GETJUMPTGT(code, i);
oldblock = blocks[j];
newblock = ++blockcnt;
for (; j<len ; j++) {
if (blocks[j] != (unsigned)oldblock)
break;
blocks[j] = newblock;
}
break;
}
}
return blocks;
}
static PyObject * static PyObject *
optimize_code(PyObject *code, PyObject* consts) optimize_code(PyObject *code, PyObject* consts)
...@@ -372,24 +335,18 @@ optimize_code(PyObject *code, PyObject* consts) ...@@ -372,24 +335,18 @@ optimize_code(PyObject *code, PyObject* consts)
int i, j, codelen; int i, j, codelen;
int tgt, tgttgt, opcode; int tgt, tgttgt, opcode;
unsigned char *codestr; unsigned char *codestr;
unsigned int *blocks;
/* Make a modifiable copy of the code string */ /* Make a modifiable copy of the code string */
if (!PyString_Check(code)) if (!PyString_Check(code))
goto exitUnchanged; goto exitUnchanged;
codelen = PyString_Size(code); codelen = PyString_Size(code);
codestr = PyMem_Malloc(codelen); codestr = PyMem_Malloc(codelen);
if (codestr == NULL) if (codestr == NULL)
goto exitUnchanged; goto exitUnchanged;
codestr = memcpy(codestr, PyString_AS_STRING(code), codelen); codestr = memcpy(codestr, PyString_AS_STRING(code), codelen);
blocks = markblocks(codestr, codelen);
if (blocks == NULL) {
PyMem_Free(codestr);
goto exitUnchanged;
}
assert(PyTuple_Check(consts)); assert(PyTuple_Check(consts));
for (i=0 ; i<codelen ; i += CODESIZE(codestr[i])) { for (i=0 ; i<codelen-7 ; i += HAS_ARG(codestr[i]) ? 3 : 1) {
opcode = codestr[i]; opcode = codestr[i];
switch (opcode) { switch (opcode) {
...@@ -406,8 +363,8 @@ optimize_code(PyObject *code, PyObject* consts) ...@@ -406,8 +363,8 @@ optimize_code(PyObject *code, PyObject* consts)
SETARG(codestr, i, 4); SETARG(codestr, i, 4);
break; break;
/* Replace BUILD_SEQN 2 UNPACK_SEQN 2 with ROT2 JMP+2 NOP NOP. /* Replace BUILD_SEQN 2 UNPACK_SEQN 2 with ROT2 JMP+2.
Replace BUILD_SEQN 3 UNPACK_SEQN 3 with ROT3 ROT2 JMP+1 NOP. Replace BUILD_SEQN 3 UNPACK_SEQN 3 with ROT3 ROT2 JMP+1.
Note, these opcodes occur together only in assignment Note, these opcodes occur together only in assignment
statements. Accordingly, the unpack opcode is never statements. Accordingly, the unpack opcode is never
a jump target. */ a jump target. */
...@@ -420,8 +377,8 @@ optimize_code(PyObject *code, PyObject* consts) ...@@ -420,8 +377,8 @@ optimize_code(PyObject *code, PyObject* consts)
codestr[i] = ROT_TWO; codestr[i] = ROT_TWO;
codestr[i+1] = JUMP_FORWARD; codestr[i+1] = JUMP_FORWARD;
SETARG(codestr, i+1, 2); SETARG(codestr, i+1, 2);
codestr[i+4] = NOP; codestr[i+4] = DUP_TOP; /* Filler codes used as NOPs */
codestr[i+5] = NOP; codestr[i+5] = POP_TOP;
continue; continue;
} }
if (GETARG(codestr, i) == 3 && \ if (GETARG(codestr, i) == 3 && \
...@@ -429,41 +386,11 @@ optimize_code(PyObject *code, PyObject* consts) ...@@ -429,41 +386,11 @@ optimize_code(PyObject *code, PyObject* consts)
codestr[i] = ROT_THREE; codestr[i] = ROT_THREE;
codestr[i+1] = ROT_TWO; codestr[i+1] = ROT_TWO;
codestr[i+2] = JUMP_FORWARD; codestr[i+2] = JUMP_FORWARD;
SETARG(codestr, i+2, 1); SETARG(codestr, i+2, 1);
codestr[i+5] = NOP; codestr[i+5] = DUP_TOP;
} }
break; break;
/* Simplify inverted tests.
Must verify that sequence is a basic block because the jump
can itself be a jump target. Also, must verify that *both*
jump alternatives go to a POP_TOP. Otherwise, the code will
expect the stack value to have been inverted. */
case UNARY_NOT:
if (codestr[i+1] != JUMP_IF_FALSE || \
codestr[i+4] != POP_TOP || \
!ISBASICBLOCK(blocks,i,5))
continue;
tgt = GETJUMPTGT(codestr, (i+1));
if (codestr[tgt] != POP_TOP)
continue;
codestr[i] = NOP;
codestr[i+1] = JUMP_IF_TRUE;
break;
/* not a is b --> a is not b
not a in b --> a not in b
not a is not b --> a is b
not a not in b --> a in b */
case COMPARE_OP:
j = GETARG(codestr, i);
if (codestr[i+3] != UNARY_NOT || j < 6 || \
j > 9 || !ISBASICBLOCK(blocks,i,4))
continue;
SETARG(codestr, i, (j^1));
codestr[i+3] = NOP;
break;
/* Replace jumps to unconditional jumps */ /* Replace jumps to unconditional jumps */
case FOR_ITER: case FOR_ITER:
case JUMP_FORWARD: case JUMP_FORWARD:
...@@ -475,7 +402,7 @@ optimize_code(PyObject *code, PyObject* consts) ...@@ -475,7 +402,7 @@ optimize_code(PyObject *code, PyObject* consts)
case SETUP_EXCEPT: case SETUP_EXCEPT:
case SETUP_FINALLY: case SETUP_FINALLY:
tgt = GETJUMPTGT(codestr, i); tgt = GETJUMPTGT(codestr, i);
if (!UNCONDITIONAL_JUMP(codestr[tgt])) if (!UNCONDITIONAL_JUMP(codestr[tgt]))
continue; continue;
tgttgt = GETJUMPTGT(codestr, tgt); tgttgt = GETJUMPTGT(codestr, tgt);
if (opcode == JUMP_FORWARD) /* JMP_ABS can go backwards */ if (opcode == JUMP_FORWARD) /* JMP_ABS can go backwards */
...@@ -495,7 +422,6 @@ optimize_code(PyObject *code, PyObject* consts) ...@@ -495,7 +422,6 @@ optimize_code(PyObject *code, PyObject* consts)
} }
code = PyString_FromStringAndSize(codestr, codelen); code = PyString_FromStringAndSize(codestr, codelen);
PyMem_Free(codestr); PyMem_Free(codestr);
PyMem_Free(blocks);
return code; return code;
exitUnchanged: exitUnchanged:
......
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