Merge mozilla-central and tracemonkey. (a=blockers)
[mozilla-central.git] / js / src / jsinterp.h
blob6e6761c65cf52ae5178cccb6d4447507f30c3a29
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
15 * License.
17 * The Original Code is Mozilla Communicator client code, released
18 * March 31, 1998.
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.
25 * Contributor(s):
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 ***** */
41 #ifndef jsinterp_h___
42 #define jsinterp_h___
44 * JS interpreter interface.
46 #include "jsprvtd.h"
47 #include "jspubtd.h"
48 #include "jsfun.h"
49 #include "jsopcode.h"
50 #include "jsscript.h"
51 #include "jsvalue.h"
53 struct JSFrameRegs
55 STATIC_SKIP_INFERENCE
56 js::Value *sp; /* stack pointer */
57 jsbytecode *pc; /* program counter */
58 JSStackFrame *fp; /* active frame */
61 /* Flags to toggle js::Interpret() execution. */
62 enum JSInterpMode
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_ */
71 enum JSFrameFlags
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 */
78 /* Frame subtypes */
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).
112 struct JSStackFrame
114 private:
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 */
119 } exec;
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 */
124 } args;
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);
142 public:
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();
206 /* Used for eval. */
207 inline void initEvalFrame(JSContext *cx, JSScript *script, JSStackFrame *prev,
208 uint32 flags);
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);
219 * Previous frame
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 {
232 return prev_;
235 inline void resetGeneratorPrev(JSContext *cx);
238 * Frame slots
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());
256 return slots()[i];
260 * Script
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));
274 return prevpc_;
277 JSScript *script() const {
278 JS_ASSERT(isScriptFrame());
279 return isFunctionFrame()
280 ? isEvalFrame() ? args.script : fun()->script()
281 : exec.script;
284 JSScript *functionScript() const {
285 JS_ASSERT(isFunctionFrame());
286 return isEvalFrame() ? args.script : fun()->script();
289 JSScript *globalScript() const {
290 JS_ASSERT(isGlobalFrame());
291 return exec.script;
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;
312 * Function
314 * All function frames have an associated interpreted JSFunction.
317 JSFunction* fun() const {
318 JS_ASSERT(isFunctionFrame());
319 return exec.fun;
322 JSFunction* maybeFun() const {
323 return isFunctionFrame() ? fun() : NULL;
327 * Arguments
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());
352 return fun()->nargs;
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
372 ? formalArgs()
373 : NULL;
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());
393 return *args.obj;
396 JSObject *maybeArgsObj() const {
397 return hasArgsObj() ? &argsObj() : NULL;
400 inline void setArgsObj(JSObject &obj);
401 inline void clearArgsObj();
404 * This value
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());
419 if (isEvalFrame())
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);
443 * Callee
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());
451 if (isEvalFrame())
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);
474 * Scope chain
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;
497 return *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();
511 * Imacropc
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());
524 return imacropc_;
527 jsbytecode *maybeImacropc() const {
528 return hasImacropc() ? imacropc() : NULL;
531 void clearImacropc() {
532 flags_ &= ~JSFRAME_HAS_IMACRO_PC;
535 void setImacropc(jsbytecode *pc) {
536 JS_ASSERT(pc);
537 JS_ASSERT(!(flags_ & JSFRAME_HAS_IMACRO_PC));
538 imacropc_ = 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;
550 annotation_ = annot;
553 /* Debugger hook data */
555 bool hasHookData() const {
556 return !!(flags_ & JSFRAME_HAS_HOOK_DATA);
559 void* hookData() const {
560 JS_ASSERT(hasHookData());
561 return hookData_;
564 void* maybeHookData() const {
565 return hasHookData() ? hookData_ : NULL;
568 void setHookData(void *v) {
569 hookData_ = v;
570 flags_ |= JSFRAME_HAS_HOOK_DATA;
573 /* Return value */
575 const js::Value &returnValue() {
576 if (!(flags_ & JSFRAME_HAS_RVAL))
577 rval_.setUndefined();
578 return rval_;
581 void markReturnValue() {
582 flags_ |= JSFRAME_HAS_RVAL;
585 void setReturnValue(const js::Value &v) {
586 rval_ = v;
587 markReturnValue();
590 void clearReturnValue() {
591 rval_.setUndefined();
592 markReturnValue();
595 /* Native-code return address */
597 void *nativeReturnAddress() const {
598 return ncode_;
601 void setNativeReturnAddress(void *addr) {
602 ncode_ = addr;
605 void **addressOfNativeReturnAddress() {
606 return &ncode_;
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;
640 * Other flags
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);
650 return flags_;
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;
685 bool isYielding() {
686 return !!(flags_ & JSFRAME_YIELDING);
689 void setYielding() {
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() {
731 return &args;
734 static size_t offsetOfScopeChain() {
735 return offsetof(JSStackFrame, scopeChain_);
738 JSObject **addressOfScopeChain() {
739 JS_ASSERT(flags_ & JSFRAME_HAS_SCOPECHAIN);
740 return &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) {
761 return fun == NULL
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);
782 #ifdef JS_METHODJIT
783 js::mjit::JITScript *jit() {
784 return script()->getJIT(isConstructing());
786 #endif
788 void methodjitStaticAsserts();
790 #ifdef DEBUG
791 /* Poison scopeChain value set before a frame is flushed. */
792 static JSObject *const sInvalidScopeChain;
793 #endif
796 namespace js {
798 static const size_t VALUES_PER_STACK_FRAME = sizeof(JSStackFrame) / sizeof(Value);
800 extern JSObject *
801 GetBlockChain(JSContext *cx, JSStackFrame *fp);
803 extern JSObject *
804 GetBlockChainFast(JSContext *cx, JSStackFrame *fp, JSOp op, size_t oplen);
806 extern JSObject *
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.
816 extern JSObject *
817 GetScopeChain(JSContext *cx, JSStackFrame *fp);
819 extern JSObject *
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.
826 void
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);
840 inline void
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.
849 extern bool
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.
856 struct CallArgs
858 Value *argv_;
859 uintN argc_;
860 protected:
861 CallArgs() {}
862 CallArgs(Value *argv, uintN argc) : argv_(argv), argc_(argc) {}
863 public:
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))
892 * ...
894 * while (...) {
895 * // write actual args (not callee, this)
896 * session[0] = ...
897 * ...
898 * session[argc - 1] = ...
900 * if (!session.invoke(cx, session))
901 * ...
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:
914 * js_Invoke
915 * js_InternalInvoke
916 * js_ValueToFunction
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.
935 extern bool
936 ExternalInvoke(JSContext *cx, const Value &thisv, const Value &fval,
937 uintN argc, Value *argv, Value *rval);
939 extern bool
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);
958 extern bool
959 ExternalInvokeConstructor(JSContext *cx, const Value &fval, uintN argc, Value *argv,
960 Value *rval);
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
984 * frame.
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);
1000 extern bool
1001 CheckRedeclaration(JSContext *cx, JSObject *obj, jsid id, uintN attrs);
1003 extern bool
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. */
1007 extern bool
1008 SameValue(JSContext *cx, const Value &v1, const Value &v2, JSBool *same);
1010 extern JSType
1011 TypeOfValue(JSContext *cx, const Value &v);
1013 inline bool
1014 InstanceOf(JSContext *cx, JSObject *obj, Class *clasp, Value *argv)
1016 if (obj && obj->getClass() == clasp)
1017 return true;
1018 extern bool InstanceOfSlow(JSContext *, JSObject *, Class *, Value *);
1019 return InstanceOfSlow(cx, obj, clasp, argv);
1022 extern JSBool
1023 HasInstance(JSContext *cx, JSObject *obj, const js::Value *v, JSBool *bp);
1025 inline void *
1026 GetInstancePrivate(JSContext *cx, JSObject *obj, Class *clasp, Value *argv)
1028 if (!InstanceOf(cx, obj, clasp, argv))
1029 return NULL;
1030 return obj->getPrivate();
1033 extern bool
1034 ValueToId(JSContext *cx, const Value &v, jsid *idp);
1037 * @param closureLevel The static level of the closure that the cookie
1038 * pertains to.
1039 * @param cookie Level amount is a "skip" (delta) value from the
1040 * closure level.
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
1060 # ifdef _MSC_VER
1061 # define JS_LONE_INTERPRET 0
1062 # else
1063 # define JS_LONE_INTERPRET 1
1064 # endif
1065 #endif
1067 #define JS_MAX_INLINE_CALL_COUNT 3000
1069 #if !JS_LONE_INTERPRET
1070 # define JS_STATIC_INTERPRET static
1071 #else
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.
1086 extern JSBool
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
1091 * previous opcode.
1093 extern JS_REQUIRES_STACK void
1094 js_LogOpcode(JSContext *cx);
1097 * JS_OPMETER helper functions.
1099 extern void
1100 js_MeterOpcodePair(JSOp op1, JSOp op2);
1102 extern void
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);
1113 extern JSBool
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___ */