[Python-Dev] Accessing globals without dict lookup (original) (raw)
Jeremy Hylton jeremy@alum.mit.edu
Sat, 9 Feb 2002 19:04:19 -0500
- Previous message: [Python-Dev] Accessing globals without dict lookup
- Next message: [Python-Dev] Accessing globals without dict lookup
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]
Here's a brief review of the example function.
def mylen(s): return len(s)
LOAD_BUILTIN 0 (len) LOAD_FAST 0 (s) CALL_FUNCTION 1 RETURN_VALUE
The interpreter has a dlict for all the builtins. The details don't matter here. Let's say that len is at index 4.
The function mylen has an array: func_builtin_index = [4] # an index for each builtin used in mylen
The entry at index 0 of func_builtin_index is the index of len in the interpreter's builtin dlict. It is either initialized when the function is created or on first use of len. (It doesn't matter for the mechanism and there's no need to decide which is better yet.)
The module has an md_globals_dirty flag. If it is true, then a global was introduced dynamically, i.e. a name binding op occurred that the compiler did not detect statically.
The code object has a co_builtin_names that is like co_names except that it only contains the names of builtins used by LOAD_BUILTIN. It's there to get the correct behavior when shadowing of a builtin by a local occurs at runtime.
The frame grows a bunch of pointers --
f_module from the function (which stores it instead of func_globals)
f_builtin_names from the code object
f_builtins from the interpreter
The implementation of LOAD_BUILTIN 0 is straightforward -- in pidgin C:
case LOAD_BUILTIN:
if (f->f_module->md_globals_dirty) {
PyObject w = PyTuple_GET_ITEM(f->f_builtin_names);
... / rest is just like current LOAD_GLOBAL
except that is used PyDLict_GetItem()
*/
} else {
int builtin_index = f->f_builtin_index[oparg];
PyObject *x = f->f_builtins[builtin_index];
if (x == NULL)
raise NameError
Py_INCREF(x);
PUSH(x);
}
The LOAD_GLOBAL opcode ends up looking basically the same, except that it doesn't need to check md_globals_dirty.
case LOAD_GLOBAL: int global_index = f->f_global_index[oparg]; PyObject *x = f->f_module->md_globals[global_index]; if (x == NULL) { check for dynamically introduced builtin } Py_INCREF(x); PUSH(x);
In the x == NULL case above, we need to take extra care for a builtin that the compiler didn't expect. It's an odd case. There is a global for the module named spam that hasn't yet been assigned to in the module and there's also a builtin named spam that will be hidden once spam is bound in the module.
Jeremy
- Previous message: [Python-Dev] Accessing globals without dict lookup
- Next message: [Python-Dev] Accessing globals without dict lookup
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]