Each sub has three phases; compilation, creation, and execution; for named
subs, creation happens at the same time as compilation; for anon subs, its
later, and there can be multiple creations, which is why they're more
interesting.

At compile time, a note is made for each sub, of what outer lexicals it
makes use of; at creation time, the sub is given its pad, with the first
instance of each of its lexical vars created and stored within; also, a
reference to the current instance of each outer lexical is stored in the
pad. So the pad contains references to both its own lexical vars and to
any outer ones.

On first execution, all the vars are available in the pad. On return from
the sub, all the sub's own lexical vars are abandoned, and new empty ones
created in the pad, ready for the next execution (if any).

There's a bit more to it than that, but that's the main effect. For more
details, looks at pad.c in the perl source: S_pad_findlex() is the main
function that does the compile-time stuff; I wrote that about 10 years
ago, and don't remember much of what it does any more :-(. Then,
Perl_cv_clone() shows what happens at create time for anon subs (the
creation for named subs happens in parallel with compilation, and nothing
special needs doing for it). Finally, in pp_*.c, the pp_pad?v functions
show what happens to a lexical variable on entry to a scope (basically
SAVECLEARSV() is called), while in scope.c, the SAVEt_CLEARSV branch of
Perl_leave_scope shows what happens on scope exit, including an
optimisation to just clear the var in place if nothing else is using it.