Bug 588735 - Mirror glass caption buttons for rtl windows. r=roc, a=blocking-betaN.
[mozilla-central.git] / js / src / jsfun.h
blob95d932d4adf8136abebbfa7ed5a3b65cc75aaffa
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 "jsstr.h"
51 typedef struct JSLocalNameMap JSLocalNameMap;
54 * Depending on the number of arguments and variables in the function their
55 * names and attributes are stored either as a single atom or as an array of
56 * tagged atoms (when there are few locals) or as a hash-based map (when there
57 * are many locals). In the first 2 cases the lowest bit of the atom is used
58 * as a tag to distinguish const from var. See jsfun.c for details.
60 typedef union JSLocalNames {
61 jsuword taggedAtom;
62 jsuword *array;
63 JSLocalNameMap *map;
64 } JSLocalNames;
67 * The high two bits of JSFunction.flags encode whether the function is native
68 * or interpreted, and if interpreted, what kind of optimized closure form (if
69 * any) it might be.
71 * 00 not interpreted
72 * 01 interpreted, neither flat nor null closure
73 * 10 interpreted, flat closure
74 * 11 interpreted, null closure
76 * FUN_FLAT_CLOSURE implies FUN_INTERPRETED and u.i.script->upvarsOffset != 0.
77 * FUN_NULL_CLOSURE implies FUN_INTERPRETED and u.i.script->upvarsOffset == 0.
79 * FUN_INTERPRETED but not FUN_FLAT_CLOSURE and u.i.script->upvarsOffset != 0
80 * is an Algol-like function expression or nested function, i.e., a function
81 * that never escapes upward or downward (heapward), and is only ever called.
83 * Finally, FUN_INTERPRETED and u.i.script->upvarsOffset == 0 could be either
84 * a non-closure (a global function definition, or any function that uses no
85 * outer names), or a closure of an escaping function that uses outer names
86 * whose values can't be snapshot (because the outer names could be reassigned
87 * after the closure is formed, or because assignments could not be analyzed
88 * due to with or eval).
90 * Such a hard-case function must use JSOP_NAME, etc., and reify outer function
91 * activations' call objects, etc. if it's not a global function.
93 * NB: JSFUN_EXPR_CLOSURE reuses JSFUN_STUB_GSOPS, which is an API request flag
94 * bit only, never stored in fun->flags.
96 * If we need more bits in the future, all flags for FUN_INTERPRETED functions
97 * can move to u.i.script->flags. For now we use function flag bits to minimize
98 * pointer-chasing.
100 #define JSFUN_JOINABLE 0x0001 /* function is null closure that does not
101 appear to call itself via its own name
102 or arguments.callee */
104 #define JSFUN_FAST_NATIVE_CTOR 0x0002 /* JSFastNative directly invokable
105 * during construction. */
108 * Extra JSCLASS flag indicating the native passed to JS_InitClass is
109 * a fast native constructor. This is internal for now as the 'this' value passed
110 * to such a constructor is a magic value, and there is no way to query this
111 * in the API. See bug 581263.
113 #define JSCLASS_FAST_CONSTRUCTOR (1<<4)
115 #define JSFUN_EXPR_CLOSURE 0x1000 /* expression closure: function(x) x*x */
116 #define JSFUN_TRCINFO 0x2000 /* when set, u.n.trcinfo is non-null,
117 JSFunctionSpec::call points to a
118 JSNativeTraceInfo. */
119 #define JSFUN_INTERPRETED 0x4000 /* use u.i if kind >= this value else u.n */
120 #define JSFUN_FLAT_CLOSURE 0x8000 /* flag (aka "display") closure */
121 #define JSFUN_NULL_CLOSURE 0xc000 /* null closure entrains no scope chain */
122 #define JSFUN_KINDMASK 0xc000 /* encode interp vs. native and closure
123 optimization level -- see above */
125 #define FUN_OBJECT(fun) (static_cast<JSObject *>(fun))
126 #define FUN_KIND(fun) ((fun)->flags & JSFUN_KINDMASK)
127 #define FUN_SET_KIND(fun,k) ((fun)->flags = ((fun)->flags & ~JSFUN_KINDMASK) | (k))
128 #define FUN_INTERPRETED(fun) (FUN_KIND(fun) >= JSFUN_INTERPRETED)
129 #define FUN_FLAT_CLOSURE(fun)(FUN_KIND(fun) == JSFUN_FLAT_CLOSURE)
130 #define FUN_NULL_CLOSURE(fun)(FUN_KIND(fun) == JSFUN_NULL_CLOSURE)
131 #define FUN_SLOW_NATIVE(fun) (!FUN_INTERPRETED(fun) && !((fun)->flags & JSFUN_FAST_NATIVE))
132 #define FUN_SCRIPT(fun) (FUN_INTERPRETED(fun) ? (fun)->u.i.script : NULL)
133 #define FUN_NATIVE(fun) (FUN_SLOW_NATIVE(fun) ? (fun)->u.n.native : NULL)
134 #define FUN_FAST_NATIVE(fun) (((fun)->flags & JSFUN_FAST_NATIVE) \
135 ? (js::FastNative) (fun)->u.n.native \
136 : NULL)
137 #define FUN_MINARGS(fun) (((fun)->flags & JSFUN_FAST_NATIVE) \
138 ? 0 \
139 : (fun)->nargs)
140 #define FUN_CLASP(fun) (JS_ASSERT(!FUN_INTERPRETED(fun)), \
141 fun->u.n.clasp)
142 #define FUN_TRCINFO(fun) (JS_ASSERT(!FUN_INTERPRETED(fun)), \
143 JS_ASSERT((fun)->flags & JSFUN_TRCINFO), \
144 fun->u.n.trcinfo)
146 struct JSFunction : public JSObject
148 uint16 nargs; /* maximum number of specified arguments,
149 reflected as f.length/f.arity */
150 uint16 flags; /* flags, see JSFUN_* below and in jsapi.h */
151 union {
152 struct {
153 uint16 extra; /* number of arg slots for local GC roots */
154 uint16 spare; /* reserved for future use */
155 js::Native native; /* native method pointer or null */
156 js::Class *clasp; /* class of objects constructed
157 by this function */
158 JSNativeTraceInfo *trcinfo;
159 } n;
160 struct {
161 uint16 nvars; /* number of local variables */
162 uint16 nupvars; /* number of upvars (computable from script
163 but here for faster access) */
164 uint16 skipmin; /* net skip amount up (toward zero) from
165 script->staticLevel to nearest upvar,
166 including upvars in nested functions */
167 JSPackedBool wrapper; /* true if this function is a wrapper that
168 rewrites bytecode optimized for a function
169 judged non-escaping by the compiler, which
170 then escaped via the debugger or a rogue
171 indirect eval; if true, then this function
172 object's proto is the wrapped object */
173 JSScript *script; /* interpreted bytecode descriptor or null */
174 JSLocalNames names; /* argument and variable names */
175 } i;
176 } u;
177 JSAtom *atom; /* name for diagnostics and decompiling */
179 bool optimizedClosure() const { return FUN_KIND(this) > JSFUN_INTERPRETED; }
180 bool needsWrapper() const { return FUN_NULL_CLOSURE(this) && u.i.skipmin != 0; }
181 bool isInterpreted() const { return FUN_INTERPRETED(this); }
182 bool isFastNative() const { return !!(flags & JSFUN_FAST_NATIVE); }
183 bool isFastConstructor() const { return !!(flags & JSFUN_FAST_NATIVE_CTOR); }
184 bool isHeavyweight() const { return JSFUN_HEAVYWEIGHT_TEST(flags); }
185 unsigned minArgs() const { return FUN_MINARGS(this); }
187 inline bool inStrictMode() const;
189 inline bool isBound() const;
191 uintN countVars() const {
192 JS_ASSERT(FUN_INTERPRETED(this));
193 return u.i.nvars;
196 /* uint16 representation bounds number of call object dynamic slots. */
197 enum { MAX_ARGS_AND_VARS = 2 * ((1U << 16) - 1) };
199 uintN countArgsAndVars() const {
200 JS_ASSERT(FUN_INTERPRETED(this));
201 return nargs + u.i.nvars;
204 uintN countLocalNames() const {
205 JS_ASSERT(FUN_INTERPRETED(this));
206 return countArgsAndVars() + u.i.nupvars;
209 bool hasLocalNames() const {
210 JS_ASSERT(FUN_INTERPRETED(this));
211 return countLocalNames() != 0;
214 int sharpSlotBase(JSContext *cx);
217 * If fun's formal parameters include any duplicate names, return one
218 * of them (chosen arbitrarily). If they are all unique, return NULL.
220 JSAtom *findDuplicateFormal() const;
222 uint32 countInterpretedReservedSlots() const;
224 bool mightEscape() const {
225 return FUN_INTERPRETED(this) && (FUN_FLAT_CLOSURE(this) || u.i.nupvars == 0);
228 bool joinable() const {
229 return flags & JSFUN_JOINABLE;
232 private:
234 * js_FunctionClass reserves two slots, which are free in JSObject::fslots
235 * without requiring dslots allocation. Null closures that can be joined to
236 * a compiler-created function object use the first one to hold a mutable
237 * methodAtom() state variable, needed for correct foo.caller handling.
239 enum {
240 METHOD_ATOM_SLOT = JSSLOT_FUN_METHOD_ATOM
243 public:
244 void setJoinable() {
245 JS_ASSERT(FUN_INTERPRETED(this));
246 fslots[METHOD_ATOM_SLOT].setNull();
247 flags |= JSFUN_JOINABLE;
251 * Method name imputed from property uniquely assigned to or initialized,
252 * where the function does not need to be cloned to carry a scope chain or
253 * flattened upvars.
255 JSAtom *methodAtom() const {
256 return (joinable() && fslots[METHOD_ATOM_SLOT].isString())
257 ? STRING_TO_ATOM(fslots[METHOD_ATOM_SLOT].toString())
258 : NULL;
261 void setMethodAtom(JSAtom *atom) {
262 JS_ASSERT(joinable());
263 fslots[METHOD_ATOM_SLOT].setString(ATOM_TO_STRING(atom));
267 JS_STATIC_ASSERT(sizeof(JSFunction) % JS_GCTHING_ALIGN == 0);
270 * Trace-annotated native. This expands to a JSFunctionSpec initializer (like
271 * JS_FN in jsapi.h). fastcall is a FastNative; trcinfo is a
272 * JSNativeTraceInfo*.
274 #ifdef JS_TRACER
275 /* MSVC demands the intermediate (void *) cast here. */
276 # define JS_TN(name,fastcall,nargs,flags,trcinfo) \
277 JS_FN(name, JS_DATA_TO_FUNC_PTR(JSNative, trcinfo), nargs, \
278 (flags) | JSFUN_FAST_NATIVE | JSFUN_STUB_GSOPS | JSFUN_TRCINFO)
279 #else
280 # define JS_TN(name,fastcall,nargs,flags,trcinfo) \
281 JS_FN(name, fastcall, nargs, flags)
282 #endif
285 * NB: the Arguments classes are uninitialized internal classes that masquerade
286 * (according to Object.prototype.toString.call(arguments)) as "Arguments",
287 * while having Object.getPrototypeOf(arguments) === Object.prototype.
289 * WARNING (to alert embedders reading this private .h file): arguments objects
290 * are *not* thread-safe and should not be used concurrently -- they should be
291 * used by only one thread at a time, preferably by only one thread over their
292 * lifetime (a JS worker that migrates from one OS thread to another but shares
293 * nothing is ok).
295 * Yes, this is an incompatible change, which prefigures the impending move to
296 * single-threaded objects and GC heaps.
298 extern js::Class js_ArgumentsClass;
299 namespace js {
300 extern Class StrictArgumentsClass;
303 inline bool
304 JSObject::isNormalArguments() const
306 return getClass() == &js_ArgumentsClass;
309 inline bool
310 JSObject::isStrictArguments() const
312 return getClass() == &js::StrictArgumentsClass;
315 inline bool
316 JSObject::isArguments() const
318 return isNormalArguments() || isStrictArguments();
321 #define JS_ARGUMENT_OBJECT_ON_TRACE ((void *)0xa126)
323 extern JS_PUBLIC_DATA(js::Class) js_CallClass;
324 extern JS_PUBLIC_DATA(js::Class) js_FunctionClass;
325 extern js::Class js_DeclEnvClass;
326 extern const uint32 CALL_CLASS_FIXED_RESERVED_SLOTS;
328 inline bool
329 JSObject::isFunction() const
331 return getClass() == &js_FunctionClass;
334 inline bool
335 JSObject::isCallable()
337 return isFunction() || getClass()->call;
340 static inline bool
341 js_IsCallable(const js::Value &v)
343 return v.isObject() && v.toObject().isCallable();
347 * NB: jsapi.h and jsobj.h must be included before any call to this macro.
349 #define VALUE_IS_FUNCTION(cx, v) \
350 (!JSVAL_IS_PRIMITIVE(v) && JSVAL_TO_OBJECT(v)->isFunction())
352 static JS_ALWAYS_INLINE bool
353 IsFunctionObject(const js::Value &v)
355 return v.isObject() && v.toObject().isFunction();
358 static JS_ALWAYS_INLINE bool
359 IsFunctionObject(const js::Value &v, JSObject **funobj)
361 return v.isObject() && (*funobj = &v.toObject())->isFunction();
365 * Macro to access the private slot of the function object after the slot is
366 * initialized.
368 #define GET_FUNCTION_PRIVATE(cx, funobj) \
369 (JS_ASSERT((funobj)->isFunction()), \
370 (JSFunction *) (funobj)->getPrivate())
372 extern JSFunction *
373 js_NewFunction(JSContext *cx, JSObject *funobj, js::Native native, uintN nargs,
374 uintN flags, JSObject *parent, JSAtom *atom);
376 namespace js {
379 * Return true if this is a compiler-created internal function accessed by
380 * its own object. Such a function object must not be accessible to script
381 * or embedding code.
383 inline bool
384 IsInternalFunctionObject(JSObject *funobj)
386 JS_ASSERT(funobj->isFunction());
387 JSFunction *fun = (JSFunction *) funobj->getPrivate();
388 return funobj == fun && (fun->flags & JSFUN_LAMBDA) && !funobj->getParent();
391 extern JSString *
392 fun_toStringHelper(JSContext *cx, JSObject *obj, uintN indent);
394 } /* namespace js */
396 extern JSObject *
397 js_InitFunctionClass(JSContext *cx, JSObject *obj);
399 extern JSObject *
400 js_InitArgumentsClass(JSContext *cx, JSObject *obj);
402 extern void
403 js_TraceFunction(JSTracer *trc, JSFunction *fun);
405 extern void
406 js_FinalizeFunction(JSContext *cx, JSFunction *fun);
408 extern JSObject * JS_FASTCALL
409 js_CloneFunctionObject(JSContext *cx, JSFunction *fun, JSObject *parent,
410 JSObject *proto);
412 inline JSObject *
413 CloneFunctionObject(JSContext *cx, JSFunction *fun, JSObject *parent)
415 JS_ASSERT(parent);
416 JSObject *proto;
417 if (!js_GetClassPrototype(cx, parent, JSProto_Function, &proto))
418 return NULL;
419 return js_CloneFunctionObject(cx, fun, parent, proto);
422 extern JS_REQUIRES_STACK JSObject *
423 js_NewFlatClosure(JSContext *cx, JSFunction *fun);
425 extern JS_REQUIRES_STACK JSObject *
426 js_NewDebuggableFlatClosure(JSContext *cx, JSFunction *fun);
428 extern JSFunction *
429 js_DefineFunction(JSContext *cx, JSObject *obj, JSAtom *atom, js::Native native,
430 uintN nargs, uintN flags);
433 * Flags for js_ValueToFunction and js_ReportIsNotFunction. We depend on the
434 * fact that JSINVOKE_CONSTRUCT (aka JSFRAME_CONSTRUCTING) is 1, and test that
435 * with #if/#error in jsfun.c.
437 #define JSV2F_CONSTRUCT JSINVOKE_CONSTRUCT
438 #define JSV2F_SEARCH_STACK 0x10000
440 extern JSFunction *
441 js_ValueToFunction(JSContext *cx, const js::Value *vp, uintN flags);
443 extern JSObject *
444 js_ValueToFunctionObject(JSContext *cx, js::Value *vp, uintN flags);
446 extern JSObject *
447 js_ValueToCallableObject(JSContext *cx, js::Value *vp, uintN flags);
449 extern void
450 js_ReportIsNotFunction(JSContext *cx, const js::Value *vp, uintN flags);
452 extern JSObject *
453 js_GetCallObject(JSContext *cx, JSStackFrame *fp);
455 extern JSObject * JS_FASTCALL
456 js_CreateCallObjectOnTrace(JSContext *cx, JSFunction *fun, JSObject *callee, JSObject *scopeChain);
458 extern void
459 js_PutCallObject(JSContext *cx, JSStackFrame *fp);
461 extern JSBool JS_FASTCALL
462 js_PutCallObjectOnTrace(JSContext *cx, JSObject *scopeChain, uint32 nargs,
463 js::Value *argv, uint32 nvars, js::Value *slots);
465 extern JSFunction *
466 js_GetCallObjectFunction(JSObject *obj);
468 extern JSBool
469 js_GetCallArg(JSContext *cx, JSObject *obj, jsid id, js::Value *vp);
471 extern JSBool
472 js_GetCallVar(JSContext *cx, JSObject *obj, jsid id, js::Value *vp);
474 extern JSBool
475 SetCallArg(JSContext *cx, JSObject *obj, jsid id, js::Value *vp);
477 extern JSBool
478 SetCallVar(JSContext *cx, JSObject *obj, jsid id, js::Value *vp);
481 * Slower version of js_GetCallVar used when call_resolve detects an attempt to
482 * leak an optimized closure via indirect or debugger eval.
484 extern JSBool
485 js_GetCallVarChecked(JSContext *cx, JSObject *obj, jsid id, js::Value *vp);
487 extern JSBool
488 js_GetArgsValue(JSContext *cx, JSStackFrame *fp, js::Value *vp);
490 extern JSBool
491 js_GetArgsProperty(JSContext *cx, JSStackFrame *fp, jsid id, js::Value *vp);
494 * Get the arguments object for the given frame. If the frame is strict mode
495 * code, its current arguments will be copied into the arguments object.
497 * NB: Callers *must* get the arguments object before any parameters are
498 * mutated when the frame is strict mode code! The emitter ensures this
499 * occurs for strict mode functions containing syntax which might mutate a
500 * named parameter by synthesizing an arguments access at the start of the
501 * function.
503 extern JSObject *
504 js_GetArgsObject(JSContext *cx, JSStackFrame *fp);
506 extern void
507 js_PutArgsObject(JSContext *cx, JSStackFrame *fp);
509 inline bool
510 js_IsNamedLambda(JSFunction *fun) { return (fun->flags & JSFUN_LAMBDA) && fun->atom; }
513 * Maximum supported value of arguments.length. It bounds the maximum number of
514 * arguments that can be supplied via the second (so-called |argArray|) param
515 * to Function.prototype.apply. This value also bounds the number of elements
516 * parsed in an array initialiser.
518 * The thread's stack is the limiting factor for this number. It is currently
519 * 2MB, which fits a little less than 2^19 arguments (once the stack frame,
520 * callstack, etc. are included). Pick a max args length that is a little less.
522 const uint32 JS_ARGS_LENGTH_MAX = JS_BIT(19) - 1024;
525 * JSSLOT_ARGS_LENGTH stores ((argc << 1) | overwritten_flag) as an Int32
526 * Value. Thus (JS_ARGS_LENGTH_MAX << 1) | 1 must be less than JSVAL_INT_MAX.
528 JS_STATIC_ASSERT(JS_ARGS_LENGTH_MAX <= JS_BIT(30));
529 JS_STATIC_ASSERT(((JS_ARGS_LENGTH_MAX << 1) | 1) <= JSVAL_INT_MAX);
531 extern JSBool
532 js_XDRFunctionObject(JSXDRState *xdr, JSObject **objp);
534 typedef enum JSLocalKind {
535 JSLOCAL_NONE,
536 JSLOCAL_ARG,
537 JSLOCAL_VAR,
538 JSLOCAL_CONST,
539 JSLOCAL_UPVAR
540 } JSLocalKind;
542 extern JSBool
543 js_AddLocal(JSContext *cx, JSFunction *fun, JSAtom *atom, JSLocalKind kind);
546 * Look up an argument or variable name returning its kind when found or
547 * JSLOCAL_NONE when no such name exists. When indexp is not null and the name
548 * exists, *indexp will receive the index of the corresponding argument or
549 * variable.
551 extern JSLocalKind
552 js_LookupLocal(JSContext *cx, JSFunction *fun, JSAtom *atom, uintN *indexp);
555 * Functions to work with local names as an array of words.
557 * js_GetLocalNameArray returns the array, or null if we are out of memory.
558 * This function must be called only when fun->hasLocalNames().
560 * The supplied pool is used to allocate the returned array, so the caller is
561 * obligated to mark and release to free it.
563 * The elements of the array with index less than fun->nargs correspond to the
564 * names of function formal parameters. An index >= fun->nargs addresses a var
565 * binding. Use JS_LOCAL_NAME_TO_ATOM to convert array's element to an atom
566 * pointer. This pointer can be null when the element is for a formal parameter
567 * corresponding to a destructuring pattern.
569 * If nameWord does not name a formal parameter, use JS_LOCAL_NAME_IS_CONST to
570 * check if nameWord corresponds to the const declaration.
572 extern jsuword *
573 js_GetLocalNameArray(JSContext *cx, JSFunction *fun, struct JSArenaPool *pool);
575 #define JS_LOCAL_NAME_TO_ATOM(nameWord) \
576 ((JSAtom *) ((nameWord) & ~(jsuword) 1))
578 #define JS_LOCAL_NAME_IS_CONST(nameWord) \
579 ((((nameWord) & (jsuword) 1)) != 0)
581 extern void
582 js_FreezeLocalNames(JSContext *cx, JSFunction *fun);
584 extern JSBool
585 js_fun_apply(JSContext *cx, uintN argc, js::Value *vp);
587 extern JSBool
588 js_fun_call(JSContext *cx, uintN argc, js::Value *vp);
590 #endif /* jsfun_h___ */