JSObjects of the same class,
Functions implemented in C/C++.
See JSNative, JSFastNative. JSTraceableNative.
Script-internal function objects
Script-internal function objects are models for script functions. When a FunctionDeclaration or FunctionExpression is evaluated, the interpreter creates a clone of the script-internal function object, populated with the correct parent and reserved slots.
Script-internal function objects must never be exposed to arbitrary code, because the parent and slots may not be populated. Calling such a function can cause a crash.
XDR can serialize script-internal functions.
General closures are the base case. When the function object is created, its parent is set to the first object on the scope chain. When a name is evaluated that doesn't refer to a local variable, the interpreter consults the scope chain to find the variable. When
eval are used, we have to do this for correctness.
This is slow, not only because walking the scope chain is a drag, but also because we'd rather avoid actually creating the scope chain at all, if possible. General closures force the interpreter to reify the whole scope chain. So we optimize this when we can.
These optimizations depend on being sure that we will never have to walk the scope chain, so
eval inhibit them all.
Null closures. If we can prove at compile time that a function does not refer to any locals or arguments of enclosing functions, it is a null closure. Since it will never need to walk the scope chain, its parent is the global object. This is the best case. Barring
eval, all outermost functions are null closures.
Null closures with upvars. A nested function is algol-like if it is only ever defined and called, and it isn't accessed in any other way (and it is not a generator-function). Such a function is guaranteed never to be called again after the enclosing function exits. An algol-like function may read the local variables and arguments of its immediate enclosing function from the stack, as if by magic. (
JSContext::display caches the enclosing function's stack frame.) If that function is also algol-like, its child can read locals and variables from the next enclosing function, and so on. The compiler detects these cases and makes such functions null closures too.
Flat closures. Suppose a function reads some variables from enclosing functions but is not algol-like. If the function does not assign to any closed-on vars/args, and it only reads closed-on local variables and arguments that never change value after the function is created, then the function can be implemented as a flat closure. When a flat closure is created, all the closed-on values are copied from the stack into reserved slots of the function object. To evaluate a name, instead of walking the scope chain, we just take the value from the reserved slot. The function object's parent is the global object.