Merge mozilla-central and tracemonkey. (a=blockers)
[mozilla-central.git] / js / src / jsfun.h
bloba52092c9ed19b327663286efef4d2de26370e063
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
3 * ***** BEGIN LICENSE BLOCK *****
4 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
6 * The contents of this file are subject to the Mozilla Public License Version
7 * 1.1 (the "License"); you may not use this file except in compliance with
8 * the License. You may obtain a copy of the License at
9 * http://www.mozilla.org/MPL/
11 * Software distributed under the License is distributed on an "AS IS" basis,
12 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
13 * for the specific language governing rights and limitations under the
14 * License.
16 * The Original Code is Mozilla Communicator client code, released
17 * March 31, 1998.
19 * The Initial Developer of the Original Code is
20 * Netscape Communications Corporation.
21 * Portions created by the Initial Developer are Copyright (C) 1998
22 * the Initial Developer. All Rights Reserved.
24 * Contributor(s):
26 * Alternatively, the contents of this file may be used under the terms of
27 * either of the GNU General Public License Version 2 or later (the "GPL"),
28 * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
29 * in which case the provisions of the GPL or the LGPL are applicable instead
30 * of those above. If you wish to allow use of your version of this file only
31 * under the terms of either the GPL or the LGPL, and not to allow others to
32 * use your version of this file under the terms of the MPL, indicate your
33 * decision by deleting the provisions above and replace them with the notice
34 * and other provisions required by the GPL or the LGPL. If you do not delete
35 * the provisions above, a recipient may use your version of this file under
36 * the terms of any one of the MPL, the GPL or the LGPL.
38 * ***** END LICENSE BLOCK ***** */
40 #ifndef jsfun_h___
41 #define jsfun_h___
43 * JS function definitions.
45 #include "jsprvtd.h"
46 #include "jspubtd.h"
47 #include "jsobj.h"
48 #include "jsatom.h"
49 #include "jsscript.h"
50 #include "jsstr.h"
51 #include "jsopcode.h"
54 * The high two bits of JSFunction.flags encode whether the function is native
55 * or interpreted, and if interpreted, what kind of optimized closure form (if
56 * any) it might be.
58 * 00 not interpreted
59 * 01 interpreted, neither flat nor null closure
60 * 10 interpreted, flat closure
61 * 11 interpreted, null closure
63 * FUN_FLAT_CLOSURE implies FUN_INTERPRETED and u.i.script->upvarsOffset != 0.
64 * FUN_NULL_CLOSURE implies FUN_INTERPRETED and u.i.script->upvarsOffset == 0.
66 * FUN_INTERPRETED but not FUN_FLAT_CLOSURE and u.i.script->upvarsOffset != 0
67 * is an Algol-like function expression or nested function, i.e., a function
68 * that never escapes upward or downward (heapward), and is only ever called.
70 * Finally, FUN_INTERPRETED and u.i.script->upvarsOffset == 0 could be either
71 * a non-closure (a global function definition, or any function that uses no
72 * outer names), or a closure of an escaping function that uses outer names
73 * whose values can't be snapshot (because the outer names could be reassigned
74 * after the closure is formed, or because assignments could not be analyzed
75 * due to with or eval).
77 * Such a hard-case function must use JSOP_NAME, etc., and reify outer function
78 * activations' call objects, etc. if it's not a global function.
80 * NB: JSFUN_EXPR_CLOSURE reuses JSFUN_STUB_GSOPS, which is an API request flag
81 * bit only, never stored in fun->flags.
83 * If we need more bits in the future, all flags for FUN_INTERPRETED functions
84 * can move to u.i.script->flags. For now we use function flag bits to minimize
85 * pointer-chasing.
87 #define JSFUN_JOINABLE 0x0001 /* function is null closure that does not
88 appear to call itself via its own name
89 or arguments.callee */
91 #define JSFUN_PROTOTYPE 0x0800 /* function is Function.prototype for some
92 global object */
94 #define JSFUN_EXPR_CLOSURE 0x1000 /* expression closure: function(x) x*x */
95 #define JSFUN_TRCINFO 0x2000 /* when set, u.n.trcinfo is non-null,
96 JSFunctionSpec::call points to a
97 JSNativeTraceInfo. */
98 #define JSFUN_INTERPRETED 0x4000 /* use u.i if kind >= this value else u.n */
99 #define JSFUN_FLAT_CLOSURE 0x8000 /* flag (aka "display") closure */
100 #define JSFUN_NULL_CLOSURE 0xc000 /* null closure entrains no scope chain */
101 #define JSFUN_KINDMASK 0xc000 /* encode interp vs. native and closure
102 optimization level -- see above */
104 #define FUN_OBJECT(fun) (static_cast<JSObject *>(fun))
105 #define FUN_KIND(fun) ((fun)->flags & JSFUN_KINDMASK)
106 #define FUN_SET_KIND(fun,k) ((fun)->flags = ((fun)->flags & ~JSFUN_KINDMASK) | (k))
107 #define FUN_INTERPRETED(fun) (FUN_KIND(fun) >= JSFUN_INTERPRETED)
108 #define FUN_FLAT_CLOSURE(fun)(FUN_KIND(fun) == JSFUN_FLAT_CLOSURE)
109 #define FUN_NULL_CLOSURE(fun)(FUN_KIND(fun) == JSFUN_NULL_CLOSURE)
110 #define FUN_SCRIPT(fun) (FUN_INTERPRETED(fun) ? (fun)->u.i.script : NULL)
111 #define FUN_CLASP(fun) (JS_ASSERT(!FUN_INTERPRETED(fun)), \
112 fun->u.n.clasp)
113 #define FUN_TRCINFO(fun) (JS_ASSERT(!FUN_INTERPRETED(fun)), \
114 JS_ASSERT((fun)->flags & JSFUN_TRCINFO), \
115 fun->u.n.trcinfo)
117 struct JSFunction : public JSObject_Slots2
119 /* Functions always have two fixed slots (FUN_CLASS_RESERVED_SLOTS). */
121 uint16 nargs; /* maximum number of specified arguments,
122 reflected as f.length/f.arity */
123 uint16 flags; /* flags, see JSFUN_* below and in jsapi.h */
124 union U {
125 struct {
126 js::Native native; /* native method pointer or null */
127 js::Class *clasp; /* class of objects constructed
128 by this function */
129 JSNativeTraceInfo *trcinfo;
130 } n;
131 struct Scripted {
132 JSScript *script; /* interpreted bytecode descriptor or null */
133 uint16 skipmin; /* net skip amount up (toward zero) from
134 script->staticLevel to nearest upvar,
135 including upvars in nested functions */
136 JSPackedBool wrapper; /* true if this function is a wrapper that
137 rewrites bytecode optimized for a function
138 judged non-escaping by the compiler, which
139 then escaped via the debugger or a rogue
140 indirect eval; if true, then this function
141 object's proto is the wrapped object */
142 js::Shape *names; /* argument and variable names */
143 } i;
144 void *nativeOrScript;
145 } u;
146 JSAtom *atom; /* name for diagnostics and decompiling */
148 bool optimizedClosure() const { return FUN_KIND(this) > JSFUN_INTERPRETED; }
149 bool needsWrapper() const { return FUN_NULL_CLOSURE(this) && u.i.skipmin != 0; }
150 bool isInterpreted() const { return FUN_INTERPRETED(this); }
151 bool isNative() const { return !FUN_INTERPRETED(this); }
152 bool isConstructor() const { return flags & JSFUN_CONSTRUCTOR; }
153 bool isHeavyweight() const { return JSFUN_HEAVYWEIGHT_TEST(flags); }
154 bool isFlatClosure() const { return FUN_KIND(this) == JSFUN_FLAT_CLOSURE; }
156 bool isFunctionPrototype() const { return flags & JSFUN_PROTOTYPE; }
158 /* Returns the strictness of this function, which must be interpreted. */
159 inline bool inStrictMode() const;
161 void setArgCount(uint16 nargs) {
162 JS_ASSERT(this->nargs == 0);
163 this->nargs = nargs;
166 /* uint16 representation bounds number of call object dynamic slots. */
167 enum { MAX_ARGS_AND_VARS = 2 * ((1U << 16) - 1) };
169 #define JS_LOCAL_NAME_TO_ATOM(nameWord) ((JSAtom *) ((nameWord) & ~(jsuword) 1))
170 #define JS_LOCAL_NAME_IS_CONST(nameWord) ((((nameWord) & (jsuword) 1)) != 0)
172 bool mightEscape() const {
173 return isInterpreted() && (isFlatClosure() || !script()->bindings.hasUpvars());
176 bool joinable() const {
177 return flags & JSFUN_JOINABLE;
180 JSObject &compiledFunObj() {
181 return *this;
184 private:
186 * js_FunctionClass reserves two slots, which are free in JSObject::fslots
187 * without requiring dslots allocation. Null closures that can be joined to
188 * a compiler-created function object use the first one to hold a mutable
189 * methodAtom() state variable, needed for correct foo.caller handling.
191 enum {
192 METHOD_ATOM_SLOT = JSSLOT_FUN_METHOD_ATOM
195 public:
196 void setJoinable() {
197 JS_ASSERT(FUN_INTERPRETED(this));
198 getSlotRef(METHOD_ATOM_SLOT).setNull();
199 flags |= JSFUN_JOINABLE;
203 * Method name imputed from property uniquely assigned to or initialized,
204 * where the function does not need to be cloned to carry a scope chain or
205 * flattened upvars.
207 JSAtom *methodAtom() const {
208 return (joinable() && getSlot(METHOD_ATOM_SLOT).isString())
209 ? STRING_TO_ATOM(getSlot(METHOD_ATOM_SLOT).toString())
210 : NULL;
213 void setMethodAtom(JSAtom *atom) {
214 JS_ASSERT(joinable());
215 getSlotRef(METHOD_ATOM_SLOT).setString(ATOM_TO_STRING(atom));
218 js::Native maybeNative() const {
219 return isInterpreted() ? NULL : u.n.native;
222 JSScript *script() const {
223 JS_ASSERT(isInterpreted());
224 return u.i.script;
227 static uintN offsetOfNativeOrScript() {
228 JS_STATIC_ASSERT(offsetof(U, n.native) == offsetof(U, i.script));
229 JS_STATIC_ASSERT(offsetof(U, n.native) == offsetof(U, nativeOrScript));
230 return offsetof(JSFunction, u.nativeOrScript);
233 /* Number of extra fixed function object slots. */
234 static const uint32 CLASS_RESERVED_SLOTS = JSObject::FUN_CLASS_RESERVED_SLOTS;
238 * Trace-annotated native. This expands to a JSFunctionSpec initializer (like
239 * JS_FN in jsapi.h). fastcall is a FastNative; trcinfo is a
240 * JSNativeTraceInfo*.
242 #ifdef JS_TRACER
243 /* MSVC demands the intermediate (void *) cast here. */
244 # define JS_TN(name,fastcall,nargs,flags,trcinfo) \
245 JS_FN(name, JS_DATA_TO_FUNC_PTR(Native, trcinfo), nargs, \
246 (flags) | JSFUN_STUB_GSOPS | JSFUN_TRCINFO)
247 #else
248 # define JS_TN(name,fastcall,nargs,flags,trcinfo) \
249 JS_FN(name, fastcall, nargs, flags)
250 #endif
253 * NB: the Arguments classes are uninitialized internal classes that masquerade
254 * (according to Object.prototype.toString.call(arguments)) as "Arguments",
255 * while having Object.getPrototypeOf(arguments) === Object.prototype.
257 * WARNING (to alert embedders reading this private .h file): arguments objects
258 * are *not* thread-safe and should not be used concurrently -- they should be
259 * used by only one thread at a time, preferably by only one thread over their
260 * lifetime (a JS worker that migrates from one OS thread to another but shares
261 * nothing is ok).
263 * Yes, this is an incompatible change, which prefigures the impending move to
264 * single-threaded objects and GC heaps.
266 extern js::Class js_ArgumentsClass;
268 namespace js {
270 extern Class StrictArgumentsClass;
272 struct ArgumentsData {
273 js::Value callee;
274 js::Value slots[1];
279 inline bool
280 JSObject::isNormalArguments() const
282 return getClass() == &js_ArgumentsClass;
285 inline bool
286 JSObject::isStrictArguments() const
288 return getClass() == &js::StrictArgumentsClass;
291 inline bool
292 JSObject::isArguments() const
294 return isNormalArguments() || isStrictArguments();
297 #define JS_ARGUMENTS_OBJECT_ON_TRACE ((void *)0xa126)
299 extern JS_PUBLIC_DATA(js::Class) js_CallClass;
300 extern JS_PUBLIC_DATA(js::Class) js_FunctionClass;
301 extern js::Class js_DeclEnvClass;
303 inline bool
304 JSObject::isCall() const
306 return getClass() == &js_CallClass;
309 inline bool
310 JSObject::isFunction() const
312 return getClass() == &js_FunctionClass;
315 inline JSFunction *
316 JSObject::getFunctionPrivate() const
318 JS_ASSERT(isFunction());
319 return reinterpret_cast<JSFunction *>(getPrivate());
322 namespace js {
325 * Construct a call object for the given bindings. If this is a call object
326 * for a function invocation, callee should be the function being called.
327 * Otherwise it must be a call object for eval of strict mode code, and callee
328 * must be null.
330 extern JSObject *
331 NewCallObject(JSContext *cx, js::Bindings *bindings, JSObject &scopeChain, JSObject *callee);
334 * NB: jsapi.h and jsobj.h must be included before any call to this macro.
336 #define VALUE_IS_FUNCTION(cx, v) \
337 (!JSVAL_IS_PRIMITIVE(v) && JSVAL_TO_OBJECT(v)->isFunction())
339 static JS_ALWAYS_INLINE bool
340 IsFunctionObject(const js::Value &v)
342 return v.isObject() && v.toObject().isFunction();
345 static JS_ALWAYS_INLINE bool
346 IsFunctionObject(const js::Value &v, JSObject **funobj)
348 return v.isObject() && (*funobj = &v.toObject())->isFunction();
351 static JS_ALWAYS_INLINE bool
352 IsFunctionObject(const js::Value &v, JSFunction **fun)
354 JSObject *funobj;
355 bool b = IsFunctionObject(v, &funobj);
356 if (b)
357 *fun = funobj->getFunctionPrivate();
358 return b;
361 extern JS_ALWAYS_INLINE bool
362 SameTraceType(const Value &lhs, const Value &rhs)
364 return SameType(lhs, rhs) &&
365 (lhs.isPrimitive() ||
366 lhs.toObject().isFunction() == rhs.toObject().isFunction());
370 * Macro to access the private slot of the function object after the slot is
371 * initialized.
373 #define GET_FUNCTION_PRIVATE(cx, funobj) \
374 (JS_ASSERT((funobj)->isFunction()), \
375 (JSFunction *) (funobj)->getPrivate())
378 * Return true if this is a compiler-created internal function accessed by
379 * its own object. Such a function object must not be accessible to script
380 * or embedding code.
382 inline bool
383 IsInternalFunctionObject(JSObject *funobj)
385 JS_ASSERT(funobj->isFunction());
386 JSFunction *fun = (JSFunction *) funobj->getPrivate();
387 return funobj == fun && (fun->flags & JSFUN_LAMBDA) && !funobj->getParent();
390 /* Valueified JS_IsConstructing. */
391 static JS_ALWAYS_INLINE bool
392 IsConstructing(const Value *vp)
394 #ifdef DEBUG
395 JSObject *callee = &JS_CALLEE(cx, vp).toObject();
396 if (callee->isFunction()) {
397 JSFunction *fun = callee->getFunctionPrivate();
398 JS_ASSERT((fun->flags & JSFUN_CONSTRUCTOR) != 0);
399 } else {
400 JS_ASSERT(callee->getClass()->construct != NULL);
402 #endif
403 return vp[1].isMagic();
406 static JS_ALWAYS_INLINE bool
407 IsConstructing_PossiblyWithGivenThisObject(const Value *vp, JSObject **ctorThis)
409 #ifdef DEBUG
410 JSObject *callee = &JS_CALLEE(cx, vp).toObject();
411 if (callee->isFunction()) {
412 JSFunction *fun = callee->getFunctionPrivate();
413 JS_ASSERT((fun->flags & JSFUN_CONSTRUCTOR) != 0);
414 } else {
415 JS_ASSERT(callee->getClass()->construct != NULL);
417 #endif
418 bool isCtor = vp[1].isMagic();
419 if (isCtor)
420 *ctorThis = vp[1].getMagicObjectOrNullPayload();
421 return isCtor;
424 inline const char *
425 GetFunctionNameBytes(JSContext *cx, JSFunction *fun, JSAutoByteString *bytes)
427 if (fun->atom)
428 return bytes->encode(cx, ATOM_TO_STRING(fun->atom));
429 return js_anonymous_str;
432 extern JS_FRIEND_API(bool)
433 IsBuiltinFunctionConstructor(JSFunction *fun);
436 * Preconditions: funobj->isInterpreted() && !funobj->isFunctionPrototype() &&
437 * !funobj->isBoundFunction(). This is sufficient to establish that funobj has
438 * a non-configurable non-method .prototype data property, thought it might not
439 * have been resolved yet, and its value could be anything.
441 * Return the shape of the .prototype property of funobj, resolving it if
442 * needed. On error, return NULL.
444 * This is not safe to call on trace because it defines properties, which can
445 * trigger lookups that could reenter.
447 const Shape *
448 LookupInterpretedFunctionPrototype(JSContext *cx, JSObject *funobj);
450 } /* namespace js */
452 extern JSString *
453 fun_toStringHelper(JSContext *cx, JSObject *obj, uintN indent);
455 extern JSFunction *
456 js_NewFunction(JSContext *cx, JSObject *funobj, js::Native native, uintN nargs,
457 uintN flags, JSObject *parent, JSAtom *atom);
459 extern JSObject *
460 js_InitFunctionClass(JSContext *cx, JSObject *obj);
462 extern JSObject *
463 js_InitArgumentsClass(JSContext *cx, JSObject *obj);
465 extern void
466 js_TraceFunction(JSTracer *trc, JSFunction *fun);
468 extern void
469 js_FinalizeFunction(JSContext *cx, JSFunction *fun);
471 extern JSObject * JS_FASTCALL
472 js_CloneFunctionObject(JSContext *cx, JSFunction *fun, JSObject *parent,
473 JSObject *proto);
475 inline JSObject *
476 CloneFunctionObject(JSContext *cx, JSFunction *fun, JSObject *parent)
478 JS_ASSERT(parent);
479 JSObject *proto;
480 if (!js_GetClassPrototype(cx, parent, JSProto_Function, &proto))
481 return NULL;
482 return js_CloneFunctionObject(cx, fun, parent, proto);
485 extern JSObject * JS_FASTCALL
486 js_AllocFlatClosure(JSContext *cx, JSFunction *fun, JSObject *scopeChain);
488 extern JSObject *
489 js_NewFlatClosure(JSContext *cx, JSFunction *fun, JSOp op, size_t oplen);
491 extern JS_REQUIRES_STACK JSObject *
492 js_NewDebuggableFlatClosure(JSContext *cx, JSFunction *fun);
494 extern JSFunction *
495 js_DefineFunction(JSContext *cx, JSObject *obj, jsid id, js::Native native,
496 uintN nargs, uintN flags);
499 * Flags for js_ValueToFunction and js_ReportIsNotFunction. We depend on the
500 * fact that JSINVOKE_CONSTRUCT (aka JSFRAME_CONSTRUCTING) is 1, and test that
501 * with #if/#error in jsfun.c.
503 #define JSV2F_CONSTRUCT JSINVOKE_CONSTRUCT
504 #define JSV2F_SEARCH_STACK 0x10000
506 extern JSFunction *
507 js_ValueToFunction(JSContext *cx, const js::Value *vp, uintN flags);
509 extern JSObject *
510 js_ValueToFunctionObject(JSContext *cx, js::Value *vp, uintN flags);
512 extern JSObject *
513 js_ValueToCallableObject(JSContext *cx, js::Value *vp, uintN flags);
515 extern void
516 js_ReportIsNotFunction(JSContext *cx, const js::Value *vp, uintN flags);
518 extern JSObject *
519 js_GetCallObject(JSContext *cx, JSStackFrame *fp);
521 extern JSObject * JS_FASTCALL
522 js_CreateCallObjectOnTrace(JSContext *cx, JSFunction *fun, JSObject *callee, JSObject *scopeChain);
524 extern void
525 js_PutCallObject(JSContext *cx, JSStackFrame *fp);
527 extern JSBool JS_FASTCALL
528 js_PutCallObjectOnTrace(JSContext *cx, JSObject *scopeChain, uint32 nargs,
529 js::Value *argv, uint32 nvars, js::Value *slots);
531 namespace js {
533 extern JSBool
534 GetCallArg(JSContext *cx, JSObject *obj, jsid id, js::Value *vp);
536 extern JSBool
537 GetCallVar(JSContext *cx, JSObject *obj, jsid id, js::Value *vp);
540 * Slower version of js_GetCallVar used when call_resolve detects an attempt to
541 * leak an optimized closure via indirect or debugger eval.
543 extern JSBool
544 GetCallVarChecked(JSContext *cx, JSObject *obj, jsid id, js::Value *vp);
546 extern JSBool
547 GetCallUpvar(JSContext *cx, JSObject *obj, jsid id, js::Value *vp);
549 extern JSBool
550 SetCallArg(JSContext *cx, JSObject *obj, jsid id, JSBool strict, js::Value *vp);
552 extern JSBool
553 SetCallVar(JSContext *cx, JSObject *obj, jsid id, JSBool strict, js::Value *vp);
555 extern JSBool
556 SetCallUpvar(JSContext *cx, JSObject *obj, jsid id, JSBool strict, js::Value *vp);
558 } // namespace js
560 extern JSBool
561 js_GetArgsValue(JSContext *cx, JSStackFrame *fp, js::Value *vp);
563 extern JSBool
564 js_GetArgsProperty(JSContext *cx, JSStackFrame *fp, jsid id, js::Value *vp);
567 * Get the arguments object for the given frame. If the frame is strict mode
568 * code, its current arguments will be copied into the arguments object.
570 * NB: Callers *must* get the arguments object before any parameters are
571 * mutated when the frame is strict mode code! The emitter ensures this
572 * occurs for strict mode functions containing syntax which might mutate a
573 * named parameter by synthesizing an arguments access at the start of the
574 * function.
576 extern JSObject *
577 js_GetArgsObject(JSContext *cx, JSStackFrame *fp);
579 extern void
580 js_PutArgsObject(JSContext *cx, JSStackFrame *fp);
582 inline bool
583 js_IsNamedLambda(JSFunction *fun) { return (fun->flags & JSFUN_LAMBDA) && fun->atom; }
586 * Maximum supported value of arguments.length. It bounds the maximum number of
587 * arguments that can be supplied via the second (so-called |argArray|) param
588 * to Function.prototype.apply. This value also bounds the number of elements
589 * parsed in an array initialiser.
591 * The thread's stack is the limiting factor for this number. It is currently
592 * 2MB, which fits a little less than 2^19 arguments (once the stack frame,
593 * callstack, etc. are included). Pick a max args length that is a little less.
595 const uint32 JS_ARGS_LENGTH_MAX = JS_BIT(19) - 1024;
598 * JSSLOT_ARGS_LENGTH stores ((argc << 1) | overwritten_flag) as an Int32
599 * Value. Thus (JS_ARGS_LENGTH_MAX << 1) | 1 must be less than JSVAL_INT_MAX.
601 JS_STATIC_ASSERT(JS_ARGS_LENGTH_MAX <= JS_BIT(30));
602 JS_STATIC_ASSERT(((JS_ARGS_LENGTH_MAX << 1) | 1) <= JSVAL_INT_MAX);
604 extern JSBool
605 js_XDRFunctionObject(JSXDRState *xdr, JSObject **objp);
607 extern JSBool
608 js_fun_apply(JSContext *cx, uintN argc, js::Value *vp);
610 extern JSBool
611 js_fun_call(JSContext *cx, uintN argc, js::Value *vp);
613 #endif /* jsfun_h___ */