js/src/vm/Interpreter.h

Sat, 03 Jan 2015 20:18:00 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Sat, 03 Jan 2015 20:18:00 +0100
branch
TOR_BUG_3246
changeset 7
129ffea94266
permissions
-rw-r--r--

Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.

     1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
     2  * vim: set ts=8 sts=4 et sw=4 tw=99:
     3  * This Source Code Form is subject to the terms of the Mozilla Public
     4  * License, v. 2.0. If a copy of the MPL was not distributed with this
     5  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     7 #ifndef vm_Interpreter_h
     8 #define vm_Interpreter_h
    10 /*
    11  * JS interpreter interface.
    12  */
    14 #include "jsiter.h"
    15 #include "jspubtd.h"
    17 #include "vm/Stack.h"
    19 namespace js {
    21 class ScopeIter;
    23 /*
    24  * Announce to the debugger that the thread has entered a new JavaScript frame,
    25  * |frame|. Call whatever hooks have been registered to observe new frames, and
    26  * return a JSTrapStatus code indication how execution should proceed:
    27  *
    28  * - JSTRAP_CONTINUE: Continue execution normally.
    29  *
    30  * - JSTRAP_THROW: Throw an exception. ScriptDebugPrologue has set |cx|'s
    31  *   pending exception to the value to be thrown.
    32  *
    33  * - JSTRAP_ERROR: Terminate execution (as is done when a script is terminated
    34  *   for running too long). ScriptDebugPrologue has cleared |cx|'s pending
    35  *   exception.
    36  *
    37  * - JSTRAP_RETURN: Return from the new frame immediately. ScriptDebugPrologue
    38  *   has set |frame|'s return value appropriately.
    39  */
    40 extern JSTrapStatus
    41 ScriptDebugPrologue(JSContext *cx, AbstractFramePtr frame, jsbytecode *pc);
    43 /*
    44  * Announce to the debugger that the thread has exited a JavaScript frame, |frame|.
    45  * If |ok| is true, the frame is returning normally; if |ok| is false, the frame
    46  * is throwing an exception or terminating.
    47  *
    48  * Call whatever hooks have been registered to observe frame exits. Change cx's
    49  * current exception and |frame|'s return value to reflect the changes in behavior
    50  * the hooks request, if any. Return the new error/success value.
    51  *
    52  * This function may be called twice for the same outgoing frame; only the
    53  * first call has any effect. (Permitting double calls simplifies some
    54  * cases where an onPop handler's resumption value changes a return to a
    55  * throw, or vice versa: we can redirect to a complete copy of the
    56  * alternative path, containing its own call to ScriptDebugEpilogue.)
    57  */
    58 extern bool
    59 ScriptDebugEpilogue(JSContext *cx, AbstractFramePtr frame, jsbytecode *pc, bool ok);
    61 /*
    62  * Announce to the debugger that an exception has been thrown and propagated
    63  * to |frame|. Call whatever hooks have been registered to observe this and
    64  * return a JSTrapStatus code indication how execution should proceed:
    65  *
    66  * - JSTRAP_CONTINUE: Continue throwing the current exception.
    67  *
    68  * - JSTRAP_THROW: Throw another value. DebugExceptionUnwind has set |cx|'s
    69  *   pending exception to the new value.
    70  *
    71  * - JSTRAP_ERROR: Terminate execution. DebugExceptionUnwind has cleared |cx|'s
    72  *   pending exception.
    73  *
    74  * - JSTRAP_RETURN: Return from |frame|. DebugExceptionUnwind has cleared
    75  *   |cx|'s pending exception and set |frame|'s return value.
    76  */
    77 extern JSTrapStatus
    78 DebugExceptionUnwind(JSContext *cx, AbstractFramePtr frame, jsbytecode *pc);
    80 /*
    81  * For a given |call|, convert null/undefined |this| into the global object for
    82  * the callee and replace other primitives with boxed versions. This assumes
    83  * that call.callee() is not strict mode code. This is the special/slow case of
    84  * ComputeThis.
    85  */
    86 extern bool
    87 BoxNonStrictThis(JSContext *cx, const CallReceiver &call);
    89 extern JSObject *
    90 BoxNonStrictThis(JSContext *cx, HandleValue thisv);
    92 /*
    93  * Ensure that fp->thisValue() is the correct value of |this| for the scripted
    94  * call represented by |fp|. ComputeThis is necessary because fp->thisValue()
    95  * may be set to 'undefined' when 'this' should really be the global object (as
    96  * an optimization to avoid global-this computation).
    97  */
    98 inline bool
    99 ComputeThis(JSContext *cx, AbstractFramePtr frame);
   101 enum MaybeConstruct {
   102     NO_CONSTRUCT = INITIAL_NONE,
   103     CONSTRUCT = INITIAL_CONSTRUCT
   104 };
   106 /*
   107  * numToSkip is the number of stack values the expression decompiler should skip
   108  * before it reaches |v|. If it's -1, the decompiler will search the stack.
   109  */
   110 extern bool
   111 ReportIsNotFunction(JSContext *cx, HandleValue v, int numToSkip = -1,
   112                     MaybeConstruct construct = NO_CONSTRUCT);
   114 /* See ReportIsNotFunction comment for the meaning of numToSkip. */
   115 extern JSObject *
   116 ValueToCallable(JSContext *cx, HandleValue v, int numToSkip = -1,
   117                 MaybeConstruct construct = NO_CONSTRUCT);
   119 /*
   120  * Invoke assumes that the given args have been pushed on the top of the
   121  * VM stack.
   122  */
   123 extern bool
   124 Invoke(JSContext *cx, CallArgs args, MaybeConstruct construct = NO_CONSTRUCT);
   126 /*
   127  * This Invoke overload places the least requirements on the caller: it may be
   128  * called at any time and it takes care of copying the given callee, this, and
   129  * arguments onto the stack.
   130  */
   131 extern bool
   132 Invoke(JSContext *cx, const Value &thisv, const Value &fval, unsigned argc, const Value *argv,
   133        MutableHandleValue rval);
   135 /*
   136  * This helper takes care of the infinite-recursion check necessary for
   137  * getter/setter calls.
   138  */
   139 extern bool
   140 InvokeGetterOrSetter(JSContext *cx, JSObject *obj, Value fval, unsigned argc, Value *argv,
   141                      MutableHandleValue rval);
   143 /*
   144  * InvokeConstructor implement a function call from a constructor context
   145  * (e.g. 'new') handling the the creation of the new 'this' object.
   146  */
   147 extern bool
   148 InvokeConstructor(JSContext *cx, CallArgs args);
   150 /* See the fval overload of Invoke. */
   151 extern bool
   152 InvokeConstructor(JSContext *cx, Value fval, unsigned argc, Value *argv, Value *rval);
   154 /*
   155  * Executes a script with the given scopeChain/this. The 'type' indicates
   156  * whether this is eval code or global code. To support debugging, the
   157  * evalFrame parameter can point to an arbitrary frame in the context's call
   158  * stack to simulate executing an eval in that frame.
   159  */
   160 extern bool
   161 ExecuteKernel(JSContext *cx, HandleScript script, JSObject &scopeChain, const Value &thisv,
   162               ExecuteType type, AbstractFramePtr evalInFrame, Value *result);
   164 /* Execute a script with the given scopeChain as global code. */
   165 extern bool
   166 Execute(JSContext *cx, HandleScript script, JSObject &scopeChain, Value *rval);
   168 class ExecuteState;
   169 class InvokeState;
   170 class GeneratorState;
   172 // RunState is passed to RunScript and RunScript then eiter passes it to the
   173 // interpreter or to the JITs. RunState contains all information we need to
   174 // construct an interpreter or JIT frame.
   175 class RunState
   176 {
   177   protected:
   178     enum Kind { Execute, Invoke, Generator };
   179     Kind kind_;
   181     RootedScript script_;
   183     explicit RunState(JSContext *cx, Kind kind, JSScript *script)
   184       : kind_(kind),
   185         script_(cx, script)
   186     { }
   188   public:
   189     bool isExecute() const { return kind_ == Execute; }
   190     bool isInvoke() const { return kind_ == Invoke; }
   191     bool isGenerator() const { return kind_ == Generator; }
   193     ExecuteState *asExecute() const {
   194         JS_ASSERT(isExecute());
   195         return (ExecuteState *)this;
   196     }
   197     InvokeState *asInvoke() const {
   198         JS_ASSERT(isInvoke());
   199         return (InvokeState *)this;
   200     }
   201     GeneratorState *asGenerator() const {
   202         JS_ASSERT(isGenerator());
   203         return (GeneratorState *)this;
   204     }
   206     JSScript *script() const { return script_; }
   208     virtual InterpreterFrame *pushInterpreterFrame(JSContext *cx) = 0;
   209     virtual void setReturnValue(Value v) = 0;
   211   private:
   212     RunState(const RunState &other) MOZ_DELETE;
   213     RunState(const ExecuteState &other) MOZ_DELETE;
   214     RunState(const InvokeState &other) MOZ_DELETE;
   215     RunState(const GeneratorState &other) MOZ_DELETE;
   216     void operator=(const RunState &other) MOZ_DELETE;
   217 };
   219 // Eval or global script.
   220 class ExecuteState : public RunState
   221 {
   222     ExecuteType type_;
   224     RootedValue thisv_;
   225     RootedObject scopeChain_;
   227     AbstractFramePtr evalInFrame_;
   228     Value *result_;
   230   public:
   231     ExecuteState(JSContext *cx, JSScript *script, const Value &thisv, JSObject &scopeChain,
   232                  ExecuteType type, AbstractFramePtr evalInFrame, Value *result)
   233       : RunState(cx, Execute, script),
   234         type_(type),
   235         thisv_(cx, thisv),
   236         scopeChain_(cx, &scopeChain),
   237         evalInFrame_(evalInFrame),
   238         result_(result)
   239     { }
   241     Value *addressOfThisv() { return thisv_.address(); }
   242     JSObject *scopeChain() const { return scopeChain_; }
   243     ExecuteType type() const { return type_; }
   245     virtual InterpreterFrame *pushInterpreterFrame(JSContext *cx);
   247     virtual void setReturnValue(Value v) {
   248         if (result_)
   249             *result_ = v;
   250     }
   251 };
   253 // Data to invoke a function.
   254 class InvokeState : public RunState
   255 {
   256     CallArgs &args_;
   257     InitialFrameFlags initial_;
   258     bool useNewType_;
   260   public:
   261     InvokeState(JSContext *cx, CallArgs &args, InitialFrameFlags initial)
   262       : RunState(cx, Invoke, args.callee().as<JSFunction>().nonLazyScript()),
   263         args_(args),
   264         initial_(initial),
   265         useNewType_(false)
   266     { }
   268     bool useNewType() const { return useNewType_; }
   269     void setUseNewType() { useNewType_ = true; }
   271     bool constructing() const { return InitialFrameFlagsAreConstructing(initial_); }
   272     CallArgs &args() const { return args_; }
   274     virtual InterpreterFrame *pushInterpreterFrame(JSContext *cx);
   276     virtual void setReturnValue(Value v) {
   277         args_.rval().set(v);
   278     }
   279 };
   281 // Generator script.
   282 class GeneratorState : public RunState
   283 {
   284     JSContext *cx_;
   285     JSGenerator *gen_;
   286     JSGeneratorState futureState_;
   287     bool entered_;
   289   public:
   290     GeneratorState(JSContext *cx, JSGenerator *gen, JSGeneratorState futureState);
   291     ~GeneratorState();
   293     virtual InterpreterFrame *pushInterpreterFrame(JSContext *cx);
   294     virtual void setReturnValue(Value) { }
   296     JSGenerator *gen() const { return gen_; }
   297 };
   299 extern bool
   300 RunScript(JSContext *cx, RunState &state);
   302 extern bool
   303 StrictlyEqual(JSContext *cx, const Value &lval, const Value &rval, bool *equal);
   305 extern bool
   306 LooselyEqual(JSContext *cx, const Value &lval, const Value &rval, bool *equal);
   308 /* === except that NaN is the same as NaN and -0 is not the same as +0. */
   309 extern bool
   310 SameValue(JSContext *cx, const Value &v1, const Value &v2, bool *same);
   312 extern JSType
   313 TypeOfObject(JSObject *obj);
   315 extern JSType
   316 TypeOfValue(const Value &v);
   318 extern bool
   319 HasInstance(JSContext *cx, HandleObject obj, HandleValue v, bool *bp);
   321 // Unwind scope chain and iterator to match the static scope corresponding to
   322 // the given bytecode position.
   323 extern void
   324 UnwindScope(JSContext *cx, ScopeIter &si, jsbytecode *pc);
   326 /*
   327  * Unwind for an uncatchable exception. This means not running finalizers, etc;
   328  * just preserving the basic engine stack invariants.
   329  */
   330 extern void
   331 UnwindForUncatchableException(JSContext *cx, const InterpreterRegs &regs);
   333 extern bool
   334 OnUnknownMethod(JSContext *cx, HandleObject obj, Value idval, MutableHandleValue vp);
   336 class TryNoteIter
   337 {
   338     const InterpreterRegs &regs;
   339     RootedScript script; /* TryNotIter is always stack allocated. */
   340     uint32_t pcOffset;
   341     JSTryNote *tn, *tnEnd;
   343     void settle();
   345   public:
   346     explicit TryNoteIter(JSContext *cx, const InterpreterRegs &regs);
   347     bool done() const;
   348     void operator++();
   349     JSTryNote *operator*() const { return tn; }
   350 };
   352 /************************************************************************/
   354 bool
   355 Throw(JSContext *cx, HandleValue v);
   357 bool
   358 GetProperty(JSContext *cx, HandleValue value, HandlePropertyName name, MutableHandleValue vp);
   360 bool
   361 CallProperty(JSContext *cx, HandleValue value, HandlePropertyName name, MutableHandleValue vp);
   363 bool
   364 GetScopeName(JSContext *cx, HandleObject obj, HandlePropertyName name, MutableHandleValue vp);
   366 bool
   367 GetScopeNameForTypeOf(JSContext *cx, HandleObject obj, HandlePropertyName name,
   368                       MutableHandleValue vp);
   370 JSObject *
   371 Lambda(JSContext *cx, HandleFunction fun, HandleObject parent);
   373 JSObject *
   374 LambdaArrow(JSContext *cx, HandleFunction fun, HandleObject parent, HandleValue thisv);
   376 bool
   377 GetElement(JSContext *cx, MutableHandleValue lref, HandleValue rref, MutableHandleValue res);
   379 bool
   380 CallElement(JSContext *cx, MutableHandleValue lref, HandleValue rref, MutableHandleValue res);
   382 bool
   383 SetObjectElement(JSContext *cx, HandleObject obj, HandleValue index, HandleValue value,
   384                  bool strict);
   385 bool
   386 SetObjectElement(JSContext *cx, HandleObject obj, HandleValue index, HandleValue value,
   387                  bool strict, HandleScript script, jsbytecode *pc);
   389 bool
   390 InitElementArray(JSContext *cx, jsbytecode *pc,
   391                  HandleObject obj, uint32_t index, HandleValue value);
   393 bool
   394 AddValues(JSContext *cx, MutableHandleValue lhs, MutableHandleValue rhs, MutableHandleValue res);
   396 bool
   397 SubValues(JSContext *cx, MutableHandleValue lhs, MutableHandleValue rhs, MutableHandleValue res);
   399 bool
   400 MulValues(JSContext *cx, MutableHandleValue lhs, MutableHandleValue rhs, MutableHandleValue res);
   402 bool
   403 DivValues(JSContext *cx, MutableHandleValue lhs, MutableHandleValue rhs, MutableHandleValue res);
   405 bool
   406 ModValues(JSContext *cx, MutableHandleValue lhs, MutableHandleValue rhs, MutableHandleValue res);
   408 bool
   409 UrshValues(JSContext *cx, MutableHandleValue lhs, MutableHandleValue rhs, MutableHandleValue res);
   411 template <bool strict>
   412 bool
   413 SetProperty(JSContext *cx, HandleObject obj, HandleId id, const Value &value);
   415 template <bool strict>
   416 bool
   417 DeleteProperty(JSContext *ctx, HandleValue val, HandlePropertyName name, bool *bv);
   419 template <bool strict>
   420 bool
   421 DeleteElement(JSContext *cx, HandleValue val, HandleValue index, bool *bv);
   423 bool
   424 DefFunOperation(JSContext *cx, HandleScript script, HandleObject scopeChain, HandleFunction funArg);
   426 bool
   427 SetCallOperation(JSContext *cx);
   429 bool
   430 GetAndClearException(JSContext *cx, MutableHandleValue res);
   432 bool
   433 DeleteNameOperation(JSContext *cx, HandlePropertyName name, HandleObject scopeObj,
   434                     MutableHandleValue res);
   436 bool
   437 ImplicitThisOperation(JSContext *cx, HandleObject scopeObj, HandlePropertyName name,
   438                       MutableHandleValue res);
   440 bool
   441 IteratorMore(JSContext *cx, JSObject *iterobj, bool *cond, MutableHandleValue rval);
   443 bool
   444 IteratorNext(JSContext *cx, HandleObject iterobj, MutableHandleValue rval);
   446 bool
   447 RunOnceScriptPrologue(JSContext *cx, HandleScript script);
   449 bool
   450 InitGetterSetterOperation(JSContext *cx, jsbytecode *pc, HandleObject obj, HandleId id,
   451                           HandleObject val);
   453 bool
   454 InitGetterSetterOperation(JSContext *cx, jsbytecode *pc, HandleObject obj, HandlePropertyName name,
   455                           HandleObject val);
   457 bool
   458 EnterWithOperation(JSContext *cx, AbstractFramePtr frame, HandleValue val, HandleObject staticWith);
   461 bool
   462 InitGetterSetterOperation(JSContext *cx, jsbytecode *pc, HandleObject obj, HandleValue idval,
   463                           HandleObject val);
   465 inline bool
   466 SetConstOperation(JSContext *cx, HandleObject varobj, HandlePropertyName name, HandleValue rval)
   467 {
   468     return JSObject::defineProperty(cx, varobj, name, rval,
   469                                     JS_PropertyStub, JS_StrictPropertyStub,
   470                                     JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_READONLY);
   471 }
   473 }  /* namespace js */
   475 #endif /* vm_Interpreter_h */

mercurial