Closed Bug 542074 Opened 16 years ago Closed 16 years ago

Analyze implementation of closures in Lua and LuaJIT

Categories

(Core :: JavaScript Engine, defect)

defect
Not set
normal

Tracking

()

RESOLVED FIXED

People

(Reporter: dmandelin, Unassigned)

References

Details

Lua closures don't have as complex semantics as JS, so it can get away with a very simple (and fast) implementation. Instead of moving frames into the heap, it moves individual values. All upvar references can be statically bound at compile-time. There are no scope chains and there is no I-can-inject-local-variables version of eval(). The Lua equivalent of SpiderMonkey's DEFFUN/DEFLOCALFUN is CLOSURE. This allocates a new closure object, |cl|. The closure structure looks like this: struct UpVal { UpVal *next; UpVal *prev; Value *stackValue; Value heapValue; }; struct Closure { UpVal **upvals; }; The function header has pseudo-instructions that are immediately run after the closure is allocated. These are one of: * MOVE <i> <k>: Finds or creates an upval object bound to stack location {k}, then stores this in the closure's upval slot {i}. cl->upvals[i] = FindUpVal(&stack[k]); * GETUPVAL <i> <k>: Gets the {k}th upval in the current function and stores it in this closure's upval slot {i}. cl->upvals[i] = frame->upvals[i] The runtime has a list of all non-closed upval objects. FindUpVal() walks this list looking for one with a matching stack address. If not found, it allocates a new object and links it into the list. The CLOSE opcode is placed when a scope is about to die. This opcode looks for UpVar objects associated with the current scope. Each such object is unlinked from the list, and moved into a GC'able UpVar object list. The |stackValue| entry is NULL'd and the stack value is moved into the UpVar object. So it seems like Lua does not have to walk up activation records. Instead, the innermost upvar references are propagated to each parent AR, even if they're not used. So the GETUPVAL and SETUPVAL opcodes effectively are just: UpVal *u = cl->upvals[i]; if (u->stackValue) ...value is on stack... else ...value is boxed in |cl|...
Status: NEW → RESOLVED
Closed: 16 years ago
Resolution: --- → FIXED
You need to log in before you can comment on or make changes to this bug.