Skip to content

Commit f4cf76d

Browse files
committed
Revert the previous enhancement to the bytecode optimizer.
The additional code complexity and new NOP opcode were not worth it.
1 parent 7d618c7 commit f4cf76d

5 files changed

Lines changed: 9 additions & 97 deletions

File tree

Include/opcode.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,6 @@ extern "C" {
1414
#define DUP_TOP 4
1515
#define ROT_FOUR 5
1616

17-
#define NOP 9
18-
1917
#define UNARY_POSITIVE 10
2018
#define UNARY_NEGATIVE 11
2119
#define UNARY_NOT 12

Lib/opcode.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,8 +49,6 @@ def jabs_op(name, op):
4949
def_op('DUP_TOP', 4)
5050
def_op('ROT_FOUR', 5)
5151

52-
def_op('NOP', 9)
53-
5452
def_op('UNARY_POSITIVE', 10)
5553
def_op('UNARY_NEGATIVE', 11)
5654
def_op('UNARY_NOT', 12)

Misc/NEWS

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -306,13 +306,6 @@ Core and builtins
306306
value, but according to PEP 237 it really needs to be 1 now. This
307307
will be backported to Python 2.2.3 a well. (SF #660455)
308308

309-
- Added several bytecode optimizations. Provides speed-ups to
310-
inverted in/is tests, inverted jumps, while 1 loops, and jumps to
311-
unconditional jumps.
312-
313-
- Added a new opcode, NOP, which is used in some of the bytecode
314-
transformations.
315-
316309
- int(s, base) sometimes sign-folds hex and oct constants; it only
317310
does this when base is 0 and s.strip() starts with a '0'. When the
318311
sign is actually folded, as in int("0xffffffff", 0) on a 32-bit

Python/ceval.c

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -873,9 +873,6 @@ eval_frame(PyFrameObject *f)
873873

874874
/* case STOP_CODE: this is an error! */
875875

876-
case NOP:
877-
goto fast_next_opcode;
878-
879876
case LOAD_FAST:
880877
x = GETLOCAL(oparg);
881878
if (x != NULL) {

Python/compile.c

Lines changed: 9 additions & 83 deletions
Original file line numberDiff line numberDiff line change
@@ -328,68 +328,25 @@ intern_strings(PyObject *tuple)
328328
#define ABSOLUTE_JUMP(op) (op==JUMP_ABSOLUTE || op==CONTINUE_LOOP)
329329
#define GETJUMPTGT(arr, i) (GETARG(arr,i) + (ABSOLUTE_JUMP(arr[i]) ? 0 : i+3))
330330
#define SETARG(arr, i, val) arr[i+2] = val>>8; arr[i+1] = val & 255
331-
#define CODESIZE(op) (HAS_ARG(op) ? 3 : 1)
332-
#define ISBASICBLOCK(blocks, start, bytes) (blocks[start]==blocks[start+bytes-1])
333-
334-
static unsigned int *
335-
markblocks(unsigned char *code, int len)
336-
{
337-
unsigned int *blocks = PyMem_Malloc(len*sizeof(int));
338-
int i,j, opcode, oldblock, newblock, blockcnt = 0;
339-
340-
if (blocks == NULL)
341-
return NULL;
342-
memset(blocks, 0, len*sizeof(int));
343-
for (i=0 ; i<len ; i+=CODESIZE(opcode)) {
344-
opcode = code[i];
345-
switch (opcode) {
346-
case FOR_ITER:
347-
case JUMP_FORWARD:
348-
case JUMP_IF_FALSE:
349-
case JUMP_IF_TRUE:
350-
case JUMP_ABSOLUTE:
351-
case CONTINUE_LOOP:
352-
case SETUP_LOOP:
353-
case SETUP_EXCEPT:
354-
case SETUP_FINALLY:
355-
j = GETJUMPTGT(code, i);
356-
oldblock = blocks[j];
357-
newblock = ++blockcnt;
358-
for (; j<len ; j++) {
359-
if (blocks[j] != (unsigned)oldblock)
360-
break;
361-
blocks[j] = newblock;
362-
}
363-
break;
364-
}
365-
}
366-
return blocks;
367-
}
368331

369332
static PyObject *
370333
optimize_code(PyObject *code, PyObject* consts)
371334
{
372335
int i, j, codelen;
373336
int tgt, tgttgt, opcode;
374337
unsigned char *codestr;
375-
unsigned int *blocks;
376338

377339
/* Make a modifiable copy of the code string */
378340
if (!PyString_Check(code))
379341
goto exitUnchanged;
380342
codelen = PyString_Size(code);
381343
codestr = PyMem_Malloc(codelen);
382-
if (codestr == NULL)
344+
if (codestr == NULL)
383345
goto exitUnchanged;
384346
codestr = memcpy(codestr, PyString_AS_STRING(code), codelen);
385-
blocks = markblocks(codestr, codelen);
386-
if (blocks == NULL) {
387-
PyMem_Free(codestr);
388-
goto exitUnchanged;
389-
}
390347
assert(PyTuple_Check(consts));
391348

392-
for (i=0 ; i<codelen ; i += CODESIZE(codestr[i])) {
349+
for (i=0 ; i<codelen-7 ; i += HAS_ARG(codestr[i]) ? 3 : 1) {
393350
opcode = codestr[i];
394351
switch (opcode) {
395352

@@ -406,8 +363,8 @@ optimize_code(PyObject *code, PyObject* consts)
406363
SETARG(codestr, i, 4);
407364
break;
408365

409-
/* Replace BUILD_SEQN 2 UNPACK_SEQN 2 with ROT2 JMP+2 NOP NOP.
410-
Replace BUILD_SEQN 3 UNPACK_SEQN 3 with ROT3 ROT2 JMP+1 NOP.
366+
/* Replace BUILD_SEQN 2 UNPACK_SEQN 2 with ROT2 JMP+2.
367+
Replace BUILD_SEQN 3 UNPACK_SEQN 3 with ROT3 ROT2 JMP+1.
411368
Note, these opcodes occur together only in assignment
412369
statements. Accordingly, the unpack opcode is never
413370
a jump target. */
@@ -420,50 +377,20 @@ optimize_code(PyObject *code, PyObject* consts)
420377
codestr[i] = ROT_TWO;
421378
codestr[i+1] = JUMP_FORWARD;
422379
SETARG(codestr, i+1, 2);
423-
codestr[i+4] = NOP;
424-
codestr[i+5] = NOP;
380+
codestr[i+4] = DUP_TOP; /* Filler codes used as NOPs */
381+
codestr[i+5] = POP_TOP;
425382
continue;
426383
}
427384
if (GETARG(codestr, i) == 3 && \
428385
GETARG(codestr, i+3) == 3) {
429386
codestr[i] = ROT_THREE;
430387
codestr[i+1] = ROT_TWO;
431388
codestr[i+2] = JUMP_FORWARD;
432-
SETARG(codestr, i+2, 1);
433-
codestr[i+5] = NOP;
389+
SETARG(codestr, i+2, 1);
390+
codestr[i+5] = DUP_TOP;
434391
}
435392
break;
436393

437-
/* Simplify inverted tests.
438-
Must verify that sequence is a basic block because the jump
439-
can itself be a jump target. Also, must verify that *both*
440-
jump alternatives go to a POP_TOP. Otherwise, the code will
441-
expect the stack value to have been inverted. */
442-
case UNARY_NOT:
443-
if (codestr[i+1] != JUMP_IF_FALSE || \
444-
codestr[i+4] != POP_TOP || \
445-
!ISBASICBLOCK(blocks,i,5))
446-
continue;
447-
tgt = GETJUMPTGT(codestr, (i+1));
448-
if (codestr[tgt] != POP_TOP)
449-
continue;
450-
codestr[i] = NOP;
451-
codestr[i+1] = JUMP_IF_TRUE;
452-
break;
453-
454-
/* not a is b --> a is not b
455-
not a in b --> a not in b
456-
not a is not b --> a is b
457-
not a not in b --> a in b */
458-
case COMPARE_OP:
459-
j = GETARG(codestr, i);
460-
if (codestr[i+3] != UNARY_NOT || j < 6 || \
461-
j > 9 || !ISBASICBLOCK(blocks,i,4))
462-
continue;
463-
SETARG(codestr, i, (j^1));
464-
codestr[i+3] = NOP;
465-
break;
466-
467394
/* Replace jumps to unconditional jumps */
468395
case FOR_ITER:
469396
case JUMP_FORWARD:
@@ -475,7 +402,7 @@ optimize_code(PyObject *code, PyObject* consts)
475402
case SETUP_EXCEPT:
476403
case SETUP_FINALLY:
477404
tgt = GETJUMPTGT(codestr, i);
478-
if (!UNCONDITIONAL_JUMP(codestr[tgt]))
405+
if (!UNCONDITIONAL_JUMP(codestr[tgt]))
479406
continue;
480407
tgttgt = GETJUMPTGT(codestr, tgt);
481408
if (opcode == JUMP_FORWARD) /* JMP_ABS can go backwards */
@@ -495,7 +422,6 @@ optimize_code(PyObject *code, PyObject* consts)
495422
}
496423
code = PyString_FromStringAndSize(codestr, codelen);
497424
PyMem_Free(codestr);
498-
PyMem_Free(blocks);
499425
return code;
500426

501427
exitUnchanged:

0 commit comments

Comments
 (0)