mirror of
https://github.com/python/cpython.git
synced 2025-07-24 11:44:31 +00:00
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.
This commit is contained in:
parent
0c1b253fc0
commit
effb3931ea
1 changed files with 20 additions and 15 deletions
|
@ -406,14 +406,10 @@ tuple_of_constants(unsigned char *codestr, int n, PyObject *consts)
|
||||||
|
|
||||||
/* Pre-conditions */
|
/* Pre-conditions */
|
||||||
assert(PyList_CheckExact(consts));
|
assert(PyList_CheckExact(consts));
|
||||||
assert(codestr[0] == LOAD_CONST);
|
|
||||||
assert(codestr[n*3] == BUILD_TUPLE);
|
assert(codestr[n*3] == BUILD_TUPLE);
|
||||||
assert(GETARG(codestr, (n*3)) == n);
|
assert(GETARG(codestr, (n*3)) == n);
|
||||||
|
|
||||||
/* Verify chain of n load_constants */
|
|
||||||
for (i=0 ; i<n ; i++)
|
for (i=0 ; i<n ; i++)
|
||||||
if (codestr[i*3] != LOAD_CONST)
|
assert(codestr[i*3] == LOAD_CONST);
|
||||||
return 0;
|
|
||||||
|
|
||||||
/* Buildup new tuple of constants */
|
/* Buildup new tuple of constants */
|
||||||
newconst = PyTuple_New(n);
|
newconst = PyTuple_New(n);
|
||||||
|
@ -447,11 +443,13 @@ static unsigned int *
|
||||||
markblocks(unsigned char *code, int len)
|
markblocks(unsigned char *code, int len)
|
||||||
{
|
{
|
||||||
unsigned int *blocks = PyMem_Malloc(len*sizeof(int));
|
unsigned int *blocks = PyMem_Malloc(len*sizeof(int));
|
||||||
int i,j, opcode, oldblock, newblock, blockcnt = 0;
|
int i,j, opcode, blockcnt = 0;
|
||||||
|
|
||||||
if (blocks == NULL)
|
if (blocks == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
memset(blocks, 0, len*sizeof(int));
|
memset(blocks, 0, len*sizeof(int));
|
||||||
|
|
||||||
|
/* Mark labels in the first pass */
|
||||||
for (i=0 ; i<len ; i+=CODESIZE(opcode)) {
|
for (i=0 ; i<len ; i+=CODESIZE(opcode)) {
|
||||||
opcode = code[i];
|
opcode = code[i];
|
||||||
switch (opcode) {
|
switch (opcode) {
|
||||||
|
@ -465,16 +463,15 @@ markblocks(unsigned char *code, int len)
|
||||||
case SETUP_EXCEPT:
|
case SETUP_EXCEPT:
|
||||||
case SETUP_FINALLY:
|
case SETUP_FINALLY:
|
||||||
j = GETJUMPTGT(code, i);
|
j = GETJUMPTGT(code, i);
|
||||||
oldblock = blocks[j];
|
blocks[j] = 1;
|
||||||
newblock = ++blockcnt;
|
|
||||||
for (; j<len ; j++) {
|
|
||||||
if (blocks[j] != (unsigned)oldblock)
|
|
||||||
break;
|
|
||||||
blocks[j] = newblock;
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
/* Build block numbers in the second pass */
|
||||||
|
for (i=0 ; i<len ; i++) {
|
||||||
|
blockcnt += blocks[i]; /* increment blockcnt over labels */
|
||||||
|
blocks[i] = blockcnt;
|
||||||
|
}
|
||||||
return blocks;
|
return blocks;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -503,9 +500,13 @@ optimize_code(PyObject *code, PyObject* consts, PyObject *names, PyObject *linen
|
||||||
int *addrmap = NULL;
|
int *addrmap = NULL;
|
||||||
int new_line, cum_orig_line, last_line, tabsiz;
|
int new_line, cum_orig_line, last_line, tabsiz;
|
||||||
int cumlc=0, lastlc=0; /* Count runs of consecutive LOAD_CONST codes */
|
int cumlc=0, lastlc=0; /* Count runs of consecutive LOAD_CONST codes */
|
||||||
unsigned int *blocks;
|
unsigned int *blocks = NULL;
|
||||||
char *name;
|
char *name;
|
||||||
|
|
||||||
|
/* Bail out if an exception is set */
|
||||||
|
if (PyErr_Occurred())
|
||||||
|
goto exitUnchanged;
|
||||||
|
|
||||||
/* Bypass optimization when the lineno table is too complex */
|
/* Bypass optimization when the lineno table is too complex */
|
||||||
assert(PyString_Check(lineno_obj));
|
assert(PyString_Check(lineno_obj));
|
||||||
lineno = PyString_AS_STRING(lineno_obj);
|
lineno = PyString_AS_STRING(lineno_obj);
|
||||||
|
@ -614,7 +615,7 @@ optimize_code(PyObject *code, PyObject* consts, PyObject *names, PyObject *linen
|
||||||
j = GETARG(codestr, i);
|
j = GETARG(codestr, i);
|
||||||
h = i - 3 * j;
|
h = i - 3 * j;
|
||||||
if (h >= 0 &&
|
if (h >= 0 &&
|
||||||
j == lastlc &&
|
j <= lastlc &&
|
||||||
codestr[h] == LOAD_CONST &&
|
codestr[h] == LOAD_CONST &&
|
||||||
ISBASICBLOCK(blocks, h, 3*(j+1)) &&
|
ISBASICBLOCK(blocks, h, 3*(j+1)) &&
|
||||||
tuple_of_constants(&codestr[h], j, consts)) {
|
tuple_of_constants(&codestr[h], j, consts)) {
|
||||||
|
@ -647,6 +648,8 @@ optimize_code(PyObject *code, PyObject* consts, PyObject *names, PyObject *linen
|
||||||
result of the first test implies the success of a similar
|
result of the first test implies the success of a similar
|
||||||
test or the failure of the opposite test.
|
test or the failure of the opposite test.
|
||||||
Arises in code like:
|
Arises in code like:
|
||||||
|
"if a and b:"
|
||||||
|
"if a or b:"
|
||||||
"a and b or c"
|
"a and b or c"
|
||||||
"a and b and c"
|
"a and b and c"
|
||||||
x:JUMP_IF_FALSE y y:JUMP_IF_FALSE z --> x:JUMP_IF_FALSE z
|
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
|
||||||
return code;
|
return code;
|
||||||
|
|
||||||
exitUnchanged:
|
exitUnchanged:
|
||||||
|
if (blocks != NULL)
|
||||||
|
PyMem_Free(blocks);
|
||||||
if (addrmap != NULL)
|
if (addrmap != NULL)
|
||||||
PyMem_Free(addrmap);
|
PyMem_Free(addrmap);
|
||||||
if (codestr != NULL)
|
if (codestr != NULL)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue