Functions

  • Revision slug: SpiderMonkey/Internals/Functions
  • Revision title: Functions
  • Revision id: 93115
  • Created:
  • Creator: Jorend
  • Is current revision? No
  • Comment page created, 390 words added

Revision Content

There are several flavors of JavaScript function. All are JSObjects of the same class, js_FunctionClass.

Native functions

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.

Script functions

Functions written in JavaScript and compiled to bytecode. There are three variations that affect how NameExpressions are resolved.

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 actually walks the scope chain to find the variable. When with or eval are used, we have to do this in order to get the behavior correct.

But this is slow, because we prefer to avoid actually creating objects representing the scope chain whenever 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 with and eval inhibit them.

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.

There is one more special case. If we can prove at compile time that a function does not assign to any locals/args in enclosing functions, and only reads locals/args that never change value after the function is created, then the function is a flat closure. When a flat closure is created, all the closed-on values are copied (from w) into reserved slots of the function object. To evaluate a name, instead of walking the scope chain, we just take the value from the appropriate reserved slot. The function object's parent is again the global object.

Revision Source

 There are several flavors of JavaScript function. All are <code>JSObject</code>s of the same class, <code>js_FunctionClass</code>. <h2>Native functions</h2> <p>Functions implemented in C/C++.</p> <p>See JSNative, JSFastNative. JSTraceableNative.</p> <h2>Script-internal function objects</h2> <p>Script-internal function objects are models for script functions. When a FunctionDeclaration or FunctionExpression is evaluated, the interpreter creates a <em>clone</em> of the script-internal function object, populated with the correct parent and reserved slots.</p> <p>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.</p> <p>XDR can serialize script-internal functions.</p> <h2>Script functions</h2> <p>Functions written in JavaScript and compiled to bytecode. There are three variations that affect how NameExpressions are resolved.</p> <p><strong>General closures</strong> 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 actually walks the scope chain to find the variable. When <code>with</code> or <code>eval</code> are used, we have to do this in order to get the behavior correct.</p> <p>But this is slow, because we prefer to avoid actually creating objects representing the scope chain whenever possible. General closures force the interpreter to reify the whole scope chain. So we optimize this when we can. These optimizations depend on being <em>sure</em> that we will never have to walk the scope chain, so <code>with</code> and <code>eval</code> inhibit them.</p> <p>If we can prove at compile time that a function does not refer to any locals or arguments of enclosing functions, it is a <strong>null closure</strong>. Since it will never need to walk the scope chain, its parent is the global object. This is the best case.</p> <p>There is one more special case. If we can prove at compile time that a function does not <em>assign</em> to any locals/args in enclosing functions, and only reads locals/args that never change value after the function is created, then the function is a <strong>flat closure</strong>. When a flat closure is created, all the closed-on values are copied (from w) into reserved slots of the function object. To evaluate a name, instead of walking the scope chain, we just take the value from the appropriate reserved slot. The function object's parent is again the global object.</p>
Revert to this revision