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.

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

mercurial