Skip to content

Commit 7809c61

Browse files
author
guido
committed
Changes to speed up local variables enormously, by avoiding dictionary
lookup (opcode.h, ceval.[ch], compile.c, frameobject.[ch], pythonrun.c, import.c). The .pyc MAGIC number is changed again. Added get_menu_text to flmodule. git-svn-id: http://svn.python.org/projects/python/trunk@3428 6015fed2-1504-0410-9fe1-9d1591cc4771
1 parent 1b39c91 commit 7809c61

9 files changed

Lines changed: 245 additions & 71 deletions

File tree

Include/ceval.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ object *call_object PROTO((object *, object *));
2828

2929
object *getglobals PROTO((void));
3030
object *getlocals PROTO((void));
31+
void mergelocals PROTO((void));
3132

3233
void printtraceback PROTO((object *));
3334
void flushline PROTO((void));

Include/frameobject.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,8 @@ typedef struct _frame {
3636
codeobject *f_code; /* code segment */
3737
object *f_globals; /* global symbol table (dictobject) */
3838
object *f_locals; /* local symbol table (dictobject) */
39+
object *f_fastlocals; /* fast local variables (listobject) */
40+
object *f_localmap; /* local variable names (dictobject) */
3941
object **f_valuestack; /* malloc'ed array */
4042
block *f_blockstack; /* malloc'ed array */
4143
int f_nvalues; /* size of f_valuestack */

Include/opcode.h

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -72,10 +72,7 @@ OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
7272
#define RAISE_EXCEPTION 81
7373
#define LOAD_LOCALS 82
7474
#define RETURN_VALUE 83
75-
/*
76-
#define REQUIRE_ARGS 84
77-
#define REFUSE_ARGS 85
78-
*/
75+
7976
#define BUILD_FUNCTION 86
8077
#define POP_BLOCK 87
8178
#define END_FINALLY 88
@@ -113,14 +110,15 @@ OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
113110
#define LOAD_LOCAL 115 /* Index in name list */
114111
#define LOAD_GLOBAL 116 /* Index in name list */
115112

116-
#define LOAD_FAST 117 /* Local variable number */
117-
#define STORE_FAST 118 /* Local variable number */
118-
#define RESERVE_FAST 119 /* Number of local variables */
119-
120113
#define SETUP_LOOP 120 /* Target address (absolute) */
121114
#define SETUP_EXCEPT 121 /* "" */
122115
#define SETUP_FINALLY 122 /* "" */
123116

117+
#define RESERVE_FAST 123 /* Number of local variables */
118+
#define LOAD_FAST 124 /* Local variable number */
119+
#define STORE_FAST 125 /* Local variable number */
120+
#define DELETE_FAST 126 /* Local variable number */
121+
124122
#define SET_LINENO 127 /* Current line number */
125123

126124
/* Comparison operator codes (argument to COMPARE_OP) */

Modules/flmodule.c

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1200,6 +1200,14 @@ get_menu (g, args)
12001200
return call_forms_Ri (fl_get_menu, g-> ob_generic, args);
12011201
}
12021202

1203+
static object *
1204+
get_menu_text (g, args)
1205+
genericobject *g;
1206+
object *args;
1207+
{
1208+
return call_forms_Rstr (fl_get_menu_text, g-> ob_generic, args);
1209+
}
1210+
12031211
static object *
12041212
addto_menu (g, args)
12051213
genericobject *g;
@@ -1211,6 +1219,7 @@ addto_menu (g, args)
12111219
static struct methodlist menu_methods[] = {
12121220
{"set_menu", set_menu},
12131221
{"get_menu", get_menu},
1222+
{"get_menu_text", get_menu_text},
12141223
{"addto_menu", addto_menu},
12151224
{NULL, NULL} /* sentinel */
12161225
};

Objects/frameobject.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,8 @@ static struct memberlist frame_memberlist[] = {
3838
{"f_code", T_OBJECT, OFF(f_code)},
3939
{"f_globals", T_OBJECT, OFF(f_globals)},
4040
{"f_locals", T_OBJECT, OFF(f_locals)},
41+
{"f_fastlocals",T_OBJECT, OFF(f_fastlocals)},
42+
{"f_localmap", T_OBJECT, OFF(f_localmap)},
4143
{"f_lasti", T_INT, OFF(f_lasti)},
4244
{"f_lineno", T_INT, OFF(f_lineno)},
4345
{NULL} /* Sentinel */
@@ -82,6 +84,8 @@ frame_dealloc(f)
8284
XDECREF(f->f_code);
8385
XDECREF(f->f_globals);
8486
XDECREF(f->f_locals);
87+
XDECREF(f->f_fastlocals);
88+
XDECREF(f->f_localmap);
8589
f->f_back = free_list;
8690
free_list = f;
8791
}
@@ -142,6 +146,8 @@ newframeobject(back, code, globals, locals, nvalues, nblocks)
142146
f->f_globals = globals;
143147
INCREF(locals);
144148
f->f_locals = locals;
149+
f->f_fastlocals = NULL;
150+
f->f_localmap = NULL;
145151
if (nvalues > f->f_nvalues || f->f_valuestack == NULL) {
146152
XDEL(f->f_valuestack);
147153
f->f_valuestack = NEW(object *, nvalues+1);

Python/ceval.c

Lines changed: 125 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,7 @@ static int cmp_member PROTO((object *, object *));
8181
static object *cmp_outcome PROTO((int, object *, object *));
8282
static int import_from PROTO((object *, object *, object *));
8383
static object *build_class PROTO((object *, object *));
84+
static void locals_2_fast PROTO((frameobject *, int));
8485

8586

8687
/* Pointer to current frame, used to link new frames to */
@@ -994,19 +995,51 @@ eval_code(co, globals, locals, arg)
994995
break;
995996

996997
case RESERVE_FAST:
997-
if (oparg > 0) {
998-
XDECREF(fastlocals);
999-
x = newlistobject(oparg);
1000-
fastlocals = (listobject *) x;
998+
x = GETCONST(oparg);
999+
if (x == None)
1000+
break;
1001+
if (x == NULL || !is_dictobject(x)) {
1002+
fatal("bad RESERVE_FAST");
1003+
err_setstr(SystemError, "bad RESERVE_FAST");
1004+
x = NULL;
1005+
break;
10011006
}
1007+
XDECREF(f->f_fastlocals);
1008+
XDECREF(f->f_localmap);
1009+
INCREF(x);
1010+
f->f_localmap = x;
1011+
f->f_fastlocals = x = newlistobject(
1012+
x->ob_type->tp_as_mapping->mp_length(x));
1013+
fastlocals = (listobject *) x;
10021014
break;
10031015

10041016
case LOAD_FAST:
1005-
/* NYI */
1017+
x = GETLISTITEM(fastlocals, oparg);
1018+
if (x == NULL) {
1019+
err_setstr(NameError,
1020+
"undefined local variable");
1021+
break;
1022+
}
1023+
INCREF(x);
1024+
PUSH(x);
10061025
break;
10071026

10081027
case STORE_FAST:
1009-
/* NYI */
1028+
w = GETLISTITEM(fastlocals, oparg);
1029+
XDECREF(w);
1030+
w = POP();
1031+
GETLISTITEM(fastlocals, oparg) = w;
1032+
break;
1033+
1034+
case DELETE_FAST:
1035+
x = GETLISTITEM(fastlocals, oparg);
1036+
if (x == NULL) {
1037+
err_setstr(NameError,
1038+
"undefined local variable");
1039+
break;
1040+
}
1041+
DECREF(x);
1042+
GETLISTITEM(fastlocals, oparg) = NULL;
10101043
break;
10111044

10121045
case BUILD_TUPLE:
@@ -1068,6 +1101,7 @@ eval_code(co, globals, locals, arg)
10681101
w = GETNAMEV(oparg);
10691102
v = TOP();
10701103
err = import_from(f->f_locals, v, w);
1104+
locals_2_fast(f, 0);
10711105
break;
10721106

10731107
case JUMP_FORWARD:
@@ -1299,8 +1333,6 @@ eval_code(co, globals, locals, arg)
12991333

13001334
current_frame = f->f_back;
13011335
DECREF(f);
1302-
1303-
XDECREF(fastlocals);
13041336

13051337
return retval;
13061338
}
@@ -1418,10 +1450,92 @@ call_trace(p_trace, p_newtrace, f, msg, arg)
14181450
object *
14191451
getlocals()
14201452
{
1421-
if (current_frame == NULL)
1453+
/* Merge f->f_fastlocals into f->f_locals, then return the latter */
1454+
frameobject *f;
1455+
object *locals, *fast, *map;
1456+
int i;
1457+
f = current_frame;
1458+
if (f == NULL)
14221459
return NULL;
1423-
else
1424-
return current_frame->f_locals;
1460+
locals = f->f_locals;
1461+
fast = f->f_fastlocals;
1462+
map = f->f_localmap;
1463+
if (locals == NULL || fast == NULL || map == NULL)
1464+
return locals;
1465+
if (!is_dictobject(locals) || !is_listobject(fast) ||
1466+
!is_dictobject(map))
1467+
return locals;
1468+
i = getdictsize(map);
1469+
while (--i >= 0) {
1470+
object *key;
1471+
object *value;
1472+
int j;
1473+
key = getdict2key(map, i);
1474+
if (key == NULL)
1475+
continue;
1476+
value = dict2lookup(map, key);
1477+
if (value == NULL || !is_intobject(value))
1478+
continue;
1479+
j = getintvalue(value);
1480+
value = getlistitem(fast, j);
1481+
if (value == NULL) {
1482+
err_clear();
1483+
if (dict2remove(locals, key) != 0)
1484+
err_clear();
1485+
}
1486+
else {
1487+
if (dict2insert(locals, key, value) != 0)
1488+
err_clear();
1489+
}
1490+
}
1491+
return locals;
1492+
}
1493+
1494+
static void
1495+
locals_2_fast(f, clear)
1496+
frameobject *f;
1497+
int clear;
1498+
{
1499+
/* Merge f->f_locals into f->f_fastlocals */
1500+
object *locals, *fast, *map;
1501+
int i;
1502+
if (f == NULL)
1503+
return;
1504+
locals = f->f_locals;
1505+
fast = f->f_fastlocals;
1506+
map = f->f_localmap;
1507+
if (locals == NULL || fast == NULL || map == NULL)
1508+
return;
1509+
if (!is_dictobject(locals) || !is_listobject(fast) ||
1510+
!is_dictobject(map))
1511+
return;
1512+
i = getdictsize(map);
1513+
while (--i >= 0) {
1514+
object *key;
1515+
object *value;
1516+
int j;
1517+
key = getdict2key(map, i);
1518+
if (key == NULL)
1519+
continue;
1520+
value = dict2lookup(map, key);
1521+
if (value == NULL || !is_intobject(value))
1522+
continue;
1523+
j = getintvalue(value);
1524+
value = dict2lookup(locals, key);
1525+
if (value == NULL)
1526+
err_clear();
1527+
else
1528+
INCREF(value);
1529+
if (value != NULL || clear)
1530+
if (setlistitem(fast, j, value) != 0)
1531+
err_clear();
1532+
}
1533+
}
1534+
1535+
void
1536+
mergelocals()
1537+
{
1538+
locals_2_fast(current_frame, 1);
14251539
}
14261540

14271541
object *

0 commit comments

Comments
 (0)