[Python-Dev] Accessing globals without dict lookup (original) (raw)

Tim Peters tim.one@comcast.net
Sun, 10 Feb 2002 18:27:09 -0500


[Skip Montanaro]

Just to see if I have a correct mental model of what Guido proposed, I drew a picture:

http://manatee.mojam.com/~skip/python/celldict.png The cells are the small blank boxes. I guess the celldict would be the stuff I labelled "module dict". The "func cells" would be an array like fastlocals, but would refer to cells in the module's dict.

Yup, except that fastlocals are part of a frame, not part of a function object. Guido didn't make a big deal about this, but it's key to efficiency: the expense of setting up func_cells is not incurred on a per-call basis, it's done once when a function object is created (MAKE_FUNCTION), then reused across all calls to that function object.

I'm not clear where/how builtins are accessed though.

builtin is just another module, and also has a celldict for a dict. The empty squares in your diagram (the "bottom half" of your cells) sometimes point to cells in builtin's celldict. They remain empty (NULL) in builtin's celldict, though.

Is that what the extra indirection is, or are builtins incorporated into the module dict somehow?

In Guido's proposal, module celldicts sometimes point to builtin's cells. It's set up so that all names of builtins get an entry in the module's dict, even names that aren't referenced in the module (this avoids global analysis). Their initial entries look like:

"len": {NULL, pointer to the "len" cell in the builtins}

Setting "len" as a module global (if you ever do that) overwrites the NULL. Then later del'ing "len" again (if you ever do that) restores the NULL. For most purposes, a cell with a NULL first pointer acts as if it didn't exist. It's only the eval loop that understands the "deep structure".

In the variant I sketched today, there are no cross-dict pointers, and the initial entries look like

"len": {the actual value of "len" from builtins, true}

instead. Then mutating the builtins requires reaching back into modules and updating their timdicts. In return, access code is simpler+faster, and there aren't semantic changes (compared to today) if the builtins mutate after a module's dict is initially populated (Guido's scheme appears vulnerable here in at least two ways).