LCOV - app.info - js/src/jsinterp.h

LCOV - code coverage report
| Current view: | directory - js/src - jsinterp.h (source / functions) |  | Found | Hit | Coverage |
| Test: | app.info | Lines: | 19 | 19 | 100.0 %
| Date: | 2012-04-07 | Functions: | 6 | 6 | 100.0 %

           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 "jsopcode.h"
          49                 :
          50                 : #include "vm/Stack.h"
          51                 :
          52                 : namespace js {
          53                 :
          54                 : /*
          55                 :  * Refresh and return fp->scopeChain.  It may be stale if block scopes are
          56                 :  * active but not yet reflected by objects in the scope chain.  If a block
          57                 :  * scope contains a with, eval, XML filtering predicate, or similar such
          58                 :  * dynamically scoped construct, then compile-time block scope at fp->blocks
          59                 :  * must reflect at runtime.
          60                 :  */
          61                 :
          62                 : extern JSObject *
          63                 : GetScopeChain(JSContext *cx);
          64                 :
          65                 : extern JSObject *
          66                 : GetScopeChain(JSContext *cx, StackFrame *fp);
          67                 :
          68                 : /*
          69                 :  * ScriptPrologue/ScriptEpilogue must be called in pairs. ScriptPrologue
          70                 :  * must be called before the script executes. ScriptEpilogue must be called
          71                 :  * after the script returns or exits via exception.
          72                 :  */
          73                 :
          74                 : inline bool
          75                 : ScriptPrologue(JSContext *cx, StackFrame *fp, JSScript *script);
          76                 :
          77                 : inline bool
          78                 : ScriptEpilogue(JSContext *cx, StackFrame *fp, bool ok);
          79                 :
          80                 : /*
          81                 :  * It is not valid to call ScriptPrologue when a generator is resumed or to
          82                 :  * call ScriptEpilogue when a generator yields. However, the debugger still
          83                 :  * needs LIFO notification of generator start/stop. This pair of functions does
          84                 :  * the right thing based on the state of 'fp'.
          85                 :  */
          86                 :
          87                 : inline bool
          88                 : ScriptPrologueOrGeneratorResume(JSContext *cx, StackFrame *fp);
          89                 :
          90                 : inline bool
          91                 : ScriptEpilogueOrGeneratorYield(JSContext *cx, StackFrame *fp, bool ok);
          92                 :
          93                 : /* Implemented in jsdbgapi: */
          94                 :
          95                 : /*
          96                 :  * Announce to the debugger that the thread has entered a new JavaScript frame,
          97                 :  * |fp|. Call whatever hooks have been registered to observe new frames, and
          98                 :  * return a JSTrapStatus code indication how execution should proceed:
          99                 :  *
         100                 :  * - JSTRAP_CONTINUE: Continue execution normally.
         101                 :  *
         102                 :  * - JSTRAP_THROW: Throw an exception. ScriptDebugPrologue has set |cx|'s
         103                 :  *   pending exception to the value to be thrown.
         104                 :  *
         105                 :  * - JSTRAP_ERROR: Terminate execution (as is done when a script is terminated
         106                 :  *   for running too long). ScriptDebugPrologue has cleared |cx|'s pending
         107                 :  *   exception.
         108                 :  *
         109                 :  * - JSTRAP_RETURN: Return from the new frame immediately. ScriptDebugPrologue
         110                 :  *   has set |cx->fp()|'s return value appropriately.
         111                 :  */
         112                 : extern JSTrapStatus
         113                 : ScriptDebugPrologue(JSContext *cx, StackFrame *fp);
         114                 :
         115                 : /*
         116                 :  * Announce to the debugger that the thread has exited a JavaScript frame, |fp|.
         117                 :  * If |ok| is true, the frame is returning normally; if |ok| is false, the frame
         118                 :  * is throwing an exception or terminating.
         119                 :  *
         120                 :  * Call whatever hooks have been registered to observe frame exits. Change cx's
         121                 :  * current exception and |fp|'s return value to reflect the changes in behavior
         122                 :  * the hooks request, if any. Return the new error/success value.
         123                 :  *
         124                 :  * This function may be called twice for the same outgoing frame; only the
         125                 :  * first call has any effect. (Permitting double calls simplifies some
         126                 :  * cases where an onPop handler's resumption value changes a return to a
         127                 :  * throw, or vice versa: we can redirect to a complete copy of the
         128                 :  * alternative path, containing its own call to ScriptDebugEpilogue.)
         129                 :  */
         130                 : extern bool
         131                 : ScriptDebugEpilogue(JSContext *cx, StackFrame *fp, bool ok);
         132                 :
         133                 : /*
         134                 :  * For a given |call|, convert null/undefined |this| into the global object for
         135                 :  * the callee and replace other primitives with boxed versions. This assumes
         136                 :  * that call.callee() is not strict mode code. This is the special/slow case of
         137                 :  * ComputeThis.
         138                 :  */
         139                 : extern bool
         140                 : BoxNonStrictThis(JSContext *cx, const CallReceiver &call);
         141                 :
         142                 : /*
         143                 :  * Ensure that fp->thisValue() is the correct value of |this| for the scripted
         144                 :  * call represented by |fp|. ComputeThis is necessary because fp->thisValue()
         145                 :  * may be set to 'undefined' when 'this' should really be the global object (as
         146                 :  * an optimization to avoid global-this computation).
         147                 :  */
         148                 : inline bool
         149                 : ComputeThis(JSContext *cx, StackFrame *fp);
         150                 :
         151                 : enum MaybeConstruct {
         152                 :     NO_CONSTRUCT = INITIAL_NONE,
         153                 :     CONSTRUCT = INITIAL_CONSTRUCT
         154                 : };
         155                 :
         156                 : /*
         157                 :  * InvokeKernel assumes that the given args have been pushed on the top of the
         158                 :  * VM stack. Additionally, if 'args' is contained in a CallArgsList, that they
         159                 :  * have already been marked 'active'.
         160                 :  */
         161                 : extern bool
         162                 : InvokeKernel(JSContext *cx, CallArgs args, MaybeConstruct construct = NO_CONSTRUCT);
         163                 :
         164                 : /*
         165                 :  * Invoke assumes that 'args' has been pushed (via ContextStack::pushInvokeArgs)
         166                 :  * and is currently at the top of the VM stack.
         167                 :  */
         168                 : inline bool
         169         2400265 : Invoke(JSContext *cx, InvokeArgsGuard &args, MaybeConstruct construct = NO_CONSTRUCT)
         170                 : {
         171         2400265 :     args.setActive();
         172         2400265 :     bool ok = InvokeKernel(cx, args, construct);
         173         2400265 :     args.setInactive();
         174         2400265 :     return ok;
         175                 : }
         176                 :
         177                 : /*
         178                 :  * This Invoke overload places the least requirements on the caller: it may be
         179                 :  * called at any time and it takes care of copying the given callee, this, and
         180                 :  * arguments onto the stack.
         181                 :  */
         182                 : extern bool
         183                 : Invoke(JSContext *cx, const Value &thisv, const Value &fval, unsigned argc, Value *argv,
         184                 :        Value *rval);
         185                 :
         186                 : /*
         187                 :  * This helper takes care of the infinite-recursion check necessary for
         188                 :  * getter/setter calls.
         189                 :  */
         190                 : extern bool
         191                 : InvokeGetterOrSetter(JSContext *cx, JSObject *obj, const Value &fval, unsigned argc, Value *argv,
         192                 :                      Value *rval);
         193                 :
         194                 : /*
         195                 :  * InvokeConstructor* implement a function call from a constructor context
         196                 :  * (e.g. 'new') handling the the creation of the new 'this' object.
         197                 :  */
         198                 : extern bool
         199                 : InvokeConstructorKernel(JSContext *cx, const CallArgs &args);
         200                 :
         201                 : /* See the InvokeArgsGuard overload of Invoke. */
         202                 : inline bool
         203           12902 : InvokeConstructor(JSContext *cx, InvokeArgsGuard &args)
         204                 : {
         205           12902 :     args.setActive();
         206           12902 :     bool ok = InvokeConstructorKernel(cx, ImplicitCast<CallArgs>(args));
         207           12902 :     args.setInactive();
         208           12902 :     return ok;
         209                 : }
         210                 :
         211                 : /* See the fval overload of Invoke. */
         212                 : extern bool
         213                 : InvokeConstructor(JSContext *cx, const Value &fval, unsigned argc, Value *argv, Value *rval);
         214                 :
         215                 : /*
         216                 :  * Executes a script with the given scopeChain/this. The 'type' indicates
         217                 :  * whether this is eval code or global code. To support debugging, the
         218                 :  * evalFrame parameter can point to an arbitrary frame in the context's call
         219                 :  * stack to simulate executing an eval in that frame.
         220                 :  */
         221                 : extern bool
         222                 : ExecuteKernel(JSContext *cx, JSScript *script, JSObject &scopeChain, const Value &thisv,
         223                 :               ExecuteType type, StackFrame *evalInFrame, Value *result);
         224                 :
         225                 : /* Execute a script with the given scopeChain as global code. */
         226                 : extern bool
         227                 : Execute(JSContext *cx, JSScript *script, JSObject &scopeChain, Value *rval);
         228                 :
         229                 : /* Flags to toggle js::Interpret() execution. */
         230                 : enum InterpMode
         231                 : {
         232                 :     JSINTERP_NORMAL    = 0, /* interpreter is running normally */
         233                 :     JSINTERP_REJOIN    = 1, /* as normal, but the frame has already started */
         234                 :     JSINTERP_SKIP_TRAP = 2  /* as REJOIN, but skip trap at first opcode */
         235                 : };
         236                 :
         237                 : /*
         238                 :  * Execute the caller-initialized frame for a user-defined script or function
         239                 :  * pointed to by cx->fp until completion or error.
         240                 :  */
         241                 : extern JS_NEVER_INLINE bool
         242                 : Interpret(JSContext *cx, StackFrame *stopFp, InterpMode mode = JSINTERP_NORMAL);
         243                 :
         244                 : extern bool
         245                 : RunScript(JSContext *cx, JSScript *script, StackFrame *fp);
         246                 :
         247                 : extern bool
         248                 : StrictlyEqual(JSContext *cx, const Value &lval, const Value &rval, bool *equal);
         249                 :
         250                 : extern bool
         251                 : LooselyEqual(JSContext *cx, const Value &lval, const Value &rval, bool *equal);
         252                 :
         253                 : /* === except that NaN is the same as NaN and -0 is not the same as +0. */
         254                 : extern bool
         255                 : SameValue(JSContext *cx, const Value &v1, const Value &v2, bool *same);
         256                 :
         257                 : extern JSType
         258                 : TypeOfValue(JSContext *cx, const Value &v);
         259                 :
         260                 : extern JSBool
         261                 : HasInstance(JSContext *cx, JSObject *obj, const js::Value *v, JSBool *bp);
         262                 :
         263                 : extern bool
         264                 : ValueToId(JSContext *cx, const Value &v, jsid *idp);
         265                 :
         266                 : /*
         267                 :  * A linked list of the |FrameRegs regs;| variables belonging to all
         268                 :  * js::Interpret C++ frames on this thread's stack.
         269                 :  *
         270                 :  * Note that this is *not* a list of all JS frames running under the
         271                 :  * interpreter; that would include inlined frames, whose FrameRegs are
         272                 :  * saved in various pieces in various places. Rather, this lists each
         273                 :  * js::Interpret call's live 'regs'; when control returns to that call, it
         274                 :  * will resume execution with this 'regs' instance.
         275                 :  *
         276                 :  * When Debugger puts a script in single-step mode, all js::Interpret
         277                 :  * invocations that might be presently running that script must have
         278                 :  * interrupts enabled. It's not practical to simply check
         279                 :  * script->stepModeEnabled() at each point some callee could have changed
         280                 :  * it, because there are so many places js::Interpret could possibly cause
         281                 :  * JavaScript to run: each place an object might be coerced to a primitive
         282                 :  * or a number, for example. So instead, we simply expose a list of the
         283                 :  * 'regs' those frames are using, and let Debugger tweak the affected
         284                 :  * js::Interpret frames when an onStep handler is established.
         285                 :  *
         286                 :  * Elements of this list are allocated within the js::Interpret stack
         287                 :  * frames themselves; the list is headed by this thread's js::ThreadData.
         288                 :  */
         289                 : class InterpreterFrames {
         290                 :   public:
         291          517775 :     class InterruptEnablerBase {
         292                 :       public:
         293                 :         virtual void enableInterrupts() const = 0;
         294                 :     };
         295                 :
         296                 :     InterpreterFrames(JSContext *cx, FrameRegs *regs, const InterruptEnablerBase &enabler);
         297                 :     ~InterpreterFrames();
         298                 :
         299                 :     /* If this js::Interpret frame is running |script|, enable interrupts. */
         300                 :     inline void enableInterruptsIfRunning(JSScript *script);
         301                 :
         302                 :     InterpreterFrames *older;
         303                 :
         304                 :   private:
         305                 :     JSContext *context;
         306                 :     FrameRegs *regs;
         307                 :     const InterruptEnablerBase &enabler;
         308                 : };
         309                 :
         310                 : /*
         311                 :  * Unwind block and scope chains to match the given depth. The function sets
         312                 :  * fp->sp on return to stackDepth.
         313                 :  */
         314                 : extern void
         315                 : UnwindScope(JSContext *cx, uint32_t stackDepth);
         316                 :
         317                 : /*
         318                 :  * Unwind for an uncatchable exception. This means not running finalizers, etc;
         319                 :  * just preserving the basic engine stack invariants.
         320                 :  */
         321                 : extern void
         322                 : UnwindForUncatchableException(JSContext *cx, const FrameRegs &regs);
         323                 :
         324                 : extern bool
         325                 : OnUnknownMethod(JSContext *cx, JSObject *obj, Value idval, Value *vp);
         326                 :
         327                 : extern bool
         328                 : IsActiveWithOrBlock(JSContext *cx, JSObject &obj, uint32_t stackDepth);
         329                 :
         330                 : class TryNoteIter
         331                 : {
         332                 :     const FrameRegs &regs;
         333                 :     JSScript *script;
         334                 :     uint32_t pcOffset;
         335                 :     JSTryNote *tn, *tnEnd;
         336                 :     void settle();
         337                 :   public:
         338                 :     TryNoteIter(const FrameRegs &regs);
         339                 :     bool done() const;
         340                 :     void operator++();
         341           15620 :     JSTryNote *operator*() const { return tn; }
         342                 : };
         343                 :
         344                 : /************************************************************************/
         345                 :
         346                 : /*
         347                 :  * To really poison a set of values, using 'magic' or 'undefined' isn't good
         348                 :  * enough since often these will just be ignored by buggy code (see bug 629974)
         349                 :  * in debug builds and crash in release builds. Instead, we use a safe-for-crash
         350                 :  * pointer.
         351                 :  */
         352                 : static JS_ALWAYS_INLINE void
         353         5211924 : Debug_SetValueRangeToCrashOnTouch(Value *beg, Value *end)
         354                 : {
         355                 : #ifdef DEBUG
         356        70731906 :     for (Value *v = beg; v != end; ++v)
         357        65519982 :         v->setObject(*reinterpret_cast<JSObject *>(0x42));
         358                 : #endif
         359         5211924 : }
         360                 :
         361                 : static JS_ALWAYS_INLINE void
         362         5211924 : Debug_SetValueRangeToCrashOnTouch(Value *vec, size_t len)
         363                 : {
         364                 : #ifdef DEBUG
         365         5211924 :     Debug_SetValueRangeToCrashOnTouch(vec, vec + len);
         366                 : #endif
         367         5211924 : }
         368                 :
         369                 : static JS_ALWAYS_INLINE void
         370                 : Debug_SetValueRangeToCrashOnTouch(HeapValue *vec, size_t len)
         371                 : {
         372                 : #ifdef DEBUG
         373                 :     Debug_SetValueRangeToCrashOnTouch((Value *) vec, len);
         374                 : #endif
         375                 : }
         376                 :
         377                 : }  /* namespace js */
         378                 :
         379                 : #endif /* jsinterp_h___ */

Generated by: LCOV version 1.7