Probable bug & possible optimization

Tim Peters (tim@ksr.com)
Mon, 04 Apr 94 00:59:56 -0400

Guido, while looking at .pyc code two things hit my eye:

1) Probable bug, in Python/ceval.c:

case DELETE_FAST:
x = GETLISTITEM(fastlocals, oparg);
if (x == NULL) {
err_setstr(NameError,
"undefined local variable");
break;
}
**** w?! **** if (w != NULL && is_accessobject(w)) {
err = setaccessvalue(w, f->f_locals,
(object *)NULL);
break;
}
etc

I.e., "w" appears to be trash in this case (cut-&-paste, eh <smile>?),
but so long as people aren't playing with the secret "access" features
it's probably a symptomless bug.

2) Possible dirt-cheap & valuable optimization: When I look at the code
generated for, e.g.,

def studyargs(a, b):
global swapped, called
called = 1
if coerced:
a, b = a.value, b.value
if myin(a, LHS) and myin(b, RHS):
pass
elif myin(a, RHS) and myin(b, LHS):
swapped = 1
else:
raise MysteryError, (a,b)

I note that the references to the global 'coerced', 'myin', 'LHS',
'RHS' and 'MysteryError' are all done via LOAD_NAME.

However, the loop (in Python/compile.c's "optimize") that optimizes
references to locals knows that 'coerced' etc are _not_ local, so
couldn't that loop also safely replace a LOAD_NAME of a non-local with
LOAD_GLOBAL instead? The implementations of LOAD_NAME and LOAD_GLOBAL
are identical except that the former does a dictionary lookup on
f->f_locals first, and it seems to me that this lookup can never
succeed (given that "optimize" has already decided the function is
optimizable, so really does know the difference between locals and
non-locals, and is already optimizing away _all_ slow loads of locals
-- so all remaining slow loads must be of non-locals. QED <wink>.).
Or am I missing a pathology here?

I don't especially care about speeding references to global _data_,
but function and builtin names are resolved in the same way, and
it could be a nice win for everyone to speed those a bit.

brow-chewing-ly y'rs - tim

Tim Peters tim@ksr.com
not speaking for Kendall Square Research Corp