Thanks to visit codestin.com
Credit goes to github.com

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)