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
16 * The Original Code is Mozilla Communicator client code, released
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.
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 ***** */
43 * JS function definitions.
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
{
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
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
100 #define JSFUN_EXPR_CLOSURE 0x1000 /* expression closure: function(x) x*x */
101 #define JSFUN_TRCINFO 0x2000 /* when set, u.n.trcinfo is non-null,
102 JSFunctionSpec::call points to a
103 JSNativeTraceInfo. */
104 #define JSFUN_INTERPRETED 0x4000 /* use u.i if kind >= this value else u.n */
105 #define JSFUN_FLAT_CLOSURE 0x8000 /* flag (aka "display") closure */
106 #define JSFUN_NULL_CLOSURE 0xc000 /* null closure entrains no scope chain */
107 #define JSFUN_KINDMASK 0xc000 /* encode interp vs. native and closure
108 optimization level -- see above */
110 #define FUN_OBJECT(fun) (static_cast<JSObject *>(fun))
111 #define FUN_KIND(fun) ((fun)->flags & JSFUN_KINDMASK)
112 #define FUN_SET_KIND(fun,k) ((fun)->flags = ((fun)->flags & ~JSFUN_KINDMASK) | (k))
113 #define FUN_INTERPRETED(fun) (FUN_KIND(fun) >= JSFUN_INTERPRETED)
114 #define FUN_FLAT_CLOSURE(fun)(FUN_KIND(fun) == JSFUN_FLAT_CLOSURE)
115 #define FUN_NULL_CLOSURE(fun)(FUN_KIND(fun) == JSFUN_NULL_CLOSURE)
116 #define FUN_SLOW_NATIVE(fun) (!FUN_INTERPRETED(fun) && !((fun)->flags & JSFUN_FAST_NATIVE))
117 #define FUN_SCRIPT(fun) (FUN_INTERPRETED(fun) ? (fun)->u.i.script : NULL)
118 #define FUN_NATIVE(fun) (FUN_SLOW_NATIVE(fun) ? (fun)->u.n.native : NULL)
119 #define FUN_FAST_NATIVE(fun) (((fun)->flags & JSFUN_FAST_NATIVE) \
120 ? (JSFastNative) (fun)->u.n.native \
122 #define FUN_MINARGS(fun) (((fun)->flags & JSFUN_FAST_NATIVE) \
125 #define FUN_CLASP(fun) (JS_ASSERT(!FUN_INTERPRETED(fun)), \
127 #define FUN_TRCINFO(fun) (JS_ASSERT(!FUN_INTERPRETED(fun)), \
128 JS_ASSERT((fun)->flags & JSFUN_TRCINFO), \
131 struct JSFunction
: public JSObject
{
132 uint16 nargs
; /* maximum number of specified arguments,
133 reflected as f.length/f.arity */
134 uint16 flags
; /* flags, see JSFUN_* below and in jsapi.h */
137 uint16 extra
; /* number of arg slots for local GC roots */
138 uint16 spare
; /* reserved for future use */
139 JSNative native
; /* native method pointer or null */
140 JSClass
*clasp
; /* class of objects constructed
142 JSNativeTraceInfo
*trcinfo
;
145 uint16 nvars
; /* number of local variables */
146 uint16 nupvars
; /* number of upvars (computable from script
147 but here for faster access) */
148 uint16 skipmin
; /* net skip amount up (toward zero) from
149 script->staticLevel to nearest upvar,
150 including upvars in nested functions */
151 JSPackedBool wrapper
; /* true if this function is a wrapper that
152 rewrites bytecode optimized for a function
153 judged non-escaping by the compiler, which
154 then escaped via the debugger or a rogue
155 indirect eval; if true, then this function
156 object's proto is the wrapped object */
157 JSScript
*script
; /* interpreted bytecode descriptor or null */
158 JSLocalNames names
; /* argument and variable names */
161 JSAtom
*atom
; /* name for diagnostics and decompiling */
163 bool optimizedClosure() const { return FUN_KIND(this) > JSFUN_INTERPRETED
; }
164 bool needsWrapper() const { return FUN_NULL_CLOSURE(this) && u
.i
.skipmin
!= 0; }
166 uintN
countArgsAndVars() const {
167 JS_ASSERT(FUN_INTERPRETED(this));
168 return nargs
+ u
.i
.nvars
;
171 uintN
countLocalNames() const {
172 JS_ASSERT(FUN_INTERPRETED(this));
173 return countArgsAndVars() + u
.i
.nupvars
;
176 bool hasLocalNames() const {
177 JS_ASSERT(FUN_INTERPRETED(this));
178 return countLocalNames() != 0;
181 int sharpSlotBase(JSContext
*cx
);
184 * If fun's formal parameters include any duplicate names, return one
185 * of them (chosen arbitrarily). If they are all unique, return NULL.
187 JSAtom
*findDuplicateFormal() const;
189 uint32
countInterpretedReservedSlots() const;
193 * Trace-annotated native. This expands to a JSFunctionSpec initializer (like
194 * JS_FN in jsapi.h). fastcall is a JSFastNative; trcinfo is a
195 * JSNativeTraceInfo*.
198 /* MSVC demands the intermediate (void *) cast here. */
199 # define JS_TN(name,fastcall,nargs,flags,trcinfo) \
200 JS_FN(name, JS_DATA_TO_FUNC_PTR(JSNative, trcinfo), nargs, \
201 (flags) | JSFUN_FAST_NATIVE | JSFUN_STUB_GSOPS | JSFUN_TRCINFO)
203 # define JS_TN(name,fastcall,nargs,flags,trcinfo) \
204 JS_FN(name, fastcall, nargs, flags)
207 extern JSClass js_ArgumentsClass
;
208 extern JS_FRIEND_DATA(JSClass
) js_CallClass
;
209 extern JSClass js_DeclEnvClass
;
211 /* JS_FRIEND_DATA so that VALUE_IS_FUNCTION is callable from the shell. */
212 extern JS_FRIEND_DATA(JSClass
) js_FunctionClass
;
214 #define HAS_FUNCTION_CLASS(obj) (STOBJ_GET_CLASS(obj) == &js_FunctionClass)
217 * NB: jsapi.h and jsobj.h must be included before any call to this macro.
219 #define VALUE_IS_FUNCTION(cx, v) \
220 (!JSVAL_IS_PRIMITIVE(v) && HAS_FUNCTION_CLASS(JSVAL_TO_OBJECT(v)))
223 * Macro to access the private slot of the function object after the slot is
226 #define GET_FUNCTION_PRIVATE(cx, funobj) \
227 (JS_ASSERT(HAS_FUNCTION_CLASS(funobj)), \
228 (JSFunction *) (funobj)->getPrivate())
231 * Return true if this is a compiler-created internal function accessed by
232 * its own object. Such a function object must not be accessible to script
236 js_IsInternalFunctionObject(JSObject
*funobj
)
238 JS_ASSERT(HAS_FUNCTION_CLASS(funobj
));
239 JSFunction
*fun
= (JSFunction
*) funobj
->getPrivate();
240 return funobj
== fun
&& (fun
->flags
& JSFUN_LAMBDA
) && !funobj
->getParent();
243 struct js_ArgsPrivateNative
;
245 inline js_ArgsPrivateNative
*
246 js_GetArgsPrivateNative(JSObject
*argsobj
)
248 JS_ASSERT(STOBJ_GET_CLASS(argsobj
) == &js_ArgumentsClass
);
249 uintptr_t p
= (uintptr_t) argsobj
->getPrivate();
250 return (js_ArgsPrivateNative
*) (p
& 2 ? p
& ~2 : NULL
);
254 js_InitFunctionClass(JSContext
*cx
, JSObject
*obj
);
257 js_InitArgumentsClass(JSContext
*cx
, JSObject
*obj
);
260 js_NewFunction(JSContext
*cx
, JSObject
*funobj
, JSNative native
, uintN nargs
,
261 uintN flags
, JSObject
*parent
, JSAtom
*atom
);
264 js_TraceFunction(JSTracer
*trc
, JSFunction
*fun
);
267 js_FinalizeFunction(JSContext
*cx
, JSFunction
*fun
);
270 js_CloneFunctionObject(JSContext
*cx
, JSFunction
*fun
, JSObject
*parent
);
272 extern JS_REQUIRES_STACK JSObject
*
273 js_NewFlatClosure(JSContext
*cx
, JSFunction
*fun
);
275 extern JS_REQUIRES_STACK JSObject
*
276 js_NewDebuggableFlatClosure(JSContext
*cx
, JSFunction
*fun
);
279 js_DefineFunction(JSContext
*cx
, JSObject
*obj
, JSAtom
*atom
, JSNative native
,
280 uintN nargs
, uintN flags
);
283 * Flags for js_ValueToFunction and js_ReportIsNotFunction. We depend on the
284 * fact that JSINVOKE_CONSTRUCT (aka JSFRAME_CONSTRUCTING) is 1, and test that
285 * with #if/#error in jsfun.c.
287 #define JSV2F_CONSTRUCT JSINVOKE_CONSTRUCT
288 #define JSV2F_ITERATOR JSINVOKE_ITERATOR
289 #define JSV2F_SEARCH_STACK 0x10000
292 js_ValueToFunction(JSContext
*cx
, jsval
*vp
, uintN flags
);
295 js_ValueToFunctionObject(JSContext
*cx
, jsval
*vp
, uintN flags
);
298 js_ValueToCallableObject(JSContext
*cx
, jsval
*vp
, uintN flags
);
301 js_ReportIsNotFunction(JSContext
*cx
, jsval
*vp
, uintN flags
);
304 js_GetCallObject(JSContext
*cx
, JSStackFrame
*fp
);
307 js_PutCallObject(JSContext
*cx
, JSStackFrame
*fp
);
310 js_GetCallObjectFunction(JSObject
*obj
);
313 js_GetCallArg(JSContext
*cx
, JSObject
*obj
, jsid id
, jsval
*vp
);
316 js_GetCallVar(JSContext
*cx
, JSObject
*obj
, jsid id
, jsval
*vp
);
319 SetCallArg(JSContext
*cx
, JSObject
*obj
, jsid id
, jsval
*vp
);
322 SetCallVar(JSContext
*cx
, JSObject
*obj
, jsid id
, jsval
*vp
);
325 * js_SetCallArg and js_SetCallVar are extern fastcall copies of the setter
326 * functions. These versions are required in order to set call vars from traces.
327 * The normal versions must not be fastcall because they are stored in the
330 extern JSBool JS_FASTCALL
331 js_SetCallArg(JSContext
*cx
, JSObject
*obj
, jsid id
, jsval v
);
333 extern JSBool JS_FASTCALL
334 js_SetCallVar(JSContext
*cx
, JSObject
*obj
, jsid id
, jsval v
);
337 * Slower version of js_GetCallVar used when call_resolve detects an attempt to
338 * leak an optimized closure via indirect or debugger eval.
341 js_GetCallVarChecked(JSContext
*cx
, JSObject
*obj
, jsid id
, jsval
*vp
);
344 js_GetArgsValue(JSContext
*cx
, JSStackFrame
*fp
, jsval
*vp
);
347 js_GetArgsProperty(JSContext
*cx
, JSStackFrame
*fp
, jsid id
, jsval
*vp
);
350 js_GetArgsObject(JSContext
*cx
, JSStackFrame
*fp
);
353 js_PutArgsObject(JSContext
*cx
, JSStackFrame
*fp
);
356 * Reserved slot structure for Arguments objects:
358 * JSSLOT_PRIVATE - the corresponding frame until the frame exits.
359 * JSSLOT_ARGS_LENGTH - the number of actual arguments and a flag indicating
360 * whether arguments.length was overwritten.
361 * JSSLOT_ARGS_CALLEE - the arguments.callee value or JSVAL_HOLE if that was
363 * JSSLOT_ARGS_COPY_START .. - room to store the corresponding arguments after
364 * the frame exists. The slot's value will be JSVAL_HOLE
365 * if arguments[i] was deleted or overwritten.
367 const uint32 JSSLOT_ARGS_LENGTH
= JSSLOT_PRIVATE
+ 1;
368 const uint32 JSSLOT_ARGS_CALLEE
= JSSLOT_PRIVATE
+ 2;
369 const uint32 JSSLOT_ARGS_COPY_START
= JSSLOT_PRIVATE
+ 3;
371 /* Number of extra fixed slots besides JSSLOT_PRIVATE. */
372 const uint32 ARGS_CLASS_FIXED_RESERVED_SLOTS
= JSSLOT_ARGS_COPY_START
-
376 * JSSLOT_ARGS_LENGTH stores ((argc << 1) | overwritten_flag) as int jsval.
377 * Thus (JS_ARGS_LENGTH_MAX << 1) | 1 must fit JSVAL_INT_MAX. To assert that
378 * we check first that the shift does not overflow uint32.
380 JS_STATIC_ASSERT(JS_ARGS_LENGTH_MAX
<= JS_BIT(30));
381 JS_STATIC_ASSERT(jsval((JS_ARGS_LENGTH_MAX
<< 1) | 1) <= JSVAL_INT_MAX
);
384 js_IsOverriddenArgsLength(JSObject
*obj
)
386 JS_ASSERT(STOBJ_GET_CLASS(obj
) == &js_ArgumentsClass
);
388 jsval v
= obj
->fslots
[JSSLOT_ARGS_LENGTH
];
389 return (JSVAL_TO_INT(v
) & 1) != 0;
393 js_XDRFunctionObject(JSXDRState
*xdr
, JSObject
**objp
);
395 typedef enum JSLocalKind
{
404 js_AddLocal(JSContext
*cx
, JSFunction
*fun
, JSAtom
*atom
, JSLocalKind kind
);
407 * Look up an argument or variable name returning its kind when found or
408 * JSLOCAL_NONE when no such name exists. When indexp is not null and the name
409 * exists, *indexp will receive the index of the corresponding argument or
413 js_LookupLocal(JSContext
*cx
, JSFunction
*fun
, JSAtom
*atom
, uintN
*indexp
);
416 * Functions to work with local names as an array of words.
418 * js_GetLocalNameArray returns the array, or null if we are out of memory.
419 * This function must be called only when fun->hasLocalNames().
421 * The supplied pool is used to allocate the returned array, so the caller is
422 * obligated to mark and release to free it.
424 * The elements of the array with index less than fun->nargs correspond to the
425 * names of function formal parameters. An index >= fun->nargs addresses a var
426 * binding. Use JS_LOCAL_NAME_TO_ATOM to convert array's element to an atom
427 * pointer. This pointer can be null when the element is for a formal parameter
428 * corresponding to a destructuring pattern.
430 * If nameWord does not name a formal parameter, use JS_LOCAL_NAME_IS_CONST to
431 * check if nameWord corresponds to the const declaration.
433 extern JS_FRIEND_API(jsuword
*)
434 js_GetLocalNameArray(JSContext
*cx
, JSFunction
*fun
, struct JSArenaPool
*pool
);
436 #define JS_LOCAL_NAME_TO_ATOM(nameWord) \
437 ((JSAtom *) ((nameWord) & ~(jsuword) 1))
439 #define JS_LOCAL_NAME_IS_CONST(nameWord) \
440 ((((nameWord) & (jsuword) 1)) != 0)
443 js_FreezeLocalNames(JSContext
*cx
, JSFunction
*fun
);
446 js_fun_apply(JSContext
*cx
, uintN argc
, jsval
*vp
);
449 js_fun_call(JSContext
*cx
, uintN argc
, jsval
*vp
);
454 #endif /* jsfun_h___ */