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.
56 js::Value
*sp
; /* stack pointer */
57 jsbytecode
*pc
; /* program counter */
58 JSStackFrame
*fp
; /* active frame */
61 /* Flags to toggle js::Interpret() execution. */
64 JSINTERP_NORMAL
= 0, /* interpreter is running normally */
65 JSINTERP_RECORD
= 1, /* interpreter has been started to record/run traces */
66 JSINTERP_SAFEPOINT
= 2, /* interpreter should leave on a method JIT safe point */
67 JSINTERP_PROFILE
= 3 /* interpreter should profile a loop */
70 /* Flags used in JSStackFrame::flags_ */
73 /* Primary frame type */
74 JSFRAME_GLOBAL
= 0x1, /* frame pushed for a global script */
75 JSFRAME_FUNCTION
= 0x2, /* frame pushed for a scripted call */
76 JSFRAME_DUMMY
= 0x4, /* frame pushed for bookkeeping */
79 JSFRAME_EVAL
= 0x8, /* frame pushed for eval() or debugger eval */
80 JSFRAME_DEBUGGER
= 0x10, /* frame pushed for debugger eval */
81 JSFRAME_GENERATOR
= 0x20, /* frame is associated with a generator */
82 JSFRAME_FLOATING_GENERATOR
= 0x40, /* frame is is in generator obj, not on stack */
83 JSFRAME_CONSTRUCTING
= 0x80, /* frame is for a constructor invocation */
85 /* Temporary frame states */
86 JSFRAME_ASSIGNING
= 0x100, /* not-JOF_ASSIGNING op is assigning */
87 JSFRAME_YIELDING
= 0x200, /* js::Interpret dispatched JSOP_YIELD */
88 JSFRAME_FINISHED_IN_INTERPRETER
= 0x400, /* set if frame finished in Interpret() */
90 /* Concerning function arguments */
91 JSFRAME_OVERRIDE_ARGS
= 0x1000, /* overridden arguments local variable */
92 JSFRAME_OVERFLOW_ARGS
= 0x2000, /* numActualArgs > numFormalArgs */
93 JSFRAME_UNDERFLOW_ARGS
= 0x4000, /* numActualArgs < numFormalArgs */
95 /* Lazy frame initialization */
96 JSFRAME_HAS_IMACRO_PC
= 0x8000, /* frame has imacpc value available */
97 JSFRAME_HAS_CALL_OBJ
= 0x10000, /* frame has a callobj reachable from scopeChain_ */
98 JSFRAME_HAS_ARGS_OBJ
= 0x20000, /* frame has an argsobj in JSStackFrame::args */
99 JSFRAME_HAS_HOOK_DATA
= 0x40000, /* frame has hookData_ set */
100 JSFRAME_HAS_ANNOTATION
= 0x80000, /* frame has annotation_ set */
101 JSFRAME_HAS_RVAL
= 0x100000, /* frame has rval_ set */
102 JSFRAME_HAS_SCOPECHAIN
= 0x200000, /* frame has scopeChain_ set */
103 JSFRAME_HAS_PREVPC
= 0x400000 /* frame has prevpc_ set */
106 namespace js
{ namespace mjit
{ struct JITScript
; } }
109 * A stack frame is a part of a stack segment (see js::StackSegment) which is
110 * on the per-thread VM stack (see js::StackSpace).
115 mutable uint32 flags_
; /* bits described by JSFrameFlags */
116 union { /* describes what code is executing in a */
117 JSScript
*script
; /* global frame */
118 JSFunction
*fun
; /* function frame, pre GetScopeChain */
120 union { /* describes the arguments of a function */
121 uintN nactual
; /* pre GetArgumentsObject */
122 JSObject
*obj
; /* post GetArgumentsObject */
123 JSScript
*script
; /* eval has no args, but needs a script */
125 mutable JSObject
*scopeChain_
; /* current scope chain */
126 JSStackFrame
*prev_
; /* previous cx->regs->fp */
127 void *ncode_
; /* return address for method JIT */
129 /* Lazily initialized */
130 js::Value rval_
; /* return value of the frame */
131 jsbytecode
*prevpc_
; /* pc of previous frame*/
132 jsbytecode
*imacropc_
; /* pc of macro caller */
133 void *hookData_
; /* closure returned by call hook */
134 void *annotation_
; /* perhaps remove with bug 546848 */
136 friend class js::StackSpace
;
137 friend class js::FrameRegsIter
;
138 friend struct JSContext
;
140 inline void initPrev(JSContext
*cx
);
144 * Stack frame sort (see JSStackFrame comment above)
146 * A stack frame may have one of three types, which determines which
147 * members of the frame may be accessed and other invariants:
149 * global frame: execution of global code or an eval in global code
150 * function frame: execution of function code or an eval in a function
151 * dummy frame: bookkeeping frame (read: hack)
153 * As noted, global and function frames may optionally be 'eval frames', which
154 * further restricts the stack frame members which may be used. Namely, the
155 * argument-related members of function eval frames are not valid, since an eval
156 * shares its containing function's arguments rather than having its own.
159 bool isFunctionFrame() const {
160 return !!(flags_
& JSFRAME_FUNCTION
);
163 bool isGlobalFrame() const {
164 return !!(flags_
& JSFRAME_GLOBAL
);
167 bool isDummyFrame() const {
168 return !!(flags_
& JSFRAME_DUMMY
);
171 bool isScriptFrame() const {
172 return !!(flags_
& (JSFRAME_FUNCTION
| JSFRAME_GLOBAL
));
175 bool isEvalFrame() const {
176 JS_ASSERT_IF(flags_
& JSFRAME_EVAL
, isScriptFrame());
177 return flags_
& JSFRAME_EVAL
;
180 bool isExecuteFrame() const {
181 return !!(flags_
& (JSFRAME_GLOBAL
| JSFRAME_EVAL
));
185 * Frame initialization
187 * After acquiring a pointer to an uninitialized stack frame on the VM
188 * stack from js::StackSpace, these members are used to initialize the
189 * stack frame before officially pushing the frame into the context.
190 * Collecting frame initialization into a set of inline helpers allows
191 * simpler reasoning and makes call-optimization easier.
194 /* Used for Invoke, Interpret, trace-jit LeaveTree, and method-jit stubs. */
195 inline void initCallFrame(JSContext
*cx
, JSObject
&callee
, JSFunction
*fun
,
196 uint32 nactual
, uint32 flags
);
198 /* Used for SessionInvoke. */
199 inline void resetInvokeCallFrame();
201 /* Called by method-jit stubs and serve as a specification for jit-code. */
202 inline void initCallFrameCallerHalf(JSContext
*cx
, uint32 flags
, void *ncode
);
203 inline void initCallFrameEarlyPrologue(JSFunction
*fun
, uint32 nactual
);
204 inline void initCallFrameLatePrologue();
207 inline void initEvalFrame(JSContext
*cx
, JSScript
*script
, JSStackFrame
*prev
,
209 inline void initGlobalFrame(JSScript
*script
, JSObject
&chain
, uint32 flags
);
211 /* Used when activating generators. */
212 inline void stealFrameAndSlots(js::Value
*vp
, JSStackFrame
*otherfp
,
213 js::Value
*othervp
, js::Value
*othersp
);
215 /* Perhaps one fine day we will remove dummy frames. */
216 inline void initDummyFrame(JSContext
*cx
, JSObject
&chain
);
221 * A frame's 'prev' frame is either null or the previous frame pointed to
222 * by cx->regs->fp when this frame was pushed. Often, given two prev-linked
223 * frames, the next-frame is a function or eval that was called by the
224 * prev-frame, but not always: the prev-frame may have called a native that
225 * reentered the VM through JS_CallFunctionValue on the same context
226 * (without calling JS_SaveFrameChain) which pushed the next-frame. Thus,
227 * 'prev' has little semantic meaning and basically just tells the VM what
228 * to set cx->regs->fp to when this frame is popped.
231 JSStackFrame
*prev() const {
235 inline void resetGeneratorPrev(JSContext
*cx
);
240 * A frame's 'slots' are the fixed slots associated with the frame (like
241 * local variables) followed by an expression stack holding temporary
242 * values. A frame's 'base' is the base of the expression stack.
245 js::Value
*slots() const {
246 return (js::Value
*)(this + 1);
249 js::Value
*base() const {
250 return slots() + script()->nfixed
;
253 js::Value
&varSlot(uintN i
) {
254 JS_ASSERT(i
< script()->nfixed
);
255 JS_ASSERT_IF(maybeFun(), i
< script()->bindings
.countVars());
262 * All function and global frames have an associated JSScript which holds
263 * the bytecode being executed for the frame.
267 * Get the frame's current bytecode, assuming |this| is in |cx|.
268 * next is frame whose prev == this, NULL if not known or if this == cx->fp().
270 jsbytecode
*pc(JSContext
*cx
, JSStackFrame
*next
= NULL
);
272 jsbytecode
*prevpc() {
273 JS_ASSERT((prev_
!= NULL
) && (flags_
& JSFRAME_HAS_PREVPC
));
277 JSScript
*script() const {
278 JS_ASSERT(isScriptFrame());
279 return isFunctionFrame()
280 ? isEvalFrame() ? args
.script
: fun()->script()
284 JSScript
*functionScript() const {
285 JS_ASSERT(isFunctionFrame());
286 return isEvalFrame() ? args
.script
: fun()->script();
289 JSScript
*globalScript() const {
290 JS_ASSERT(isGlobalFrame());
294 JSScript
*maybeScript() const {
295 return isScriptFrame() ? script() : NULL
;
298 size_t numFixed() const {
299 return script()->nfixed
;
302 size_t numSlots() const {
303 return script()->nslots
;
306 size_t numGlobalVars() const {
307 JS_ASSERT(isGlobalFrame());
308 return exec
.script
->nfixed
;
314 * All function frames have an associated interpreted JSFunction.
317 JSFunction
* fun() const {
318 JS_ASSERT(isFunctionFrame());
322 JSFunction
* maybeFun() const {
323 return isFunctionFrame() ? fun() : NULL
;
329 * Only non-eval function frames have arguments. A frame follows its
330 * arguments contiguously in memory. The arguments pushed by the caller are
331 * the 'actual' arguments. The declared arguments of the callee are the
332 * 'formal' arguments. When the caller passes less or equal actual
333 * arguments, the actual and formal arguments are the same array (but with
334 * different extents). When the caller passes too many arguments, the
335 * formal subset of the actual arguments is copied onto the top of the
336 * stack. This allows the engine to maintain a jit-time constant offset of
337 * arguments from the frame pointer. Since the formal subset of the actual
338 * arguments is potentially on the stack twice, it is important for all
339 * reads/writes to refer to the same canonical memory location.
341 * An arguments object (the object returned by the 'arguments' keyword) is
342 * lazily created, so a given function frame may or may not have one.
345 /* True if this frame has arguments. Contrast with hasArgsObj. */
346 bool hasArgs() const {
347 return isFunctionFrame() && !isEvalFrame();
350 uintN
numFormalArgs() const {
351 JS_ASSERT(hasArgs());
355 js::Value
&formalArg(uintN i
) const {
356 JS_ASSERT(i
< numFormalArgs());
357 return formalArgs()[i
];
360 js::Value
*formalArgs() const {
361 JS_ASSERT(hasArgs());
362 return (js::Value
*)this - numFormalArgs();
365 js::Value
*formalArgsEnd() const {
366 JS_ASSERT(hasArgs());
367 return (js::Value
*)this;
370 js::Value
*maybeFormalArgs() const {
371 return (flags_
& (JSFRAME_FUNCTION
| JSFRAME_EVAL
)) == JSFRAME_FUNCTION
376 inline uintN
numActualArgs() const;
377 inline js::Value
*actualArgs() const;
378 inline js::Value
*actualArgsEnd() const;
380 inline js::Value
&canonicalActualArg(uintN i
) const;
381 template <class Op
> inline void forEachCanonicalActualArg(Op op
);
382 template <class Op
> inline void forEachFormalArg(Op op
);
384 inline void clearMissingArgs();
386 bool hasArgsObj() const {
387 return !!(flags_
& JSFRAME_HAS_ARGS_OBJ
);
390 JSObject
&argsObj() const {
391 JS_ASSERT(hasArgsObj());
392 JS_ASSERT(!isEvalFrame());
396 JSObject
*maybeArgsObj() const {
397 return hasArgsObj() ? &argsObj() : NULL
;
400 inline void setArgsObj(JSObject
&obj
);
401 inline void clearArgsObj();
406 * Every frame has a this value although, until 'this' is computed, the
407 * value may not be the semantically-correct 'this' value.
409 * The 'this' value is stored before the formal arguments for function
410 * frames and directly before the frame for global frames. The *Args
411 * members assert !isEvalFrame(), so we implement specialized inline
412 * methods for accessing 'this'. When the caller has static knowledge that
413 * a frame is a function or global frame, 'functionThis' and 'globalThis',
414 * respectively, allow more efficient access.
417 js::Value
&functionThis() const {
418 JS_ASSERT(isFunctionFrame());
420 return ((js::Value
*)this)[-1];
421 return formalArgs()[-1];
424 JSObject
&constructorThis() const {
425 JS_ASSERT(hasArgs());
426 return formalArgs()[-1].toObject();
429 js::Value
&globalThis() const {
430 JS_ASSERT(isGlobalFrame());
431 return ((js::Value
*)this)[-1];
434 js::Value
&thisValue() const {
435 if (flags_
& (JSFRAME_EVAL
| JSFRAME_GLOBAL
))
436 return ((js::Value
*)this)[-1];
437 return formalArgs()[-1];
440 inline bool computeThis(JSContext
*cx
);
445 * Only function frames have a callee. An eval frame in a function has the
446 * same caller as its containing function frame.
449 js::Value
&calleeValue() const {
450 JS_ASSERT(isFunctionFrame());
452 return ((js::Value
*)this)[-2];
453 return formalArgs()[-2];
456 JSObject
&callee() const {
457 JS_ASSERT(isFunctionFrame());
458 return calleeValue().toObject();
461 JSObject
*maybeCallee() const {
462 return isFunctionFrame() ? &callee() : NULL
;
466 * getValidCalleeObject is a fallible getter to compute the correct callee
467 * function object, which may require deferred cloning due to the JSObject
468 * methodReadBarrier. For a non-function frame, return true with *vp set
469 * from calleeValue, which may not be an object (it could be undefined).
471 bool getValidCalleeObject(JSContext
*cx
, js::Value
*vp
);
476 * Every frame has a scopeChain which, when traversed via the 'parent' link
477 * to the root, indicates the current global object. A 'call object' is a
478 * node on a scope chain representing a function's activation record. A
479 * call object is used for dynamically-scoped name lookup and lexically-
480 * scoped upvar access. The call object holds the values of locals and
481 * arguments when a function returns (and its stack frame is popped). For
482 * performance reasons, call objects are created lazily for 'lightweight'
483 * functions, i.e., functions which are not statically known to require a
484 * call object. Thus, a given function frame may or may not have a call
485 * object. When a function does have a call object, it is found by walking
486 * up the scope chain until the first call object. Thus, it is important,
487 * when setting the scope chain, to indicate whether the new scope chain
488 * contains a new call object and thus changes the 'hasCallObj' state.
491 JSObject
&scopeChain() const {
492 JS_ASSERT_IF(!(flags_
& JSFRAME_HAS_SCOPECHAIN
), isFunctionFrame());
493 if (!(flags_
& JSFRAME_HAS_SCOPECHAIN
)) {
494 scopeChain_
= callee().getParent();
495 flags_
|= JSFRAME_HAS_SCOPECHAIN
;
500 bool hasCallObj() const {
501 return !!(flags_
& JSFRAME_HAS_CALL_OBJ
);
504 inline JSObject
&callObj() const;
505 inline JSObject
*maybeCallObj() const;
506 inline void setScopeChainNoCallObj(JSObject
&obj
);
507 inline void setScopeChainAndCallObj(JSObject
&obj
);
508 inline void clearCallObj();
513 * A frame's IMacro pc is the bytecode address when an imacro started
514 * executing (guaranteed non-null). An imacro does not push a frame, so
515 * when the imacro finishes, the frame's IMacro pc becomes the current pc.
518 bool hasImacropc() const {
519 return flags_
& JSFRAME_HAS_IMACRO_PC
;
522 jsbytecode
*imacropc() const {
523 JS_ASSERT(hasImacropc());
527 jsbytecode
*maybeImacropc() const {
528 return hasImacropc() ? imacropc() : NULL
;
531 void clearImacropc() {
532 flags_
&= ~JSFRAME_HAS_IMACRO_PC
;
535 void setImacropc(jsbytecode
*pc
) {
537 JS_ASSERT(!(flags_
& JSFRAME_HAS_IMACRO_PC
));
539 flags_
|= JSFRAME_HAS_IMACRO_PC
;
542 /* Annotation (will be removed after bug 546848) */
544 void* annotation() const {
545 return (flags_
& JSFRAME_HAS_ANNOTATION
) ? annotation_
: NULL
;
548 void setAnnotation(void *annot
) {
549 flags_
|= JSFRAME_HAS_ANNOTATION
;
553 /* Debugger hook data */
555 bool hasHookData() const {
556 return !!(flags_
& JSFRAME_HAS_HOOK_DATA
);
559 void* hookData() const {
560 JS_ASSERT(hasHookData());
564 void* maybeHookData() const {
565 return hasHookData() ? hookData_
: NULL
;
568 void setHookData(void *v
) {
570 flags_
|= JSFRAME_HAS_HOOK_DATA
;
575 const js::Value
&returnValue() {
576 if (!(flags_
& JSFRAME_HAS_RVAL
))
577 rval_
.setUndefined();
581 void markReturnValue() {
582 flags_
|= JSFRAME_HAS_RVAL
;
585 void setReturnValue(const js::Value
&v
) {
590 void clearReturnValue() {
591 rval_
.setUndefined();
595 /* Native-code return address */
597 void *nativeReturnAddress() const {
601 void setNativeReturnAddress(void *addr
) {
605 void **addressOfNativeReturnAddress() {
610 * Generator-specific members
612 * A non-eval function frame may optionally be the activation of a
613 * generator. For the most part, generator frames act like ordinary frames.
614 * For exceptions, see js_FloatingFrameIfGenerator.
617 bool isGeneratorFrame() const {
618 return !!(flags_
& JSFRAME_GENERATOR
);
621 bool isFloatingGenerator() const {
622 JS_ASSERT_IF(flags_
& JSFRAME_FLOATING_GENERATOR
, isGeneratorFrame());
623 return !!(flags_
& JSFRAME_FLOATING_GENERATOR
);
626 void initFloatingGenerator() {
627 JS_ASSERT(!(flags_
& JSFRAME_GENERATOR
));
628 flags_
|= (JSFRAME_GENERATOR
| JSFRAME_FLOATING_GENERATOR
);
631 void unsetFloatingGenerator() {
632 flags_
&= ~JSFRAME_FLOATING_GENERATOR
;
635 void setFloatingGenerator() {
636 flags_
|= JSFRAME_FLOATING_GENERATOR
;
643 bool isConstructing() const {
644 return !!(flags_
& JSFRAME_CONSTRUCTING
);
647 uint32
isConstructingFlag() const {
648 JS_ASSERT(isFunctionFrame());
649 JS_ASSERT((flags_
& ~(JSFRAME_CONSTRUCTING
| JSFRAME_FUNCTION
)) == 0);
653 bool isDebuggerFrame() const {
654 return !!(flags_
& JSFRAME_DEBUGGER
);
657 bool isEvalOrDebuggerFrame() const {
658 return !!(flags_
& (JSFRAME_EVAL
| JSFRAME_DEBUGGER
));
661 bool hasOverriddenArgs() const {
662 return !!(flags_
& JSFRAME_OVERRIDE_ARGS
);
665 bool hasOverflowArgs() const {
666 return !!(flags_
& JSFRAME_OVERFLOW_ARGS
);
669 void setOverriddenArgs() {
670 flags_
|= JSFRAME_OVERRIDE_ARGS
;
673 bool isAssigning() const {
674 return !!(flags_
& JSFRAME_ASSIGNING
);
677 void setAssigning() {
678 flags_
|= JSFRAME_ASSIGNING
;
681 void clearAssigning() {
682 flags_
&= ~JSFRAME_ASSIGNING
;
686 return !!(flags_
& JSFRAME_YIELDING
);
690 flags_
|= JSFRAME_YIELDING
;
693 void clearYielding() {
694 flags_
&= ~JSFRAME_YIELDING
;
697 void setFinishedInInterpreter() {
698 flags_
|= JSFRAME_FINISHED_IN_INTERPRETER
;
701 bool finishedInInterpreter() const {
702 return !!(flags_
& JSFRAME_FINISHED_IN_INTERPRETER
);
706 * Variables object accessors
708 * A stack frame's 'varobj' refers to the 'variables object' (ES3 term)
709 * associated with the Execution Context's VariableEnvironment (ES5 10.3).
711 * To compute the frame's varobj, the caller must supply the segment
712 * containing the frame (see js::StackSegment comment). As an abbreviation,
713 * the caller may pass the context if the frame is contained in that
714 * context's active segment.
717 inline JSObject
&varobj(js::StackSegment
*seg
) const;
718 inline JSObject
&varobj(JSContext
*cx
) const;
720 /* Access to privates from the jits. */
722 static size_t offsetOfFlags() {
723 return offsetof(JSStackFrame
, flags_
);
726 static size_t offsetOfExec() {
727 return offsetof(JSStackFrame
, exec
);
730 void *addressOfArgs() {
734 static size_t offsetOfScopeChain() {
735 return offsetof(JSStackFrame
, scopeChain_
);
738 JSObject
**addressOfScopeChain() {
739 JS_ASSERT(flags_
& JSFRAME_HAS_SCOPECHAIN
);
743 static size_t offsetOfPrev() {
744 return offsetof(JSStackFrame
, prev_
);
747 static size_t offsetOfReturnValue() {
748 return offsetof(JSStackFrame
, rval_
);
751 static ptrdiff_t offsetOfncode() {
752 return offsetof(JSStackFrame
, ncode_
);
755 static ptrdiff_t offsetOfCallee(JSFunction
*fun
) {
756 JS_ASSERT(fun
!= NULL
);
757 return -(fun
->nargs
+ 2) * sizeof(js::Value
);
760 static ptrdiff_t offsetOfThis(JSFunction
*fun
) {
762 ? -1 * ptrdiff_t(sizeof(js::Value
))
763 : -(fun
->nargs
+ 1) * ptrdiff_t(sizeof(js::Value
));
766 static ptrdiff_t offsetOfFormalArg(JSFunction
*fun
, uintN i
) {
767 JS_ASSERT(i
< fun
->nargs
);
768 return (-(int)fun
->nargs
+ i
) * sizeof(js::Value
);
771 static size_t offsetOfFixed(uintN i
) {
772 return sizeof(JSStackFrame
) + i
* sizeof(js::Value
);
775 /* Workaround for static asserts on private members. */
777 void staticAsserts() {
778 JS_STATIC_ASSERT(offsetof(JSStackFrame
, rval_
) % sizeof(js::Value
) == 0);
779 JS_STATIC_ASSERT(sizeof(JSStackFrame
) % sizeof(js::Value
) == 0);
783 js::mjit::JITScript
*jit() {
784 return script()->getJIT(isConstructing());
788 void methodjitStaticAsserts();
791 /* Poison scopeChain value set before a frame is flushed. */
792 static JSObject
*const sInvalidScopeChain
;
798 static const size_t VALUES_PER_STACK_FRAME
= sizeof(JSStackFrame
) / sizeof(Value
);
801 GetBlockChain(JSContext
*cx
, JSStackFrame
*fp
);
804 GetBlockChainFast(JSContext
*cx
, JSStackFrame
*fp
, JSOp op
, size_t oplen
);
807 GetScopeChain(JSContext
*cx
);
810 * Refresh and return fp->scopeChain. It may be stale if block scopes are
811 * active but not yet reflected by objects in the scope chain. If a block
812 * scope contains a with, eval, XML filtering predicate, or similar such
813 * dynamically scoped construct, then compile-time block scope at fp->blocks
814 * must reflect at runtime.
817 GetScopeChain(JSContext
*cx
, JSStackFrame
*fp
);
820 GetScopeChainFast(JSContext
*cx
, JSStackFrame
*fp
, JSOp op
, size_t oplen
);
823 * Report an error that the this value passed as |this| in the given arguments
824 * vector is not compatible with the specified class.
827 ReportIncompatibleMethod(JSContext
*cx
, Value
*vp
, Class
*clasp
);
830 * Given a context and a vector of [callee, this, args...] for a function
831 * whose JSFUN_PRIMITIVE_THIS flag is set, set |*v| to the primitive value
832 * of |this|. If |this| is an object, insist that it be an instance of the
833 * appropriate wrapper class for T, and set |*v| to its private slot value.
834 * If |this| is a primitive, unbox it into |*v| if it's of the required
835 * type, and throw an error otherwise.
837 template <typename T
>
838 bool GetPrimitiveThis(JSContext
*cx
, Value
*vp
, T
*v
);
841 PutActivationObjects(JSContext
*cx
, JSStackFrame
*fp
);
844 * For a call's vp (which necessarily includes callee at vp[0] and the original
845 * specified |this| at vp[1]), convert null/undefined |this| into the global
846 * object for the callee and replace other primitives with boxed versions. The
847 * callee must not be strict mode code.
850 BoxThisForVp(JSContext
*cx
, js::Value
*vp
);
853 * Abstracts the layout of the stack passed to natives from the engine and from
854 * natives to js::Invoke.
862 CallArgs(Value
*argv
, uintN argc
) : argv_(argv
), argc_(argc
) {}
864 Value
*base() const { return argv_
- 2; }
865 Value
&callee() const { return argv_
[-2]; }
866 Value
&thisv() const { return argv_
[-1]; }
867 Value
&operator[](unsigned i
) const { JS_ASSERT(i
< argc_
); return argv_
[i
]; }
868 Value
*argv() const { return argv_
; }
869 uintN
argc() const { return argc_
; }
870 Value
&rval() const { return argv_
[-2]; }
874 * The js::InvokeArgumentsGuard passed to js_Invoke must come from an
875 * immediately-enclosing successful call to js::StackSpace::pushInvokeArgs,
876 * i.e., there must have been no un-popped pushes to cx->stack(). Furthermore,
877 * |args.getvp()[0]| should be the callee, |args.getvp()[1]| should be |this|,
878 * and the range [args.getvp() + 2, args.getvp() + 2 + args.getArgc()) should
879 * be initialized actual arguments.
881 extern JS_REQUIRES_STACK
bool
882 Invoke(JSContext
*cx
, const CallArgs
&args
, uint32 flags
);
885 * Natives like sort/forEach/replace call Invoke repeatedly with the same
886 * callee, this, and number of arguments. To optimize this, such natives can
887 * start an "invoke session" to factor out much of the dynamic setup logic
888 * required by a normal Invoke. Usage is:
890 * InvokeSessionGuard session(cx);
891 * if (!session.start(cx, callee, thisp, argc, &session))
895 * // write actual args (not callee, this)
898 * session[argc - 1] = ...
900 * if (!session.invoke(cx, session))
903 * ... = session.rval();
906 * // session ended by ~InvokeSessionGuard
908 class InvokeSessionGuard
;
911 * Consolidated js_Invoke flags simply rename certain JSFRAME_* flags, so that
912 * we can share bits stored in JSStackFrame.flags and passed to:
917 * js_ValueToFunctionObject
918 * js_ValueToCallableObject
919 * js_ReportIsNotFunction
921 * See jsfun.h for the latter four and flag renaming macros.
923 #define JSINVOKE_CONSTRUCT JSFRAME_CONSTRUCTING
926 * Mask to isolate construct and iterator flags for use with jsfun.h functions.
928 #define JSINVOKE_FUNFLAGS JSINVOKE_CONSTRUCT
931 * "External" calls may come from C or C++ code using a JSContext on which no
932 * JS is running (!cx->fp), so they may need to push a dummy JSStackFrame.
936 ExternalInvoke(JSContext
*cx
, const Value
&thisv
, const Value
&fval
,
937 uintN argc
, Value
*argv
, Value
*rval
);
940 ExternalGetOrSet(JSContext
*cx
, JSObject
*obj
, jsid id
, const Value
&fval
,
941 JSAccessMode mode
, uintN argc
, Value
*argv
, Value
*rval
);
944 * These two functions invoke a function called from a constructor context
945 * (e.g. 'new'). InvokeConstructor handles the general case where a new object
946 * needs to be created for/by the constructor. ConstructWithGivenThis directly
947 * calls the constructor with the given 'this', hence the caller must
948 * understand the semantics of the constructor call.
951 extern JS_REQUIRES_STACK
bool
952 InvokeConstructor(JSContext
*cx
, const CallArgs
&args
);
954 extern JS_REQUIRES_STACK
bool
955 InvokeConstructorWithGivenThis(JSContext
*cx
, JSObject
*thisobj
, const Value
&fval
,
956 uintN argc
, Value
*argv
, Value
*rval
);
959 ExternalInvokeConstructor(JSContext
*cx
, const Value
&fval
, uintN argc
, Value
*argv
,
963 * Performs a direct eval for the given arguments, which must correspond to the
964 * currently-executing stack frame, which must be a script frame. evalfun must
965 * be the built-in eval function and must correspond to the callee in vp[0].
966 * When this function succeeds it returns the result in *vp, adjusts the JS
967 * stack pointer, and returns true.
969 extern JS_REQUIRES_STACK
bool
970 DirectEval(JSContext
*cx
, JSFunction
*evalfun
, uint32 argc
, Value
*vp
);
973 * Performs a direct eval for the given arguments, which must correspond to the
974 * currently-executing stack frame, which must be a script frame. evalfun must
975 * be the built-in eval function and must correspond to the callee in vp[0].
976 * When this function succeeds it returns the result in *vp, adjusts the JS
977 * stack pointer, and returns true.
979 extern JS_REQUIRES_STACK
bool
980 DirectEval(JSContext
*cx
, JSFunction
*evalfun
, uint32 argc
, Value
*vp
);
983 * Executes a script with the given scope chain in the context of the given
986 extern JS_FORCES_STACK
bool
987 Execute(JSContext
*cx
, JSObject
*chain
, JSScript
*script
,
988 JSStackFrame
*prev
, uintN flags
, Value
*result
);
991 * Execute the caller-initialized frame for a user-defined script or function
992 * pointed to by cx->fp until completion or error.
994 extern JS_REQUIRES_STACK JS_NEVER_INLINE
bool
995 Interpret(JSContext
*cx
, JSStackFrame
*stopFp
, uintN inlineCallCount
= 0, JSInterpMode mode
= JSINTERP_NORMAL
);
997 extern JS_REQUIRES_STACK
bool
998 RunScript(JSContext
*cx
, JSScript
*script
, JSStackFrame
*fp
);
1001 CheckRedeclaration(JSContext
*cx
, JSObject
*obj
, jsid id
, uintN attrs
);
1004 StrictlyEqual(JSContext
*cx
, const Value
&lval
, const Value
&rval
, JSBool
*equal
);
1006 /* === except that NaN is the same as NaN and -0 is not the same as +0. */
1008 SameValue(JSContext
*cx
, const Value
&v1
, const Value
&v2
, JSBool
*same
);
1011 TypeOfValue(JSContext
*cx
, const Value
&v
);
1014 InstanceOf(JSContext
*cx
, JSObject
*obj
, Class
*clasp
, Value
*argv
)
1016 if (obj
&& obj
->getClass() == clasp
)
1018 extern bool InstanceOfSlow(JSContext
*, JSObject
*, Class
*, Value
*);
1019 return InstanceOfSlow(cx
, obj
, clasp
, argv
);
1023 HasInstance(JSContext
*cx
, JSObject
*obj
, const js::Value
*v
, JSBool
*bp
);
1026 GetInstancePrivate(JSContext
*cx
, JSObject
*obj
, Class
*clasp
, Value
*argv
)
1028 if (!InstanceOf(cx
, obj
, clasp
, argv
))
1030 return obj
->getPrivate();
1034 ValueToId(JSContext
*cx
, const Value
&v
, jsid
*idp
);
1037 * @param closureLevel The static level of the closure that the cookie
1039 * @param cookie Level amount is a "skip" (delta) value from the
1041 * @return The value of the upvar.
1043 extern const js::Value
&
1044 GetUpvar(JSContext
*cx
, uintN level
, js::UpvarCookie cookie
);
1046 } /* namespace js */
1049 * JS_LONE_INTERPRET indicates that the compiler should see just the code for
1050 * the js_Interpret function when compiling jsinterp.cpp. The rest of the code
1051 * from the file should be visible only when compiling jsinvoke.cpp. It allows
1052 * platform builds to optimize selectively js_Interpret when the granularity
1053 * of the optimizations with the given compiler is a compilation unit.
1055 * JS_STATIC_INTERPRET is the modifier for functions defined in jsinterp.cpp
1056 * that only js_Interpret calls. When JS_LONE_INTERPRET is true all such
1057 * functions are declared below.
1059 #ifndef JS_LONE_INTERPRET
1061 # define JS_LONE_INTERPRET 0
1063 # define JS_LONE_INTERPRET 1
1067 #define JS_MAX_INLINE_CALL_COUNT 3000
1069 #if !JS_LONE_INTERPRET
1070 # define JS_STATIC_INTERPRET static
1072 # define JS_STATIC_INTERPRET
1074 extern JS_REQUIRES_STACK JSBool
1075 js_EnterWith(JSContext
*cx
, jsint stackIndex
, JSOp op
, size_t oplen
);
1077 extern JS_REQUIRES_STACK
void
1078 js_LeaveWith(JSContext
*cx
);
1081 * Find the results of incrementing or decrementing *vp. For pre-increments,
1082 * both *vp and *vp2 will contain the result on return. For post-increments,
1083 * vp will contain the original value converted to a number and vp2 will get
1084 * the result. Both vp and vp2 must be roots.
1087 js_DoIncDec(JSContext
*cx
, const JSCodeSpec
*cs
, js::Value
*vp
, js::Value
*vp2
);
1090 * Opcode tracing helper. When len is not 0, cx->fp->regs->pc[-len] gives the
1093 extern JS_REQUIRES_STACK
void
1094 js_LogOpcode(JSContext
*cx
);
1097 * JS_OPMETER helper functions.
1100 js_MeterOpcodePair(JSOp op1
, JSOp op2
);
1103 js_MeterSlotOpcode(JSOp op
, uint32 slot
);
1105 #endif /* JS_LONE_INTERPRET */
1107 * Unwind block and scope chains to match the given depth. The function sets
1108 * fp->sp on return to stackDepth.
1110 extern JS_REQUIRES_STACK JSBool
1111 js_UnwindScope(JSContext
*cx
, jsint stackDepth
, JSBool normalUnwind
);
1114 js_OnUnknownMethod(JSContext
*cx
, js::Value
*vp
);
1116 extern JS_REQUIRES_STACK
js::Class
*
1117 js_IsActiveWithOrBlock(JSContext
*cx
, JSObject
*obj
, int stackDepth
);
1119 #endif /* jsinterp_h___ */