upvar means that you have access to the variables of the calling function. You can ask, what is the value of local variable foo in the scope that is calling here?
It's a facepalm-stupid thing to put into a programming language. Programs that use it will not be efficently compilable; the compiled code will have to provide upvar access similarly in order to make them work.
When compiling a function, you don't know which callee might ask for an upvar, so you can't optimize away variables or keep them in registers across calls.