1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2 * vim: set ts=4 sw=4 et tw=78:
4 * ***** BEGIN LICENSE BLOCK *****
5 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
7 * The contents of this file are subject to the Mozilla Public License Version
8 * 1.1 (the "License"); you may not use this file except in compliance with
9 * the License. You may obtain a copy of the License at
10 * http://www.mozilla.org/MPL/
12 * Software distributed under the License is distributed on an "AS IS" basis,
13 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
14 * for the specific language governing rights and limitations under the
17 * The Original Code is Mozilla Communicator client code, released
20 * The Initial Developer of the Original Code is
21 * Netscape Communications Corporation.
22 * Portions created by the Initial Developer are Copyright (C) 1998
23 * the Initial Developer. All Rights Reserved.
27 * Alternatively, the contents of this file may be used under the terms of
28 * either of the GNU General Public License Version 2 or later (the "GPL"),
29 * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
30 * in which case the provisions of the GPL or the LGPL are applicable instead
31 * of those above. If you wish to allow use of your version of this file only
32 * under the terms of either the GPL or the LGPL, and not to allow others to
33 * use your version of this file under the terms of the MPL, indicate your
34 * decision by deleting the provisions above and replace them with the notice
35 * and other provisions required by the GPL or the LGPL. If you do not delete
36 * the provisions above, a recipient may use your version of this file under
37 * the terms of any one of the MPL, the GPL or the LGPL.
39 * ***** END LICENSE BLOCK ***** */
44 * JS interpreter interface.
53 typedef struct JSFrameRegs
{
54 jsbytecode
*pc
; /* program counter */
55 js::Value
*sp
; /* stack pointer */
58 /* JS stack frame flags. */
60 JSFRAME_CONSTRUCTING
= 0x01, /* frame is for a constructor invocation */
61 JSFRAME_COMPUTED_THIS
= 0x02, /* frame.thisv was computed already and
62 JSVAL_IS_OBJECT(thisv) */
63 JSFRAME_ASSIGNING
= 0x04, /* a complex (not simplex JOF_ASSIGNING) op
64 is currently assigning to a property */
65 JSFRAME_DEBUGGER
= 0x08, /* frame for JS_EvaluateInStackFrame */
66 JSFRAME_EVAL
= 0x10, /* frame for obj_eval */
67 JSFRAME_FLOATING_GENERATOR
= 0x20, /* frame copy stored in a generator obj */
68 JSFRAME_YIELDING
= 0x40, /* js_Interpret dispatched JSOP_YIELD */
69 JSFRAME_GENERATOR
= 0x80, /* frame belongs to generator-iterator */
70 JSFRAME_OVERRIDE_ARGS
= 0x100, /* overridden arguments local variable */
72 JSFRAME_SPECIAL
= JSFRAME_DEBUGGER
| JSFRAME_EVAL
76 * JS stack frame, may be allocated on the C stack by native callers. Always
77 * allocated on cx->stackPool for calls from the interpreter to an interpreted
80 * NB: This struct is manually initialized in jsinterp.c and jsiter.c. If you
81 * add new members, update both files.
85 jsbytecode
*imacpc
; /* null or interpreter macro call pc */
86 JSObject
*callobj
; /* lazily created Call object */
87 JSObject
*argsobj
; /* lazily created arguments object */
88 JSScript
*script
; /* script being interpreted */
89 js::Value thisv
; /* "this" pointer if in method */
90 JSFunction
*fun
; /* function being called or null */
91 uintN argc
; /* actual argument count */
92 js::Value
*argv
; /* base of argument stack slots */
93 void *annotation
; /* used by Java security */
94 js::Value rval
; /* function return value */
96 /* Maintained by StackSpace operations */
97 JSStackFrame
*down
; /* previous frame, part of
98 stack layout invariant */
99 jsbytecode
*savedPC
; /* only valid if cx->fp != this */
101 static jsbytecode
*const sInvalidPC
;
105 * We can't determine in advance which local variables can live on
106 * the stack and be freed when their dynamic scope ends, and which
107 * will be closed over and need to live in the heap. So we place
108 * variables on the stack initially, note when they are closed
109 * over, and copy those that are out to the heap when we leave
110 * their dynamic scope.
112 * The bytecode compiler produces a tree of block objects
113 * accompanying each JSScript representing those lexical blocks in
114 * the script that have let-bound variables associated with them.
115 * These block objects are never modified, and never become part
116 * of any function's scope chain. Their parent slots point to the
117 * innermost block that encloses them, or are NULL in the
118 * outermost blocks within a function or in eval or global code.
120 * When we are in the static scope of such a block, blockChain
121 * points to its compiler-allocated block object; otherwise, it is
124 * scopeChain is the current scope chain, including 'call' and
125 * 'block' objects for those function calls and lexical blocks
126 * whose static scope we are currently executing in, and 'with'
127 * objects for with statements; the chain is typically terminated
128 * by a global object. However, as an optimization, the young end
129 * of the chain omits block objects we have not yet cloned. To
130 * create a closure, we clone the missing blocks from blockChain
131 * (which is always current), place them at the head of
132 * scopeChain, and use that for the closure's scope chain. If we
133 * never close over a lexical block, we never place a mutable
134 * clone of it on scopeChain.
136 * This lazy cloning is implemented in js_GetScopeChain, which is
137 * also used in some other cases --- entering 'with' blocks, for
140 JSObject
*scopeChain
;
141 JSObject
*blockChain
;
143 uint32 flags
; /* frame flags -- see below */
144 JSStackFrame
*displaySave
; /* previous value of display entry for
145 script->staticLevel */
147 /* Members only needed for inline calls. */
148 void *hookData
; /* debugger call hook data */
149 JSVersion callerVersion
; /* dynamic version of calling script */
151 void putActivationObjects(JSContext
*cx
) {
153 * The order of calls here is important as js_PutCallObject needs to
157 js_PutCallObject(cx
, this);
159 } else if (argsobj
) {
160 js_PutArgsObject(cx
, this);
164 /* Get the frame's current bytecode, assuming |this| is in |cx|. */
165 jsbytecode
*pc(JSContext
*cx
) const;
167 js::Value
*argEnd() const {
168 return (js::Value
*)this;
171 js::Value
*slots() const {
172 return (js::Value
*)(this + 1);
175 js::Value
*base() const {
176 return slots() + script
->nfixed
;
179 const js::Value
&calleeValue() {
185 return argv
? &argv
[-2].toObject() : NULL
;
189 * Get the object associated with the Execution Context's
190 * VariableEnvironment (ES5 10.3). The given CallStackSegment must contain
193 JSObject
*varobj(js::CallStackSegment
*css
) const;
195 /* Short for: varobj(cx->activeCallStack()). */
196 JSObject
*varobj(JSContext
*cx
) const;
198 inline JSObject
*getThisObject(JSContext
*cx
);
200 bool isGenerator() const { return !!(flags
& JSFRAME_GENERATOR
); }
201 bool isFloatingGenerator() const {
202 JS_ASSERT_IF(flags
& JSFRAME_FLOATING_GENERATOR
, isGenerator());
203 return !!(flags
& JSFRAME_FLOATING_GENERATOR
);
206 bool isDummyFrame() const { return !script
&& !fun
; }
211 JS_STATIC_ASSERT(sizeof(JSStackFrame
) % sizeof(Value
) == 0);
212 static const size_t VALUES_PER_STACK_FRAME
= sizeof(JSStackFrame
) / sizeof(Value
);
214 JS_STATIC_ASSERT(offsetof(JSStackFrame
, rval
) % sizeof(Value
) == 0);
215 JS_STATIC_ASSERT(offsetof(JSStackFrame
, thisv
) % sizeof(Value
) == 0);
219 static JS_INLINE uintN
220 GlobalVarCount(JSStackFrame
*fp
)
223 return fp
->script
->nfixed
;
227 * Refresh and return fp->scopeChain. It may be stale if block scopes are
228 * active but not yet reflected by objects in the scope chain. If a block
229 * scope contains a with, eval, XML filtering predicate, or similar such
230 * dynamically scoped construct, then compile-time block scope at fp->blocks
231 * must reflect at runtime.
234 js_GetScopeChain(JSContext
*cx
, JSStackFrame
*fp
);
237 * Given a context and a vector of [callee, this, args...] for a function that
238 * was specified with a JSFUN_THISP_PRIMITIVE flag, get the primitive value of
239 * |this| into *thisvp. In doing so, if |this| is an object, insist it is an
240 * instance of clasp and extract its private slot value to return via *thisvp.
242 * NB: this function loads and uses *vp before storing *thisvp, so the two may
243 * alias the same Value.
246 js_GetPrimitiveThis(JSContext
*cx
, js::Value
*vp
, js::Class
*clasp
,
247 const js::Value
**vpp
);
252 * For a call with arguments argv including argv[-1] (nominal |this|) and
253 * argv[-2] (callee) replace null |this| with callee's parent, replace
254 * primitive values with the equivalent wrapper objects and censor activation
255 * objects as, per ECMA-262, they may not be referred to by |this|. argv[-1]
256 * must not be a JSVAL_VOID.
259 ComputeThisFromArgv(JSContext
*cx
, js::Value
*argv
);
261 JS_ALWAYS_INLINE JSObject
*
262 ComputeThisFromVp(JSContext
*cx
, js::Value
*vp
)
264 return ComputeThisFromArgv(cx
, vp
+ 2);
267 JS_ALWAYS_INLINE
bool
268 PrimitiveThisTest(JSFunction
*fun
, const Value
&v
)
270 uint16 flags
= fun
->flags
;
271 return (v
.isString() && !!(flags
& JSFUN_THISP_STRING
)) ||
272 (v
.isNumber() && !!(flags
& JSFUN_THISP_NUMBER
)) ||
273 (v
.isBoolean() && !!(flags
& JSFUN_THISP_BOOLEAN
));
277 * The js::InvokeArgumentsGuard passed to js_Invoke must come from an
278 * immediately-enclosing successful call to js::StackSpace::pushInvokeArgs,
279 * i.e., there must have been no un-popped pushes to cx->stack(). Furthermore,
280 * |args.getvp()[0]| should be the callee, |args.getvp()[1]| should be |this|,
281 * and the range [args.getvp() + 2, args.getvp() + 2 + args.getArgc()) should
282 * be initialized actual arguments.
284 extern JS_REQUIRES_STACK
bool
285 Invoke(JSContext
*cx
, const InvokeArgsGuard
&args
, uintN flags
);
287 extern JS_REQUIRES_STACK
JS_FRIEND_API(bool)
288 InvokeFriendAPI(JSContext
*cx
, const InvokeArgsGuard
&args
, uintN flags
);
291 * Consolidated js_Invoke flags simply rename certain JSFRAME_* flags, so that
292 * we can share bits stored in JSStackFrame.flags and passed to:
297 * js_ValueToFunctionObject
298 * js_ValueToCallableObject
299 * js_ReportIsNotFunction
301 * See jsfun.h for the latter four and flag renaming macros.
303 #define JSINVOKE_CONSTRUCT JSFRAME_CONSTRUCTING
306 * Mask to isolate construct and iterator flags for use with jsfun.h functions.
308 #define JSINVOKE_FUNFLAGS JSINVOKE_CONSTRUCT
311 * "Internal" calls may come from C or C++ code using a JSContext on which no
312 * JS is running (!cx->fp), so they may need to push a dummy JSStackFrame.
315 InternalInvoke(JSContext
*cx
, const Value
&thisv
, const Value
&fval
, uintN flags
,
316 uintN argc
, Value
*argv
, Value
*rval
);
318 static JS_ALWAYS_INLINE
bool
319 InternalCall(JSContext
*cx
, JSObject
*obj
, const Value
&fval
,
320 uintN argc
, Value
*argv
, Value
*rval
)
322 return InternalInvoke(cx
, ObjectOrNullValue(obj
), fval
, 0, argc
, argv
, rval
);
325 static JS_ALWAYS_INLINE
bool
326 InternalConstruct(JSContext
*cx
, JSObject
*obj
, const Value
&fval
,
327 uintN argc
, Value
*argv
, Value
*rval
)
329 return InternalInvoke(cx
, ObjectOrNullValue(obj
), fval
, JSINVOKE_CONSTRUCT
, argc
, argv
, rval
);
333 InternalGetOrSet(JSContext
*cx
, JSObject
*obj
, jsid id
, const Value
&fval
,
334 JSAccessMode mode
, uintN argc
, Value
*argv
, Value
*rval
);
336 extern JS_FORCES_STACK
bool
337 Execute(JSContext
*cx
, JSObject
*chain
, JSScript
*script
,
338 JSStackFrame
*down
, uintN flags
, Value
*result
);
340 extern JS_REQUIRES_STACK
bool
341 InvokeConstructor(JSContext
*cx
, const InvokeArgsGuard
&args
);
343 extern JS_REQUIRES_STACK
bool
344 Interpret(JSContext
*cx
);
346 #define JSPROP_INITIALIZER 0x100 /* NB: Not a valid property attribute. */
349 CheckRedeclaration(JSContext
*cx
, JSObject
*obj
, jsid id
, uintN attrs
,
350 JSObject
**objp
, JSProperty
**propp
);
353 StrictlyEqual(JSContext
*cx
, const Value
&lval
, const Value
&rval
);
355 /* === except that NaN is the same as NaN and -0 is not the same as +0. */
357 SameValue(const Value
&v1
, const Value
&v2
, JSContext
*cx
);
360 TypeOfValue(JSContext
*cx
, const Value
&v
);
363 InstanceOf(JSContext
*cx
, JSObject
*obj
, Class
*clasp
, Value
*argv
)
365 if (obj
&& obj
->getClass() == clasp
)
367 extern bool InstanceOfSlow(JSContext
*, JSObject
*, Class
*, Value
*);
368 return InstanceOfSlow(cx
, obj
, clasp
, argv
);
372 HasInstance(JSContext
*cx
, JSObject
*obj
, const js::Value
*v
, JSBool
*bp
);
375 GetInstancePrivate(JSContext
*cx
, JSObject
*obj
, Class
*clasp
, Value
*argv
)
377 if (!InstanceOf(cx
, obj
, clasp
, argv
))
379 return obj
->getPrivate();
383 ValueToId(JSContext
*cx
, const Value
&v
, jsid
*idp
);
386 * @param closureLevel The static level of the closure that the cookie
388 * @param cookie Level amount is a "skip" (delta) value from the
390 * @return The value of the upvar.
392 extern const js::Value
&
393 GetUpvar(JSContext
*cx
, uintN level
, js::UpvarCookie cookie
);
398 * JS_LONE_INTERPRET indicates that the compiler should see just the code for
399 * the js_Interpret function when compiling jsinterp.cpp. The rest of the code
400 * from the file should be visible only when compiling jsinvoke.cpp. It allows
401 * platform builds to optimize selectively js_Interpret when the granularity
402 * of the optimizations with the given compiler is a compilation unit.
404 * JS_STATIC_INTERPRET is the modifier for functions defined in jsinterp.cpp
405 * that only js_Interpret calls. When JS_LONE_INTERPRET is true all such
406 * functions are declared below.
408 #ifndef JS_LONE_INTERPRET
410 # define JS_LONE_INTERPRET 0
412 # define JS_LONE_INTERPRET 1
416 #define JS_MAX_INLINE_CALL_COUNT 3000
418 #if !JS_LONE_INTERPRET
419 # define JS_STATIC_INTERPRET static
421 # define JS_STATIC_INTERPRET
423 extern JS_REQUIRES_STACK JSBool
424 js_EnterWith(JSContext
*cx
, jsint stackIndex
);
426 extern JS_REQUIRES_STACK
void
427 js_LeaveWith(JSContext
*cx
);
429 extern JS_REQUIRES_STACK
js::Class
*
430 js_IsActiveWithOrBlock(JSContext
*cx
, JSObject
*obj
, int stackDepth
);
433 * Unwind block and scope chains to match the given depth. The function sets
434 * fp->sp on return to stackDepth.
436 extern JS_REQUIRES_STACK JSBool
437 js_UnwindScope(JSContext
*cx
, jsint stackDepth
, JSBool normalUnwind
);
440 js_OnUnknownMethod(JSContext
*cx
, js::Value
*vp
);
443 * Find the results of incrementing or decrementing *vp. For pre-increments,
444 * both *vp and *vp2 will contain the result on return. For post-increments,
445 * vp will contain the original value converted to a number and vp2 will get
446 * the result. Both vp and vp2 must be roots.
449 js_DoIncDec(JSContext
*cx
, const JSCodeSpec
*cs
, js::Value
*vp
, js::Value
*vp2
);
452 * Opcode tracing helper. When len is not 0, cx->fp->regs->pc[-len] gives the
455 extern JS_REQUIRES_STACK
void
456 js_TraceOpcode(JSContext
*cx
);
459 * JS_OPMETER helper functions.
462 js_MeterOpcodePair(JSOp op1
, JSOp op2
);
465 js_MeterSlotOpcode(JSOp op
, uint32 slot
);
467 #endif /* JS_LONE_INTERPRET */
470 JSStackFrame::getThisObject(JSContext
*cx
)
472 if (flags
& JSFRAME_COMPUTED_THIS
)
473 return &thisv
.toObject();
474 if (!js::ComputeThisFromArgv(cx
, argv
))
477 flags
|= JSFRAME_COMPUTED_THIS
;
478 return &thisv
.toObject();
481 #endif /* jsinterp_h___ */