Imported Upstream version 1.0.0
[platform/upstream/js.git] / js / src / jsinterp.h
1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2  * vim: set ts=4 sw=4 et tw=78:
3  *
4  * ***** BEGIN LICENSE BLOCK *****
5  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
6  *
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/
11  *
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.
16  *
17  * The Original Code is Mozilla Communicator client code, released
18  * March 31, 1998.
19  *
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.
24  *
25  * Contributor(s):
26  *
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.
38  *
39  * ***** END LICENSE BLOCK ***** */
40
41 #ifndef jsinterp_h___
42 #define jsinterp_h___
43 /*
44  * JS interpreter interface.
45  */
46 #include "jsprvtd.h"
47 #include "jspubtd.h"
48 #include "jsfun.h"
49 #include "jsopcode.h"
50 #include "jsscript.h"
51 #include "jsvalue.h"
52
53 struct JSFrameRegs
54 {
55     STATIC_SKIP_INFERENCE
56     js::Value       *sp;                  /* stack pointer */
57     jsbytecode      *pc;                  /* program counter */
58     JSStackFrame    *fp;                  /* active frame */
59 };
60
61 /* Flags to toggle js::Interpret() execution. */
62 enum JSInterpMode
63 {
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 */
68 };
69
70 /* Flags used in JSStackFrame::flags_ */
71 enum JSFrameFlags
72 {
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 */
77
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 */
84
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() */
89
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 */
94
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 */
104 };
105
106 namespace js { namespace mjit { struct JITScript; } }
107
108 /*
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).
111  */
112 struct JSStackFrame
113 {
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 */
128
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 */
135
136     friend class js::StackSpace;
137     friend class js::FrameRegsIter;
138     friend struct JSContext;
139
140     inline void initPrev(JSContext *cx);
141
142   public:
143     /*
144      * Stack frame sort (see JSStackFrame comment above)
145      *
146      * A stack frame may have one of three types, which determines which
147      * members of the frame may be accessed and other invariants:
148      *
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)
152      *
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.
157      */
158
159     bool isFunctionFrame() const {
160         return !!(flags_ & JSFRAME_FUNCTION);
161     }
162
163     bool isGlobalFrame() const {
164         return !!(flags_ & JSFRAME_GLOBAL);
165     }
166
167     bool isDummyFrame() const {
168         return !!(flags_ & JSFRAME_DUMMY);
169     }
170
171     bool isScriptFrame() const {
172         return !!(flags_ & (JSFRAME_FUNCTION | JSFRAME_GLOBAL));
173     }
174
175     bool isEvalFrame() const {
176         JS_ASSERT_IF(flags_ & JSFRAME_EVAL, isScriptFrame());
177         return flags_ & JSFRAME_EVAL;
178     }
179
180     bool isExecuteFrame() const {
181         return !!(flags_ & (JSFRAME_GLOBAL | JSFRAME_EVAL));
182     }
183
184     /*
185      * Frame initialization
186      *
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.
192      */
193
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);
197
198     /* Used for SessionInvoke. */
199     inline void resetInvokeCallFrame();
200
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();
205
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);
210
211     /* Used when activating generators. */
212     inline void stealFrameAndSlots(js::Value *vp, JSStackFrame *otherfp,
213                                    js::Value *othervp, js::Value *othersp);
214
215     /* Perhaps one fine day we will remove dummy frames. */
216     inline void initDummyFrame(JSContext *cx, JSObject &chain);
217
218     /*
219      * Previous frame
220      *
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.
229      */
230
231     JSStackFrame *prev() const {
232         return prev_;
233     }
234
235     inline void resetGeneratorPrev(JSContext *cx);
236
237     /*
238      * Frame slots
239      *
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.
243      */
244
245     js::Value *slots() const {
246         return (js::Value *)(this + 1);
247     }
248
249     js::Value *base() const {
250         return slots() + script()->nfixed;
251     }
252
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];
257     }
258
259     /*
260      * Script
261      *
262      * All function and global frames have an associated JSScript which holds
263      * the bytecode being executed for the frame.
264      */
265
266     /*
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().
269      */
270     jsbytecode *pc(JSContext *cx, JSStackFrame *next = NULL);
271
272     jsbytecode *prevpc() {
273         JS_ASSERT((prev_ != NULL) && (flags_ & JSFRAME_HAS_PREVPC));
274         return prevpc_;
275     }
276
277     JSScript *script() const {
278         JS_ASSERT(isScriptFrame());
279         return isFunctionFrame()
280                ? isEvalFrame() ? args.script : fun()->script()
281                : exec.script;
282     }
283
284     JSScript *functionScript() const {
285         JS_ASSERT(isFunctionFrame());
286         return isEvalFrame() ? args.script : fun()->script();
287     }
288
289     JSScript *globalScript() const {
290         JS_ASSERT(isGlobalFrame());
291         return exec.script;
292     }
293
294     JSScript *maybeScript() const {
295         return isScriptFrame() ? script() : NULL;
296     }
297
298     size_t numFixed() const {
299         return script()->nfixed;
300     }
301
302     size_t numSlots() const {
303         return script()->nslots;
304     }
305
306     size_t numGlobalVars() const {
307         JS_ASSERT(isGlobalFrame());
308         return exec.script->nfixed;
309     }
310
311     /*
312      * Function
313      *
314      * All function frames have an associated interpreted JSFunction.
315      */
316
317     JSFunction* fun() const {
318         JS_ASSERT(isFunctionFrame());
319         return exec.fun;
320     }
321
322     JSFunction* maybeFun() const {
323         return isFunctionFrame() ? fun() : NULL;
324     }
325
326     /*
327      * Arguments
328      *
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.
340      *
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.
343      */
344
345     /* True if this frame has arguments. Contrast with hasArgsObj. */
346     bool hasArgs() const {
347         return isFunctionFrame() && !isEvalFrame();
348     }
349
350     uintN numFormalArgs() const {
351         JS_ASSERT(hasArgs());
352         return fun()->nargs;
353     }
354
355     js::Value &formalArg(uintN i) const {
356         JS_ASSERT(i < numFormalArgs());
357         return formalArgs()[i];
358     }
359
360     js::Value *formalArgs() const {
361         JS_ASSERT(hasArgs());
362         return (js::Value *)this - numFormalArgs();
363     }
364
365     js::Value *formalArgsEnd() const {
366         JS_ASSERT(hasArgs());
367         return (js::Value *)this;
368     }
369
370     js::Value *maybeFormalArgs() const {
371         return (flags_ & (JSFRAME_FUNCTION | JSFRAME_EVAL)) == JSFRAME_FUNCTION
372                ? formalArgs()
373                : NULL;
374     }
375
376     inline uintN numActualArgs() const;
377     inline js::Value *actualArgs() const;
378     inline js::Value *actualArgsEnd() const;
379
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);
383
384     inline void clearMissingArgs();
385
386     bool hasArgsObj() const {
387         return !!(flags_ & JSFRAME_HAS_ARGS_OBJ);
388     }
389
390     JSObject &argsObj() const {
391         JS_ASSERT(hasArgsObj());
392         JS_ASSERT(!isEvalFrame());
393         return *args.obj;
394     }
395
396     JSObject *maybeArgsObj() const {
397         return hasArgsObj() ? &argsObj() : NULL;
398     }
399
400     inline void setArgsObj(JSObject &obj);
401     inline void clearArgsObj();
402
403     /*
404      * This value
405      *
406      * Every frame has a this value although, until 'this' is computed, the
407      * value may not be the semantically-correct 'this' value.
408      *
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.
415      */
416
417     js::Value &functionThis() const {
418         JS_ASSERT(isFunctionFrame());
419         if (isEvalFrame())
420             return ((js::Value *)this)[-1];
421         return formalArgs()[-1];
422     }
423
424     JSObject &constructorThis() const {
425         JS_ASSERT(hasArgs());
426         return formalArgs()[-1].toObject();
427     }
428
429     js::Value &globalThis() const {
430         JS_ASSERT(isGlobalFrame());
431         return ((js::Value *)this)[-1];
432     }
433
434     js::Value &thisValue() const {
435         if (flags_ & (JSFRAME_EVAL | JSFRAME_GLOBAL))
436             return ((js::Value *)this)[-1];
437         return formalArgs()[-1];
438     }
439
440     inline bool computeThis(JSContext *cx);
441
442     /*
443      * Callee
444      *
445      * Only function frames have a callee. An eval frame in a function has the
446      * same caller as its containing function frame.
447      */
448
449     js::Value &calleeValue() const {
450         JS_ASSERT(isFunctionFrame());
451         if (isEvalFrame())
452             return ((js::Value *)this)[-2];
453         return formalArgs()[-2];
454     }
455
456     JSObject &callee() const {
457         JS_ASSERT(isFunctionFrame());
458         return calleeValue().toObject();
459     }
460
461     JSObject *maybeCallee() const {
462         return isFunctionFrame() ? &callee() : NULL;
463     }
464
465     /*
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).
470      */
471     bool getValidCalleeObject(JSContext *cx, js::Value *vp);
472
473     /*
474      * Scope chain
475      *
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.
489      */
490
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;
496         }
497         return *scopeChain_;
498     }
499
500     bool hasCallObj() const {
501         return !!(flags_ & JSFRAME_HAS_CALL_OBJ);
502     }
503
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();
509
510     /*
511      * Imacropc
512      *
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.
516      */
517
518     bool hasImacropc() const {
519         return flags_ & JSFRAME_HAS_IMACRO_PC;
520     }
521
522     jsbytecode *imacropc() const {
523         JS_ASSERT(hasImacropc());
524         return imacropc_;
525     }
526
527     jsbytecode *maybeImacropc() const {
528         return hasImacropc() ? imacropc() : NULL;
529     }
530
531     void clearImacropc() {
532         flags_ &= ~JSFRAME_HAS_IMACRO_PC;
533     }
534
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;
540     }
541
542     /* Annotation (will be removed after bug 546848) */
543
544     void* annotation() const {
545         return (flags_ & JSFRAME_HAS_ANNOTATION) ? annotation_ : NULL;
546     }
547
548     void setAnnotation(void *annot) {
549         flags_ |= JSFRAME_HAS_ANNOTATION;
550         annotation_ = annot;
551     }
552
553     /* Debugger hook data */
554
555     bool hasHookData() const {
556         return !!(flags_ & JSFRAME_HAS_HOOK_DATA);
557     }
558
559     void* hookData() const {
560         JS_ASSERT(hasHookData());
561         return hookData_;
562     }
563
564     void* maybeHookData() const {
565         return hasHookData() ? hookData_ : NULL;
566     }
567
568     void setHookData(void *v) {
569         hookData_ = v;
570         flags_ |= JSFRAME_HAS_HOOK_DATA;
571     }
572
573     /* Return value */
574
575     const js::Value &returnValue() {
576         if (!(flags_ & JSFRAME_HAS_RVAL))
577             rval_.setUndefined();
578         return rval_;
579     }
580
581     void markReturnValue() {
582         flags_ |= JSFRAME_HAS_RVAL;
583     }
584
585     void setReturnValue(const js::Value &v) {
586         rval_ = v;
587         markReturnValue();
588     }
589
590     void clearReturnValue() {
591         rval_.setUndefined();
592         markReturnValue();
593     }
594
595     /* Native-code return address */
596
597     void *nativeReturnAddress() const {
598         return ncode_;
599     }
600
601     void setNativeReturnAddress(void *addr) {
602         ncode_ = addr;
603     }
604
605     void **addressOfNativeReturnAddress() {
606         return &ncode_;
607     }
608
609     /*
610      * Generator-specific members
611      *
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.
615      */
616
617     bool isGeneratorFrame() const {
618         return !!(flags_ & JSFRAME_GENERATOR);
619     }
620
621     bool isFloatingGenerator() const {
622         JS_ASSERT_IF(flags_ & JSFRAME_FLOATING_GENERATOR, isGeneratorFrame());
623         return !!(flags_ & JSFRAME_FLOATING_GENERATOR);
624     }
625
626     void initFloatingGenerator() {
627         JS_ASSERT(!(flags_ & JSFRAME_GENERATOR));
628         flags_ |= (JSFRAME_GENERATOR | JSFRAME_FLOATING_GENERATOR);
629     }
630
631     void unsetFloatingGenerator() {
632         flags_ &= ~JSFRAME_FLOATING_GENERATOR;
633     }
634
635     void setFloatingGenerator() {
636         flags_ |= JSFRAME_FLOATING_GENERATOR;
637     }
638
639     /*
640      * Other flags
641      */
642
643     bool isConstructing() const {
644         return !!(flags_ & JSFRAME_CONSTRUCTING);
645     }
646
647     uint32 isConstructingFlag() const {
648         JS_ASSERT(isFunctionFrame());
649         JS_ASSERT((flags_ & ~(JSFRAME_CONSTRUCTING | JSFRAME_FUNCTION)) == 0);
650         return flags_;
651     }
652
653     bool isDebuggerFrame() const {
654         return !!(flags_ & JSFRAME_DEBUGGER);
655     }
656
657     bool isEvalOrDebuggerFrame() const {
658         return !!(flags_ & (JSFRAME_EVAL | JSFRAME_DEBUGGER));
659     }
660
661     bool hasOverriddenArgs() const {
662         return !!(flags_ & JSFRAME_OVERRIDE_ARGS);
663     }
664
665     bool hasOverflowArgs() const {
666         return !!(flags_ & JSFRAME_OVERFLOW_ARGS);
667     }
668
669     void setOverriddenArgs() {
670         flags_ |= JSFRAME_OVERRIDE_ARGS;
671     }
672
673     bool isAssigning() const {
674         return !!(flags_ & JSFRAME_ASSIGNING);
675     }
676
677     void setAssigning() {
678         flags_ |= JSFRAME_ASSIGNING;
679     }
680
681     void clearAssigning() {
682         flags_ &= ~JSFRAME_ASSIGNING;
683     }
684
685     bool isYielding() {
686         return !!(flags_ & JSFRAME_YIELDING);
687     }
688
689     void setYielding() {
690         flags_ |= JSFRAME_YIELDING;
691     }
692
693     void clearYielding() {
694         flags_ &= ~JSFRAME_YIELDING;
695     }
696
697     void setFinishedInInterpreter() {
698         flags_ |= JSFRAME_FINISHED_IN_INTERPRETER;
699     }
700
701     bool finishedInInterpreter() const {
702         return !!(flags_ & JSFRAME_FINISHED_IN_INTERPRETER);
703     }
704
705     /*
706      * Variables object accessors
707      *
708      * A stack frame's 'varobj' refers to the 'variables object' (ES3 term)
709      * associated with the Execution Context's VariableEnvironment (ES5 10.3).
710      *
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.
715      */
716
717     inline JSObject &varobj(js::StackSegment *seg) const;
718     inline JSObject &varobj(JSContext *cx) const;
719
720     /* Access to privates from the jits. */
721
722     static size_t offsetOfFlags() {
723         return offsetof(JSStackFrame, flags_);
724     }
725
726     static size_t offsetOfExec() {
727         return offsetof(JSStackFrame, exec);
728     }
729
730     void *addressOfArgs() {
731         return &args;
732     }
733
734     static size_t offsetOfScopeChain() {
735         return offsetof(JSStackFrame, scopeChain_);
736     }
737
738     JSObject **addressOfScopeChain() {
739         JS_ASSERT(flags_ & JSFRAME_HAS_SCOPECHAIN);
740         return &scopeChain_;
741     }
742
743     static size_t offsetOfPrev() {
744         return offsetof(JSStackFrame, prev_);
745     }
746
747     static size_t offsetOfReturnValue() {
748         return offsetof(JSStackFrame, rval_);
749     }
750
751     static ptrdiff_t offsetOfncode() {
752         return offsetof(JSStackFrame, ncode_);
753     }
754
755     static ptrdiff_t offsetOfCallee(JSFunction *fun) {
756         JS_ASSERT(fun != NULL);
757         return -(fun->nargs + 2) * sizeof(js::Value);
758     }
759
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));
764     }
765
766     static ptrdiff_t offsetOfFormalArg(JSFunction *fun, uintN i) {
767         JS_ASSERT(i < fun->nargs);
768         return (-(int)fun->nargs + i) * sizeof(js::Value);
769     }
770
771     static size_t offsetOfFixed(uintN i) {
772         return sizeof(JSStackFrame) + i * sizeof(js::Value);
773     }
774
775     /* Workaround for static asserts on private members. */
776
777     void staticAsserts() {
778         JS_STATIC_ASSERT(offsetof(JSStackFrame, rval_) % sizeof(js::Value) == 0);
779         JS_STATIC_ASSERT(sizeof(JSStackFrame) % sizeof(js::Value) == 0);
780     }
781
782 #ifdef JS_METHODJIT
783     js::mjit::JITScript *jit() {
784         return script()->getJIT(isConstructing());
785     }
786 #endif
787
788     void methodjitStaticAsserts();
789
790 #ifdef DEBUG
791     /* Poison scopeChain value set before a frame is flushed. */
792     static JSObject *const sInvalidScopeChain;
793 #endif
794 };
795
796 namespace js {
797
798 static const size_t VALUES_PER_STACK_FRAME = sizeof(JSStackFrame) / sizeof(Value);
799
800 extern JSObject *
801 GetBlockChain(JSContext *cx, JSStackFrame *fp);
802
803 extern JSObject *
804 GetBlockChainFast(JSContext *cx, JSStackFrame *fp, JSOp op, size_t oplen);
805
806 extern JSObject *
807 GetScopeChain(JSContext *cx);
808
809 /*
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.
815  */
816 extern JSObject *
817 GetScopeChain(JSContext *cx, JSStackFrame *fp);
818
819 extern JSObject *
820 GetScopeChainFast(JSContext *cx, JSStackFrame *fp, JSOp op, size_t oplen);
821
822 /*
823  * Report an error that the this value passed as |this| in the given arguments
824  * vector is not compatible with the specified class.
825  */
826 void
827 ReportIncompatibleMethod(JSContext *cx, Value *vp, Class *clasp);
828
829 /*
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.
836  */
837 template <typename T>
838 bool GetPrimitiveThis(JSContext *cx, Value *vp, T *v);
839
840 inline void
841 PutActivationObjects(JSContext *cx, JSStackFrame *fp);
842
843 inline void
844 PutOwnedActivationObjects(JSContext *cx, JSStackFrame *fp);
845
846 /*
847  * For a call's vp (which necessarily includes callee at vp[0] and the original
848  * specified |this| at vp[1]), convert null/undefined |this| into the global
849  * object for the callee and replace other primitives with boxed versions. The
850  * callee must not be strict mode code.
851  */
852 extern bool
853 BoxThisForVp(JSContext *cx, js::Value *vp);
854
855 /*
856  * Abstracts the layout of the stack passed to natives from the engine and from
857  * natives to js::Invoke.
858  */
859 struct CallArgs
860 {
861     Value *argv_;
862     uintN argc_;
863   protected:
864     CallArgs() {}
865     CallArgs(Value *argv, uintN argc) : argv_(argv), argc_(argc) {}
866   public:
867     Value *base() const { return argv_ - 2; }
868     Value &callee() const { return argv_[-2]; }
869     Value &thisv() const { return argv_[-1]; }
870     Value &operator[](unsigned i) const { JS_ASSERT(i < argc_); return argv_[i]; }
871     Value *argv() const { return argv_; }
872     uintN argc() const { return argc_; }
873     Value &rval() const { return argv_[-2]; }
874 };
875
876 /*
877  * The js::InvokeArgumentsGuard passed to js_Invoke must come from an
878  * immediately-enclosing successful call to js::StackSpace::pushInvokeArgs,
879  * i.e., there must have been no un-popped pushes to cx->stack(). Furthermore,
880  * |args.getvp()[0]| should be the callee, |args.getvp()[1]| should be |this|,
881  * and the range [args.getvp() + 2, args.getvp() + 2 + args.getArgc()) should
882  * be initialized actual arguments.
883  */
884 extern JS_REQUIRES_STACK bool
885 Invoke(JSContext *cx, const CallArgs &args, uint32 flags);
886
887 /*
888  * Natives like sort/forEach/replace call Invoke repeatedly with the same
889  * callee, this, and number of arguments. To optimize this, such natives can
890  * start an "invoke session" to factor out much of the dynamic setup logic
891  * required by a normal Invoke. Usage is:
892  *
893  *   InvokeSessionGuard session(cx);
894  *   if (!session.start(cx, callee, thisp, argc, &session))
895  *     ...
896  *
897  *   while (...) {
898  *     // write actual args (not callee, this)
899  *     session[0] = ...
900  *     ...
901  *     session[argc - 1] = ...
902  *
903  *     if (!session.invoke(cx, session))
904  *       ...
905  *
906  *     ... = session.rval();
907  *   }
908  *
909  *   // session ended by ~InvokeSessionGuard
910  */
911 class InvokeSessionGuard;
912
913 /*
914  * Consolidated js_Invoke flags simply rename certain JSFRAME_* flags, so that
915  * we can share bits stored in JSStackFrame.flags and passed to:
916  *
917  *   js_Invoke
918  *   js_InternalInvoke
919  *   js_ValueToFunction
920  *   js_ValueToFunctionObject
921  *   js_ValueToCallableObject
922  *   js_ReportIsNotFunction
923  *
924  * See jsfun.h for the latter four and flag renaming macros.
925  */
926 #define JSINVOKE_CONSTRUCT      JSFRAME_CONSTRUCTING
927
928 /*
929  * Mask to isolate construct and iterator flags for use with jsfun.h functions.
930  */
931 #define JSINVOKE_FUNFLAGS       JSINVOKE_CONSTRUCT
932
933 /*
934  * "External" calls may come from C or C++ code using a JSContext on which no
935  * JS is running (!cx->fp), so they may need to push a dummy JSStackFrame.
936  */
937
938 extern bool
939 ExternalInvoke(JSContext *cx, const Value &thisv, const Value &fval,
940                uintN argc, Value *argv, Value *rval);
941
942 extern bool
943 ExternalGetOrSet(JSContext *cx, JSObject *obj, jsid id, const Value &fval,
944                  JSAccessMode mode, uintN argc, Value *argv, Value *rval);
945
946 /*
947  * These two functions invoke a function called from a constructor context
948  * (e.g. 'new'). InvokeConstructor handles the general case where a new object
949  * needs to be created for/by the constructor. ConstructWithGivenThis directly
950  * calls the constructor with the given 'this', hence the caller must
951  * understand the semantics of the constructor call.
952  */
953
954 extern JS_REQUIRES_STACK bool
955 InvokeConstructor(JSContext *cx, const CallArgs &args);
956
957 extern JS_REQUIRES_STACK bool
958 InvokeConstructorWithGivenThis(JSContext *cx, JSObject *thisobj, const Value &fval,
959                                uintN argc, Value *argv, Value *rval);
960
961 extern bool
962 ExternalInvokeConstructor(JSContext *cx, const Value &fval, uintN argc, Value *argv,
963                           Value *rval);
964
965 /*
966  * Performs a direct eval for the given arguments, which must correspond to the
967  * currently-executing stack frame, which must be a script frame.  evalfun must
968  * be the built-in eval function and must correspond to the callee in vp[0].
969  * When this function succeeds it returns the result in *vp, adjusts the JS
970  * stack pointer, and returns true.
971  */
972 extern JS_REQUIRES_STACK bool
973 DirectEval(JSContext *cx, JSFunction *evalfun, uint32 argc, Value *vp);
974
975 /*
976  * Performs a direct eval for the given arguments, which must correspond to the
977  * currently-executing stack frame, which must be a script frame.  evalfun must
978  * be the built-in eval function and must correspond to the callee in vp[0].
979  * When this function succeeds it returns the result in *vp, adjusts the JS
980  * stack pointer, and returns true.
981  */
982 extern JS_REQUIRES_STACK bool
983 DirectEval(JSContext *cx, JSFunction *evalfun, uint32 argc, Value *vp);
984
985 /*
986  * Executes a script with the given scope chain in the context of the given
987  * frame.
988  */
989 extern JS_FORCES_STACK bool
990 Execute(JSContext *cx, JSObject *chain, JSScript *script,
991         JSStackFrame *prev, uintN flags, Value *result);
992
993 /*
994  * Execute the caller-initialized frame for a user-defined script or function
995  * pointed to by cx->fp until completion or error.
996  */
997 extern JS_REQUIRES_STACK JS_NEVER_INLINE bool
998 Interpret(JSContext *cx, JSStackFrame *stopFp, uintN inlineCallCount = 0, JSInterpMode mode = JSINTERP_NORMAL);
999
1000 extern JS_REQUIRES_STACK bool
1001 RunScript(JSContext *cx, JSScript *script, JSStackFrame *fp);
1002
1003 extern bool
1004 CheckRedeclaration(JSContext *cx, JSObject *obj, jsid id, uintN attrs);
1005
1006 extern bool
1007 StrictlyEqual(JSContext *cx, const Value &lval, const Value &rval, JSBool *equal);
1008
1009 /* === except that NaN is the same as NaN and -0 is not the same as +0. */
1010 extern bool
1011 SameValue(JSContext *cx, const Value &v1, const Value &v2, JSBool *same);
1012
1013 extern JSType
1014 TypeOfValue(JSContext *cx, const Value &v);
1015
1016 inline bool
1017 InstanceOf(JSContext *cx, JSObject *obj, Class *clasp, Value *argv)
1018 {
1019     if (obj && obj->getClass() == clasp)
1020         return true;
1021     extern bool InstanceOfSlow(JSContext *, JSObject *, Class *, Value *);
1022     return InstanceOfSlow(cx, obj, clasp, argv);
1023 }
1024
1025 extern JSBool
1026 HasInstance(JSContext *cx, JSObject *obj, const js::Value *v, JSBool *bp);
1027
1028 inline void *
1029 GetInstancePrivate(JSContext *cx, JSObject *obj, Class *clasp, Value *argv)
1030 {
1031     if (!InstanceOf(cx, obj, clasp, argv))
1032         return NULL;
1033     return obj->getPrivate();
1034 }
1035
1036 extern bool
1037 ValueToId(JSContext *cx, const Value &v, jsid *idp);
1038
1039 /*
1040  * @param closureLevel      The static level of the closure that the cookie
1041  *                          pertains to.
1042  * @param cookie            Level amount is a "skip" (delta) value from the
1043  *                          closure level.
1044  * @return  The value of the upvar.
1045  */
1046 extern const js::Value &
1047 GetUpvar(JSContext *cx, uintN level, js::UpvarCookie cookie);
1048
1049 } /* namespace js */
1050
1051 /*
1052  * JS_LONE_INTERPRET indicates that the compiler should see just the code for
1053  * the js_Interpret function when compiling jsinterp.cpp. The rest of the code
1054  * from the file should be visible only when compiling jsinvoke.cpp. It allows
1055  * platform builds to optimize selectively js_Interpret when the granularity
1056  * of the optimizations with the given compiler is a compilation unit.
1057  *
1058  * JS_STATIC_INTERPRET is the modifier for functions defined in jsinterp.cpp
1059  * that only js_Interpret calls. When JS_LONE_INTERPRET is true all such
1060  * functions are declared below.
1061  */
1062 #ifndef JS_LONE_INTERPRET
1063 # ifdef _MSC_VER
1064 #  define JS_LONE_INTERPRET 0
1065 # else
1066 #  define JS_LONE_INTERPRET 1
1067 # endif
1068 #endif
1069
1070 #define JS_MAX_INLINE_CALL_COUNT 3000
1071
1072 #if !JS_LONE_INTERPRET
1073 # define JS_STATIC_INTERPRET    static
1074 #else
1075 # define JS_STATIC_INTERPRET
1076
1077 extern JS_REQUIRES_STACK JSBool
1078 js_EnterWith(JSContext *cx, jsint stackIndex, JSOp op, size_t oplen);
1079
1080 extern JS_REQUIRES_STACK void
1081 js_LeaveWith(JSContext *cx);
1082
1083 /*
1084  * Find the results of incrementing or decrementing *vp. For pre-increments,
1085  * both *vp and *vp2 will contain the result on return. For post-increments,
1086  * vp will contain the original value converted to a number and vp2 will get
1087  * the result. Both vp and vp2 must be roots.
1088  */
1089 extern JSBool
1090 js_DoIncDec(JSContext *cx, const JSCodeSpec *cs, js::Value *vp, js::Value *vp2);
1091
1092 /*
1093  * Opcode tracing helper. When len is not 0, cx->fp->regs->pc[-len] gives the
1094  * previous opcode.
1095  */
1096 extern JS_REQUIRES_STACK void
1097 js_LogOpcode(JSContext *cx);
1098
1099 /*
1100  * JS_OPMETER helper functions.
1101  */
1102 extern void
1103 js_MeterOpcodePair(JSOp op1, JSOp op2);
1104
1105 extern void
1106 js_MeterSlotOpcode(JSOp op, uint32 slot);
1107
1108 #endif /* JS_LONE_INTERPRET */
1109 /*
1110  * Unwind block and scope chains to match the given depth. The function sets
1111  * fp->sp on return to stackDepth.
1112  */
1113 extern JS_REQUIRES_STACK JSBool
1114 js_UnwindScope(JSContext *cx, jsint stackDepth, JSBool normalUnwind);
1115
1116 extern JSBool
1117 js_OnUnknownMethod(JSContext *cx, js::Value *vp);
1118
1119 extern JS_REQUIRES_STACK js::Class *
1120 js_IsActiveWithOrBlock(JSContext *cx, JSObject *obj, int stackDepth);
1121
1122 #endif /* jsinterp_h___ */