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

Skip to content

Commit effb393

Browse files
committed
Adopt some peepholer suggestions from Armin Rigo:
* Use simpler, faster two pass algorithm for markblocks(). * Free the blocks variable if not NULL and exiting without change. * Verify that the rest of the compiler has not set an exception. * Make the test for tuple of constants less restrictive. * Embellish the comment for chained conditional jumps.
1 parent 0c1b253 commit effb393

1 file changed

Lines changed: 20 additions & 15 deletions

File tree

Python/compile.c

Lines changed: 20 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -406,14 +406,10 @@ tuple_of_constants(unsigned char *codestr, int n, PyObject *consts)
406406

407407
/* Pre-conditions */
408408
assert(PyList_CheckExact(consts));
409-
assert(codestr[0] == LOAD_CONST);
410409
assert(codestr[n*3] == BUILD_TUPLE);
411410
assert(GETARG(codestr, (n*3)) == n);
412-
413-
/* Verify chain of n load_constants */
414411
for (i=0 ; i<n ; i++)
415-
if (codestr[i*3] != LOAD_CONST)
416-
return 0;
412+
assert(codestr[i*3] == LOAD_CONST);
417413

418414
/* Buildup new tuple of constants */
419415
newconst = PyTuple_New(n);
@@ -447,11 +443,13 @@ static unsigned int *
447443
markblocks(unsigned char *code, int len)
448444
{
449445
unsigned int *blocks = PyMem_Malloc(len*sizeof(int));
450-
int i,j, opcode, oldblock, newblock, blockcnt = 0;
446+
int i,j, opcode, blockcnt = 0;
451447

452448
if (blocks == NULL)
453449
return NULL;
454450
memset(blocks, 0, len*sizeof(int));
451+
452+
/* Mark labels in the first pass */
455453
for (i=0 ; i<len ; i+=CODESIZE(opcode)) {
456454
opcode = code[i];
457455
switch (opcode) {
@@ -465,16 +463,15 @@ markblocks(unsigned char *code, int len)
465463
case SETUP_EXCEPT:
466464
case SETUP_FINALLY:
467465
j = GETJUMPTGT(code, i);
468-
oldblock = blocks[j];
469-
newblock = ++blockcnt;
470-
for (; j<len ; j++) {
471-
if (blocks[j] != (unsigned)oldblock)
472-
break;
473-
blocks[j] = newblock;
474-
}
466+
blocks[j] = 1;
475467
break;
476468
}
477469
}
470+
/* Build block numbers in the second pass */
471+
for (i=0 ; i<len ; i++) {
472+
blockcnt += blocks[i]; /* increment blockcnt over labels */
473+
blocks[i] = blockcnt;
474+
}
478475
return blocks;
479476
}
480477

@@ -503,9 +500,13 @@ optimize_code(PyObject *code, PyObject* consts, PyObject *names, PyObject *linen
503500
int *addrmap = NULL;
504501
int new_line, cum_orig_line, last_line, tabsiz;
505502
int cumlc=0, lastlc=0; /* Count runs of consecutive LOAD_CONST codes */
506-
unsigned int *blocks;
503+
unsigned int *blocks = NULL;
507504
char *name;
508505

506+
/* Bail out if an exception is set */
507+
if (PyErr_Occurred())
508+
goto exitUnchanged;
509+
509510
/* Bypass optimization when the lineno table is too complex */
510511
assert(PyString_Check(lineno_obj));
511512
lineno = PyString_AS_STRING(lineno_obj);
@@ -614,7 +615,7 @@ optimize_code(PyObject *code, PyObject* consts, PyObject *names, PyObject *linen
614615
j = GETARG(codestr, i);
615616
h = i - 3 * j;
616617
if (h >= 0 &&
617-
j == lastlc &&
618+
j <= lastlc &&
618619
codestr[h] == LOAD_CONST &&
619620
ISBASICBLOCK(blocks, h, 3*(j+1)) &&
620621
tuple_of_constants(&codestr[h], j, consts)) {
@@ -647,6 +648,8 @@ optimize_code(PyObject *code, PyObject* consts, PyObject *names, PyObject *linen
647648
result of the first test implies the success of a similar
648649
test or the failure of the opposite test.
649650
Arises in code like:
651+
"if a and b:"
652+
"if a or b:"
650653
"a and b or c"
651654
"a and b and c"
652655
x:JUMP_IF_FALSE y y:JUMP_IF_FALSE z --> x:JUMP_IF_FALSE z
@@ -755,6 +758,8 @@ optimize_code(PyObject *code, PyObject* consts, PyObject *names, PyObject *linen
755758
return code;
756759

757760
exitUnchanged:
761+
if (blocks != NULL)
762+
PyMem_Free(blocks);
758763
if (addrmap != NULL)
759764
PyMem_Free(addrmap);
760765
if (codestr != NULL)

0 commit comments

Comments
 (0)