LCOV - code coverage report
Current view: top level - js/src/vm - Interpreter.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 1644 2464 66.7 %
Date: 2017-07-14 16:53:18 Functions: 134 169 79.3 %
Legend: Lines: hit not hit

          Line data    Source code
       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/. */
       6             : 
       7             : /*
       8             :  * JavaScript bytecode interpreter.
       9             :  */
      10             : 
      11             : #include "vm/Interpreter-inl.h"
      12             : 
      13             : #include "mozilla/ArrayUtils.h"
      14             : #include "mozilla/DebugOnly.h"
      15             : #include "mozilla/FloatingPoint.h"
      16             : #include "mozilla/Maybe.h"
      17             : #include "mozilla/PodOperations.h"
      18             : #include "mozilla/Sprintf.h"
      19             : 
      20             : #include <string.h>
      21             : 
      22             : #include "jsarray.h"
      23             : #include "jsatom.h"
      24             : #include "jscntxt.h"
      25             : #include "jsfun.h"
      26             : #include "jsgc.h"
      27             : #include "jsiter.h"
      28             : #include "jslibmath.h"
      29             : #include "jsnum.h"
      30             : #include "jsobj.h"
      31             : #include "jsopcode.h"
      32             : #include "jsprf.h"
      33             : #include "jsscript.h"
      34             : #include "jsstr.h"
      35             : 
      36             : #include "builtin/Eval.h"
      37             : #include "jit/AtomicOperations.h"
      38             : #include "jit/BaselineJIT.h"
      39             : #include "jit/Ion.h"
      40             : #include "jit/IonAnalysis.h"
      41             : #include "vm/AsyncFunction.h"
      42             : #include "vm/AsyncIteration.h"
      43             : #include "vm/Debugger.h"
      44             : #include "vm/GeneratorObject.h"
      45             : #include "vm/Opcodes.h"
      46             : #include "vm/Scope.h"
      47             : #include "vm/Shape.h"
      48             : #include "vm/Stopwatch.h"
      49             : #include "vm/TraceLogging.h"
      50             : 
      51             : #include "jsatominlines.h"
      52             : #include "jsboolinlines.h"
      53             : #include "jsfuninlines.h"
      54             : #include "jsscriptinlines.h"
      55             : 
      56             : #include "jit/JitFrames-inl.h"
      57             : #include "vm/Debugger-inl.h"
      58             : #include "vm/EnvironmentObject-inl.h"
      59             : #include "vm/NativeObject-inl.h"
      60             : #include "vm/Probes-inl.h"
      61             : #include "vm/Stack-inl.h"
      62             : 
      63             : using namespace js;
      64             : using namespace js::gc;
      65             : 
      66             : using mozilla::ArrayLength;
      67             : using mozilla::DebugOnly;
      68             : using mozilla::NumberEqualsInt32;
      69             : using mozilla::PodCopy;
      70             : using JS::ForOfIterator;
      71             : 
      72             : template <bool Eq>
      73             : static MOZ_ALWAYS_INLINE bool
      74        1772 : LooseEqualityOp(JSContext* cx, InterpreterRegs& regs)
      75             : {
      76        1772 :     HandleValue rval = regs.stackHandleAt(-1);
      77        1772 :     HandleValue lval = regs.stackHandleAt(-2);
      78             :     bool cond;
      79        1772 :     if (!LooselyEqual(cx, lval, rval, &cond))
      80           0 :         return false;
      81        1772 :     cond = (cond == Eq);
      82        1772 :     regs.sp--;
      83        1772 :     regs.sp[-1].setBoolean(cond);
      84        1772 :     return true;
      85             : }
      86             : 
      87             : bool
      88         275 : js::BoxNonStrictThis(JSContext* cx, HandleValue thisv, MutableHandleValue vp)
      89             : {
      90             :     /*
      91             :      * Check for SynthesizeFrame poisoning and fast constructors which
      92             :      * didn't check their callee properly.
      93             :      */
      94         275 :     MOZ_ASSERT(!thisv.isMagic());
      95             : 
      96         275 :     if (thisv.isNullOrUndefined()) {
      97         275 :         vp.set(GetThisValue(cx->global()));
      98         275 :         return true;
      99             :     }
     100             : 
     101           0 :     if (thisv.isObject()) {
     102           0 :         vp.set(thisv);
     103           0 :         return true;
     104             :     }
     105             : 
     106           0 :     JSObject* obj = PrimitiveToObject(cx, thisv);
     107           0 :     if (!obj)
     108           0 :         return false;
     109             : 
     110           0 :     vp.setObject(*obj);
     111           0 :     return true;
     112             : }
     113             : 
     114             : bool
     115        5631 : js::GetFunctionThis(JSContext* cx, AbstractFramePtr frame, MutableHandleValue res)
     116             : {
     117        5631 :     MOZ_ASSERT(frame.isFunctionFrame());
     118        5631 :     MOZ_ASSERT(!frame.callee()->isArrow());
     119             : 
     120       11463 :     if (frame.thisArgument().isObject() ||
     121        5634 :         frame.callee()->strict() ||
     122           3 :         frame.callee()->isSelfHostedBuiltin())
     123             :     {
     124        5628 :         res.set(frame.thisArgument());
     125        5628 :         return true;
     126             :     }
     127             : 
     128           6 :     RootedValue thisv(cx, frame.thisArgument());
     129           3 :     return BoxNonStrictThis(cx, thisv, res);
     130             : }
     131             : 
     132             : bool
     133         148 : js::GetNonSyntacticGlobalThis(JSContext* cx, HandleObject envChain, MutableHandleValue res)
     134             : {
     135         296 :     RootedObject env(cx, envChain);
     136             :     while (true) {
     137         148 :         if (IsExtensibleLexicalEnvironment(env)) {
     138         148 :             res.set(env->as<LexicalEnvironmentObject>().thisValue());
     139         148 :             return true;
     140             :         }
     141           0 :         if (!env->enclosingEnvironment()) {
     142             :             // This can only happen in Debugger eval frames: in that case we
     143             :             // don't always have a global lexical env, see EvaluateInEnv.
     144           0 :             MOZ_ASSERT(env->is<GlobalObject>());
     145           0 :             res.set(GetThisValue(env));
     146           0 :             return true;
     147             :         }
     148           0 :         env = env->enclosingEnvironment();
     149             :     }
     150             : 
     151             :     return true;
     152             : }
     153             : 
     154             : bool
     155         238 : js::Debug_CheckSelfHosted(JSContext* cx, HandleValue fun)
     156             : {
     157             : #ifndef DEBUG
     158             :     MOZ_CRASH("self-hosted checks should only be done in Debug builds");
     159             : #endif
     160             : 
     161         476 :     RootedObject funObj(cx, UncheckedUnwrap(&fun.toObject()));
     162         238 :     MOZ_ASSERT(funObj->as<JSFunction>().isSelfHostedOrIntrinsic());
     163             : 
     164             :     // This is purely to police self-hosted code. There is no actual operation.
     165         476 :     return true;
     166             : }
     167             : 
     168             : static inline bool
     169       33888 : GetPropertyOperation(JSContext* cx, InterpreterFrame* fp, HandleScript script, jsbytecode* pc,
     170             :                      MutableHandleValue lval, MutableHandleValue vp)
     171             : {
     172       33888 :     JSOp op = JSOp(*pc);
     173             : 
     174       33888 :     if (op == JSOP_LENGTH) {
     175        1751 :         if (IsOptimizedArguments(fp, lval)) {
     176         361 :             vp.setInt32(fp->numActualArgs());
     177         361 :             return true;
     178             :         }
     179             : 
     180        1390 :         if (GetLengthProperty(lval, vp))
     181        1306 :             return true;
     182             :     }
     183             : 
     184       64442 :     RootedPropertyName name(cx, script->getName(pc));
     185             : 
     186       32221 :     if (name == cx->names().callee && IsOptimizedArguments(fp, lval)) {
     187           0 :         vp.setObject(fp->callee());
     188           0 :         return true;
     189             :     }
     190             : 
     191             :     // Copy lval, because it might alias vp.
     192       64442 :     RootedValue v(cx, lval);
     193       32221 :     return GetProperty(cx, v, name, vp);
     194             : }
     195             : 
     196             : static inline bool
     197       15236 : GetNameOperation(JSContext* cx, InterpreterFrame* fp, jsbytecode* pc, MutableHandleValue vp)
     198             : {
     199       30472 :     RootedObject envChain(cx, fp->environmentChain());
     200       30472 :     RootedPropertyName name(cx, fp->script()->getName(pc));
     201             : 
     202             :     /*
     203             :      * Skip along the env chain to the enclosing global object. This is
     204             :      * used for GNAME opcodes where the bytecode emitter has determined a
     205             :      * name access must be on the global. It also insulates us from bugs
     206             :      * in the emitter: type inference will assume that GNAME opcodes are
     207             :      * accessing the global object, and the inferred behavior should match
     208             :      * the actual behavior even if the id could be found on the env chain
     209             :      * before the global object.
     210             :      */
     211       15236 :     if (IsGlobalOp(JSOp(*pc)) && !fp->script()->hasNonSyntacticScope())
     212       13000 :         envChain = &envChain->global().lexicalEnvironment();
     213             : 
     214             :     /* Kludge to allow (typeof foo == "undefined") tests. */
     215       15236 :     JSOp op2 = JSOp(pc[JSOP_GETNAME_LENGTH]);
     216       15236 :     if (op2 == JSOP_TYPEOF)
     217          33 :         return GetEnvironmentName<GetNameMode::TypeOf>(cx, envChain, name, vp);
     218       15203 :     return GetEnvironmentName<GetNameMode::Normal>(cx, envChain, name, vp);
     219             : }
     220             : 
     221             : static inline bool
     222           0 : GetImportOperation(JSContext* cx, InterpreterFrame* fp, jsbytecode* pc, MutableHandleValue vp)
     223             : {
     224           0 :     RootedObject obj(cx, fp->environmentChain()), env(cx), pobj(cx);
     225           0 :     RootedPropertyName name(cx, fp->script()->getName(pc));
     226           0 :     Rooted<PropertyResult> prop(cx);
     227             : 
     228           0 :     MOZ_ALWAYS_TRUE(LookupName(cx, name, obj, &env, &pobj, &prop));
     229           0 :     MOZ_ASSERT(env && env->is<ModuleEnvironmentObject>());
     230           0 :     MOZ_ASSERT(env->as<ModuleEnvironmentObject>().hasImportBinding(name));
     231           0 :     return FetchName<GetNameMode::Normal>(cx, env, pobj, name, prop, vp);
     232             : }
     233             : 
     234             : static bool
     235        4508 : SetPropertyOperation(JSContext* cx, JSOp op, HandleValue lval, HandleId id, HandleValue rval)
     236             : {
     237        4508 :     MOZ_ASSERT(op == JSOP_SETPROP || op == JSOP_STRICTSETPROP);
     238             : 
     239        9015 :     RootedObject obj(cx, ToObjectFromStack(cx, lval));
     240        4508 :     if (!obj)
     241           0 :         return false;
     242             : 
     243        4508 :     ObjectOpResult result;
     244       22536 :     return SetProperty(cx, obj, id, rval, lval, result) &&
     245       13521 :            result.checkStrictErrorOrWarning(cx, obj, id, op == JSOP_STRICTSETPROP);
     246             : }
     247             : 
     248             : JSFunction*
     249           3 : js::MakeDefaultConstructor(JSContext* cx, HandleScript script, jsbytecode* pc, HandleObject proto)
     250             : {
     251           3 :     JSOp op = JSOp(*pc);
     252           3 :     JSAtom* atom = script->getAtom(pc);
     253           3 :     bool derived = op == JSOP_DERIVEDCONSTRUCTOR;
     254           3 :     MOZ_ASSERT(derived == !!proto);
     255             : 
     256           3 :     jssrcnote* classNote = GetSrcNote(cx, script, pc);
     257           3 :     MOZ_ASSERT(classNote && SN_TYPE(classNote) == SRC_CLASS_SPAN);
     258             : 
     259           3 :     PropertyName* lookup = derived ? cx->names().DefaultDerivedClassConstructor
     260           6 :                                    : cx->names().DefaultBaseClassConstructor;
     261             : 
     262           6 :     RootedPropertyName selfHostedName(cx, lookup);
     263           6 :     RootedAtom name(cx, atom == cx->names().empty ? nullptr : atom);
     264             : 
     265           6 :     RootedFunction ctor(cx);
     266           3 :     if (!cx->runtime()->createLazySelfHostedFunctionClone(cx, selfHostedName, name,
     267             :                                                           /* nargs = */ !!derived,
     268             :                                                           proto, TenuredObject, &ctor))
     269             :     {
     270           0 :         return nullptr;
     271             :     }
     272             : 
     273           3 :     ctor->setIsConstructor();
     274           3 :     ctor->setIsClassConstructor();
     275           3 :     MOZ_ASSERT(ctor->infallibleIsDefaultClassConstructor(cx));
     276             : 
     277             :     // Create the script now, as the source span needs to be overridden for
     278             :     // toString. Calling toString on a class constructor must not return the
     279             :     // source for just the constructor function.
     280           3 :     JSScript *ctorScript = JSFunction::getOrCreateScript(cx, ctor);
     281           3 :     if (!ctorScript)
     282           0 :         return nullptr;
     283           3 :     uint32_t classStartOffset = GetSrcNoteOffset(classNote, 0);
     284           3 :     uint32_t classEndOffset = GetSrcNoteOffset(classNote, 1);
     285           3 :     ctorScript->setDefaultClassConstructorSpan(script->sourceObject(), classStartOffset,
     286           3 :                                                classEndOffset);
     287             : 
     288           3 :     return ctor;
     289             : }
     290             : 
     291             : bool
     292           0 : js::ReportIsNotFunction(JSContext* cx, HandleValue v, int numToSkip, MaybeConstruct construct)
     293             : {
     294           0 :     unsigned error = construct ? JSMSG_NOT_CONSTRUCTOR : JSMSG_NOT_FUNCTION;
     295           0 :     int spIndex = numToSkip >= 0 ? -(numToSkip + 1) : JSDVG_SEARCH_STACK;
     296             : 
     297           0 :     ReportValueError(cx, error, spIndex, v, nullptr);
     298           0 :     return false;
     299             : }
     300             : 
     301             : JSObject*
     302           0 : js::ValueToCallable(JSContext* cx, HandleValue v, int numToSkip, MaybeConstruct construct)
     303             : {
     304           0 :     if (v.isObject() && v.toObject().isCallable()) {
     305           0 :         return &v.toObject();
     306             :     }
     307             : 
     308           0 :     ReportIsNotFunction(cx, v, numToSkip, construct);
     309           0 :     return nullptr;
     310             : }
     311             : 
     312             : bool
     313       38204 : RunState::maybeCreateThisForConstructor(JSContext* cx)
     314             : {
     315       38204 :     if (isInvoke()) {
     316       38204 :         InvokeState& invoke = *asInvoke();
     317       38204 :         if (invoke.constructing() && invoke.args().thisv().isPrimitive()) {
     318        1052 :             RootedObject callee(cx, &invoke.args().callee());
     319         526 :             if (callee->isBoundFunction()) {
     320           0 :                 invoke.args().setThis(MagicValue(JS_UNINITIALIZED_LEXICAL));
     321         526 :             } else if (script()->isDerivedClassConstructor()) {
     322          60 :                 MOZ_ASSERT(callee->as<JSFunction>().isClassConstructor());
     323          60 :                 invoke.args().setThis(MagicValue(JS_UNINITIALIZED_LEXICAL));
     324             :             } else {
     325         466 :                 MOZ_ASSERT(invoke.args().thisv().isMagic(JS_IS_CONSTRUCTING));
     326         932 :                 RootedObject newTarget(cx, &invoke.args().newTarget().toObject());
     327         466 :                 NewObjectKind newKind = invoke.createSingleton() ? SingletonObject : GenericObject;
     328         466 :                 JSObject* obj = CreateThisForFunction(cx, callee, newTarget, newKind);
     329         466 :                 if (!obj)
     330           0 :                     return false;
     331         466 :                 invoke.args().setThis(ObjectValue(*obj));
     332             :             }
     333             :         }
     334             :     }
     335       38204 :     return true;
     336             : }
     337             : 
     338             : static MOZ_NEVER_INLINE bool
     339             : Interpret(JSContext* cx, RunState& state);
     340             : 
     341             : InterpreterFrame*
     342        9929 : InvokeState::pushInterpreterFrame(JSContext* cx)
     343             : {
     344        9929 :     return cx->interpreterStack().pushInvokeFrame(cx, args_, construct_);
     345             : }
     346             : 
     347             : InterpreterFrame*
     348         498 : ExecuteState::pushInterpreterFrame(JSContext* cx)
     349             : {
     350         996 :     return cx->interpreterStack().pushExecuteFrame(cx, script_, newTargetValue_,
     351         996 :                                                    envChain_, evalInFrame_);
     352             : }
     353             : // MSVC with PGO inlines a lot of functions in RunScript, resulting in large
     354             : // stack frames and stack overflow issues, see bug 1167883. Turn off PGO to
     355             : // avoid this.
     356             : #ifdef _MSC_VER
     357             : # pragma optimize("g", off)
     358             : #endif
     359             : bool
     360       17387 : js::RunScript(JSContext* cx, RunState& state)
     361             : {
     362       17387 :     if (!CheckRecursionLimit(cx))
     363           0 :         return false;
     364             : 
     365             :     // Since any script can conceivably GC, make sure it's safe to do so.
     366       17387 :     cx->verifyIsSafeToGC();
     367             : 
     368       17387 :     MOZ_DIAGNOSTIC_ASSERT(cx->compartment()->isSystem() ||
     369             :                           cx->runtime()->allowContentJS());
     370             : 
     371       17387 :     MOZ_ASSERT(!cx->enableAccessValidation ||
     372             :                cx->compartment()->isAccessValid());
     373             : 
     374       17387 :     if (!Debugger::checkNoExecute(cx, state.script()))
     375           0 :         return false;
     376             : 
     377             : #if defined(MOZ_HAVE_RDTSC)
     378       34766 :     js::AutoStopwatch stopwatch(cx);
     379             : #endif // defined(MOZ_HAVE_RDTSC)
     380             : 
     381       34766 :     GeckoProfilerEntryMarker marker(cx->runtime(), state.script());
     382             : 
     383       17387 :     state.script()->ensureNonLazyCanonicalFunction();
     384             : 
     385       17387 :     if (jit::IsIonEnabled(cx)) {
     386       17387 :         jit::MethodStatus status = jit::CanEnter(cx, state);
     387       17387 :         if (status == jit::Method_Error)
     388           0 :             return false;
     389       17387 :         if (status == jit::Method_Compiled) {
     390          35 :             jit::JitExecStatus status = jit::IonCannon(cx, state);
     391          35 :             return !IsErrorStatus(status);
     392             :         }
     393             :     }
     394             : 
     395       17352 :     if (jit::IsBaselineEnabled(cx)) {
     396       17352 :         jit::MethodStatus status = jit::CanEnterBaselineMethod(cx, state);
     397       17352 :         if (status == jit::Method_Error)
     398           0 :             return false;
     399       17352 :         if (status == jit::Method_Compiled) {
     400        6925 :             jit::JitExecStatus status = jit::EnterBaselineMethod(cx, state);
     401        6925 :             return !IsErrorStatus(status);
     402             :         }
     403             :     }
     404             : 
     405       10427 :     if (state.isInvoke()) {
     406        9929 :         InvokeState& invoke = *state.asInvoke();
     407        9929 :         TypeMonitorCall(cx, invoke.args(), invoke.constructing());
     408             :     }
     409             : 
     410       10427 :     return Interpret(cx, state);
     411             : }
     412             : #ifdef _MSC_VER
     413             : # pragma optimize("", on)
     414             : #endif
     415             : 
     416             : struct AutoGCIfRequested
     417             : {
     418             :     JSRuntime* runtime;
     419       48591 :     explicit AutoGCIfRequested(JSRuntime* rt) : runtime(rt) {}
     420       48581 :     ~AutoGCIfRequested() { runtime->gc.gcIfRequested(); }
     421             : };
     422             : 
     423             : /*
     424             :  * Find a function reference and its 'this' value implicit first parameter
     425             :  * under argc arguments on cx's stack, and call the function.  Push missing
     426             :  * required arguments, allocate declared local variables, and pop everything
     427             :  * when done.  Then push the return value.
     428             :  *
     429             :  * Note: This function DOES NOT call GetThisValue to munge |args.thisv()| if
     430             :  *       necessary.  The caller (usually the interpreter) must have performed
     431             :  *       this step already!
     432             :  */
     433             : bool
     434       48591 : js::InternalCallOrConstruct(JSContext* cx, const CallArgs& args, MaybeConstruct construct)
     435             : {
     436       48591 :     MOZ_ASSERT(args.length() <= ARGS_LENGTH_MAX);
     437       48591 :     MOZ_ASSERT(!cx->zone()->types.activeAnalysis);
     438             : 
     439             :     /* Perform GC if necessary on exit from the function. */
     440       97172 :     AutoGCIfRequested gcIfRequested(cx->runtime());
     441             : 
     442       48591 :     unsigned skipForCallee = args.length() + 1 + (construct == CONSTRUCT);
     443       48591 :     if (args.calleev().isPrimitive())
     444           0 :         return ReportIsNotFunction(cx, args.calleev(), skipForCallee, construct);
     445             : 
     446             :     /* Invoke non-functions. */
     447       48591 :     if (MOZ_UNLIKELY(!args.callee().is<JSFunction>())) {
     448        5019 :         MOZ_ASSERT_IF(construct, !args.callee().constructHook());
     449        5019 :         JSNative call = args.callee().callHook();
     450        5019 :         if (!call)
     451           0 :             return ReportIsNotFunction(cx, args.calleev(), skipForCallee, construct);
     452        5019 :         return CallJSNative(cx, call, args);
     453             :     }
     454             : 
     455             :     /* Invoke native functions. */
     456       87134 :     RootedFunction fun(cx, &args.callee().as<JSFunction>());
     457       43572 :     if (construct != CONSTRUCT && fun->isClassConstructor()) {
     458           0 :         JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_CANT_CALL_CLASS_CONSTRUCTOR);
     459           0 :         return false;
     460             :     }
     461             : 
     462       43572 :     if (fun->isNative()) {
     463       26683 :         MOZ_ASSERT_IF(construct, !fun->isConstructor());
     464       26683 :         JSNative native = fun->native();
     465       26683 :         if (!construct && args.ignoresReturnValue()) {
     466        5251 :             const JSJitInfo* jitInfo = fun->jitInfo();
     467        5251 :             if (jitInfo && jitInfo->type() == JSJitInfo::IgnoresReturnValueNative)
     468          14 :                 native = jitInfo->ignoresReturnValueMethod;
     469             :         }
     470       26683 :         return CallJSNative(cx, native, args);
     471             :     }
     472             : 
     473       16889 :     if (!JSFunction::getOrCreateScript(cx, fun))
     474           0 :         return false;
     475             : 
     476             :     /* Run function until JSOP_RETRVAL, JSOP_RETURN or error. */
     477       33774 :     InvokeState state(cx, args, construct);
     478             : 
     479             :     // Check to see if createSingleton flag should be set for this frame.
     480       16889 :     if (construct) {
     481             :         jsbytecode* pc;
     482         209 :         if (JSScript* script = cx->currentScript(&pc)) {
     483          53 :             if (ObjectGroup::useSingletonForNewObject(cx, script, pc))
     484           0 :                 state.setCreateSingleton();
     485             :         }
     486             :     }
     487             : 
     488       16889 :     bool ok = RunScript(cx, state);
     489             : 
     490       16885 :     MOZ_ASSERT_IF(ok && construct, args.rval().isObject());
     491       16885 :     return ok;
     492             : }
     493             : 
     494             : static bool
     495       48382 : InternalCall(JSContext* cx, const AnyInvokeArgs& args)
     496             : {
     497       48382 :     MOZ_ASSERT(args.array() + args.length() == args.end(),
     498             :                "must pass calling arguments to a calling attempt");
     499             : 
     500       48382 :     if (args.thisv().isObject()) {
     501             :         // We must call the thisValue hook in case we are not called from the
     502             :         // interpreter, where a prior bytecode has computed an appropriate
     503             :         // |this| already.  But don't do that if fval is a DOM function.
     504       30110 :         HandleValue fval = args.calleev();
     505      115612 :         if (!fval.isObject() || !fval.toObject().is<JSFunction>() ||
     506       38897 :             !fval.toObject().as<JSFunction>().isNative() ||
     507       46932 :             !fval.toObject().as<JSFunction>().jitInfo() ||
     508        3207 :             fval.toObject().as<JSFunction>().jitInfo()->needsOuterizedThisObject())
     509             :         {
     510       28789 :             JSObject* thisObj = &args.thisv().toObject();
     511       28789 :             args.mutableThisv().set(GetThisValue(thisObj));
     512             :         }
     513             :     }
     514             : 
     515       48382 :     return InternalCallOrConstruct(cx, args, NO_CONSTRUCT);
     516             : }
     517             : 
     518             : bool
     519       32997 : js::CallFromStack(JSContext* cx, const CallArgs& args)
     520             : {
     521       32997 :     return InternalCall(cx, static_cast<const AnyInvokeArgs&>(args));
     522             : }
     523             : 
     524             : // ES7 rev 0c1bd3004329336774cbc90de727cd0cf5f11e93 7.3.12 Call.
     525             : bool
     526       15385 : js::Call(JSContext* cx, HandleValue fval, HandleValue thisv, const AnyInvokeArgs& args,
     527             :          MutableHandleValue rval)
     528             : {
     529             :     // Explicitly qualify these methods to bypass AnyInvokeArgs's deliberate
     530             :     // shadowing.
     531       15385 :     args.CallArgs::setCallee(fval);
     532       15385 :     args.CallArgs::setThis(thisv);
     533             : 
     534       15385 :     if (!InternalCall(cx, args))
     535         201 :         return false;
     536             : 
     537       15181 :     rval.set(args.rval());
     538       15181 :     return true;
     539             : }
     540             : 
     541             : static bool
     542         958 : InternalConstruct(JSContext* cx, const AnyConstructArgs& args)
     543             : {
     544         958 :     MOZ_ASSERT(args.array() + args.length() + 1 == args.end(),
     545             :                "must pass constructing arguments to a construction attempt");
     546         958 :     MOZ_ASSERT(!JSFunction::class_.getConstruct());
     547             : 
     548             :     // Callers are responsible for enforcing these preconditions.
     549         958 :     MOZ_ASSERT(IsConstructor(args.calleev()),
     550             :                "trying to construct a value that isn't a constructor");
     551         958 :     MOZ_ASSERT(IsConstructor(args.CallArgs::newTarget()),
     552             :                "provided new.target value must be a constructor");
     553             : 
     554         958 :     MOZ_ASSERT(args.thisv().isMagic(JS_IS_CONSTRUCTING) || args.thisv().isObject());
     555             : 
     556         958 :     JSObject& callee = args.callee();
     557         958 :     if (callee.is<JSFunction>()) {
     558        1488 :         RootedFunction fun(cx, &callee.as<JSFunction>());
     559             : 
     560         744 :         if (fun->isNative())
     561         535 :             return CallJSNativeConstructor(cx, fun->native(), args);
     562             : 
     563         209 :         if (!InternalCallOrConstruct(cx, args, CONSTRUCT))
     564           0 :             return false;
     565             : 
     566         209 :         MOZ_ASSERT(args.CallArgs::rval().isObject());
     567         209 :         return true;
     568             :     }
     569             : 
     570         214 :     JSNative construct = callee.constructHook();
     571         214 :     MOZ_ASSERT(construct != nullptr, "IsConstructor without a construct hook?");
     572             : 
     573         214 :     return CallJSNativeConstructor(cx, construct, args);
     574             : }
     575             : 
     576             : // Check that |callee|, the callee in a |new| expression, is a constructor.
     577             : static bool
     578         780 : StackCheckIsConstructorCalleeNewTarget(JSContext* cx, HandleValue callee, HandleValue newTarget)
     579             : {
     580             :     // Calls from the stack could have any old non-constructor callee.
     581         780 :     if (!IsConstructor(callee)) {
     582           0 :         ReportValueError(cx, JSMSG_NOT_CONSTRUCTOR, JSDVG_SEARCH_STACK, callee, nullptr);
     583           0 :         return false;
     584             :     }
     585             : 
     586             :     // The new.target has already been vetted by previous calls, or is the callee.
     587             :     // We can just assert that it's a constructor.
     588         780 :     MOZ_ASSERT(IsConstructor(newTarget));
     589             : 
     590         780 :     return true;
     591             : }
     592             : 
     593             : bool
     594         780 : js::ConstructFromStack(JSContext* cx, const CallArgs& args)
     595             : {
     596         780 :     if (!StackCheckIsConstructorCalleeNewTarget(cx, args.calleev(), args.newTarget()))
     597           0 :         return false;
     598             : 
     599         780 :     return InternalConstruct(cx, static_cast<const AnyConstructArgs&>(args));
     600             : }
     601             : 
     602             : bool
     603         178 : js::Construct(JSContext* cx, HandleValue fval, const AnyConstructArgs& args, HandleValue newTarget,
     604             :               MutableHandleObject objp)
     605             : {
     606         178 :     MOZ_ASSERT(args.thisv().isMagic(JS_IS_CONSTRUCTING));
     607             : 
     608             :     // Explicitly qualify to bypass AnyConstructArgs's deliberate shadowing.
     609         178 :     args.CallArgs::setCallee(fval);
     610         178 :     args.CallArgs::newTarget().set(newTarget);
     611             : 
     612         178 :     if (!InternalConstruct(cx, args))
     613           0 :         return false;
     614             : 
     615         178 :     MOZ_ASSERT(args.CallArgs::rval().isObject());
     616         178 :     objp.set(&args.CallArgs::rval().toObject());
     617         178 :     return true;
     618             : }
     619             : 
     620             : bool
     621           0 : js::InternalConstructWithProvidedThis(JSContext* cx, HandleValue fval, HandleValue thisv,
     622             :                                       const AnyConstructArgs& args, HandleValue newTarget,
     623             :                                       MutableHandleValue rval)
     624             : {
     625           0 :     args.CallArgs::setCallee(fval);
     626             : 
     627           0 :     MOZ_ASSERT(thisv.isObject());
     628           0 :     args.CallArgs::setThis(thisv);
     629             : 
     630           0 :     args.CallArgs::newTarget().set(newTarget);
     631             : 
     632           0 :     if (!InternalConstruct(cx, args))
     633           0 :         return false;
     634             : 
     635           0 :     rval.set(args.CallArgs::rval());
     636           0 :     return true;
     637             : }
     638             : 
     639             : bool
     640        5691 : js::CallGetter(JSContext* cx, HandleValue thisv, HandleValue getter, MutableHandleValue rval)
     641             : {
     642             :     // Invoke could result in another try to get or set the same id again, see
     643             :     // bug 355497.
     644        5691 :     if (!CheckRecursionLimit(cx))
     645           0 :         return false;
     646             : 
     647       11382 :     FixedInvokeArgs<0> args(cx);
     648             : 
     649        5691 :     return Call(cx, getter, thisv, args, rval);
     650             : }
     651             : 
     652             : bool
     653         300 : js::CallSetter(JSContext* cx, HandleValue thisv, HandleValue setter, HandleValue v)
     654             : {
     655         300 :     if (!CheckRecursionLimit(cx))
     656           0 :         return false;
     657             : 
     658         599 :     FixedInvokeArgs<1> args(cx);
     659             : 
     660         300 :     args[0].set(v);
     661             : 
     662         599 :     RootedValue ignored(cx);
     663         300 :     return Call(cx, setter, thisv, args, &ignored);
     664             : }
     665             : 
     666             : bool
     667         498 : js::ExecuteKernel(JSContext* cx, HandleScript script, JSObject& envChainArg,
     668             :                   const Value& newTargetValue, AbstractFramePtr evalInFrame,
     669             :                   Value* result)
     670             : {
     671         498 :     MOZ_ASSERT_IF(script->isGlobalCode(),
     672             :                   IsGlobalLexicalEnvironment(&envChainArg) ||
     673             :                   !IsSyntacticEnvironment(&envChainArg));
     674             : #ifdef DEBUG
     675         992 :     RootedObject terminatingEnv(cx, &envChainArg);
     676        1150 :     while (IsSyntacticEnvironment(terminatingEnv))
     677         326 :         terminatingEnv = terminatingEnv->enclosingEnvironment();
     678         498 :     MOZ_ASSERT(terminatingEnv->is<GlobalObject>() ||
     679             :                script->hasNonSyntacticScope());
     680             : #endif
     681             : 
     682         498 :     if (script->treatAsRunOnce()) {
     683          16 :         if (script->hasRunOnce()) {
     684           0 :             JS_ReportErrorASCII(cx, "Trying to execute a run-once script multiple times");
     685           0 :             return false;
     686             :         }
     687             : 
     688          16 :         script->setHasRunOnce();
     689             :     }
     690             : 
     691         498 :     if (script->isEmpty()) {
     692           0 :         if (result)
     693           0 :             result->setUndefined();
     694           0 :         return true;
     695             :     }
     696             : 
     697         498 :     probes::StartExecution(script);
     698         992 :     ExecuteState state(cx, script, newTargetValue, envChainArg, evalInFrame, result);
     699         498 :     bool ok = RunScript(cx, state);
     700         494 :     probes::StopExecution(script);
     701             : 
     702         494 :     return ok;
     703             : }
     704             : 
     705             : bool
     706         452 : js::Execute(JSContext* cx, HandleScript script, JSObject& envChainArg, Value* rval)
     707             : {
     708             :     /* The env chain is something we control, so we know it can't
     709             :        have any outer objects on it. */
     710         901 :     RootedObject envChain(cx, &envChainArg);
     711         452 :     MOZ_ASSERT(!IsWindowProxy(envChain));
     712             : 
     713         452 :     if (script->module()) {
     714           0 :         MOZ_RELEASE_ASSERT(envChain == script->module()->environment(),
     715             :                            "Module scripts can only be executed in the module's environment");
     716             :     } else {
     717         452 :         MOZ_RELEASE_ASSERT(IsGlobalLexicalEnvironment(envChain) || script->hasNonSyntacticScope(),
     718             :                            "Only global scripts with non-syntactic envs can be executed with "
     719             :                            "interesting envchains");
     720             :     }
     721             : 
     722             :     /* Ensure the env chain is all same-compartment and terminates in a global. */
     723             : #ifdef DEBUG
     724         452 :     JSObject* s = envChain;
     725        2222 :     do {
     726        2222 :         assertSameCompartment(cx, s);
     727        2222 :         MOZ_ASSERT_IF(!s->enclosingEnvironment(), s->is<GlobalObject>());
     728        2222 :     } while ((s = s->enclosingEnvironment()));
     729             : #endif
     730             : 
     731         901 :     return ExecuteKernel(cx, script, *envChain, NullValue(),
     732        1802 :                          NullFramePtr() /* evalInFrame */, rval);
     733             : }
     734             : 
     735             : /*
     736             :  * ES6 (4-25-16) 12.10.4 InstanceofOperator
     737             :  */
     738             : extern bool
     739          75 : js::InstanceOfOperator(JSContext* cx, HandleObject obj, HandleValue v, bool* bp)
     740             : {
     741             :     /* Step 1. is handled by caller. */
     742             : 
     743             :     /* Step 2. */
     744         150 :     RootedValue hasInstance(cx);
     745         150 :     RootedId id(cx, SYMBOL_TO_JSID(cx->wellKnownSymbols().hasInstance));
     746          75 :     if (!GetProperty(cx, obj, obj, id, &hasInstance))
     747           0 :         return false;
     748             : 
     749          75 :     if (!hasInstance.isNullOrUndefined()) {
     750          75 :         if (!IsCallable(hasInstance))
     751           0 :             return ReportIsNotFunction(cx, hasInstance);
     752             : 
     753             :         /* Step 3. */
     754         150 :         RootedValue rval(cx);
     755          75 :         if (!Call(cx, hasInstance, obj, v, &rval))
     756           0 :             return false;
     757          75 :         *bp = ToBoolean(rval);
     758          75 :         return true;
     759             :     }
     760             : 
     761             :     /* Step 4. */
     762           0 :     if (!obj->isCallable()) {
     763           0 :         RootedValue val(cx, ObjectValue(*obj));
     764           0 :         return ReportIsNotFunction(cx, val);
     765             :     }
     766             : 
     767             :     /* Step 5. */
     768           0 :     return OrdinaryHasInstance(cx, obj, v, bp);
     769             : }
     770             : 
     771             : bool
     772         261 : js::HasInstance(JSContext* cx, HandleObject obj, HandleValue v, bool* bp)
     773             : {
     774         261 :     const Class* clasp = obj->getClass();
     775         522 :     RootedValue local(cx, v);
     776         261 :     if (JSHasInstanceOp hasInstance = clasp->getHasInstance())
     777         186 :         return hasInstance(cx, obj, &local, bp);
     778          75 :     return js::InstanceOfOperator(cx, obj, local, bp);
     779             : }
     780             : 
     781             : static inline bool
     782        8264 : EqualGivenSameType(JSContext* cx, HandleValue lval, HandleValue rval, bool* equal)
     783             : {
     784        8264 :     MOZ_ASSERT(SameType(lval, rval));
     785             : 
     786        8264 :     if (lval.isString())
     787        5403 :         return EqualStrings(cx, lval.toString(), rval.toString(), equal);
     788        2861 :     if (lval.isDouble()) {
     789          32 :         *equal = (lval.toDouble() == rval.toDouble());
     790          32 :         return true;
     791             :     }
     792        2829 :     if (lval.isGCThing()) {  // objects or symbols
     793         540 :         *equal = (lval.toGCThing() == rval.toGCThing());
     794         540 :         return true;
     795             :     }
     796        2289 :     *equal = lval.get().payloadAsRawUint32() == rval.get().payloadAsRawUint32();
     797        2289 :     MOZ_ASSERT_IF(lval.isUndefined() || lval.isNull(), *equal);
     798        2289 :     return true;
     799             : }
     800             : 
     801             : static inline bool
     802           0 : LooselyEqualBooleanAndOther(JSContext* cx, HandleValue lval, HandleValue rval, bool* result)
     803             : {
     804           0 :     MOZ_ASSERT(!rval.isBoolean());
     805           0 :     RootedValue lvalue(cx, Int32Value(lval.toBoolean() ? 1 : 0));
     806             : 
     807             :     // The tail-call would end up in Step 3.
     808           0 :     if (rval.isNumber()) {
     809           0 :         *result = (lvalue.toNumber() == rval.toNumber());
     810           0 :         return true;
     811             :     }
     812             :     // The tail-call would end up in Step 6.
     813           0 :     if (rval.isString()) {
     814             :         double num;
     815           0 :         if (!StringToNumber(cx, rval.toString(), &num))
     816           0 :             return false;
     817           0 :         *result = (lvalue.toNumber() == num);
     818           0 :         return true;
     819             :     }
     820             : 
     821           0 :     return LooselyEqual(cx, lvalue, rval, result);
     822             : }
     823             : 
     824             : // ES6 draft rev32 7.2.12 Abstract Equality Comparison
     825             : bool
     826        2195 : js::LooselyEqual(JSContext* cx, HandleValue lval, HandleValue rval, bool* result)
     827             : {
     828             :     // Step 3.
     829        2195 :     if (SameType(lval, rval))
     830        2025 :         return EqualGivenSameType(cx, lval, rval, result);
     831             : 
     832             :     // Handle int32 x double.
     833         170 :     if (lval.isNumber() && rval.isNumber()) {
     834           1 :         *result = (lval.toNumber() == rval.toNumber());
     835           1 :         return true;
     836             :     }
     837             : 
     838             :     // Step 4. This a bit more complex, because of the undefined emulating object.
     839         169 :     if (lval.isNullOrUndefined()) {
     840             :         // We can return early here, because null | undefined is only equal to the same set.
     841         104 :         *result = rval.isNullOrUndefined() ||
     842          55 :                   (rval.isObject() && EmulatesUndefined(&rval.toObject()));
     843          52 :         return true;
     844             :     }
     845             : 
     846             :     // Step 5.
     847         117 :     if (rval.isNullOrUndefined()) {
     848          74 :         MOZ_ASSERT(!lval.isNullOrUndefined());
     849          74 :         *result = lval.isObject() && EmulatesUndefined(&lval.toObject());
     850          74 :         return true;
     851             :     }
     852             : 
     853             :     // Step 6.
     854          43 :     if (lval.isNumber() && rval.isString()) {
     855             :         double num;
     856           0 :         if (!StringToNumber(cx, rval.toString(), &num))
     857           0 :             return false;
     858           0 :         *result = (lval.toNumber() == num);
     859           0 :         return true;
     860             :     }
     861             : 
     862             :     // Step 7.
     863          43 :     if (lval.isString() && rval.isNumber()) {
     864             :         double num;
     865           0 :         if (!StringToNumber(cx, lval.toString(), &num))
     866           0 :             return false;
     867           0 :         *result = (num == rval.toNumber());
     868           0 :         return true;
     869             :     }
     870             : 
     871             :     // Step 8.
     872          43 :     if (lval.isBoolean())
     873           0 :         return LooselyEqualBooleanAndOther(cx, lval, rval, result);
     874             : 
     875             :     // Step 9.
     876          43 :     if (rval.isBoolean())
     877           0 :         return LooselyEqualBooleanAndOther(cx, rval, lval, result);
     878             : 
     879             :     // Step 10.
     880          43 :     if ((lval.isString() || lval.isNumber() || lval.isSymbol()) && rval.isObject()) {
     881           0 :         RootedValue rvalue(cx, rval);
     882           0 :         if (!ToPrimitive(cx, &rvalue))
     883           0 :             return false;
     884           0 :         return LooselyEqual(cx, lval, rvalue, result);
     885             :     }
     886             : 
     887             :     // Step 11.
     888          43 :     if (lval.isObject() && (rval.isString() || rval.isNumber() || rval.isSymbol())) {
     889          84 :         RootedValue lvalue(cx, lval);
     890          42 :         if (!ToPrimitive(cx, &lvalue))
     891           0 :             return false;
     892          42 :         return LooselyEqual(cx, lvalue, rval, result);
     893             :     }
     894             : 
     895             :     // Step 12.
     896           1 :     *result = false;
     897           1 :     return true;
     898             : }
     899             : 
     900             : bool
     901        8312 : js::StrictlyEqual(JSContext* cx, HandleValue lval, HandleValue rval, bool* equal)
     902             : {
     903        8312 :     if (SameType(lval, rval))
     904        6239 :         return EqualGivenSameType(cx, lval, rval, equal);
     905             : 
     906        2073 :     if (lval.isNumber() && rval.isNumber()) {
     907          94 :         *equal = (lval.toNumber() == rval.toNumber());
     908          94 :         return true;
     909             :     }
     910             : 
     911        1979 :     *equal = false;
     912        1979 :     return true;
     913             : }
     914             : 
     915             : static inline bool
     916        6036 : IsNegativeZero(const Value& v)
     917             : {
     918        6036 :     return v.isDouble() && mozilla::IsNegativeZero(v.toDouble());
     919             : }
     920             : 
     921             : static inline bool
     922        3018 : IsNaN(const Value& v)
     923             : {
     924        3018 :     return v.isDouble() && mozilla::IsNaN(v.toDouble());
     925             : }
     926             : 
     927             : bool
     928        3018 : js::SameValue(JSContext* cx, HandleValue v1, HandleValue v2, bool* same)
     929             : {
     930        3018 :     if (IsNegativeZero(v1)) {
     931           0 :         *same = IsNegativeZero(v2);
     932           0 :         return true;
     933             :     }
     934        3018 :     if (IsNegativeZero(v2)) {
     935           0 :         *same = false;
     936           0 :         return true;
     937             :     }
     938        3018 :     if (IsNaN(v1) && IsNaN(v2)) {
     939           0 :         *same = true;
     940           0 :         return true;
     941             :     }
     942        3018 :     return StrictlyEqual(cx, v1, v2, same);
     943             : }
     944             : 
     945             : JSType
     946       11817 : js::TypeOfObject(JSObject* obj)
     947             : {
     948       11817 :     if (EmulatesUndefined(obj))
     949           0 :         return JSTYPE_UNDEFINED;
     950       11817 :     if (obj->isCallable())
     951       11386 :         return JSTYPE_FUNCTION;
     952         431 :     return JSTYPE_OBJECT;
     953             : }
     954             : 
     955             : JSType
     956       12564 : js::TypeOfValue(const Value& v)
     957             : {
     958       12564 :     if (v.isNumber())
     959         160 :         return JSTYPE_NUMBER;
     960       12404 :     if (v.isString())
     961         375 :         return JSTYPE_STRING;
     962       12029 :     if (v.isNull())
     963          26 :         return JSTYPE_OBJECT;
     964       12003 :     if (v.isUndefined())
     965         171 :         return JSTYPE_UNDEFINED;
     966       11832 :     if (v.isObject())
     967       11746 :         return TypeOfObject(&v.toObject());
     968          86 :     if (v.isBoolean())
     969          23 :         return JSTYPE_BOOLEAN;
     970          63 :     MOZ_ASSERT(v.isSymbol());
     971          63 :     return JSTYPE_SYMBOL;
     972             : }
     973             : 
     974             : bool
     975          32 : js::CheckClassHeritageOperation(JSContext* cx, HandleValue heritage)
     976             : {
     977          32 :     if (IsConstructor(heritage))
     978          29 :         return true;
     979             : 
     980           3 :     if (heritage.isNull())
     981           3 :         return true;
     982             : 
     983           0 :     if (heritage.isObject()) {
     984           0 :         ReportIsNotFunction(cx, heritage, 0, CONSTRUCT);
     985           0 :         return false;
     986             :     }
     987             : 
     988           0 :     ReportValueError2(cx, JSMSG_BAD_HERITAGE, -1, heritage, nullptr, "not an object or null");
     989           0 :     return false;
     990             : }
     991             : 
     992             : JSObject*
     993          32 : js::ObjectWithProtoOperation(JSContext* cx, HandleValue val)
     994             : {
     995          32 :     if (!val.isObjectOrNull()) {
     996           0 :         ReportValueError(cx, JSMSG_NOT_OBJORNULL, -1, val, nullptr);
     997           0 :         return nullptr;
     998             :     }
     999             : 
    1000          64 :     RootedObject proto(cx, val.toObjectOrNull());
    1001          32 :     return NewObjectWithGivenProto<PlainObject>(cx, proto);
    1002             : }
    1003             : 
    1004             : JSObject*
    1005          29 : js::FunWithProtoOperation(JSContext* cx, HandleFunction fun, HandleObject parent,
    1006             :                           HandleObject proto)
    1007             : {
    1008          29 :     return CloneFunctionObjectIfNotSingleton(cx, fun, parent, proto);
    1009             : }
    1010             : 
    1011             : /*
    1012             :  * Enter the new with environment using an object at sp[-1] and associate the
    1013             :  * depth of the with block with sp + stackIndex.
    1014             :  */
    1015             : bool
    1016           0 : js::EnterWithOperation(JSContext* cx, AbstractFramePtr frame, HandleValue val,
    1017             :                        Handle<WithScope*> scope)
    1018             : {
    1019           0 :     RootedObject obj(cx);
    1020           0 :     if (val.isObject()) {
    1021           0 :         obj = &val.toObject();
    1022             :     } else {
    1023           0 :         obj = ToObject(cx, val);
    1024           0 :         if (!obj)
    1025           0 :             return false;
    1026             :     }
    1027             : 
    1028           0 :     RootedObject envChain(cx, frame.environmentChain());
    1029           0 :     WithEnvironmentObject* withobj = WithEnvironmentObject::create(cx, obj, envChain, scope);
    1030           0 :     if (!withobj)
    1031           0 :         return false;
    1032             : 
    1033           0 :     frame.pushOnEnvironmentChain(*withobj);
    1034           0 :     return true;
    1035             : }
    1036             : 
    1037             : static void
    1038       14893 : PopEnvironment(JSContext* cx, EnvironmentIter& ei)
    1039             : {
    1040       14893 :     switch (ei.scope().kind()) {
    1041             :       case ScopeKind::Lexical:
    1042             :       case ScopeKind::SimpleCatch:
    1043             :       case ScopeKind::Catch:
    1044             :       case ScopeKind::NamedLambda:
    1045             :       case ScopeKind::StrictNamedLambda:
    1046        1177 :         if (MOZ_UNLIKELY(cx->compartment()->isDebuggee()))
    1047           0 :             DebugEnvironments::onPopLexical(cx, ei);
    1048        1177 :         if (ei.scope().hasEnvironment())
    1049         134 :             ei.initialFrame().popOffEnvironmentChain<LexicalEnvironmentObject>();
    1050        1177 :         break;
    1051             :       case ScopeKind::With:
    1052           0 :         if (MOZ_UNLIKELY(cx->compartment()->isDebuggee()))
    1053           0 :             DebugEnvironments::onPopWith(ei.initialFrame());
    1054           0 :         ei.initialFrame().popOffEnvironmentChain<WithEnvironmentObject>();
    1055           0 :         break;
    1056             :       case ScopeKind::Function:
    1057       11736 :         if (MOZ_UNLIKELY(cx->compartment()->isDebuggee()))
    1058           0 :             DebugEnvironments::onPopCall(cx, ei.initialFrame());
    1059       11736 :         if (ei.scope().hasEnvironment())
    1060        1291 :             ei.initialFrame().popOffEnvironmentChain<CallObject>();
    1061       11736 :         break;
    1062             :       case ScopeKind::FunctionBodyVar:
    1063             :       case ScopeKind::ParameterExpressionVar:
    1064             :       case ScopeKind::StrictEval:
    1065          89 :         if (MOZ_UNLIKELY(cx->compartment()->isDebuggee()))
    1066           0 :             DebugEnvironments::onPopVar(cx, ei);
    1067          89 :         if (ei.scope().hasEnvironment())
    1068          32 :             ei.initialFrame().popOffEnvironmentChain<VarEnvironmentObject>();
    1069          89 :         break;
    1070             :       case ScopeKind::Eval:
    1071             :       case ScopeKind::Global:
    1072             :       case ScopeKind::NonSyntactic:
    1073             :       case ScopeKind::Module:
    1074        1891 :         break;
    1075             :       case ScopeKind::WasmFunction:
    1076           0 :         MOZ_CRASH("wasm is not interpreted");
    1077             :         break;
    1078             :     }
    1079       14893 : }
    1080             : 
    1081             : // Unwind environment chain and iterator to match the env corresponding to
    1082             : // the given bytecode position.
    1083             : void
    1084        1981 : js::UnwindEnvironment(JSContext* cx, EnvironmentIter& ei, jsbytecode* pc)
    1085             : {
    1086        1981 :     if (!ei.withinInitialFrame())
    1087           0 :         return;
    1088             : 
    1089        3962 :     RootedScope scope(cx, ei.initialFrame().script()->innermostScope(pc));
    1090             : 
    1091             : #ifdef DEBUG
    1092             :     // A frame's environment chain cannot be unwound to anything enclosing the
    1093             :     // body scope of a script.  This includes the parameter defaults
    1094             :     // environment and the decl env object. These environments, once pushed
    1095             :     // onto the environment chain, are expected to be there for the duration
    1096             :     // of the frame.
    1097             :     //
    1098             :     // Attempting to unwind to the parameter defaults code in a script is a
    1099             :     // bug; that section of code has no try-catch blocks.
    1100        1981 :     JSScript* script = ei.initialFrame().script();
    1101        1986 :     for (uint32_t i = 0; i < script->bodyScopeIndex(); i++)
    1102           5 :         MOZ_ASSERT(scope != script->getScope(i));
    1103             : #endif
    1104             : 
    1105        2009 :     for (; ei.maybeScope() != scope; ei++)
    1106          14 :         PopEnvironment(cx, ei);
    1107             : }
    1108             : 
    1109             : // Unwind all environments. This is needed because block scopes may cover the
    1110             : // first bytecode at a script's main(). e.g.,
    1111             : //
    1112             : //     function f() { { let i = 0; } }
    1113             : //
    1114             : // will have no pc location distinguishing the first block scope from the
    1115             : // outermost function scope.
    1116             : void
    1117       27104 : js::UnwindAllEnvironmentsInFrame(JSContext* cx, EnvironmentIter& ei)
    1118             : {
    1119       41983 :     for (; ei.withinInitialFrame(); ei++)
    1120       14879 :         PopEnvironment(cx, ei);
    1121       12225 : }
    1122             : 
    1123             : // Compute the pc needed to unwind the environment to the beginning of a try
    1124             : // block. We cannot unwind to *after* the JSOP_TRY, because that might be the
    1125             : // first opcode of an inner scope, with the same problem as above. e.g.,
    1126             : //
    1127             : // try { { let x; } }
    1128             : //
    1129             : // will have no pc location distinguishing the try block scope from the inner
    1130             : // let block scope.
    1131             : jsbytecode*
    1132        1981 : js::UnwindEnvironmentToTryPc(JSScript* script, JSTryNote* tn)
    1133             : {
    1134        1981 :     jsbytecode* pc = script->main() + tn->start;
    1135        3962 :     if (tn->kind == JSTRY_CATCH || tn->kind == JSTRY_FINALLY) {
    1136        1981 :         pc -= JSOP_TRY_LENGTH;
    1137        1981 :         MOZ_ASSERT(*pc == JSOP_TRY);
    1138           0 :     } else if (tn->kind == JSTRY_DESTRUCTURING_ITERCLOSE) {
    1139           0 :         pc -= JSOP_TRY_DESTRUCTURING_ITERCLOSE_LENGTH;
    1140           0 :         MOZ_ASSERT(*pc == JSOP_TRY_DESTRUCTURING_ITERCLOSE);
    1141             :     }
    1142        1981 :     return pc;
    1143             : }
    1144             : 
    1145             : static bool
    1146           0 : ForcedReturn(JSContext* cx, EnvironmentIter& ei, InterpreterRegs& regs, bool frameOk = true)
    1147             : {
    1148           0 :     bool ok = Debugger::onLeaveFrame(cx, regs.fp(), regs.pc, frameOk);
    1149             :     // Point the frame to the end of the script, regardless of error. The
    1150             :     // caller must jump to the correct continuation depending on 'ok'.
    1151           0 :     regs.setToEndOfScript();
    1152           0 :     return ok;
    1153             : }
    1154             : 
    1155             : static bool
    1156           0 : ForcedReturn(JSContext* cx, InterpreterRegs& regs)
    1157             : {
    1158           0 :     EnvironmentIter ei(cx, regs.fp(), regs.pc);
    1159           0 :     return ForcedReturn(cx, ei, regs);
    1160             : }
    1161             : 
    1162             : static void
    1163          66 : SettleOnTryNote(JSContext* cx, JSTryNote* tn, EnvironmentIter& ei, InterpreterRegs& regs)
    1164             : {
    1165             :     // Unwind the environment to the beginning of the JSOP_TRY.
    1166          66 :     UnwindEnvironment(cx, ei, UnwindEnvironmentToTryPc(regs.fp()->script(), tn));
    1167             : 
    1168             :     // Set pc to the first bytecode after the the try note to point
    1169             :     // to the beginning of catch or finally.
    1170          66 :     regs.pc = regs.fp()->script()->main() + tn->start + tn->length;
    1171          66 :     regs.sp = regs.spForStackDepth(tn->stackDepth);
    1172          66 : }
    1173             : 
    1174             : class InterpreterFrameStackDepthOp
    1175             : {
    1176             :     const InterpreterRegs& regs_;
    1177             :   public:
    1178          78 :     explicit InterpreterFrameStackDepthOp(const InterpreterRegs& regs)
    1179          78 :       : regs_(regs)
    1180          78 :     { }
    1181          66 :     uint32_t operator()() { return regs_.stackDepth(); }
    1182             : };
    1183             : 
    1184          78 : class TryNoteIterInterpreter : public TryNoteIter<InterpreterFrameStackDepthOp>
    1185             : {
    1186             :   public:
    1187          78 :     TryNoteIterInterpreter(JSContext* cx, const InterpreterRegs& regs)
    1188          78 :       : TryNoteIter(cx, regs.fp()->script(), regs.pc, InterpreterFrameStackDepthOp(regs))
    1189          78 :     { }
    1190             : };
    1191             : 
    1192             : static void
    1193           0 : UnwindIteratorsForUncatchableException(JSContext* cx, const InterpreterRegs& regs)
    1194             : {
    1195             :     // c.f. the regular (catchable) TryNoteIterInterpreter loop in
    1196             :     // ProcessTryNotes.
    1197           0 :     for (TryNoteIterInterpreter tni(cx, regs); !tni.done(); ++tni) {
    1198           0 :         JSTryNote* tn = *tni;
    1199           0 :         if (tn->kind == JSTRY_FOR_IN) {
    1200           0 :             Value* sp = regs.spForStackDepth(tn->stackDepth);
    1201           0 :             UnwindIteratorForUncatchableException(cx, &sp[-1].toObject());
    1202             :         }
    1203             :     }
    1204           0 : }
    1205             : 
    1206             : enum HandleErrorContinuation
    1207             : {
    1208             :     SuccessfulReturnContinuation,
    1209             :     ErrorReturnContinuation,
    1210             :     CatchContinuation,
    1211             :     FinallyContinuation
    1212             : };
    1213             : 
    1214             : static HandleErrorContinuation
    1215          78 : ProcessTryNotes(JSContext* cx, EnvironmentIter& ei, InterpreterRegs& regs)
    1216             : {
    1217          78 :     bool inForOfIterClose = false;
    1218          78 :     for (TryNoteIterInterpreter tni(cx, regs); !tni.done(); ++tni) {
    1219          66 :         JSTryNote* tn = *tni;
    1220             : 
    1221          66 :         switch (tn->kind) {
    1222             :           case JSTRY_CATCH:
    1223             :             /* Catch cannot intercept the closing of a generator. */
    1224          66 :             if (cx->isClosingGenerator())
    1225           0 :                 break;
    1226             : 
    1227             :             // If IteratorClose due to abnormal completion threw inside a
    1228             :             // for-of loop, it is not catchable by try statements inside of
    1229             :             // the for-of loop.
    1230             :             //
    1231             :             // This is handled by this weirdness in the exception handler
    1232             :             // instead of in bytecode because it is hard to do so in bytecode:
    1233             :             //
    1234             :             //   1. IteratorClose emitted due to abnormal completion (break,
    1235             :             //   throw, return) are emitted inline, at the source location of
    1236             :             //   the break, throw, or return statement. For example:
    1237             :             //
    1238             :             //     for (x of iter) {
    1239             :             //       try { return; } catch (e) { }
    1240             :             //     }
    1241             :             //
    1242             :             //   From the try-note nesting's perspective, the IteratorClose
    1243             :             //   resulting from |return| is covered by the inner try, when it
    1244             :             //   should not be.
    1245             :             //
    1246             :             //   2. Try-catch notes cannot be disjoint. That is, we can't have
    1247             :             //   multiple notes with disjoint pc ranges jumping to the same
    1248             :             //   catch block.
    1249          66 :             if (inForOfIterClose)
    1250           0 :                 break;
    1251          66 :             SettleOnTryNote(cx, tn, ei, regs);
    1252          66 :             return CatchContinuation;
    1253             : 
    1254             :           case JSTRY_FINALLY:
    1255             :             // See note above.
    1256           0 :             if (inForOfIterClose)
    1257           0 :                 break;
    1258           0 :             SettleOnTryNote(cx, tn, ei, regs);
    1259           0 :             return FinallyContinuation;
    1260             : 
    1261             :           case JSTRY_FOR_IN: {
    1262             :             /* This is similar to JSOP_ENDITER in the interpreter loop. */
    1263           0 :             DebugOnly<jsbytecode*> pc = regs.fp()->script()->main() + tn->start + tn->length;
    1264           0 :             MOZ_ASSERT(JSOp(*pc) == JSOP_ENDITER);
    1265           0 :             Value* sp = regs.spForStackDepth(tn->stackDepth);
    1266           0 :             RootedObject obj(cx, &sp[-1].toObject());
    1267           0 :             if (!UnwindIteratorForException(cx, obj)) {
    1268             :                 // We should only settle on the note only if
    1269             :                 // UnwindIteratorForException itself threw, as
    1270             :                 // onExceptionUnwind should be called anew with the new
    1271             :                 // location of the throw (the iterator). Indeed, we must
    1272             :                 // settle to avoid infinitely handling the same exception.
    1273           0 :                 SettleOnTryNote(cx, tn, ei, regs);
    1274           0 :                 return ErrorReturnContinuation;
    1275             :             }
    1276           0 :             break;
    1277             :           }
    1278             : 
    1279             :           case JSTRY_DESTRUCTURING_ITERCLOSE: {
    1280             :             // Whether the destructuring iterator is done is at the top of the
    1281             :             // stack. The iterator object is second from the top.
    1282           0 :             MOZ_ASSERT(tn->stackDepth > 1);
    1283           0 :             Value* sp = regs.spForStackDepth(tn->stackDepth);
    1284           0 :             RootedValue doneValue(cx, sp[-1]);
    1285           0 :             bool done = ToBoolean(doneValue);
    1286           0 :             if (!done) {
    1287           0 :                 RootedObject iterObject(cx, &sp[-2].toObject());
    1288           0 :                 if (!IteratorCloseForException(cx, iterObject)) {
    1289           0 :                     SettleOnTryNote(cx, tn, ei, regs);
    1290           0 :                     return ErrorReturnContinuation;
    1291             :                 }
    1292             :             }
    1293           0 :             break;
    1294             :           }
    1295             : 
    1296             :           case JSTRY_FOR_OF_ITERCLOSE:
    1297           0 :             inForOfIterClose = true;
    1298           0 :             break;
    1299             : 
    1300             :           case JSTRY_FOR_OF:
    1301           0 :             inForOfIterClose = false;
    1302           0 :             break;
    1303             : 
    1304             :           case JSTRY_LOOP:
    1305           0 :             break;
    1306             : 
    1307             :           default:
    1308           0 :             MOZ_CRASH("Invalid try note");
    1309             :         }
    1310             :     }
    1311             : 
    1312          12 :     return SuccessfulReturnContinuation;
    1313             : }
    1314             : 
    1315             : bool
    1316          90 : js::HandleClosingGeneratorReturn(JSContext* cx, AbstractFramePtr frame, bool ok)
    1317             : {
    1318             :     /*
    1319             :      * Propagate the exception or error to the caller unless the exception
    1320             :      * is an asynchronous return from a generator.
    1321             :      */
    1322          90 :     if (cx->isClosingGenerator()) {
    1323           0 :         cx->clearPendingException();
    1324           0 :         ok = true;
    1325           0 :         SetReturnValueForClosingGenerator(cx, frame);
    1326             :     }
    1327          90 :     return ok;
    1328             : }
    1329             : 
    1330             : static HandleErrorContinuation
    1331          78 : HandleError(JSContext* cx, InterpreterRegs& regs)
    1332             : {
    1333          78 :     MOZ_ASSERT(regs.fp()->script()->containsPC(regs.pc));
    1334             : 
    1335          78 :     if (regs.fp()->script()->hasScriptCounts()) {
    1336           2 :         PCCounts* counts = regs.fp()->script()->getThrowCounts(regs.pc);
    1337             :         // If we failed to allocate, then skip the increment and continue to
    1338             :         // handle the exception.
    1339           2 :         if (counts)
    1340           2 :             counts->numExec()++;
    1341             :     }
    1342             : 
    1343         156 :     EnvironmentIter ei(cx, regs.fp(), regs.pc);
    1344          78 :     bool ok = false;
    1345             : 
    1346             :   again:
    1347          78 :     if (cx->isExceptionPending()) {
    1348             :         /* Call debugger throw hooks. */
    1349          78 :         if (!cx->isClosingGenerator()) {
    1350          78 :             JSTrapStatus status = Debugger::onExceptionUnwind(cx, regs.fp());
    1351          78 :             switch (status) {
    1352             :               case JSTRAP_ERROR:
    1353           0 :                 goto again;
    1354             : 
    1355             :               case JSTRAP_CONTINUE:
    1356             :               case JSTRAP_THROW:
    1357          78 :                 break;
    1358             : 
    1359             :               case JSTRAP_RETURN:
    1360           0 :                 UnwindIteratorsForUncatchableException(cx, regs);
    1361           0 :                 if (!ForcedReturn(cx, ei, regs))
    1362           0 :                     return ErrorReturnContinuation;
    1363           0 :                 return SuccessfulReturnContinuation;
    1364             : 
    1365             :               default:
    1366           0 :                 MOZ_CRASH("Bad Debugger::onExceptionUnwind status");
    1367             :             }
    1368             :         }
    1369             : 
    1370          78 :         HandleErrorContinuation res = ProcessTryNotes(cx, ei, regs);
    1371          78 :         switch (res) {
    1372             :           case SuccessfulReturnContinuation:
    1373          12 :             break;
    1374             :           case ErrorReturnContinuation:
    1375           0 :             goto again;
    1376             :           case CatchContinuation:
    1377             :           case FinallyContinuation:
    1378             :             // No need to increment the PCCounts number of execution here, as
    1379             :             // the interpreter increments any PCCounts if present.
    1380          66 :             MOZ_ASSERT_IF(regs.fp()->script()->hasScriptCounts(),
    1381             :                           regs.fp()->script()->maybeGetPCCounts(regs.pc));
    1382          66 :             return res;
    1383             :         }
    1384             : 
    1385          12 :         ok = HandleClosingGeneratorReturn(cx, regs.fp(), ok);
    1386          12 :         ok = Debugger::onLeaveFrame(cx, regs.fp(), regs.pc, ok);
    1387             :     } else {
    1388             :         // We may be propagating a forced return from the interrupt
    1389             :         // callback, which cannot easily force a return.
    1390           0 :         if (MOZ_UNLIKELY(cx->isPropagatingForcedReturn())) {
    1391           0 :             cx->clearPropagatingForcedReturn();
    1392           0 :             if (!ForcedReturn(cx, ei, regs))
    1393           0 :                 return ErrorReturnContinuation;
    1394           0 :             return SuccessfulReturnContinuation;
    1395             :         }
    1396             : 
    1397           0 :         UnwindIteratorsForUncatchableException(cx, regs);
    1398             :     }
    1399             : 
    1400             :     // After this point, we will pop the frame regardless. Settle the frame on
    1401             :     // the end of the script.
    1402          12 :     regs.setToEndOfScript();
    1403             : 
    1404          12 :     return ok ? SuccessfulReturnContinuation : ErrorReturnContinuation;
    1405             : }
    1406             : 
    1407             : #define REGS                     (activation.regs())
    1408             : #define PUSH_COPY(v)             do { *REGS.sp++ = (v); assertSameCompartmentDebugOnly(cx, REGS.sp[-1]); } while (0)
    1409             : #define PUSH_COPY_SKIP_CHECK(v)  *REGS.sp++ = (v)
    1410             : #define PUSH_NULL()              REGS.sp++->setNull()
    1411             : #define PUSH_UNDEFINED()         REGS.sp++->setUndefined()
    1412             : #define PUSH_BOOLEAN(b)          REGS.sp++->setBoolean(b)
    1413             : #define PUSH_DOUBLE(d)           REGS.sp++->setDouble(d)
    1414             : #define PUSH_INT32(i)            REGS.sp++->setInt32(i)
    1415             : #define PUSH_SYMBOL(s)           REGS.sp++->setSymbol(s)
    1416             : #define PUSH_STRING(s)           do { REGS.sp++->setString(s); assertSameCompartmentDebugOnly(cx, REGS.sp[-1]); } while (0)
    1417             : #define PUSH_OBJECT(obj)         do { REGS.sp++->setObject(obj); assertSameCompartmentDebugOnly(cx, REGS.sp[-1]); } while (0)
    1418             : #define PUSH_OBJECT_OR_NULL(obj) do { REGS.sp++->setObjectOrNull(obj); assertSameCompartmentDebugOnly(cx, REGS.sp[-1]); } while (0)
    1419             : #define PUSH_MAGIC(magic)        REGS.sp++->setMagic(magic)
    1420             : #define POP_COPY_TO(v)           (v) = *--REGS.sp
    1421             : #define POP_RETURN_VALUE()       REGS.fp()->setReturnValue(*--REGS.sp)
    1422             : 
    1423             : #define FETCH_OBJECT(cx, n, obj)                                              \
    1424             :     JS_BEGIN_MACRO                                                            \
    1425             :         HandleValue val = REGS.stackHandleAt(n);                              \
    1426             :         obj = ToObjectFromStack((cx), (val));                                 \
    1427             :         if (!obj)                                                             \
    1428             :             goto error;                                                       \
    1429             :     JS_END_MACRO
    1430             : 
    1431             : /*
    1432             :  * Same for JSOP_SETNAME and JSOP_SETPROP, which differ only slightly but
    1433             :  * remain distinct for the decompiler.
    1434             :  */
    1435             : JS_STATIC_ASSERT(JSOP_SETNAME_LENGTH == JSOP_SETPROP_LENGTH);
    1436             : 
    1437             : /* See TRY_BRANCH_AFTER_COND. */
    1438             : JS_STATIC_ASSERT(JSOP_IFNE_LENGTH == JSOP_IFEQ_LENGTH);
    1439             : JS_STATIC_ASSERT(JSOP_IFNE == JSOP_IFEQ + 1);
    1440             : 
    1441             : /*
    1442             :  * Compute the implicit |this| parameter for a call expression where the callee
    1443             :  * funval was resolved from an unqualified name reference to a property on obj
    1444             :  * (an object on the env chain).
    1445             :  *
    1446             :  * We can avoid computing |this| eagerly and push the implicit callee-coerced
    1447             :  * |this| value, undefined, if either of these conditions hold:
    1448             :  *
    1449             :  * 1. The nominal |this|, obj, is a global object.
    1450             :  *
    1451             :  * 2. The nominal |this|, obj, has one of LexicalEnvironment or Call class (this
    1452             :  *    is what IsCacheableEnvironment tests). Such objects-as-envs must be
    1453             :  *    censored with undefined.
    1454             :  *
    1455             :  * Otherwise, we bind |this| to the result of GetThisValue(). Only names inside
    1456             :  * |with| statements and embedding-specific environment objects fall into this
    1457             :  * category.
    1458             :  *
    1459             :  * If the callee is a strict mode function, then code implementing JSOP_THIS
    1460             :  * in the interpreter and JITs will leave undefined as |this|. If funval is a
    1461             :  * function not in strict mode, JSOP_THIS code replaces undefined with funval's
    1462             :  * global.
    1463             :  */
    1464             : static inline Value
    1465         919 : ComputeImplicitThis(JSObject* obj)
    1466             : {
    1467         919 :     if (obj->is<GlobalObject>())
    1468         482 :         return UndefinedValue();
    1469             : 
    1470         437 :     if (IsCacheableEnvironment(obj))
    1471           7 :         return UndefinedValue();
    1472             : 
    1473         430 :     return GetThisValue(obj);
    1474             : }
    1475             : 
    1476             : static MOZ_ALWAYS_INLINE bool
    1477        2308 : AddOperation(JSContext* cx, MutableHandleValue lhs, MutableHandleValue rhs, MutableHandleValue res)
    1478             : {
    1479        2308 :     if (lhs.isInt32() && rhs.isInt32()) {
    1480        1267 :         int32_t l = lhs.toInt32(), r = rhs.toInt32();
    1481             :         int32_t t;
    1482        1267 :         if (MOZ_LIKELY(SafeAdd(l, r, &t))) {
    1483        1267 :             res.setInt32(t);
    1484        1267 :             return true;
    1485             :         }
    1486             :     }
    1487             : 
    1488        1041 :     if (!ToPrimitive(cx, lhs))
    1489           0 :         return false;
    1490        1041 :     if (!ToPrimitive(cx, rhs))
    1491           0 :         return false;
    1492             : 
    1493             :     bool lIsString, rIsString;
    1494        1041 :     if ((lIsString = lhs.isString()) | (rIsString = rhs.isString())) {
    1495             :         JSString* lstr;
    1496        1026 :         if (lIsString) {
    1497        1024 :             lstr = lhs.toString();
    1498             :         } else {
    1499           2 :             lstr = ToString<CanGC>(cx, lhs);
    1500           2 :             if (!lstr)
    1501           0 :                 return false;
    1502             :         }
    1503             : 
    1504             :         JSString* rstr;
    1505        1026 :         if (rIsString) {
    1506         976 :             rstr = rhs.toString();
    1507             :         } else {
    1508             :             // Save/restore lstr in case of GC activity under ToString.
    1509          50 :             lhs.setString(lstr);
    1510          50 :             rstr = ToString<CanGC>(cx, rhs);
    1511          50 :             if (!rstr)
    1512           0 :                 return false;
    1513          50 :             lstr = lhs.toString();
    1514             :         }
    1515        1026 :         JSString* str = ConcatStrings<NoGC>(cx, lstr, rstr);
    1516        1026 :         if (!str) {
    1517           0 :             RootedString nlstr(cx, lstr), nrstr(cx, rstr);
    1518           0 :             str = ConcatStrings<CanGC>(cx, nlstr, nrstr);
    1519           0 :             if (!str)
    1520           0 :                 return false;
    1521             :         }
    1522        1026 :         res.setString(str);
    1523             :     } else {
    1524             :         double l, r;
    1525          15 :         if (!ToNumber(cx, lhs, &l) || !ToNumber(cx, rhs, &r))
    1526           0 :             return false;
    1527          15 :         res.setNumber(l + r);
    1528             :     }
    1529             : 
    1530        1041 :     return true;
    1531             : }
    1532             : 
    1533             : static MOZ_ALWAYS_INLINE bool
    1534         253 : SubOperation(JSContext* cx, HandleValue lhs, HandleValue rhs, MutableHandleValue res)
    1535             : {
    1536             :     double d1, d2;
    1537         253 :     if (!ToNumber(cx, lhs, &d1) || !ToNumber(cx, rhs, &d2))
    1538           0 :         return false;
    1539         253 :     res.setNumber(d1 - d2);
    1540         253 :     return true;
    1541             : }
    1542             : 
    1543             : static MOZ_ALWAYS_INLINE bool
    1544          66 : MulOperation(JSContext* cx, HandleValue lhs, HandleValue rhs, MutableHandleValue res)
    1545             : {
    1546             :     double d1, d2;
    1547          66 :     if (!ToNumber(cx, lhs, &d1) || !ToNumber(cx, rhs, &d2))
    1548           0 :         return false;
    1549          66 :     res.setNumber(d1 * d2);
    1550          66 :     return true;
    1551             : }
    1552             : 
    1553             : static MOZ_ALWAYS_INLINE bool
    1554          42 : DivOperation(JSContext* cx, HandleValue lhs, HandleValue rhs, MutableHandleValue res)
    1555             : {
    1556             :     double d1, d2;
    1557          42 :     if (!ToNumber(cx, lhs, &d1) || !ToNumber(cx, rhs, &d2))
    1558           0 :         return false;
    1559          42 :     res.setNumber(NumberDiv(d1, d2));
    1560          42 :     return true;
    1561             : }
    1562             : 
    1563             : static MOZ_ALWAYS_INLINE bool
    1564           1 : ModOperation(JSContext* cx, HandleValue lhs, HandleValue rhs, MutableHandleValue res)
    1565             : {
    1566             :     int32_t l, r;
    1567           3 :     if (lhs.isInt32() && rhs.isInt32() &&
    1568           2 :         (l = lhs.toInt32()) >= 0 && (r = rhs.toInt32()) > 0) {
    1569           1 :         int32_t mod = l % r;
    1570           1 :         res.setInt32(mod);
    1571           1 :         return true;
    1572             :     }
    1573             : 
    1574             :     double d1, d2;
    1575           0 :     if (!ToNumber(cx, lhs, &d1) || !ToNumber(cx, rhs, &d2))
    1576           0 :         return false;
    1577             : 
    1578           0 :     res.setNumber(NumberMod(d1, d2));
    1579           0 :     return true;
    1580             : }
    1581             : 
    1582             : static MOZ_ALWAYS_INLINE bool
    1583        1850 : SetObjectElementOperation(JSContext* cx, HandleObject obj, HandleId id, HandleValue value,
    1584             :                           HandleValue receiver, bool strict,
    1585             :                           JSScript* script = nullptr, jsbytecode* pc = nullptr)
    1586             : {
    1587             :     // receiver != obj happens only at super[expr], where we expect to find the property
    1588             :     // People probably aren't building hashtables with |super| anyway.
    1589        1850 :     TypeScript::MonitorAssign(cx, obj, id);
    1590             : 
    1591        1850 :     if (obj->isNative() && JSID_IS_INT(id)) {
    1592         328 :         uint32_t length = obj->as<NativeObject>().getDenseInitializedLength();
    1593         328 :         int32_t i = JSID_TO_INT(id);
    1594         328 :         if ((uint32_t)i >= length) {
    1595             :             // Annotate script if provided with information (e.g. baseline)
    1596          81 :             if (script && script->hasBaselineScript() && IsSetElemPC(pc))
    1597          42 :                 script->baselineScript()->noteHasDenseAdd(script->pcToOffset(pc));
    1598             :         }
    1599             :     }
    1600             : 
    1601             :     // Set the HadElementsAccess flag on the object if needed. This flag is
    1602             :     // used to do more eager dictionary-mode conversion for objects that are
    1603             :     // used as hashmaps. Set this flag only for objects with many properties,
    1604             :     // to avoid unnecessary Shape changes.
    1605        5520 :     if (obj->isNative() &&
    1606        3312 :         JSID_IS_ATOM(id) &&
    1607        2936 :         !obj->as<NativeObject>().inDictionaryMode() &&
    1608        4521 :         !obj->hadElementsAccess() &&
    1609        1227 :         obj->as<NativeObject>().slotSpan() > PropertyTree::MAX_HEIGHT_WITH_ELEMENTS_ACCESS / 3)
    1610             :     {
    1611          10 :         if (!JSObject::setHadElementsAccess(cx, obj))
    1612           0 :             return false;
    1613             :     }
    1614             : 
    1615        1850 :     ObjectOpResult result;
    1616        3700 :     return SetProperty(cx, obj, id, value, receiver, result) &&
    1617        3700 :            result.checkStrictErrorOrWarning(cx, obj, id, strict);
    1618             : }
    1619             : 
    1620             : /*
    1621             :  * Get the innermost enclosing function that has a 'this' binding.
    1622             :  *
    1623             :  * Implements ES6 12.3.5.2 GetSuperConstructor() steps 1-3, including
    1624             :  * the loop in ES6 8.3.2 GetThisEnvironment(). Our implementation of
    1625             :  * ES6 12.3.5.3 MakeSuperPropertyReference() also uses this code.
    1626             :  */
    1627             : static JSFunction&
    1628          34 : GetSuperEnvFunction(JSContext* cx, InterpreterRegs& regs)
    1629             : {
    1630          34 :     JSObject* env = regs.fp()->environmentChain();
    1631          34 :     Scope* scope = regs.fp()->script()->innermostScope(regs.pc);
    1632          40 :     for (EnvironmentIter ei(cx, env, scope); ei; ei++) {
    1633          40 :         if (ei.hasSyntacticEnvironment() && ei.scope().is<FunctionScope>()) {
    1634          34 :             JSFunction& callee = ei.environment().as<CallObject>().callee();
    1635             : 
    1636             :             // Arrow functions don't have the information we're looking for,
    1637             :             // their enclosing scopes do. Nevertheless, they might have call
    1638             :             // objects. Skip them to find what we came for.
    1639          34 :             if (callee.isArrow())
    1640           0 :                 continue;
    1641             : 
    1642          68 :             return callee;
    1643             :         }
    1644             :     }
    1645           0 :     MOZ_CRASH("unexpected env chain for GetSuperEnvFunction");
    1646             : }
    1647             : 
    1648             : 
    1649             : /*
    1650             :  * As an optimization, the interpreter creates a handful of reserved Rooted<T>
    1651             :  * variables at the beginning, thus inserting them into the Rooted list once
    1652             :  * upon entry. ReservedRooted "borrows" a reserved Rooted variable and uses it
    1653             :  * within a local scope, resetting the value to nullptr (or the appropriate
    1654             :  * equivalent for T) at scope end. This avoids inserting/removing the Rooted
    1655             :  * from the rooter list, while preventing stale values from being kept alive
    1656             :  * unnecessarily.
    1657             :  */
    1658             : 
    1659             : template<typename T>
    1660             : class ReservedRooted : public RootedBase<T, ReservedRooted<T>>
    1661             : {
    1662             :     Rooted<T>* savedRoot;
    1663             : 
    1664             :   public:
    1665       73707 :     ReservedRooted(Rooted<T>* root, const T& ptr) : savedRoot(root) {
    1666       73707 :         *root = ptr;
    1667       73707 :     }
    1668             : 
    1669       36953 :     explicit ReservedRooted(Rooted<T>* root) : savedRoot(root) {
    1670       36953 :         *root = JS::GCPolicy<T>::initial();
    1671       36953 :     }
    1672             : 
    1673      110659 :     ~ReservedRooted() {
    1674      110659 :         *savedRoot = JS::GCPolicy<T>::initial();
    1675      110659 :     }
    1676             : 
    1677        3450 :     void set(const T& p) const { *savedRoot = p; }
    1678       67845 :     operator Handle<T>() { return *savedRoot; }
    1679         755 :     operator Rooted<T>&() { return *savedRoot; }
    1680       35187 :     MutableHandle<T> operator&() { return &*savedRoot; }
    1681             : 
    1682       87487 :     DECLARE_NONPOINTER_ACCESSOR_METHODS(savedRoot->get())
    1683             :     DECLARE_NONPOINTER_MUTABLE_ACCESSOR_METHODS(savedRoot->get())
    1684       86397 :     DECLARE_POINTER_CONSTREF_OPS(T)
    1685        2564 :     DECLARE_POINTER_ASSIGN_OPS(ReservedRooted, T)
    1686             : };
    1687             : 
    1688             : static MOZ_NEVER_INLINE bool
    1689       10427 : Interpret(JSContext* cx, RunState& state)
    1690             : {
    1691             : /*
    1692             :  * Define macros for an interpreter loop. Opcode dispatch may be either by a
    1693             :  * switch statement or by indirect goto (aka a threaded interpreter), depending
    1694             :  * on compiler support.
    1695             :  *
    1696             :  * Threaded interpretation appears to be well-supported by GCC 3 and higher.
    1697             :  * IBM's C compiler when run with the right options (e.g., -qlanglvl=extended)
    1698             :  * also supports threading. Ditto the SunPro C compiler.
    1699             :  */
    1700             : #if (defined(__GNUC__) ||                                                         \
    1701             :      (__IBMC__ >= 700 && defined __IBM_COMPUTED_GOTO) ||                      \
    1702             :      __SUNPRO_C >= 0x570)
    1703             : // Non-standard but faster indirect-goto-based dispatch.
    1704             : # define INTERPRETER_LOOP()
    1705             : # define CASE(OP)                 label_##OP:
    1706             : # define DEFAULT()                label_default:
    1707             : # define DISPATCH_TO(OP)          goto* addresses[(OP)]
    1708             : 
    1709             : # define LABEL(X)                 (&&label_##X)
    1710             : 
    1711             :     // Use addresses instead of offsets to optimize for runtime speed over
    1712             :     // load-time relocation overhead.
    1713             :     static const void* const addresses[EnableInterruptsPseudoOpcode + 1] = {
    1714             : # define OPCODE_LABEL(op, ...)  LABEL(op),
    1715             :         FOR_EACH_OPCODE(OPCODE_LABEL)
    1716             : # undef OPCODE_LABEL
    1717             : # define TRAILING_LABEL(v)                                                    \
    1718             :     ((v) == EnableInterruptsPseudoOpcode                                      \
    1719             :      ? LABEL(EnableInterruptsPseudoOpcode)                                    \
    1720             :      : LABEL(default)),
    1721             :         FOR_EACH_TRAILING_UNUSED_OPCODE(TRAILING_LABEL)
    1722             : # undef TRAILING_LABEL
    1723             :     };
    1724             : #else
    1725             : // Portable switch-based dispatch.
    1726             : # define INTERPRETER_LOOP()       the_switch: switch (switchOp)
    1727             : # define CASE(OP)                 case OP:
    1728             : # define DEFAULT()                default:
    1729             : # define DISPATCH_TO(OP)                                                      \
    1730             :     JS_BEGIN_MACRO                                                            \
    1731             :         switchOp = (OP);                                                      \
    1732             :         goto the_switch;                                                      \
    1733             :     JS_END_MACRO
    1734             : 
    1735             :     // This variable is effectively a parameter to the_switch.
    1736             :     jsbytecode switchOp;
    1737             : #endif
    1738             : 
    1739             :     /*
    1740             :      * Increment REGS.pc by N, load the opcode at that position,
    1741             :      * and jump to the code to execute it.
    1742             :      *
    1743             :      * When Debugger puts a script in single-step mode, all js::Interpret
    1744             :      * invocations that might be presently running that script must have
    1745             :      * interrupts enabled. It's not practical to simply check
    1746             :      * script->stepModeEnabled() at each point some callee could have changed
    1747             :      * it, because there are so many places js::Interpret could possibly cause
    1748             :      * JavaScript to run: each place an object might be coerced to a primitive
    1749             :      * or a number, for example. So instead, we expose a simple mechanism to
    1750             :      * let Debugger tweak the affected js::Interpret frames when an onStep
    1751             :      * handler is added: calling activation.enableInterruptsUnconditionally()
    1752             :      * will enable interrupts, and activation.opMask() is or'd with the opcode
    1753             :      * to implement a simple alternate dispatch.
    1754             :      */
    1755             : #define ADVANCE_AND_DISPATCH(N)                                               \
    1756             :     JS_BEGIN_MACRO                                                            \
    1757             :         REGS.pc += (N);                                                       \
    1758             :         SANITY_CHECKS();                                                      \
    1759             :         DISPATCH_TO(*REGS.pc | activation.opMask());                          \
    1760             :     JS_END_MACRO
    1761             : 
    1762             :    /*
    1763             :     * Shorthand for the common sequence at the end of a fixed-size opcode.
    1764             :     */
    1765             : #define END_CASE(OP)              ADVANCE_AND_DISPATCH(OP##_LENGTH);
    1766             : 
    1767             :     /*
    1768             :      * Prepare to call a user-supplied branch handler, and abort the script
    1769             :      * if it returns false.
    1770             :      */
    1771             : #define CHECK_BRANCH()                                                        \
    1772             :     JS_BEGIN_MACRO                                                            \
    1773             :         if (!CheckForInterrupt(cx))                                           \
    1774             :             goto error;                                                       \
    1775             :     JS_END_MACRO
    1776             : 
    1777             :     /*
    1778             :      * This is a simple wrapper around ADVANCE_AND_DISPATCH which also does
    1779             :      * a CHECK_BRANCH() if n is not positive, which possibly indicates that it
    1780             :      * is the backedge of a loop.
    1781             :      */
    1782             : #define BRANCH(n)                                                             \
    1783             :     JS_BEGIN_MACRO                                                            \
    1784             :         int32_t nlen = (n);                                                   \
    1785             :         if (nlen <= 0)                                                        \
    1786             :             CHECK_BRANCH();                                                   \
    1787             :         ADVANCE_AND_DISPATCH(nlen);                                           \
    1788             :     JS_END_MACRO
    1789             : 
    1790             :     /*
    1791             :      * Initialize code coverage vectors.
    1792             :      */
    1793             : #define INIT_COVERAGE()                                                       \
    1794             :     JS_BEGIN_MACRO                                                            \
    1795             :         if (!script->hasScriptCounts()) {                                     \
    1796             :             if (cx->compartment()->collectCoverageForDebug()) {               \
    1797             :                 if (!script->initScriptCounts(cx))                            \
    1798             :                     goto error;                                               \
    1799             :             }                                                                 \
    1800             :         }                                                                     \
    1801             :     JS_END_MACRO
    1802             : 
    1803             :     /*
    1804             :      * Increment the code coverage counter associated with the given pc.
    1805             :      */
    1806             : #define COUNT_COVERAGE_PC(PC)                                                 \
    1807             :     JS_BEGIN_MACRO                                                            \
    1808             :         if (script->hasScriptCounts()) {                                      \
    1809             :             PCCounts* counts = script->maybeGetPCCounts(PC);                  \
    1810             :             MOZ_ASSERT(counts);                                               \
    1811             :             counts->numExec()++;                                              \
    1812             :         }                                                                     \
    1813             :     JS_END_MACRO
    1814             : 
    1815             : #define COUNT_COVERAGE_MAIN()                                                 \
    1816             :     JS_BEGIN_MACRO                                                            \
    1817             :         jsbytecode* main = script->main();                                    \
    1818             :         if (!BytecodeIsJumpTarget(JSOp(*main)))                               \
    1819             :             COUNT_COVERAGE_PC(main);                                          \
    1820             :     JS_END_MACRO
    1821             : 
    1822             : #define COUNT_COVERAGE()                                                      \
    1823             :     JS_BEGIN_MACRO                                                            \
    1824             :         MOZ_ASSERT(BytecodeIsJumpTarget(JSOp(*REGS.pc)));                     \
    1825             :         COUNT_COVERAGE_PC(REGS.pc);                                           \
    1826             :     JS_END_MACRO
    1827             : 
    1828             : #define LOAD_DOUBLE(PCOFF, dbl)                                               \
    1829             :     ((dbl) = script->getConst(GET_UINT32_INDEX(REGS.pc + (PCOFF))).toDouble())
    1830             : 
    1831             : #define SET_SCRIPT(s)                                                         \
    1832             :     JS_BEGIN_MACRO                                                            \
    1833             :         script = (s);                                                         \
    1834             :         if (script->hasAnyBreakpointsOrStepMode() || script->hasScriptCounts()) \
    1835             :             activation.enableInterruptsUnconditionally();                     \
    1836             :     JS_END_MACRO
    1837             : 
    1838             : #define SANITY_CHECKS()                                                       \
    1839             :     JS_BEGIN_MACRO                                                            \
    1840             :         js::gc::MaybeVerifyBarriers(cx);                                      \
    1841             :     JS_END_MACRO
    1842             : 
    1843       10427 :     gc::MaybeVerifyBarriers(cx, true);
    1844       10427 :     MOZ_ASSERT(!cx->zone()->types.activeAnalysis);
    1845             : 
    1846       10427 :     InterpreterFrame* entryFrame = state.pushInterpreterFrame(cx);
    1847       10427 :     if (!entryFrame)
    1848           0 :         return false;
    1849             : 
    1850       20846 :     ActivationEntryMonitor entryMonitor(cx, entryFrame);
    1851       20846 :     InterpreterActivation activation(state, cx, entryFrame);
    1852             : 
    1853             :     /* The script is used frequently, so keep a local copy. */
    1854       20846 :     RootedScript script(cx);
    1855       10427 :     SET_SCRIPT(REGS.fp()->script());
    1856             : 
    1857       10427 :     TraceLoggerThread* logger = TraceLoggerForCurrentThread(cx);
    1858       20846 :     TraceLoggerEvent scriptEvent(TraceLogger_Scripts, script);
    1859       10427 :     TraceLogStartEvent(logger, scriptEvent);
    1860       10427 :     TraceLogStartEvent(logger, TraceLogger_Interpreter);
    1861             : 
    1862             :     /*
    1863             :      * Pool of rooters for use in this interpreter frame. References to these
    1864             :      * are used for local variables within interpreter cases. This avoids
    1865             :      * creating new rooters each time an interpreter case is entered, and also
    1866             :      * correctness pitfalls due to incorrect compilation of destructor calls
    1867             :      * around computed gotos.
    1868             :      */
    1869       20846 :     RootedValue rootValue0(cx), rootValue1(cx);
    1870       20846 :     RootedString rootString0(cx), rootString1(cx);
    1871       20846 :     RootedObject rootObject0(cx), rootObject1(cx), rootObject2(cx);
    1872       20846 :     RootedNativeObject rootNativeObject0(cx);
    1873       20846 :     RootedFunction rootFunction0(cx);
    1874       20846 :     RootedPropertyName rootName0(cx);
    1875       20846 :     RootedId rootId0(cx);
    1876       20846 :     RootedShape rootShape0(cx);
    1877       20846 :     RootedScript rootScript0(cx);
    1878       20846 :     Rooted<Scope*> rootScope0(cx);
    1879       20846 :     DebugOnly<uint32_t> blockDepth;
    1880             : 
    1881             :     /* State communicated between non-local jumps: */
    1882             :     bool interpReturnOK;
    1883             :     bool frameHalfInitialized;
    1884             : 
    1885       10427 :     if (!activation.entryFrame()->prologue(cx))
    1886           0 :         goto prologue_error;
    1887             : 
    1888       10427 :     switch (Debugger::onEnterFrame(cx, activation.entryFrame())) {
    1889             :       case JSTRAP_CONTINUE:
    1890       10427 :         break;
    1891             :       case JSTRAP_RETURN:
    1892           0 :         if (!ForcedReturn(cx, REGS))
    1893           0 :             goto error;
    1894           0 :         goto successful_return_continuation;
    1895             :       case JSTRAP_THROW:
    1896             :       case JSTRAP_ERROR:
    1897           0 :         goto error;
    1898             :       default:
    1899           0 :         MOZ_CRASH("bad Debugger::onEnterFrame status");
    1900             :     }
    1901             : 
    1902             :     // Increment the coverage for the main entry point.
    1903       10427 :     INIT_COVERAGE();
    1904       10427 :     COUNT_COVERAGE_MAIN();
    1905             : 
    1906             :     // Enter the interpreter loop starting at the current pc.
    1907       10427 :     ADVANCE_AND_DISPATCH(0);
    1908             : 
    1909             : INTERPRETER_LOOP() {
    1910             : 
    1911             : CASE(EnableInterruptsPseudoOpcode)
    1912             : {
    1913         473 :     bool moreInterrupts = false;
    1914         473 :     jsbytecode op = *REGS.pc;
    1915             : 
    1916         473 :     if (!script->hasScriptCounts() && cx->compartment()->collectCoverageForDebug()) {
    1917           0 :         if (!script->initScriptCounts(cx))
    1918           0 :             goto error;
    1919             :     }
    1920             : 
    1921         473 :     if (script->isDebuggee()) {
    1922           0 :         if (script->stepModeEnabled()) {
    1923           0 :             RootedValue rval(cx);
    1924           0 :             JSTrapStatus status = JSTRAP_CONTINUE;
    1925           0 :             status = Debugger::onSingleStep(cx, &rval);
    1926           0 :             switch (status) {
    1927             :               case JSTRAP_ERROR:
    1928           0 :                 goto error;
    1929             :               case JSTRAP_CONTINUE:
    1930           0 :                 break;
    1931             :               case JSTRAP_RETURN:
    1932           0 :                 REGS.fp()->setReturnValue(rval);
    1933           0 :                 if (!ForcedReturn(cx, REGS))
    1934           0 :                     goto error;
    1935           0 :                 goto successful_return_continuation;
    1936             :               case JSTRAP_THROW:
    1937           0 :                 cx->setPendingException(rval);
    1938           0 :                 goto error;
    1939             :               default:;
    1940             :             }
    1941           0 :             moreInterrupts = true;
    1942             :         }
    1943             : 
    1944           0 :         if (script->hasAnyBreakpointsOrStepMode())
    1945           0 :             moreInterrupts = true;
    1946             : 
    1947           0 :         if (script->hasBreakpointsAt(REGS.pc)) {
    1948           0 :             RootedValue rval(cx);
    1949           0 :             JSTrapStatus status = Debugger::onTrap(cx, &rval);
    1950           0 :             switch (status) {
    1951             :               case JSTRAP_ERROR:
    1952           0 :                 goto error;
    1953             :               case JSTRAP_RETURN:
    1954           0 :                 REGS.fp()->setReturnValue(rval);
    1955           0 :                 if (!ForcedReturn(cx, REGS))
    1956           0 :                     goto error;
    1957           0 :                 goto successful_return_continuation;
    1958             :               case JSTRAP_THROW:
    1959           0 :                 cx->setPendingException(rval);
    1960           0 :                 goto error;
    1961             :               default:
    1962           0 :                 break;
    1963             :             }
    1964           0 :             MOZ_ASSERT(status == JSTRAP_CONTINUE);
    1965           0 :             MOZ_ASSERT(rval.isInt32() && rval.toInt32() == op);
    1966             :         }
    1967             :     }
    1968             : 
    1969         473 :     MOZ_ASSERT(activation.opMask() == EnableInterruptsPseudoOpcode);
    1970         473 :     if (!moreInterrupts)
    1971         473 :         activation.clearInterruptsMask();
    1972             : 
    1973             :     /* Commence executing the actual opcode. */
    1974         473 :     SANITY_CHECKS();
    1975         473 :     DISPATCH_TO(op);
    1976             : }
    1977             : 
    1978             : /* Various 1-byte no-ops. */
    1979             : CASE(JSOP_NOP)
    1980             : CASE(JSOP_NOP_DESTRUCTURING)
    1981             : CASE(JSOP_TRY_DESTRUCTURING_ITERCLOSE)
    1982             : CASE(JSOP_UNUSED222)
    1983             : CASE(JSOP_UNUSED223)
    1984             : CASE(JSOP_CONDSWITCH)
    1985             : {
    1986        1373 :     MOZ_ASSERT(CodeSpec[*REGS.pc].length == 1);
    1987        1373 :     ADVANCE_AND_DISPATCH(1);
    1988             : }
    1989             : 
    1990             : CASE(JSOP_TRY)
    1991             : CASE(JSOP_JUMPTARGET)
    1992             : CASE(JSOP_LOOPHEAD)
    1993             : {
    1994       34423 :     MOZ_ASSERT(CodeSpec[*REGS.pc].length == 1);
    1995       34423 :     COUNT_COVERAGE();
    1996       34423 :     ADVANCE_AND_DISPATCH(1);
    1997             : }
    1998             : 
    1999             : CASE(JSOP_LABEL)
    2000           0 : END_CASE(JSOP_LABEL)
    2001             : 
    2002             : CASE(JSOP_LOOPENTRY)
    2003        2152 :     COUNT_COVERAGE();
    2004             :     // Attempt on-stack replacement with Baseline code.
    2005        2152 :     if (jit::IsBaselineEnabled(cx)) {
    2006        2152 :         jit::MethodStatus status = jit::CanEnterBaselineAtBranch(cx, REGS.fp(), false);
    2007        2152 :         if (status == jit::Method_Error)
    2008           0 :             goto error;
    2009        2152 :         if (status == jit::Method_Compiled) {
    2010         141 :             bool wasProfiler = REGS.fp()->hasPushedGeckoProfilerFrame();
    2011             : 
    2012             :             jit::JitExecStatus maybeOsr;
    2013             :             {
    2014         282 :                 GeckoProfilerBaselineOSRMarker osr(cx->runtime(), wasProfiler);
    2015         141 :                 maybeOsr = jit::EnterBaselineAtBranch(cx, REGS.fp(), REGS.pc);
    2016             :             }
    2017             : 
    2018             :             // We failed to call into baseline at all, so treat as an error.
    2019         141 :             if (maybeOsr == jit::JitExec_Aborted)
    2020           0 :                 goto error;
    2021             : 
    2022         141 :             interpReturnOK = (maybeOsr == jit::JitExec_Ok);
    2023             : 
    2024             :             // Pop the profiler frame pushed by the interpreter.  (The compiled
    2025             :             // version of the function popped a copy of the frame pushed by the
    2026             :             // OSR trampoline.)
    2027         141 :             if (wasProfiler)
    2028           0 :                 cx->runtime()->geckoProfiler().exit(script, script->functionNonDelazifying());
    2029             : 
    2030         141 :             if (activation.entryFrame() != REGS.fp())
    2031          47 :                 goto jit_return_pop_frame;
    2032          94 :             goto leave_on_safe_point;
    2033             :         }
    2034             :     }
    2035        2011 : END_CASE(JSOP_LOOPENTRY)
    2036             : 
    2037             : CASE(JSOP_LINENO)
    2038           2 : END_CASE(JSOP_LINENO)
    2039             : 
    2040             : CASE(JSOP_FORCEINTERPRETER)
    2041          76 : END_CASE(JSOP_FORCEINTERPRETER)
    2042             : 
    2043             : CASE(JSOP_UNDEFINED)
    2044             :     // If this ever changes, change what JSOP_GIMPLICITTHIS does too.
    2045       17324 :     PUSH_UNDEFINED();
    2046       17324 : END_CASE(JSOP_UNDEFINED)
    2047             : 
    2048             : CASE(JSOP_POP)
    2049       51597 :     REGS.sp--;
    2050       51597 : END_CASE(JSOP_POP)
    2051             : 
    2052             : CASE(JSOP_POPN)
    2053           0 :     MOZ_ASSERT(GET_UINT16(REGS.pc) <= REGS.stackDepth());
    2054           0 :     REGS.sp -= GET_UINT16(REGS.pc);
    2055           0 : END_CASE(JSOP_POPN)
    2056             : 
    2057             : CASE(JSOP_DUPAT)
    2058             : {
    2059        1022 :     MOZ_ASSERT(GET_UINT24(REGS.pc) < REGS.stackDepth());
    2060        1022 :     unsigned i = GET_UINT24(REGS.pc);
    2061        1022 :     const Value& rref = REGS.sp[-int(i + 1)];
    2062        1022 :     PUSH_COPY(rref);
    2063             : }
    2064        1022 : END_CASE(JSOP_DUPAT)
    2065             : 
    2066             : CASE(JSOP_SETRVAL)
    2067        1691 :     POP_RETURN_VALUE();
    2068        1691 : END_CASE(JSOP_SETRVAL)
    2069             : 
    2070             : CASE(JSOP_GETRVAL)
    2071          23 :     PUSH_COPY(REGS.fp()->returnValue());
    2072          23 : END_CASE(JSOP_GETRVAL)
    2073             : 
    2074             : CASE(JSOP_ENTERWITH)
    2075             : {
    2076           0 :     ReservedRooted<Value> val(&rootValue0, REGS.sp[-1]);
    2077           0 :     REGS.sp--;
    2078           0 :     ReservedRooted<Scope*> scope(&rootScope0, script->getScope(REGS.pc));
    2079             : 
    2080           0 :     if (!EnterWithOperation(cx, REGS.fp(), val, scope.as<WithScope>()))
    2081           0 :         goto error;
    2082             : }
    2083           0 : END_CASE(JSOP_ENTERWITH)
    2084             : 
    2085             : CASE(JSOP_LEAVEWITH)
    2086           0 :     REGS.fp()->popOffEnvironmentChain<WithEnvironmentObject>();
    2087           0 : END_CASE(JSOP_LEAVEWITH)
    2088             : 
    2089             : CASE(JSOP_RETURN)
    2090        7572 :     POP_RETURN_VALUE();
    2091             :     /* FALL THROUGH */
    2092             : 
    2093             : CASE(JSOP_RETRVAL)
    2094             : {
    2095             :     /*
    2096             :      * When the inlined frame exits with an exception or an error, ok will be
    2097             :      * false after the inline_return label.
    2098             :      */
    2099       11886 :     CHECK_BRANCH();
    2100             : 
    2101             :   successful_return_continuation:
    2102       12135 :     interpReturnOK = true;
    2103             : 
    2104             :   return_continuation:
    2105       12147 :     frameHalfInitialized = false;
    2106             : 
    2107             :   prologue_return_continuation:
    2108             : 
    2109       12147 :     if (activation.entryFrame() != REGS.fp()) {
    2110             :         // Stop the engine. (No details about which engine exactly, could be
    2111             :         // interpreter, Baseline or IonMonkey.)
    2112        1822 :         TraceLogStopEvent(logger, TraceLogger_Engine);
    2113        1822 :         TraceLogStopEvent(logger, TraceLogger_Scripts);
    2114             : 
    2115        1822 :         if (MOZ_LIKELY(!frameHalfInitialized)) {
    2116        1822 :             interpReturnOK = Debugger::onLeaveFrame(cx, REGS.fp(), REGS.pc, interpReturnOK);
    2117             : 
    2118        1822 :             REGS.fp()->epilogue(cx, REGS.pc);
    2119             :         }
    2120             : 
    2121             :   jit_return_pop_frame:
    2122             : 
    2123        1869 :         activation.popInlineFrame(REGS.fp());
    2124        1869 :         SET_SCRIPT(REGS.fp()->script());
    2125             : 
    2126             :   jit_return:
    2127             : 
    2128        2441 :         MOZ_ASSERT(CodeSpec[*REGS.pc].format & JOF_INVOKE);
    2129             : 
    2130             :         /* Resume execution in the calling frame. */
    2131        2441 :         if (MOZ_LIKELY(interpReturnOK)) {
    2132        2440 :             TypeScript::Monitor(cx, script, REGS.pc, REGS.sp[-1]);
    2133             : 
    2134        2440 :             ADVANCE_AND_DISPATCH(JSOP_CALL_LENGTH);
    2135             :         }
    2136             : 
    2137           1 :         goto error;
    2138             :     } else {
    2139       10325 :         MOZ_ASSERT(REGS.stackDepth() == 0);
    2140             :     }
    2141       10325 :     goto exit;
    2142             : }
    2143             : 
    2144             : CASE(JSOP_DEFAULT)
    2145          15 :     REGS.sp--;
    2146             :     /* FALL THROUGH */
    2147             : CASE(JSOP_GOTO)
    2148             : {
    2149        3333 :     BRANCH(GET_JUMP_OFFSET(REGS.pc));
    2150             : }
    2151             : 
    2152             : CASE(JSOP_IFEQ)
    2153             : {
    2154       16556 :     bool cond = ToBoolean(REGS.stackHandleAt(-1));
    2155       16556 :     REGS.sp--;
    2156       16556 :     if (!cond)
    2157       11931 :         BRANCH(GET_JUMP_OFFSET(REGS.pc));
    2158             : }
    2159        4625 : END_CASE(JSOP_IFEQ)
    2160             : 
    2161             : CASE(JSOP_IFNE)
    2162             : {
    2163         132 :     bool cond = ToBoolean(REGS.stackHandleAt(-1));
    2164         132 :     REGS.sp--;
    2165         132 :     if (cond)
    2166          94 :         BRANCH(GET_JUMP_OFFSET(REGS.pc));
    2167             : }
    2168          38 : END_CASE(JSOP_IFNE)
    2169             : 
    2170             : CASE(JSOP_OR)
    2171             : {
    2172        2594 :     bool cond = ToBoolean(REGS.stackHandleAt(-1));
    2173        2594 :     if (cond)
    2174         588 :         ADVANCE_AND_DISPATCH(GET_JUMP_OFFSET(REGS.pc));
    2175             : }
    2176        2006 : END_CASE(JSOP_OR)
    2177             : 
    2178             : CASE(JSOP_AND)
    2179             : {
    2180        1580 :     bool cond = ToBoolean(REGS.stackHandleAt(-1));
    2181        1580 :     if (!cond)
    2182         545 :         ADVANCE_AND_DISPATCH(GET_JUMP_OFFSET(REGS.pc));
    2183             : }
    2184        1035 : END_CASE(JSOP_AND)
    2185             : 
    2186             : #define FETCH_ELEMENT_ID(n, id)                                               \
    2187             :     JS_BEGIN_MACRO                                                            \
    2188             :         if (!ToPropertyKey(cx, REGS.stackHandleAt(n), &(id)))                 \
    2189             :             goto error;                                                       \
    2190             :     JS_END_MACRO
    2191             : 
    2192             : #define TRY_BRANCH_AFTER_COND(cond,spdec)                                     \
    2193             :     JS_BEGIN_MACRO                                                            \
    2194             :         MOZ_ASSERT(CodeSpec[*REGS.pc].length == 1);                           \
    2195             :         unsigned diff_ = (unsigned) GET_UINT8(REGS.pc) - (unsigned) JSOP_IFEQ; \
    2196             :         if (diff_ <= 1) {                                                     \
    2197             :             REGS.sp -= (spdec);                                               \
    2198             :             if ((cond) == (diff_ != 0)) {                                     \
    2199             :                 ++REGS.pc;                                                    \
    2200             :                 BRANCH(GET_JUMP_OFFSET(REGS.pc));                             \
    2201             :             }                                                                 \
    2202             :             ADVANCE_AND_DISPATCH(1 + JSOP_IFEQ_LENGTH);                       \
    2203             :         }                                                                     \
    2204             :     JS_END_MACRO
    2205             : 
    2206             : CASE(JSOP_IN)
    2207             : {
    2208         680 :     HandleValue rref = REGS.stackHandleAt(-1);
    2209         680 :     if (!rref.isObject()) {
    2210           0 :         ReportValueError(cx, JSMSG_IN_NOT_OBJECT, -1, rref, nullptr);
    2211           0 :         goto error;
    2212             :     }
    2213             :     bool found;
    2214             :     {
    2215        1360 :         ReservedRooted<JSObject*> obj(&rootObject0, &rref.toObject());
    2216        1360 :         ReservedRooted<jsid> id(&rootId0);
    2217         680 :         FETCH_ELEMENT_ID(-2, id);
    2218         680 :         if (!HasProperty(cx, obj, id, &found))
    2219           0 :             goto error;
    2220             :     }
    2221         680 :     TRY_BRANCH_AFTER_COND(found, 2);
    2222         247 :     REGS.sp--;
    2223         247 :     REGS.sp[-1].setBoolean(found);
    2224             : }
    2225         247 : END_CASE(JSOP_IN)
    2226             : 
    2227             : CASE(JSOP_HASOWN)
    2228             : {
    2229          28 :     HandleValue val = REGS.stackHandleAt(-1);
    2230          28 :     HandleValue idval = REGS.stackHandleAt(-2);
    2231             : 
    2232             :     bool found;
    2233          28 :     if (!HasOwnProperty(cx, val, idval, &found))
    2234           0 :         goto error;
    2235             : 
    2236          28 :     REGS.sp--;
    2237          28 :     REGS.sp[-1].setBoolean(found);
    2238             : }
    2239          28 : END_CASE(JSOP_HASOWN)
    2240             : 
    2241             : CASE(JSOP_ITER)
    2242             : {
    2243          39 :     MOZ_ASSERT(REGS.stackDepth() >= 1);
    2244          39 :     uint8_t flags = GET_UINT8(REGS.pc);
    2245          39 :     HandleValue val = REGS.stackHandleAt(-1);
    2246          78 :     ReservedRooted<JSObject*> iter(&rootObject0);
    2247          39 :     iter.set(ValueToIterator(cx, flags, val));
    2248          39 :     if (!iter)
    2249           0 :         goto error;
    2250          39 :     REGS.sp[-1].setObject(*iter);
    2251             : }
    2252          39 : END_CASE(JSOP_ITER)
    2253             : 
    2254             : CASE(JSOP_MOREITER)
    2255             : {
    2256         166 :     MOZ_ASSERT(REGS.stackDepth() >= 1);
    2257         166 :     MOZ_ASSERT(REGS.sp[-1].isObject());
    2258         166 :     PUSH_NULL();
    2259         332 :     ReservedRooted<JSObject*> obj(&rootObject0, &REGS.sp[-2].toObject());
    2260         166 :     if (!IteratorMore(cx, obj, REGS.stackHandleAt(-1)))
    2261           0 :         goto error;
    2262             : }
    2263         166 : END_CASE(JSOP_MOREITER)
    2264             : 
    2265             : CASE(JSOP_ISNOITER)
    2266             : {
    2267         166 :     bool b = REGS.sp[-1].isMagic(JS_NO_ITER_VALUE);
    2268         166 :     PUSH_BOOLEAN(b);
    2269             : }
    2270         166 : END_CASE(JSOP_ISNOITER)
    2271             : 
    2272             : CASE(JSOP_ENDITER)
    2273             : {
    2274          26 :     MOZ_ASSERT(REGS.stackDepth() >= 1);
    2275          26 :     COUNT_COVERAGE();
    2276          52 :     ReservedRooted<JSObject*> obj(&rootObject0, &REGS.sp[-1].toObject());
    2277          26 :     bool ok = CloseIterator(cx, obj);
    2278          26 :     REGS.sp--;
    2279          26 :     if (!ok)
    2280           0 :         goto error;
    2281             : }
    2282          26 : END_CASE(JSOP_ENDITER)
    2283             : 
    2284             : CASE(JSOP_ISGENCLOSING)
    2285             : {
    2286           0 :     bool b = REGS.sp[-1].isMagic(JS_GENERATOR_CLOSING);
    2287           0 :     PUSH_BOOLEAN(b);
    2288             : }
    2289           0 : END_CASE(JSOP_ISGENCLOSING)
    2290             : 
    2291             : CASE(JSOP_DUP)
    2292             : {
    2293       20410 :     MOZ_ASSERT(REGS.stackDepth() >= 1);
    2294       20410 :     const Value& rref = REGS.sp[-1];
    2295       20410 :     PUSH_COPY(rref);
    2296             : }
    2297       20410 : END_CASE(JSOP_DUP)
    2298             : 
    2299             : CASE(JSOP_DUP2)
    2300             : {
    2301          70 :     MOZ_ASSERT(REGS.stackDepth() >= 2);
    2302          70 :     const Value& lref = REGS.sp[-2];
    2303          70 :     const Value& rref = REGS.sp[-1];
    2304          70 :     PUSH_COPY(lref);
    2305          70 :     PUSH_COPY(rref);
    2306             : }
    2307          70 : END_CASE(JSOP_DUP2)
    2308             : 
    2309             : CASE(JSOP_SWAP)
    2310             : {
    2311       14737 :     MOZ_ASSERT(REGS.stackDepth() >= 2);
    2312       14737 :     Value& lref = REGS.sp[-2];
    2313       14737 :     Value& rref = REGS.sp[-1];
    2314       14737 :     lref.swap(rref);
    2315             : }
    2316       14737 : END_CASE(JSOP_SWAP)
    2317             : 
    2318             : CASE(JSOP_PICK)
    2319             : {
    2320         269 :     unsigned i = GET_UINT8(REGS.pc);
    2321         269 :     MOZ_ASSERT(REGS.stackDepth() >= i + 1);
    2322         269 :     Value lval = REGS.sp[-int(i + 1)];
    2323         269 :     memmove(REGS.sp - (i + 1), REGS.sp - i, sizeof(Value) * i);
    2324         269 :     REGS.sp[-1] = lval;
    2325             : }
    2326         269 : END_CASE(JSOP_PICK)
    2327             : 
    2328             : CASE(JSOP_UNPICK)
    2329             : {
    2330         444 :     int i = GET_UINT8(REGS.pc);
    2331         444 :     MOZ_ASSERT(REGS.stackDepth() >= unsigned(i) + 1);
    2332         444 :     Value lval = REGS.sp[-1];
    2333         444 :     memmove(REGS.sp - i, REGS.sp - (i + 1), sizeof(Value) * i);
    2334         444 :     REGS.sp[-(i + 1)] = lval;
    2335             : }
    2336         444 : END_CASE(JSOP_UNPICK)
    2337             : 
    2338             : CASE(JSOP_BINDGNAME)
    2339             : CASE(JSOP_BINDNAME)
    2340             : {
    2341         847 :     JSOp op = JSOp(*REGS.pc);
    2342        1694 :     ReservedRooted<JSObject*> envChain(&rootObject0);
    2343         847 :     if (op == JSOP_BINDNAME || script->hasNonSyntacticScope())
    2344         156 :         envChain.set(REGS.fp()->environmentChain());
    2345             :     else
    2346         691 :         envChain.set(&REGS.fp()->global().lexicalEnvironment());
    2347        1694 :     ReservedRooted<PropertyName*> name(&rootName0, script->getName(REGS.pc));
    2348             : 
    2349             :     /* Assigning to an undeclared name adds a property to the global object. */
    2350        1694 :     ReservedRooted<JSObject*> env(&rootObject1);
    2351         847 :     if (!LookupNameUnqualified(cx, name, envChain, &env))
    2352           0 :         goto error;
    2353             : 
    2354         847 :     PUSH_OBJECT(*env);
    2355             : 
    2356             :     static_assert(JSOP_BINDNAME_LENGTH == JSOP_BINDGNAME_LENGTH,
    2357             :                   "We're sharing the END_CASE so the lengths better match");
    2358             : }
    2359         847 : END_CASE(JSOP_BINDNAME)
    2360             : 
    2361             : CASE(JSOP_BINDVAR)
    2362             : {
    2363           0 :     PUSH_OBJECT(REGS.fp()->varObj());
    2364             : }
    2365           0 : END_CASE(JSOP_BINDVAR)
    2366             : 
    2367             : #define BITWISE_OP(OP)                                                        \
    2368             :     JS_BEGIN_MACRO                                                            \
    2369             :         int32_t i, j;                                                         \
    2370             :         if (!ToInt32(cx, REGS.stackHandleAt(-2), &i))                         \
    2371             :             goto error;                                                       \
    2372             :         if (!ToInt32(cx, REGS.stackHandleAt(-1), &j))                         \
    2373             :             goto error;                                                       \
    2374             :         i = i OP j;                                                           \
    2375             :         REGS.sp--;                                                            \
    2376             :         REGS.sp[-1].setInt32(i);                                              \
    2377             :     JS_END_MACRO
    2378             : 
    2379             : CASE(JSOP_BITOR)
    2380         426 :     BITWISE_OP(|);
    2381         426 : END_CASE(JSOP_BITOR)
    2382             : 
    2383             : CASE(JSOP_BITXOR)
    2384           0 :     BITWISE_OP(^);
    2385           0 : END_CASE(JSOP_BITXOR)
    2386             : 
    2387             : CASE(JSOP_BITAND)
    2388         256 :     BITWISE_OP(&);
    2389         256 : END_CASE(JSOP_BITAND)
    2390             : 
    2391             : #undef BITWISE_OP
    2392             : 
    2393             : CASE(JSOP_EQ)
    2394        1094 :     if (!LooseEqualityOp<true>(cx, REGS))
    2395           0 :         goto error;
    2396        1094 : END_CASE(JSOP_EQ)
    2397             : 
    2398             : CASE(JSOP_NE)
    2399         678 :     if (!LooseEqualityOp<false>(cx, REGS))
    2400           0 :         goto error;
    2401         678 : END_CASE(JSOP_NE)
    2402             : 
    2403             : #define STRICT_EQUALITY_OP(OP, COND)                                          \
    2404             :     JS_BEGIN_MACRO                                                            \
    2405             :         HandleValue lval = REGS.stackHandleAt(-2);                            \
    2406             :         HandleValue rval = REGS.stackHandleAt(-1);                            \
    2407             :         bool equal;                                                           \
    2408             :         if (!StrictlyEqual(cx, lval, rval, &equal))                           \
    2409             :             goto error;                                                       \
    2410             :         (COND) = equal OP true;                                               \
    2411             :         REGS.sp--;                                                            \
    2412             :     JS_END_MACRO
    2413             : 
    2414             : CASE(JSOP_STRICTEQ)
    2415             : {
    2416             :     bool cond;
    2417        3924 :     STRICT_EQUALITY_OP(==, cond);
    2418        3924 :     REGS.sp[-1].setBoolean(cond);
    2419             : }
    2420        3924 : END_CASE(JSOP_STRICTEQ)
    2421             : 
    2422             : CASE(JSOP_STRICTNE)
    2423             : {
    2424             :     bool cond;
    2425         481 :     STRICT_EQUALITY_OP(!=, cond);
    2426         481 :     REGS.sp[-1].setBoolean(cond);
    2427             : }
    2428         481 : END_CASE(JSOP_STRICTNE)
    2429             : 
    2430             : CASE(JSOP_CASE)
    2431             : {
    2432             :     bool cond;
    2433         519 :     STRICT_EQUALITY_OP(==, cond);
    2434         519 :     if (cond) {
    2435         154 :         REGS.sp--;
    2436         154 :         BRANCH(GET_JUMP_OFFSET(REGS.pc));
    2437             :     }
    2438             : }
    2439         365 : END_CASE(JSOP_CASE)
    2440             : 
    2441             : #undef STRICT_EQUALITY_OP
    2442             : 
    2443             : CASE(JSOP_LT)
    2444             : {
    2445             :     bool cond;
    2446         846 :     MutableHandleValue lval = REGS.stackHandleAt(-2);
    2447         846 :     MutableHandleValue rval = REGS.stackHandleAt(-1);
    2448         846 :     if (!LessThanOperation(cx, lval, rval, &cond))
    2449           0 :         goto error;
    2450         846 :     TRY_BRANCH_AFTER_COND(cond, 2);
    2451          26 :     REGS.sp[-2].setBoolean(cond);
    2452          26 :     REGS.sp--;
    2453             : }
    2454          26 : END_CASE(JSOP_LT)
    2455             : 
    2456             : CASE(JSOP_LE)
    2457             : {
    2458             :     bool cond;
    2459          83 :     MutableHandleValue lval = REGS.stackHandleAt(-2);
    2460          83 :     MutableHandleValue rval = REGS.stackHandleAt(-1);
    2461          83 :     if (!LessThanOrEqualOperation(cx, lval, rval, &cond))
    2462           0 :         goto error;
    2463          83 :     TRY_BRANCH_AFTER_COND(cond, 2);
    2464          24 :     REGS.sp[-2].setBoolean(cond);
    2465          24 :     REGS.sp--;
    2466             : }
    2467          24 : END_CASE(JSOP_LE)
    2468             : 
    2469             : CASE(JSOP_GT)
    2470             : {
    2471             :     bool cond;
    2472         300 :     MutableHandleValue lval = REGS.stackHandleAt(-2);
    2473         300 :     MutableHandleValue rval = REGS.stackHandleAt(-1);
    2474         300 :     if (!GreaterThanOperation(cx, lval, rval, &cond))
    2475           0 :         goto error;
    2476         300 :     TRY_BRANCH_AFTER_COND(cond, 2);
    2477          54 :     REGS.sp[-2].setBoolean(cond);
    2478          54 :     REGS.sp--;
    2479             : }
    2480          54 : END_CASE(JSOP_GT)
    2481             : 
    2482             : CASE(JSOP_GE)
    2483             : {
    2484             :     bool cond;
    2485         779 :     MutableHandleValue lval = REGS.stackHandleAt(-2);
    2486         779 :     MutableHandleValue rval = REGS.stackHandleAt(-1);
    2487         779 :     if (!GreaterThanOrEqualOperation(cx, lval, rval, &cond))
    2488           0 :         goto error;
    2489         779 :     TRY_BRANCH_AFTER_COND(cond, 2);
    2490         120 :     REGS.sp[-2].setBoolean(cond);
    2491         120 :     REGS.sp--;
    2492             : }
    2493         120 : END_CASE(JSOP_GE)
    2494             : 
    2495             : #define SIGNED_SHIFT_OP(OP)                                                   \
    2496             :     JS_BEGIN_MACRO                                                            \
    2497             :         int32_t i, j;                                                         \
    2498             :         if (!ToInt32(cx, REGS.stackHandleAt(-2), &i))                         \
    2499             :             goto error;                                                       \
    2500             :         if (!ToInt32(cx, REGS.stackHandleAt(-1), &j))                         \
    2501             :             goto error;                                                       \
    2502             :         i = i OP (j & 31);                                                    \
    2503             :         REGS.sp--;                                                            \
    2504             :         REGS.sp[-1].setInt32(i);                                              \
    2505             :     JS_END_MACRO
    2506             : 
    2507             : CASE(JSOP_LSH)
    2508           0 :     SIGNED_SHIFT_OP(<<);
    2509           0 : END_CASE(JSOP_LSH)
    2510             : 
    2511             : CASE(JSOP_RSH)
    2512           3 :     SIGNED_SHIFT_OP(>>);
    2513           3 : END_CASE(JSOP_RSH)
    2514             : 
    2515             : #undef SIGNED_SHIFT_OP
    2516             : 
    2517             : CASE(JSOP_URSH)
    2518             : {
    2519           1 :     HandleValue lval = REGS.stackHandleAt(-2);
    2520           1 :     HandleValue rval = REGS.stackHandleAt(-1);
    2521           1 :     MutableHandleValue res = REGS.stackHandleAt(-2);
    2522           1 :     if (!UrshOperation(cx, lval, rval, res))
    2523           0 :         goto error;
    2524           1 :     REGS.sp--;
    2525             : }
    2526           1 : END_CASE(JSOP_URSH)
    2527             : 
    2528             : CASE(JSOP_ADD)
    2529             : {
    2530        2105 :     MutableHandleValue lval = REGS.stackHandleAt(-2);
    2531        2105 :     MutableHandleValue rval = REGS.stackHandleAt(-1);
    2532        2105 :     MutableHandleValue res = REGS.stackHandleAt(-2);
    2533        2105 :     if (!AddOperation(cx, lval, rval, res))
    2534           0 :         goto error;
    2535        2105 :     REGS.sp--;
    2536             : }
    2537        2105 : END_CASE(JSOP_ADD)
    2538             : 
    2539             : CASE(JSOP_SUB)
    2540             : {
    2541         438 :     ReservedRooted<Value> lval(&rootValue0, REGS.sp[-2]);
    2542         438 :     ReservedRooted<Value> rval(&rootValue1, REGS.sp[-1]);
    2543         219 :     MutableHandleValue res = REGS.stackHandleAt(-2);
    2544         219 :     if (!SubOperation(cx, lval, rval, res))
    2545           0 :         goto error;
    2546         219 :     REGS.sp--;
    2547             : }
    2548         219 : END_CASE(JSOP_SUB)
    2549             : 
    2550             : CASE(JSOP_MUL)
    2551             : {
    2552         132 :     ReservedRooted<Value> lval(&rootValue0, REGS.sp[-2]);
    2553         132 :     ReservedRooted<Value> rval(&rootValue1, REGS.sp[-1]);
    2554          66 :     MutableHandleValue res = REGS.stackHandleAt(-2);
    2555          66 :     if (!MulOperation(cx, lval, rval, res))
    2556           0 :         goto error;
    2557          66 :     REGS.sp--;
    2558             : }
    2559          66 : END_CASE(JSOP_MUL)
    2560             : 
    2561             : CASE(JSOP_DIV)
    2562             : {
    2563          82 :     ReservedRooted<Value> lval(&rootValue0, REGS.sp[-2]);
    2564          82 :     ReservedRooted<Value> rval(&rootValue1, REGS.sp[-1]);
    2565          41 :     MutableHandleValue res = REGS.stackHandleAt(-2);
    2566          41 :     if (!DivOperation(cx, lval, rval, res))
    2567           0 :         goto error;
    2568          41 :     REGS.sp--;
    2569             : }
    2570          41 : END_CASE(JSOP_DIV)
    2571             : 
    2572             : CASE(JSOP_MOD)
    2573             : {
    2574           2 :     ReservedRooted<Value> lval(&rootValue0, REGS.sp[-2]);
    2575           2 :     ReservedRooted<Value> rval(&rootValue1, REGS.sp[-1]);
    2576           1 :     MutableHandleValue res = REGS.stackHandleAt(-2);
    2577           1 :     if (!ModOperation(cx, lval, rval, res))
    2578           0 :         goto error;
    2579           1 :     REGS.sp--;
    2580             : }
    2581           1 : END_CASE(JSOP_MOD)
    2582             : 
    2583             : CASE(JSOP_POW)
    2584             : {
    2585           0 :     ReservedRooted<Value> lval(&rootValue0, REGS.sp[-2]);
    2586           0 :     ReservedRooted<Value> rval(&rootValue1, REGS.sp[-1]);
    2587           0 :     MutableHandleValue res = REGS.stackHandleAt(-2);
    2588           0 :     if (!math_pow_handle(cx, lval, rval, res))
    2589           0 :         goto error;
    2590           0 :     REGS.sp--;
    2591             : }
    2592           0 : END_CASE(JSOP_POW)
    2593             : 
    2594             : CASE(JSOP_NOT)
    2595             : {
    2596        6035 :     bool cond = ToBoolean(REGS.stackHandleAt(-1));
    2597        6035 :     REGS.sp--;
    2598        6035 :     PUSH_BOOLEAN(!cond);
    2599             : }
    2600        6035 : END_CASE(JSOP_NOT)
    2601             : 
    2602             : CASE(JSOP_BITNOT)
    2603             : {
    2604             :     int32_t i;
    2605           3 :     HandleValue value = REGS.stackHandleAt(-1);
    2606           3 :     if (!BitNot(cx, value, &i))
    2607           0 :         goto error;
    2608           3 :     REGS.sp[-1].setInt32(i);
    2609             : }
    2610           3 : END_CASE(JSOP_BITNOT)
    2611             : 
    2612             : CASE(JSOP_NEG)
    2613             : {
    2614           0 :     ReservedRooted<Value> val(&rootValue0, REGS.sp[-1]);
    2615           0 :     MutableHandleValue res = REGS.stackHandleAt(-1);
    2616           0 :     if (!NegOperation(cx, script, REGS.pc, val, res))
    2617           0 :         goto error;
    2618             : }
    2619           0 : END_CASE(JSOP_NEG)
    2620             : 
    2621             : CASE(JSOP_POS)
    2622         693 :     if (!ToNumber(cx, REGS.stackHandleAt(-1)))
    2623           0 :         goto error;
    2624         693 : END_CASE(JSOP_POS)
    2625             : 
    2626             : CASE(JSOP_DELNAME)
    2627             : {
    2628           0 :     ReservedRooted<PropertyName*> name(&rootName0, script->getName(REGS.pc));
    2629           0 :     ReservedRooted<JSObject*> envObj(&rootObject0, REGS.fp()->environmentChain());
    2630             : 
    2631           0 :     PUSH_BOOLEAN(true);
    2632           0 :     MutableHandleValue res = REGS.stackHandleAt(-1);
    2633           0 :     if (!DeleteNameOperation(cx, name, envObj, res))
    2634           0 :         goto error;
    2635             : }
    2636           0 : END_CASE(JSOP_DELNAME)
    2637             : 
    2638             : CASE(JSOP_DELPROP)
    2639             : CASE(JSOP_STRICTDELPROP)
    2640             : {
    2641             :     static_assert(JSOP_DELPROP_LENGTH == JSOP_STRICTDELPROP_LENGTH,
    2642             :                   "delprop and strictdelprop must be the same size");
    2643         132 :     ReservedRooted<jsid> id(&rootId0, NameToId(script->getName(REGS.pc)));
    2644         132 :     ReservedRooted<JSObject*> obj(&rootObject0);
    2645          66 :     FETCH_OBJECT(cx, -1, obj);
    2646             : 
    2647          66 :     ObjectOpResult result;
    2648          66 :     if (!DeleteProperty(cx, obj, id, result))
    2649           0 :         goto error;
    2650          66 :     if (!result && JSOp(*REGS.pc) == JSOP_STRICTDELPROP) {
    2651           0 :         result.reportError(cx, obj, id);
    2652           0 :         goto error;
    2653             :     }
    2654          66 :     MutableHandleValue res = REGS.stackHandleAt(-1);
    2655          66 :     res.setBoolean(result.ok());
    2656             : }
    2657          66 : END_CASE(JSOP_DELPROP)
    2658             : 
    2659             : CASE(JSOP_DELELEM)
    2660             : CASE(JSOP_STRICTDELELEM)
    2661             : {
    2662             :     static_assert(JSOP_DELELEM_LENGTH == JSOP_STRICTDELELEM_LENGTH,
    2663             :                   "delelem and strictdelelem must be the same size");
    2664             :     /* Fetch the left part and resolve it to a non-null object. */
    2665         120 :     ReservedRooted<JSObject*> obj(&rootObject0);
    2666          60 :     FETCH_OBJECT(cx, -2, obj);
    2667             : 
    2668         120 :     ReservedRooted<Value> propval(&rootValue0, REGS.sp[-1]);
    2669             : 
    2670          60 :     ObjectOpResult result;
    2671         120 :     ReservedRooted<jsid> id(&rootId0);
    2672          60 :     if (!ToPropertyKey(cx, propval, &id))
    2673           0 :         goto error;
    2674          60 :     if (!DeleteProperty(cx, obj, id, result))
    2675           0 :         goto error;
    2676          60 :     if (!result && JSOp(*REGS.pc) == JSOP_STRICTDELELEM) {
    2677           0 :         result.reportError(cx, obj, id);
    2678           0 :         goto error;
    2679             :     }
    2680             : 
    2681          60 :     MutableHandleValue res = REGS.stackHandleAt(-2);
    2682          60 :     res.setBoolean(result.ok());
    2683          60 :     REGS.sp--;
    2684             : }
    2685          60 : END_CASE(JSOP_DELELEM)
    2686             : 
    2687             : CASE(JSOP_TOID)
    2688             : {
    2689             :     /*
    2690             :      * Increment or decrement requires use to lookup the same property twice,
    2691             :      * but we need to avoid the observable stringification the second time.
    2692             :      * There must be an object value below the id, which will not be popped.
    2693             :      */
    2694          40 :     ReservedRooted<Value> idval(&rootValue1, REGS.sp[-1]);
    2695          20 :     MutableHandleValue res = REGS.stackHandleAt(-1);
    2696          20 :     if (!ToIdOperation(cx, script, REGS.pc, idval, res))
    2697           0 :         goto error;
    2698             : }
    2699          20 : END_CASE(JSOP_TOID)
    2700             : 
    2701             : CASE(JSOP_TYPEOFEXPR)
    2702             : CASE(JSOP_TYPEOF)
    2703             : {
    2704         909 :     REGS.sp[-1].setString(TypeOfOperation(REGS.sp[-1], cx->runtime()));
    2705             : }
    2706         909 : END_CASE(JSOP_TYPEOF)
    2707             : 
    2708             : CASE(JSOP_VOID)
    2709         261 :     REGS.sp[-1].setUndefined();
    2710         261 : END_CASE(JSOP_VOID)
    2711             : 
    2712             : CASE(JSOP_FUNCTIONTHIS)
    2713        5631 :     PUSH_NULL();
    2714        5631 :     if (!GetFunctionThis(cx, REGS.fp(), REGS.stackHandleAt(-1)))
    2715           0 :         goto error;
    2716        5631 : END_CASE(JSOP_FUNCTIONTHIS)
    2717             : 
    2718             : CASE(JSOP_GLOBALTHIS)
    2719             : {
    2720        1720 :     if (script->hasNonSyntacticScope()) {
    2721         148 :         PUSH_NULL();
    2722         148 :         if (!GetNonSyntacticGlobalThis(cx, REGS.fp()->environmentChain(), REGS.stackHandleAt(-1)))
    2723           0 :             goto error;
    2724             :     } else {
    2725        1572 :         PUSH_COPY(cx->global()->lexicalEnvironment().thisValue());
    2726             :     }
    2727             : }
    2728        1720 : END_CASE(JSOP_GLOBALTHIS)
    2729             : 
    2730             : CASE(JSOP_CHECKISOBJ)
    2731             : {
    2732        2107 :     if (!REGS.sp[-1].isObject()) {
    2733           0 :         MOZ_ALWAYS_FALSE(ThrowCheckIsObject(cx, CheckIsObjectKind(GET_UINT8(REGS.pc))));
    2734           0 :         goto error;
    2735             :     }
    2736             : }
    2737        2107 : END_CASE(JSOP_CHECKISOBJ)
    2738             : 
    2739             : CASE(JSOP_CHECKISCALLABLE)
    2740             : {
    2741           0 :     if (!IsCallable(REGS.sp[-1])) {
    2742           0 :         MOZ_ALWAYS_FALSE(ThrowCheckIsCallable(cx, CheckIsCallableKind(GET_UINT8(REGS.pc))));
    2743           0 :         goto error;
    2744             :     }
    2745             : }
    2746           0 : END_CASE(JSOP_CHECKISCALLABLE)
    2747             : 
    2748             : CASE(JSOP_CHECKTHIS)
    2749             : {
    2750          58 :     if (REGS.sp[-1].isMagic(JS_UNINITIALIZED_LEXICAL)) {
    2751           0 :         MOZ_ALWAYS_FALSE(ThrowUninitializedThis(cx, REGS.fp()));
    2752           0 :         goto error;
    2753             :     }
    2754             : }
    2755          58 : END_CASE(JSOP_CHECKTHIS)
    2756             : 
    2757             : CASE(JSOP_CHECKTHISREINIT)
    2758             : {
    2759          29 :     if (!REGS.sp[-1].isMagic(JS_UNINITIALIZED_LEXICAL)) {
    2760           0 :         MOZ_ALWAYS_FALSE(ThrowInitializedThis(cx, REGS.fp()));
    2761           0 :         goto error;
    2762             :     }
    2763             : }
    2764          29 : END_CASE(JSOP_CHECKTHISREINIT)
    2765             : 
    2766             : CASE(JSOP_CHECKRETURN)
    2767             : {
    2768          28 :     if (!REGS.fp()->checkReturn(cx, REGS.stackHandleAt(-1)))
    2769           0 :         goto error;
    2770          28 :     REGS.sp--;
    2771             : }
    2772          28 : END_CASE(JSOP_CHECKRETURN)
    2773             : 
    2774             : CASE(JSOP_GETPROP)
    2775             : CASE(JSOP_LENGTH)
    2776             : CASE(JSOP_CALLPROP)
    2777             : {
    2778       33888 :     MutableHandleValue lval = REGS.stackHandleAt(-1);
    2779       33888 :     if (!GetPropertyOperation(cx, REGS.fp(), script, REGS.pc, lval, lval))
    2780           4 :         goto error;
    2781             : 
    2782       33884 :     TypeScript::Monitor(cx, script, REGS.pc, lval);
    2783       33884 :     assertSameCompartmentDebugOnly(cx, lval);
    2784             : }
    2785       33884 : END_CASE(JSOP_GETPROP)
    2786             : 
    2787             : CASE(JSOP_GETPROP_SUPER)
    2788             : {
    2789          10 :     ReservedRooted<Value> receiver(&rootValue0, REGS.sp[-2]);
    2790          10 :     ReservedRooted<JSObject*> obj(&rootObject1, &REGS.sp[-1].toObject());
    2791           5 :     MutableHandleValue rref = REGS.stackHandleAt(-2);
    2792             : 
    2793           5 :     if (!GetProperty(cx, obj, receiver, script->getName(REGS.pc), rref))
    2794           0 :         goto error;
    2795             : 
    2796           5 :     TypeScript::Monitor(cx, script, REGS.pc, rref);
    2797           5 :     assertSameCompartmentDebugOnly(cx, rref);
    2798             : 
    2799           5 :     REGS.sp--;
    2800             : }
    2801           5 : END_CASE(JSOP_GETPROP_SUPER)
    2802             : 
    2803             : CASE(JSOP_GETBOUNDNAME)
    2804             : {
    2805           0 :     ReservedRooted<JSObject*> env(&rootObject0, &REGS.sp[-1].toObject());
    2806           0 :     ReservedRooted<jsid> id(&rootId0, NameToId(script->getName(REGS.pc)));
    2807           0 :     MutableHandleValue rval = REGS.stackHandleAt(-1);
    2808           0 :     if (!GetNameBoundInEnvironment(cx, env, id, rval))
    2809           0 :         goto error;
    2810             : 
    2811           0 :     TypeScript::Monitor(cx, script, REGS.pc, rval);
    2812           0 :     assertSameCompartmentDebugOnly(cx, rval);
    2813             : }
    2814           0 : END_CASE(JSOP_GETBOUNDNAME)
    2815             : 
    2816             : CASE(JSOP_SETINTRINSIC)
    2817             : {
    2818          87 :     HandleValue value = REGS.stackHandleAt(-1);
    2819             : 
    2820          87 :     if (!SetIntrinsicOperation(cx, script, REGS.pc, value))
    2821           0 :         goto error;
    2822             : }
    2823          87 : END_CASE(JSOP_SETINTRINSIC)
    2824             : 
    2825             : CASE(JSOP_SETGNAME)
    2826             : CASE(JSOP_STRICTSETGNAME)
    2827             : CASE(JSOP_SETNAME)
    2828             : CASE(JSOP_STRICTSETNAME)
    2829             : {
    2830             :     static_assert(JSOP_SETNAME_LENGTH == JSOP_STRICTSETNAME_LENGTH,
    2831             :                   "setname and strictsetname must be the same size");
    2832             :     static_assert(JSOP_SETGNAME_LENGTH == JSOP_STRICTSETGNAME_LENGTH,
    2833             :                   "setganem adn strictsetgname must be the same size");
    2834             :     static_assert(JSOP_SETNAME_LENGTH == JSOP_SETGNAME_LENGTH,
    2835             :                   "We're sharing the END_CASE so the lengths better match");
    2836             : 
    2837        1692 :     ReservedRooted<JSObject*> env(&rootObject0, &REGS.sp[-2].toObject());
    2838         846 :     HandleValue value = REGS.stackHandleAt(-1);
    2839             : 
    2840         846 :     if (!SetNameOperation(cx, script, REGS.pc, env, value))
    2841           0 :         goto error;
    2842             : 
    2843         846 :     REGS.sp[-2] = REGS.sp[-1];
    2844         846 :     REGS.sp--;
    2845             : }
    2846         846 : END_CASE(JSOP_SETNAME)
    2847             : 
    2848             : CASE(JSOP_SETPROP)
    2849             : CASE(JSOP_STRICTSETPROP)
    2850             : {
    2851             :     static_assert(JSOP_SETPROP_LENGTH == JSOP_STRICTSETPROP_LENGTH,
    2852             :                   "setprop and strictsetprop must be the same size");
    2853        4508 :     HandleValue lval = REGS.stackHandleAt(-2);
    2854        4508 :     HandleValue rval = REGS.stackHandleAt(-1);
    2855             : 
    2856        9015 :     ReservedRooted<jsid> id(&rootId0, NameToId(script->getName(REGS.pc)));
    2857        4508 :     if (!SetPropertyOperation(cx, JSOp(*REGS.pc), lval, id, rval))
    2858           0 :         goto error;
    2859             : 
    2860        4507 :     REGS.sp[-2] = REGS.sp[-1];
    2861        4507 :     REGS.sp--;
    2862             : }
    2863        4507 : END_CASE(JSOP_SETPROP)
    2864             : 
    2865             : CASE(JSOP_SETPROP_SUPER)
    2866             : CASE(JSOP_STRICTSETPROP_SUPER)
    2867             : {
    2868             :     static_assert(JSOP_SETPROP_SUPER_LENGTH == JSOP_STRICTSETPROP_SUPER_LENGTH,
    2869             :                   "setprop-super and strictsetprop-super must be the same size");
    2870             : 
    2871           0 :     ReservedRooted<Value> receiver(&rootValue0, REGS.sp[-3]);
    2872           0 :     ReservedRooted<JSObject*> obj(&rootObject0, &REGS.sp[-2].toObject());
    2873           0 :     ReservedRooted<Value> rval(&rootValue1, REGS.sp[-1]);
    2874           0 :     ReservedRooted<PropertyName*> name(&rootName0, script->getName(REGS.pc));
    2875             : 
    2876           0 :     bool strict = JSOp(*REGS.pc) == JSOP_STRICTSETPROP_SUPER;
    2877             : 
    2878           0 :     if (!SetPropertySuper(cx, obj, receiver, name, rval, strict))
    2879           0 :         goto error;
    2880             : 
    2881           0 :     REGS.sp[-3] = REGS.sp[-1];
    2882           0 :     REGS.sp -= 2;
    2883             : }
    2884           0 : END_CASE(JSOP_SETPROP_SUPER)
    2885             : 
    2886             : CASE(JSOP_GETELEM)
    2887             : CASE(JSOP_CALLELEM)
    2888             : {
    2889        3600 :     MutableHandleValue lval = REGS.stackHandleAt(-2);
    2890        3600 :     HandleValue rval = REGS.stackHandleAt(-1);
    2891        3600 :     MutableHandleValue res = REGS.stackHandleAt(-2);
    2892             : 
    2893        3600 :     bool done = false;
    2894        3600 :     if (!GetElemOptimizedArguments(cx, REGS.fp(), lval, rval, res, &done))
    2895           3 :         goto error;
    2896             : 
    2897        3600 :     if (!done) {
    2898        3465 :         if (!GetElementOperation(cx, JSOp(*REGS.pc), lval, rval, res))
    2899           3 :             goto error;
    2900             :     }
    2901             : 
    2902        3597 :     TypeScript::Monitor(cx, script, REGS.pc, res);
    2903        3597 :     REGS.sp--;
    2904             : }
    2905        3597 : END_CASE(JSOP_GETELEM)
    2906             : 
    2907             : CASE(JSOP_GETELEM_SUPER)
    2908             : {
    2909           0 :     ReservedRooted<Value> rval(&rootValue0, REGS.sp[-3]);
    2910           0 :     ReservedRooted<Value> receiver(&rootValue1, REGS.sp[-2]);
    2911           0 :     ReservedRooted<JSObject*> obj(&rootObject1, &REGS.sp[-1].toObject());
    2912             : 
    2913           0 :     MutableHandleValue res = REGS.stackHandleAt(-3);
    2914             : 
    2915             :     // Since we have asserted that obj has to be an object, it cannot be
    2916             :     // either optimized arguments, or indeed any primitive. This simplifies
    2917             :     // our task some.
    2918           0 :     if (!GetObjectElementOperation(cx, JSOp(*REGS.pc), obj, receiver, rval, res))
    2919           0 :         goto error;
    2920             : 
    2921           0 :     TypeScript::Monitor(cx, script, REGS.pc, res);
    2922           0 :     REGS.sp -= 2;
    2923             : }
    2924           0 : END_CASE(JSOP_GETELEM_SUPER)
    2925             : 
    2926             : CASE(JSOP_SETELEM)
    2927             : CASE(JSOP_STRICTSETELEM)
    2928             : {
    2929             :     static_assert(JSOP_SETELEM_LENGTH == JSOP_STRICTSETELEM_LENGTH,
    2930             :                   "setelem and strictsetelem must be the same size");
    2931         705 :     HandleValue receiver = REGS.stackHandleAt(-3);
    2932        1410 :     ReservedRooted<JSObject*> obj(&rootObject0);
    2933         705 :     obj = ToObjectFromStack(cx, receiver);
    2934         705 :     if (!obj)
    2935           0 :         goto error;
    2936        1410 :     ReservedRooted<jsid> id(&rootId0);
    2937         705 :     FETCH_ELEMENT_ID(-2, id);
    2938         705 :     HandleValue value = REGS.stackHandleAt(-1);
    2939         705 :     if (!SetObjectElementOperation(cx, obj, id, value, receiver, *REGS.pc == JSOP_STRICTSETELEM))
    2940           0 :         goto error;
    2941         705 :     REGS.sp[-3] = value;
    2942         705 :     REGS.sp -= 2;
    2943             : }
    2944         705 : END_CASE(JSOP_SETELEM)
    2945             : 
    2946             : CASE(JSOP_SETELEM_SUPER)
    2947             : CASE(JSOP_STRICTSETELEM_SUPER)
    2948             : {
    2949             :     static_assert(JSOP_SETELEM_SUPER_LENGTH == JSOP_STRICTSETELEM_SUPER_LENGTH,
    2950             :                   "setelem-super and strictsetelem-super must be the same size");
    2951             : 
    2952           0 :     ReservedRooted<Value> index(&rootValue1, REGS.sp[-4]);
    2953           0 :     ReservedRooted<Value> receiver(&rootValue0, REGS.sp[-3]);
    2954           0 :     ReservedRooted<JSObject*> obj(&rootObject1, &REGS.sp[-2].toObject());
    2955           0 :     HandleValue value = REGS.stackHandleAt(-1);
    2956             : 
    2957           0 :     bool strict = JSOp(*REGS.pc) == JSOP_STRICTSETELEM_SUPER;
    2958           0 :     if (!SetObjectElement(cx, obj, index, value, receiver, strict))
    2959           0 :         goto error;
    2960           0 :     REGS.sp[-4] = value;
    2961           0 :     REGS.sp -= 3;
    2962             : }
    2963           0 : END_CASE(JSOP_SETELEM_SUPER)
    2964             : 
    2965             : CASE(JSOP_EVAL)
    2966             : CASE(JSOP_STRICTEVAL)
    2967             : {
    2968             :     static_assert(JSOP_EVAL_LENGTH == JSOP_STRICTEVAL_LENGTH,
    2969             :                   "eval and stricteval must be the same size");
    2970             : 
    2971           2 :     CallArgs args = CallArgsFromSp(GET_ARGC(REGS.pc), REGS.sp);
    2972           2 :     if (REGS.fp()->environmentChain()->global().valueIsEval(args.calleev())) {
    2973           2 :         if (!DirectEval(cx, args.get(0), args.rval()))
    2974           0 :             goto error;
    2975             :     } else {
    2976           0 :         if (!CallFromStack(cx, args))
    2977           0 :             goto error;
    2978             :     }
    2979             : 
    2980           2 :     REGS.sp = args.spAfterCall();
    2981           2 :     TypeScript::Monitor(cx, script, REGS.pc, REGS.sp[-1]);
    2982             : }
    2983           2 : END_CASE(JSOP_EVAL)
    2984             : 
    2985             : CASE(JSOP_SPREADNEW)
    2986             : CASE(JSOP_SPREADCALL)
    2987             : CASE(JSOP_SPREADSUPERCALL)
    2988          24 :     if (REGS.fp()->hasPushedGeckoProfilerFrame())
    2989           0 :         cx->runtime()->geckoProfiler().updatePC(script, REGS.pc);
    2990             :     /* FALL THROUGH */
    2991             : 
    2992             : CASE(JSOP_SPREADEVAL)
    2993             : CASE(JSOP_STRICTSPREADEVAL)
    2994             : {
    2995             :     static_assert(JSOP_SPREADEVAL_LENGTH == JSOP_STRICTSPREADEVAL_LENGTH,
    2996             :                   "spreadeval and strictspreadeval must be the same size");
    2997          24 :     bool construct = JSOp(*REGS.pc) == JSOP_SPREADNEW || JSOp(*REGS.pc) == JSOP_SPREADSUPERCALL;;
    2998             : 
    2999          24 :     MOZ_ASSERT(REGS.stackDepth() >= 3u + construct);
    3000             : 
    3001          24 :     HandleValue callee = REGS.stackHandleAt(-3 - construct);
    3002          24 :     HandleValue thisv = REGS.stackHandleAt(-2 - construct);
    3003          24 :     HandleValue arr = REGS.stackHandleAt(-1 - construct);
    3004          24 :     MutableHandleValue ret = REGS.stackHandleAt(-3 - construct);
    3005             : 
    3006          24 :     RootedValue& newTarget = rootValue0;
    3007          24 :     if (construct)
    3008           0 :         newTarget = REGS.sp[-1];
    3009             :     else
    3010          24 :         newTarget = NullValue();
    3011             : 
    3012          24 :     if (!SpreadCallOperation(cx, script, REGS.pc, thisv, callee, arr, newTarget, ret))
    3013           0 :         goto error;
    3014             : 
    3015          24 :     REGS.sp -= 2 + construct;
    3016             : }
    3017          24 : END_CASE(JSOP_SPREADCALL)
    3018             : 
    3019             : CASE(JSOP_FUNAPPLY)
    3020             : {
    3021         113 :     CallArgs args = CallArgsFromSp(GET_ARGC(REGS.pc), REGS.sp);
    3022         113 :     if (!GuardFunApplyArgumentsOptimization(cx, REGS.fp(), args))
    3023           0 :         goto error;
    3024             :     /* FALL THROUGH */
    3025             : }
    3026             : 
    3027             : CASE(JSOP_NEW)
    3028             : CASE(JSOP_CALL)
    3029             : CASE(JSOP_CALL_IGNORES_RV)
    3030             : CASE(JSOP_CALLITER)
    3031             : CASE(JSOP_SUPERCALL)
    3032             : CASE(JSOP_FUNCALL)
    3033             : {
    3034       32042 :     if (REGS.fp()->hasPushedGeckoProfilerFrame())
    3035           0 :         cx->runtime()->geckoProfiler().updatePC(script, REGS.pc);
    3036             : 
    3037       32042 :     MaybeConstruct construct = MaybeConstruct(*REGS.pc == JSOP_NEW || *REGS.pc == JSOP_SUPERCALL);
    3038       32042 :     bool ignoresReturnValue = *REGS.pc == JSOP_CALL_IGNORES_RV;
    3039       32042 :     unsigned argStackSlots = GET_ARGC(REGS.pc) + construct;
    3040             : 
    3041       32042 :     MOZ_ASSERT(REGS.stackDepth() >= 2u + GET_ARGC(REGS.pc));
    3042       32042 :     CallArgs args = CallArgsFromSp(argStackSlots, REGS.sp, construct, ignoresReturnValue);
    3043             : 
    3044             :     JSFunction* maybeFun;
    3045       32042 :     bool isFunction = IsFunctionObject(args.calleev(), &maybeFun);
    3046             : 
    3047             :     /* Don't bother trying to fast-path calls to scripted non-constructors. */
    3048       64084 :     if (!isFunction || !maybeFun->isInterpreted() || !maybeFun->isConstructor() ||
    3049        4205 :         (!construct && maybeFun->isClassConstructor()))
    3050             :     {
    3051       29796 :         if (construct) {
    3052         666 :             if (!ConstructFromStack(cx, args))
    3053          73 :                 goto error;
    3054             :         } else {
    3055       29130 :             if (*REGS.pc == JSOP_CALLITER && args.calleev().isPrimitive()) {
    3056           0 :                 MOZ_ASSERT(args.length() == 0, "thisv must be on top of the stack");
    3057           0 :                 ReportValueError(cx, JSMSG_NOT_ITERABLE, -1, args.thisv(), nullptr);
    3058           0 :                 goto error;
    3059             :             }
    3060       29130 :             if (!CallFromStack(cx, args))
    3061          53 :                 goto error;
    3062             :         }
    3063       29726 :         Value* newsp = args.spAfterCall();
    3064       29726 :         TypeScript::Monitor(cx, script, REGS.pc, newsp[-1]);
    3065       29726 :         REGS.sp = newsp;
    3066       29726 :         ADVANCE_AND_DISPATCH(JSOP_CALL_LENGTH);
    3067             :     }
    3068             : 
    3069             :     {
    3070        2246 :         MOZ_ASSERT(maybeFun);
    3071        3920 :         ReservedRooted<JSFunction*> fun(&rootFunction0, maybeFun);
    3072        3920 :         ReservedRooted<JSScript*> funScript(&rootScript0, JSFunction::getOrCreateScript(cx, fun));
    3073        2246 :         if (!funScript)
    3074           0 :             goto error;
    3075             : 
    3076        2246 :         bool createSingleton = ObjectGroup::useSingletonForNewObject(cx, script, REGS.pc);
    3077             : 
    3078        2246 :         TypeMonitorCall(cx, args, construct);
    3079             : 
    3080        3920 :         mozilla::Maybe<InvokeState> state;
    3081        2246 :         state.emplace(cx, args, construct);
    3082             : 
    3083        2246 :         if (createSingleton)
    3084           0 :             state->setCreateSingleton();
    3085             : 
    3086        2246 :         if (!createSingleton && jit::IsIonEnabled(cx)) {
    3087        2246 :             jit::MethodStatus status = jit::CanEnter(cx, state.ref());
    3088        2246 :             if (status == jit::Method_Error)
    3089           0 :                 goto error;
    3090        2246 :             if (status == jit::Method_Compiled) {
    3091           0 :                 jit::JitExecStatus exec = jit::IonCannon(cx, state.ref());
    3092           0 :                 interpReturnOK = !IsErrorStatus(exec);
    3093           0 :                 if (interpReturnOK)
    3094           0 :                     CHECK_BRANCH();
    3095           0 :                 REGS.sp = args.spAfterCall();
    3096           0 :                 goto jit_return;
    3097             :             }
    3098             :         }
    3099             : 
    3100        2246 :         if (jit::IsBaselineEnabled(cx)) {
    3101        2246 :             jit::MethodStatus status = jit::CanEnterBaselineMethod(cx, state.ref());
    3102        2246 :             if (status == jit::Method_Error)
    3103           0 :                 goto error;
    3104        2246 :             if (status == jit::Method_Compiled) {
    3105         572 :                 jit::JitExecStatus exec = jit::EnterBaselineMethod(cx, state.ref());
    3106         572 :                 interpReturnOK = !IsErrorStatus(exec);
    3107         572 :                 if (interpReturnOK)
    3108         572 :                     CHECK_BRANCH();
    3109         572 :                 REGS.sp = args.spAfterCall();
    3110         572 :                 goto jit_return;
    3111             :             }
    3112             :         }
    3113             : 
    3114        1674 :         state.reset();
    3115        1674 :         funScript = fun->nonLazyScript();
    3116             : 
    3117        1674 :         if (!activation.pushInlineFrame(args, funScript, construct))
    3118           0 :             goto error;
    3119             : 
    3120        1674 :         if (createSingleton)
    3121           0 :             REGS.fp()->setCreateSingleton();
    3122             :     }
    3123             : 
    3124        1674 :     SET_SCRIPT(REGS.fp()->script());
    3125             : 
    3126             :     {
    3127        3348 :         TraceLoggerEvent event(TraceLogger_Scripts, script);
    3128        1674 :         TraceLogStartEvent(logger, event);
    3129        1674 :         TraceLogStartEvent(logger, TraceLogger_Interpreter);
    3130             :     }
    3131             : 
    3132        1674 :     if (!REGS.fp()->prologue(cx))
    3133           0 :         goto prologue_error;
    3134             : 
    3135        1674 :     switch (Debugger::onEnterFrame(cx, REGS.fp())) {
    3136             :       case JSTRAP_CONTINUE:
    3137        1674 :         break;
    3138             :       case JSTRAP_RETURN:
    3139           0 :         if (!ForcedReturn(cx, REGS))
    3140           0 :             goto error;
    3141           0 :         goto successful_return_continuation;
    3142             :       case JSTRAP_THROW:
    3143             :       case JSTRAP_ERROR:
    3144           0 :         goto error;
    3145             :       default:
    3146           0 :         MOZ_CRASH("bad Debugger::onEnterFrame status");
    3147             :     }
    3148             : 
    3149             :     // Increment the coverage for the main entry point.
    3150        1674 :     INIT_COVERAGE();
    3151        1674 :     COUNT_COVERAGE_MAIN();
    3152             : 
    3153             :     /* Load first op and dispatch it (safe since JSOP_RETRVAL). */
    3154        1674 :     ADVANCE_AND_DISPATCH(0);
    3155             : }
    3156             : 
    3157             : CASE(JSOP_OPTIMIZE_SPREADCALL)
    3158             : {
    3159           0 :     ReservedRooted<Value> val(&rootValue0, REGS.sp[-1]);
    3160             : 
    3161           0 :     bool optimized = false;
    3162           0 :     if (!OptimizeSpreadCall(cx, val, &optimized))
    3163           0 :         goto error;
    3164             : 
    3165           0 :     PUSH_BOOLEAN(optimized);
    3166             : }
    3167           0 : END_CASE(JSOP_OPTIMIZE_SPREADCALL)
    3168             : 
    3169             : CASE(JSOP_THROWMSG)
    3170             : {
    3171           0 :     JS_ALWAYS_FALSE(ThrowMsgOperation(cx, GET_UINT16(REGS.pc)));
    3172           0 :     goto error;
    3173             : }
    3174             : END_CASE(JSOP_THROWMSG)
    3175             : 
    3176             : CASE(JSOP_IMPLICITTHIS)
    3177             : CASE(JSOP_GIMPLICITTHIS)
    3178             : {
    3179        1283 :     JSOp op = JSOp(*REGS.pc);
    3180        1283 :     if (op == JSOP_IMPLICITTHIS || script->hasNonSyntacticScope()) {
    3181        1030 :         ReservedRooted<PropertyName*> name(&rootName0, script->getName(REGS.pc));
    3182        1030 :         ReservedRooted<JSObject*> envObj(&rootObject0, REGS.fp()->environmentChain());
    3183        1030 :         ReservedRooted<JSObject*> env(&rootObject1);
    3184         515 :         if (!LookupNameWithGlobalDefault(cx, name, envObj, &env))
    3185           0 :             goto error;
    3186             : 
    3187         515 :         Value v = ComputeImplicitThis(env);
    3188         515 :         PUSH_COPY(v);
    3189             :     } else {
    3190             :         // Treat it like JSOP_UNDEFINED.
    3191         768 :         PUSH_UNDEFINED();
    3192             :     }
    3193             :     static_assert(JSOP_IMPLICITTHIS_LENGTH == JSOP_GIMPLICITTHIS_LENGTH,
    3194             :                   "We're sharing the END_CASE so the lengths better match");
    3195             : }
    3196        1283 : END_CASE(JSOP_IMPLICITTHIS)
    3197             : 
    3198             : CASE(JSOP_GETGNAME)
    3199             : CASE(JSOP_GETNAME)
    3200             : {
    3201       30472 :     ReservedRooted<Value> rval(&rootValue0);
    3202       15236 :     if (!GetNameOperation(cx, REGS.fp(), REGS.pc, &rval))
    3203           0 :         goto error;
    3204             : 
    3205       15236 :     PUSH_COPY(rval);
    3206       15236 :     TypeScript::Monitor(cx, script, REGS.pc, rval);
    3207             :     static_assert(JSOP_GETNAME_LENGTH == JSOP_GETGNAME_LENGTH,
    3208             :                   "We're sharing the END_CASE so the lengths better match");
    3209             : }
    3210       15236 : END_CASE(JSOP_GETNAME)
    3211             : 
    3212             : CASE(JSOP_GETIMPORT)
    3213             : {
    3214           0 :     PUSH_NULL();
    3215           0 :     MutableHandleValue rval = REGS.stackHandleAt(-1);
    3216           0 :     if (!GetImportOperation(cx, REGS.fp(), REGS.pc, rval))
    3217           0 :         goto error;
    3218             : 
    3219           0 :     TypeScript::Monitor(cx, script, REGS.pc, rval);
    3220             : }
    3221           0 : END_CASE(JSOP_GETIMPORT)
    3222             : 
    3223             : CASE(JSOP_GETINTRINSIC)
    3224             : {
    3225       34262 :     ReservedRooted<Value> rval(&rootValue0);
    3226       17131 :     if (!GetIntrinsicOperation(cx, REGS.pc, &rval))
    3227           0 :         goto error;
    3228             : 
    3229       17131 :     PUSH_COPY(rval);
    3230       17131 :     TypeScript::Monitor(cx, script, REGS.pc, rval);
    3231             : }
    3232       17131 : END_CASE(JSOP_GETINTRINSIC)
    3233             : 
    3234             : CASE(JSOP_UINT16)
    3235         211 :     PUSH_INT32((int32_t) GET_UINT16(REGS.pc));
    3236         211 : END_CASE(JSOP_UINT16)
    3237             : 
    3238             : CASE(JSOP_UINT24)
    3239          40 :     PUSH_INT32((int32_t) GET_UINT24(REGS.pc));
    3240          40 : END_CASE(JSOP_UINT24)
    3241             : 
    3242             : CASE(JSOP_INT8)
    3243        2310 :     PUSH_INT32(GET_INT8(REGS.pc));
    3244        2310 : END_CASE(JSOP_INT8)
    3245             : 
    3246             : CASE(JSOP_INT32)
    3247          28 :     PUSH_INT32(GET_INT32(REGS.pc));
    3248          28 : END_CASE(JSOP_INT32)
    3249             : 
    3250             : CASE(JSOP_DOUBLE)
    3251             : {
    3252             :     double dbl;
    3253         773 :     LOAD_DOUBLE(0, dbl);
    3254         773 :     PUSH_DOUBLE(dbl);
    3255             : }
    3256         773 : END_CASE(JSOP_DOUBLE)
    3257             : 
    3258             : CASE(JSOP_STRING)
    3259       11644 :     PUSH_STRING(script->getAtom(REGS.pc));
    3260       11644 : END_CASE(JSOP_STRING)
    3261             : 
    3262             : CASE(JSOP_TOSTRING)
    3263             : {
    3264         121 :     MutableHandleValue oper = REGS.stackHandleAt(-1);
    3265             : 
    3266         121 :     if (!oper.isString()) {
    3267           7 :         JSString* operString = ToString<CanGC>(cx, oper);
    3268           7 :         if (!operString)
    3269           0 :             goto error;
    3270           7 :         oper.setString(operString);
    3271             :     }
    3272             : }
    3273         121 : END_CASE(JSOP_TOSTRING)
    3274             : 
    3275             : CASE(JSOP_SYMBOL)
    3276         546 :     PUSH_SYMBOL(cx->wellKnownSymbols().get(GET_UINT8(REGS.pc)));
    3277         546 : END_CASE(JSOP_SYMBOL)
    3278             : 
    3279             : CASE(JSOP_OBJECT)
    3280             : {
    3281          80 :     ReservedRooted<JSObject*> ref(&rootObject0, script->getObject(REGS.pc));
    3282          40 :     if (cx->compartment()->creationOptions().cloneSingletons()) {
    3283           0 :         JSObject* obj = DeepCloneObjectLiteral(cx, ref, TenuredObject);
    3284           0 :         if (!obj)
    3285           0 :             goto error;
    3286           0 :         PUSH_OBJECT(*obj);
    3287             :     } else {
    3288          40 :         cx->compartment()->behaviors().setSingletonsAsValues();
    3289          40 :         PUSH_OBJECT(*ref);
    3290             :     }
    3291             : }
    3292          40 : END_CASE(JSOP_OBJECT)
    3293             : 
    3294             : CASE(JSOP_CALLSITEOBJ)
    3295             : {
    3296          20 :     ReservedRooted<JSObject*> cso(&rootObject0, script->getObject(REGS.pc));
    3297          20 :     ReservedRooted<JSObject*> raw(&rootObject1, script->getObject(GET_UINT32_INDEX(REGS.pc) + 1));
    3298             : 
    3299          10 :     if (!cx->compartment()->getTemplateLiteralObject(cx, raw, &cso))
    3300           0 :         goto error;
    3301             : 
    3302          10 :     PUSH_OBJECT(*cso);
    3303             : }
    3304          10 : END_CASE(JSOP_CALLSITEOBJ)
    3305             : 
    3306             : CASE(JSOP_REGEXP)
    3307             : {
    3308             :     /*
    3309             :      * Push a regexp object cloned from the regexp literal object mapped by the
    3310             :      * bytecode at pc.
    3311             :      */
    3312         274 :     ReservedRooted<JSObject*> re(&rootObject0, script->getRegExp(REGS.pc));
    3313         137 :     JSObject* obj = CloneRegExpObject(cx, re.as<RegExpObject>());
    3314         137 :     if (!obj)
    3315           0 :         goto error;
    3316         137 :     PUSH_OBJECT(*obj);
    3317             : }
    3318         137 : END_CASE(JSOP_REGEXP)
    3319             : 
    3320             : CASE(JSOP_ZERO)
    3321        4226 :     PUSH_INT32(0);
    3322        4226 : END_CASE(JSOP_ZERO)
    3323             : 
    3324             : CASE(JSOP_ONE)
    3325        3806 :     PUSH_INT32(1);
    3326        3806 : END_CASE(JSOP_ONE)
    3327             : 
    3328             : CASE(JSOP_NULL)
    3329        3042 :     PUSH_NULL();
    3330        3042 : END_CASE(JSOP_NULL)
    3331             : 
    3332             : CASE(JSOP_FALSE)
    3333        2733 :     PUSH_BOOLEAN(false);
    3334        2733 : END_CASE(JSOP_FALSE)
    3335             : 
    3336             : CASE(JSOP_TRUE)
    3337        1813 :     PUSH_BOOLEAN(true);
    3338        1813 : END_CASE(JSOP_TRUE)
    3339             : 
    3340             : CASE(JSOP_TABLESWITCH)
    3341             : {
    3342         243 :     jsbytecode* pc2 = REGS.pc;
    3343         243 :     int32_t len = GET_JUMP_OFFSET(pc2);
    3344             : 
    3345             :     /*
    3346             :      * ECMAv2+ forbids conversion of discriminant, so we will skip to the
    3347             :      * default case if the discriminant isn't already an int jsval.  (This
    3348             :      * opcode is emitted only for dense int-domain switches.)
    3349             :      */
    3350         243 :     const Value& rref = *--REGS.sp;
    3351             :     int32_t i;
    3352         243 :     if (rref.isInt32()) {
    3353         243 :         i = rref.toInt32();
    3354             :     } else {
    3355             :         /* Use mozilla::NumberEqualsInt32 to treat -0 (double) as 0. */
    3356           0 :         if (!rref.isDouble() || !NumberEqualsInt32(rref.toDouble(), &i))
    3357           0 :             ADVANCE_AND_DISPATCH(len);
    3358             :     }
    3359             : 
    3360         243 :     pc2 += JUMP_OFFSET_LEN;
    3361         243 :     int32_t low = GET_JUMP_OFFSET(pc2);
    3362         243 :     pc2 += JUMP_OFFSET_LEN;
    3363         243 :     int32_t high = GET_JUMP_OFFSET(pc2);
    3364             : 
    3365         243 :     i -= low;
    3366         243 :     if ((uint32_t)i < (uint32_t)(high - low + 1)) {
    3367         243 :         pc2 += JUMP_OFFSET_LEN + JUMP_OFFSET_LEN * i;
    3368         243 :         int32_t off = (int32_t) GET_JUMP_OFFSET(pc2);
    3369         243 :         if (off)
    3370         243 :             len = off;
    3371             :     }
    3372         243 :     ADVANCE_AND_DISPATCH(len);
    3373             : }
    3374             : 
    3375             : CASE(JSOP_ARGUMENTS)
    3376         344 :     if (!script->ensureHasAnalyzedArgsUsage(cx))
    3377           0 :         goto error;
    3378         344 :     if (script->needsArgsObj()) {
    3379          77 :         ArgumentsObject* obj = ArgumentsObject::createExpected(cx, REGS.fp());
    3380          77 :         if (!obj)
    3381           0 :             goto error;
    3382          77 :         PUSH_COPY(ObjectValue(*obj));
    3383             :     } else {
    3384         267 :         PUSH_COPY(MagicValue(JS_OPTIMIZED_ARGUMENTS));
    3385             :     }
    3386         344 : END_CASE(JSOP_ARGUMENTS)
    3387             : 
    3388             : CASE(JSOP_RUNONCE)
    3389             : {
    3390           8 :     if (!RunOnceScriptPrologue(cx, script))
    3391           0 :         goto error;
    3392             : }
    3393           8 : END_CASE(JSOP_RUNONCE)
    3394             : 
    3395             : CASE(JSOP_REST)
    3396             : {
    3397         482 :     ReservedRooted<JSObject*> rest(&rootObject0, REGS.fp()->createRestParameter(cx));
    3398         241 :     if (!rest)
    3399           0 :         goto error;
    3400         241 :     PUSH_COPY(ObjectValue(*rest));
    3401             : }
    3402         241 : END_CASE(JSOP_REST)
    3403             : 
    3404             : CASE(JSOP_GETALIASEDVAR)
    3405             : {
    3406        5670 :     EnvironmentCoordinate ec = EnvironmentCoordinate(REGS.pc);
    3407       11340 :     ReservedRooted<Value> val(&rootValue0, REGS.fp()->aliasedEnvironment(ec).aliasedBinding(ec));
    3408             : #ifdef DEBUG
    3409             :     // Only the .this slot can hold the TDZ MagicValue.
    3410        5670 :     if (IsUninitializedLexical(val)) {
    3411           0 :         PropertyName* name = EnvironmentCoordinateName(cx->caches().envCoordinateNameCache,
    3412           0 :                                                        script, REGS.pc);
    3413           0 :         MOZ_ASSERT(name == cx->names().dotThis);
    3414           0 :         JSOp next = JSOp(*GetNextPc(REGS.pc));
    3415           0 :         MOZ_ASSERT(next == JSOP_CHECKTHIS || next == JSOP_CHECKRETURN || next == JSOP_CHECKTHISREINIT);
    3416             :     }
    3417             : #endif
    3418        5670 :     PUSH_COPY(val);
    3419        5670 :     TypeScript::Monitor(cx, script, REGS.pc, REGS.sp[-1]);
    3420             : }
    3421        5670 : END_CASE(JSOP_GETALIASEDVAR)
    3422             : 
    3423             : CASE(JSOP_SETALIASEDVAR)
    3424             : {
    3425         783 :     EnvironmentCoordinate ec = EnvironmentCoordinate(REGS.pc);
    3426         783 :     EnvironmentObject& obj = REGS.fp()->aliasedEnvironment(ec);
    3427         783 :     SetAliasedVarOperation(cx, script, REGS.pc, obj, ec, REGS.sp[-1], CheckTDZ);
    3428             : }
    3429         783 : END_CASE(JSOP_SETALIASEDVAR)
    3430             : 
    3431             : CASE(JSOP_THROWSETCONST)
    3432             : CASE(JSOP_THROWSETALIASEDCONST)
    3433             : CASE(JSOP_THROWSETCALLEE)
    3434             : {
    3435           0 :     ReportRuntimeConstAssignment(cx, script, REGS.pc);
    3436           0 :     goto error;
    3437             : }
    3438             : END_CASE(JSOP_THROWSETCONST)
    3439             : 
    3440             : CASE(JSOP_CHECKLEXICAL)
    3441             : {
    3442           1 :     uint32_t i = GET_LOCALNO(REGS.pc);
    3443           2 :     ReservedRooted<Value> val(&rootValue0, REGS.fp()->unaliasedLocal(i));
    3444           1 :     if (!CheckUninitializedLexical(cx, script, REGS.pc, val))
    3445           0 :         goto error;
    3446             : }
    3447           1 : END_CASE(JSOP_CHECKLEXICAL)
    3448             : 
    3449             : CASE(JSOP_INITLEXICAL)
    3450             : {
    3451        9717 :     uint32_t i = GET_LOCALNO(REGS.pc);
    3452        9717 :     REGS.fp()->unaliasedLocal(i) = REGS.sp[-1];
    3453             : }
    3454        9717 : END_CASE(JSOP_INITLEXICAL)
    3455             : 
    3456             : CASE(JSOP_CHECKALIASEDLEXICAL)
    3457             : {
    3458         770 :     EnvironmentCoordinate ec = EnvironmentCoordinate(REGS.pc);
    3459        1540 :     ReservedRooted<Value> val(&rootValue0, REGS.fp()->aliasedEnvironment(ec).aliasedBinding(ec));
    3460         770 :     if (!CheckUninitializedLexical(cx, script, REGS.pc, val))
    3461           0 :         goto error;
    3462             : }
    3463         770 : END_CASE(JSOP_CHECKALIASEDLEXICAL)
    3464             : 
    3465             : CASE(JSOP_INITALIASEDLEXICAL)
    3466             : {
    3467         963 :     EnvironmentCoordinate ec = EnvironmentCoordinate(REGS.pc);
    3468         963 :     EnvironmentObject& obj = REGS.fp()->aliasedEnvironment(ec);
    3469         963 :     SetAliasedVarOperation(cx, script, REGS.pc, obj, ec, REGS.sp[-1], DontCheckTDZ);
    3470             : }
    3471         963 : END_CASE(JSOP_INITALIASEDLEXICAL)
    3472             : 
    3473             : CASE(JSOP_INITGLEXICAL)
    3474             : {
    3475             :     LexicalEnvironmentObject* lexicalEnv;
    3476        2450 :     if (script->hasNonSyntacticScope())
    3477         251 :         lexicalEnv = &REGS.fp()->extensibleLexicalEnvironment();
    3478             :     else
    3479        2199 :         lexicalEnv = &cx->global()->lexicalEnvironment();
    3480        2450 :     HandleValue value = REGS.stackHandleAt(-1);
    3481        2450 :     InitGlobalLexicalOperation(cx, lexicalEnv, script, REGS.pc, value);
    3482             : }
    3483        2450 : END_CASE(JSOP_INITGLEXICAL)
    3484             : 
    3485             : CASE(JSOP_UNINITIALIZED)
    3486        3478 :     PUSH_MAGIC(JS_UNINITIALIZED_LEXICAL);
    3487        3478 : END_CASE(JSOP_UNINITIALIZED)
    3488             : 
    3489             : CASE(JSOP_GETARG)
    3490             : {
    3491       20675 :     unsigned i = GET_ARGNO(REGS.pc);
    3492       20675 :     if (script->argsObjAliasesFormals())
    3493           7 :         PUSH_COPY(REGS.fp()->argsObj().arg(i));
    3494             :     else
    3495       20668 :         PUSH_COPY(REGS.fp()->unaliasedFormal(i));
    3496             : }
    3497       20675 : END_CASE(JSOP_GETARG)
    3498             : 
    3499             : CASE(JSOP_SETARG)
    3500             : {
    3501        1732 :     unsigned i = GET_ARGNO(REGS.pc);
    3502        1732 :     if (script->argsObjAliasesFormals())
    3503           2 :         REGS.fp()->argsObj().setArg(i, REGS.sp[-1]);
    3504             :     else
    3505        1730 :         REGS.fp()->unaliasedFormal(i) = REGS.sp[-1];
    3506             : }
    3507        1732 : END_CASE(JSOP_SETARG)
    3508             : 
    3509             : CASE(JSOP_GETLOCAL)
    3510             : {
    3511       42606 :     uint32_t i = GET_LOCALNO(REGS.pc);
    3512       42606 :     PUSH_COPY_SKIP_CHECK(REGS.fp()->unaliasedLocal(i));
    3513             : 
    3514             : #ifdef DEBUG
    3515             :     // Derived class constructors store the TDZ Value in the .this slot
    3516             :     // before a super() call.
    3517       42606 :     if (IsUninitializedLexical(REGS.sp[-1])) {
    3518          29 :         MOZ_ASSERT(script->isDerivedClassConstructor());
    3519          29 :         JSOp next = JSOp(*GetNextPc(REGS.pc));
    3520          29 :         MOZ_ASSERT(next == JSOP_CHECKTHIS || next == JSOP_CHECKRETURN || next == JSOP_CHECKTHISREINIT);
    3521             :     }
    3522             : #endif
    3523             : 
    3524             :     /*
    3525             :      * Skip the same-compartment assertion if the local will be immediately
    3526             :      * popped. We do not guarantee sync for dead locals when coming in from the
    3527             :      * method JIT, and a GETLOCAL followed by POP is not considered to be
    3528             :      * a use of the variable.
    3529             :      */
    3530       42606 :     if (REGS.pc[JSOP_GETLOCAL_LENGTH] != JSOP_POP)
    3531       42606 :         assertSameCompartmentDebugOnly(cx, REGS.sp[-1]);
    3532             : }
    3533       42606 : END_CASE(JSOP_GETLOCAL)
    3534             : 
    3535             : CASE(JSOP_SETLOCAL)
    3536             : {
    3537       15979 :     uint32_t i = GET_LOCALNO(REGS.pc);
    3538             : 
    3539       15979 :     MOZ_ASSERT(!IsUninitializedLexical(REGS.fp()->unaliasedLocal(i)));
    3540             : 
    3541       15979 :     REGS.fp()->unaliasedLocal(i) = REGS.sp[-1];
    3542             : }
    3543       15979 : END_CASE(JSOP_SETLOCAL)
    3544             : 
    3545             : CASE(JSOP_DEFVAR)
    3546             : {
    3547             :     /* ES5 10.5 step 8 (with subsequent errata). */
    3548         715 :     unsigned attrs = JSPROP_ENUMERATE;
    3549         715 :     if (!REGS.fp()->isEvalFrame())
    3550         715 :         attrs |= JSPROP_PERMANENT;
    3551             : 
    3552             :     /* Step 8b. */
    3553        1430 :     ReservedRooted<JSObject*> obj(&rootObject0, &REGS.fp()->varObj());
    3554        1430 :     ReservedRooted<PropertyName*> name(&rootName0, script->getName(REGS.pc));
    3555             : 
    3556         715 :     if (!DefVarOperation(cx, obj, name, attrs))
    3557           0 :         goto error;
    3558             : }
    3559         715 : END_CASE(JSOP_DEFVAR)
    3560             : 
    3561             : CASE(JSOP_DEFCONST)
    3562             : CASE(JSOP_DEFLET)
    3563             : {
    3564             :     LexicalEnvironmentObject* lexicalEnv;
    3565             :     JSObject* varObj;
    3566        2451 :     if (script->hasNonSyntacticScope()) {
    3567         252 :         lexicalEnv = &REGS.fp()->extensibleLexicalEnvironment();
    3568         252 :         varObj = &REGS.fp()->varObj();
    3569             :     } else {
    3570        2199 :         lexicalEnv = &cx->global()->lexicalEnvironment();
    3571        2199 :         varObj = cx->global();
    3572             :     }
    3573        2451 :     if (!DefLexicalOperation(cx, lexicalEnv, varObj, script, REGS.pc))
    3574           0 :         goto error;
    3575             : }
    3576        2451 : END_CASE(JSOP_DEFLET)
    3577             : 
    3578             : CASE(JSOP_DEFFUN)
    3579             : {
    3580             :     /*
    3581             :      * A top-level function defined in Global or Eval code (see ECMA-262
    3582             :      * Ed. 3), or else a SpiderMonkey extension: a named function statement in
    3583             :      * a compound statement (not at the top statement level of global code, or
    3584             :      * at the top level of a function body).
    3585             :      */
    3586        4852 :     ReservedRooted<JSFunction*> fun(&rootFunction0, &REGS.sp[-1].toObject().as<JSFunction>());
    3587        2426 :     if (!DefFunOperation(cx, script, REGS.fp()->environmentChain(), fun))
    3588           0 :         goto error;
    3589        2426 :     REGS.sp--;
    3590             : }
    3591        2426 : END_CASE(JSOP_DEFFUN)
    3592             : 
    3593             : CASE(JSOP_LAMBDA)
    3594             : {
    3595             :     /* Load the specified function object literal. */
    3596       22352 :     ReservedRooted<JSFunction*> fun(&rootFunction0, script->getFunction(GET_UINT32_INDEX(REGS.pc)));
    3597       11176 :     JSObject* obj = Lambda(cx, fun, REGS.fp()->environmentChain());
    3598       11176 :     if (!obj)
    3599           0 :         goto error;
    3600             : 
    3601       11176 :     MOZ_ASSERT(obj->staticPrototype());
    3602       11176 :     PUSH_OBJECT(*obj);
    3603             : }
    3604       11176 : END_CASE(JSOP_LAMBDA)
    3605             : 
    3606             : CASE(JSOP_LAMBDA_ARROW)
    3607             : {
    3608             :     /* Load the specified function object literal. */
    3609        1792 :     ReservedRooted<JSFunction*> fun(&rootFunction0, script->getFunction(GET_UINT32_INDEX(REGS.pc)));
    3610        1792 :     ReservedRooted<Value> newTarget(&rootValue1, REGS.sp[-1]);
    3611         896 :     JSObject* obj = LambdaArrow(cx, fun, REGS.fp()->environmentChain(), newTarget);
    3612         896 :     if (!obj)
    3613           0 :         goto error;
    3614             : 
    3615         896 :     MOZ_ASSERT(obj->staticPrototype());
    3616         896 :     REGS.sp[-1].setObject(*obj);
    3617             : }
    3618         896 : END_CASE(JSOP_LAMBDA_ARROW)
    3619             : 
    3620             : CASE(JSOP_TOASYNC)
    3621             : {
    3622             :     ReservedRooted<JSFunction*> unwrapped(&rootFunction0,
    3623         520 :                                           &REGS.sp[-1].toObject().as<JSFunction>());
    3624         260 :     JSObject* wrapped = WrapAsyncFunction(cx, unwrapped);
    3625         260 :     if (!wrapped)
    3626           0 :         goto error;
    3627             : 
    3628         260 :     REGS.sp[-1].setObject(*wrapped);
    3629             : }
    3630         260 : END_CASE(JSOP_TOASYNC)
    3631             : 
    3632             : CASE(JSOP_TOASYNCGEN)
    3633             : {
    3634             :     ReservedRooted<JSFunction*> unwrapped(&rootFunction0,
    3635           0 :                                           &REGS.sp[-1].toObject().as<JSFunction>());
    3636           0 :     JSObject* wrapped = WrapAsyncGenerator(cx, unwrapped);
    3637           0 :     if (!wrapped)
    3638           0 :         goto error;
    3639             : 
    3640           0 :     REGS.sp[-1].setObject(*wrapped);
    3641             : }
    3642           0 : END_CASE(JSOP_TOASYNCGEN)
    3643             : 
    3644             : CASE(JSOP_TOASYNCITER)
    3645             : {
    3646           0 :     ReservedRooted<JSObject*> iter(&rootObject1, &REGS.sp[-1].toObject());
    3647           0 :     JSObject* asyncIter = CreateAsyncFromSyncIterator(cx, iter);
    3648           0 :     if (!asyncIter)
    3649           0 :         goto error;
    3650             : 
    3651           0 :     REGS.sp[-1].setObject(*asyncIter);
    3652             : }
    3653           0 : END_CASE(JSOP_TOASYNCITER)
    3654             : 
    3655             : CASE(JSOP_SETFUNNAME)
    3656             : {
    3657          10 :     MOZ_ASSERT(REGS.stackDepth() >= 2);
    3658          10 :     FunctionPrefixKind prefixKind = FunctionPrefixKind(GET_UINT8(REGS.pc));
    3659          20 :     ReservedRooted<Value> name(&rootValue0, REGS.sp[-1]);
    3660          20 :     ReservedRooted<JSFunction*> fun(&rootFunction0, &REGS.sp[-2].toObject().as<JSFunction>());
    3661          10 :     if (!SetFunctionNameIfNoOwnName(cx, fun, name, prefixKind))
    3662           0 :         goto error;
    3663             : 
    3664          10 :     REGS.sp--;
    3665             : }
    3666          10 : END_CASE(JSOP_SETFUNNAME)
    3667             : 
    3668             : CASE(JSOP_CALLEE)
    3669          13 :     MOZ_ASSERT(REGS.fp()->isFunctionFrame());
    3670          13 :     PUSH_COPY(REGS.fp()->calleev());
    3671          13 : END_CASE(JSOP_CALLEE)
    3672             : 
    3673             : CASE(JSOP_INITPROP_GETTER)
    3674             : CASE(JSOP_INITHIDDENPROP_GETTER)
    3675             : CASE(JSOP_INITPROP_SETTER)
    3676             : CASE(JSOP_INITHIDDENPROP_SETTER)
    3677             : {
    3678        1009 :     MOZ_ASSERT(REGS.stackDepth() >= 2);
    3679             : 
    3680        2018 :     ReservedRooted<JSObject*> obj(&rootObject0, &REGS.sp[-2].toObject());
    3681        2018 :     ReservedRooted<PropertyName*> name(&rootName0, script->getName(REGS.pc));
    3682        2018 :     ReservedRooted<JSObject*> val(&rootObject1, &REGS.sp[-1].toObject());
    3683             : 
    3684        1009 :     if (!InitGetterSetterOperation(cx, REGS.pc, obj, name, val))
    3685           0 :         goto error;
    3686             : 
    3687        1009 :     REGS.sp--;
    3688             : }
    3689        1009 : END_CASE(JSOP_INITPROP_GETTER)
    3690             : 
    3691             : CASE(JSOP_INITELEM_GETTER)
    3692             : CASE(JSOP_INITHIDDENELEM_GETTER)
    3693             : CASE(JSOP_INITELEM_SETTER)
    3694             : CASE(JSOP_INITHIDDENELEM_SETTER)
    3695             : {
    3696           0 :     MOZ_ASSERT(REGS.stackDepth() >= 3);
    3697             : 
    3698           0 :     ReservedRooted<JSObject*> obj(&rootObject0, &REGS.sp[-3].toObject());
    3699           0 :     ReservedRooted<Value> idval(&rootValue0, REGS.sp[-2]);
    3700           0 :     ReservedRooted<JSObject*> val(&rootObject1, &REGS.sp[-1].toObject());
    3701             : 
    3702           0 :     if (!InitGetterSetterOperation(cx, REGS.pc, obj, idval, val))
    3703           0 :         goto error;
    3704             : 
    3705           0 :     REGS.sp -= 2;
    3706             : }
    3707           0 : END_CASE(JSOP_INITELEM_GETTER)
    3708             : 
    3709             : CASE(JSOP_HOLE)
    3710           0 :     PUSH_MAGIC(JS_ELEMENTS_HOLE);
    3711           0 : END_CASE(JSOP_HOLE)
    3712             : 
    3713             : CASE(JSOP_NEWINIT)
    3714             : {
    3715         470 :     uint8_t i = GET_UINT8(REGS.pc);
    3716         470 :     MOZ_ASSERT(i == JSProto_Array || i == JSProto_Object);
    3717             : 
    3718             :     JSObject* obj;
    3719         470 :     if (i == JSProto_Array)
    3720           0 :         obj = NewArrayOperation(cx, script, REGS.pc, 0);
    3721             :     else
    3722         470 :         obj = NewObjectOperation(cx, script, REGS.pc);
    3723             : 
    3724         470 :     if (!obj)
    3725           0 :         goto error;
    3726         470 :     PUSH_OBJECT(*obj);
    3727             : }
    3728         470 : END_CASE(JSOP_NEWINIT)
    3729             : 
    3730             : CASE(JSOP_NEWARRAY)
    3731             : CASE(JSOP_SPREADCALLARRAY)
    3732             : {
    3733         896 :     uint32_t length = GET_UINT32(REGS.pc);
    3734         896 :     JSObject* obj = NewArrayOperation(cx, script, REGS.pc, length);
    3735         896 :     if (!obj)
    3736           0 :         goto error;
    3737         896 :     PUSH_OBJECT(*obj);
    3738             : }
    3739         896 : END_CASE(JSOP_NEWARRAY)
    3740             : 
    3741             : CASE(JSOP_NEWARRAY_COPYONWRITE)
    3742             : {
    3743        1510 :     ReservedRooted<JSObject*> baseobj(&rootObject0, ObjectGroup::getOrFixupCopyOnWriteObject(cx, script, REGS.pc));
    3744         755 :     if (!baseobj)
    3745           0 :         goto error;
    3746             : 
    3747        1510 :     ReservedRooted<JSObject*> obj(&rootObject1, NewDenseCopyOnWriteArray(cx, ((RootedObject&)(baseobj)).as<ArrayObject>(), gc::DefaultHeap));
    3748         755 :     if (!obj)
    3749           0 :         goto error;
    3750             : 
    3751         755 :     PUSH_OBJECT(*obj);
    3752             : }
    3753         755 : END_CASE(JSOP_NEWARRAY_COPYONWRITE)
    3754             : 
    3755             : CASE(JSOP_NEWOBJECT)
    3756             : {
    3757        2775 :     JSObject* obj = NewObjectOperation(cx, script, REGS.pc);
    3758        2775 :     if (!obj)
    3759           0 :         goto error;
    3760        2775 :     PUSH_OBJECT(*obj);
    3761             : }
    3762        2775 : END_CASE(JSOP_NEWOBJECT)
    3763             : 
    3764             : CASE(JSOP_MUTATEPROTO)
    3765             : {
    3766         101 :     MOZ_ASSERT(REGS.stackDepth() >= 2);
    3767             : 
    3768         101 :     if (REGS.sp[-1].isObjectOrNull()) {
    3769         202 :         ReservedRooted<JSObject*> newProto(&rootObject1, REGS.sp[-1].toObjectOrNull());
    3770         202 :         ReservedRooted<JSObject*> obj(&rootObject0, &REGS.sp[-2].toObject());
    3771         101 :         MOZ_ASSERT(obj->is<PlainObject>());
    3772             : 
    3773         101 :         if (!SetPrototype(cx, obj, newProto))
    3774           0 :             goto error;
    3775             :     }
    3776             : 
    3777         101 :     REGS.sp--;
    3778             : }
    3779         101 : END_CASE(JSOP_MUTATEPROTO)
    3780             : 
    3781             : CASE(JSOP_INITPROP)
    3782             : CASE(JSOP_INITLOCKEDPROP)
    3783             : CASE(JSOP_INITHIDDENPROP)
    3784             : {
    3785             :     static_assert(JSOP_INITPROP_LENGTH == JSOP_INITLOCKEDPROP_LENGTH,
    3786             :                   "initprop and initlockedprop must be the same size");
    3787             :     static_assert(JSOP_INITPROP_LENGTH == JSOP_INITHIDDENPROP_LENGTH,
    3788             :                   "initprop and inithiddenprop must be the same size");
    3789             :     /* Load the property's initial value into rval. */
    3790       13917 :     MOZ_ASSERT(REGS.stackDepth() >= 2);
    3791       27834 :     ReservedRooted<Value> rval(&rootValue0, REGS.sp[-1]);
    3792             : 
    3793             :     /* Load the object being initialized into lval/obj. */
    3794       27834 :     ReservedRooted<JSObject*> obj(&rootObject0, &REGS.sp[-2].toObject());
    3795             : 
    3796       13917 :     PropertyName* name = script->getName(REGS.pc);
    3797             : 
    3798       13917 :     RootedId& id = rootId0;
    3799       13917 :     id = NameToId(name);
    3800             : 
    3801       13917 :     if (!InitPropertyOperation(cx, JSOp(*REGS.pc), obj, id, rval))
    3802           0 :         goto error;
    3803             : 
    3804       13917 :     REGS.sp--;
    3805             : }
    3806       13917 : END_CASE(JSOP_INITPROP)
    3807             : 
    3808             : CASE(JSOP_INITELEM)
    3809             : CASE(JSOP_INITHIDDENELEM)
    3810             : {
    3811         147 :     MOZ_ASSERT(REGS.stackDepth() >= 3);
    3812         147 :     HandleValue val = REGS.stackHandleAt(-1);
    3813         147 :     HandleValue id = REGS.stackHandleAt(-2);
    3814             : 
    3815         294 :     ReservedRooted<JSObject*> obj(&rootObject0, &REGS.sp[-3].toObject());
    3816             : 
    3817         147 :     if (!InitElemOperation(cx, REGS.pc, obj, id, val))
    3818           0 :         goto error;
    3819             : 
    3820         147 :     REGS.sp -= 2;
    3821             : }
    3822         147 : END_CASE(JSOP_INITELEM)
    3823             : 
    3824             : CASE(JSOP_INITELEM_ARRAY)
    3825             : {
    3826        1481 :     MOZ_ASSERT(REGS.stackDepth() >= 2);
    3827        1481 :     HandleValue val = REGS.stackHandleAt(-1);
    3828             : 
    3829        2962 :     ReservedRooted<JSObject*> obj(&rootObject0, &REGS.sp[-2].toObject());
    3830             : 
    3831        1481 :     uint32_t index = GET_UINT32(REGS.pc);
    3832        1481 :     if (!InitArrayElemOperation(cx, REGS.pc, obj, index, val))
    3833           0 :         goto error;
    3834             : 
    3835        1481 :     REGS.sp--;
    3836             : }
    3837        1481 : END_CASE(JSOP_INITELEM_ARRAY)
    3838             : 
    3839             : CASE(JSOP_INITELEM_INC)
    3840             : {
    3841          59 :     MOZ_ASSERT(REGS.stackDepth() >= 3);
    3842          59 :     HandleValue val = REGS.stackHandleAt(-1);
    3843             : 
    3844         118 :     ReservedRooted<JSObject*> obj(&rootObject0, &REGS.sp[-3].toObject());
    3845             : 
    3846          59 :     uint32_t index = REGS.sp[-2].toInt32();
    3847          59 :     if (!InitArrayElemOperation(cx, REGS.pc, obj, index, val))
    3848           0 :         goto error;
    3849             : 
    3850          59 :     REGS.sp[-2].setInt32(index + 1);
    3851          59 :     REGS.sp--;
    3852             : }
    3853          59 : END_CASE(JSOP_INITELEM_INC)
    3854             : 
    3855             : CASE(JSOP_GOSUB)
    3856             : {
    3857          23 :     PUSH_BOOLEAN(false);
    3858          23 :     int32_t i = script->pcToOffset(REGS.pc) + JSOP_GOSUB_LENGTH;
    3859          23 :     int32_t len = GET_JUMP_OFFSET(REGS.pc);
    3860          23 :     PUSH_INT32(i);
    3861          23 :     ADVANCE_AND_DISPATCH(len);
    3862             : }
    3863             : 
    3864             : CASE(JSOP_RETSUB)
    3865             : {
    3866             :     /* Pop [exception or hole, retsub pc-index]. */
    3867          23 :     Value rval, lval;
    3868          23 :     POP_COPY_TO(rval);
    3869          23 :     POP_COPY_TO(lval);
    3870          23 :     MOZ_ASSERT(lval.isBoolean());
    3871          23 :     if (lval.toBoolean()) {
    3872             :         /*
    3873             :          * Exception was pending during finally, throw it *before* we adjust
    3874             :          * pc, because pc indexes into script->trynotes.  This turns out not to
    3875             :          * be necessary, but it seems clearer.  And it points out a FIXME:
    3876             :          * 350509, due to Igor Bukanov.
    3877             :          */
    3878           0 :         cx->setPendingException(rval);
    3879           0 :         goto error;
    3880             :     }
    3881          23 :     MOZ_ASSERT(rval.isInt32());
    3882             : 
    3883             :     /* Increment the PC by this much. */
    3884          23 :     int32_t len = rval.toInt32() - int32_t(script->pcToOffset(REGS.pc));
    3885          23 :     ADVANCE_AND_DISPATCH(len);
    3886             : }
    3887             : 
    3888             : CASE(JSOP_EXCEPTION)
    3889             : {
    3890          66 :     PUSH_NULL();
    3891          66 :     MutableHandleValue res = REGS.stackHandleAt(-1);
    3892          66 :     if (!GetAndClearException(cx, res))
    3893           0 :         goto error;
    3894             : }
    3895          66 : END_CASE(JSOP_EXCEPTION)
    3896             : 
    3897             : CASE(JSOP_FINALLY)
    3898          23 :     CHECK_BRANCH();
    3899          23 : END_CASE(JSOP_FINALLY)
    3900             : 
    3901             : CASE(JSOP_THROWING)
    3902             : {
    3903           0 :     ReservedRooted<Value> v(&rootValue0);
    3904           0 :     POP_COPY_TO(v);
    3905           0 :     MOZ_ALWAYS_TRUE(ThrowingOperation(cx, v));
    3906             : }
    3907           0 : END_CASE(JSOP_THROWING)
    3908             : 
    3909             : CASE(JSOP_THROW)
    3910             : {
    3911           6 :     CHECK_BRANCH();
    3912          12 :     ReservedRooted<Value> v(&rootValue0);
    3913           6 :     POP_COPY_TO(v);
    3914           6 :     JS_ALWAYS_FALSE(Throw(cx, v));
    3915             :     /* let the code at error try to catch the exception. */
    3916           6 :     goto error;
    3917             : }
    3918             : 
    3919             : CASE(JSOP_INSTANCEOF)
    3920             : {
    3921         322 :     ReservedRooted<Value> rref(&rootValue0, REGS.sp[-1]);
    3922         161 :     if (HandleValue(rref).isPrimitive()) {
    3923           0 :         ReportValueError(cx, JSMSG_BAD_INSTANCEOF_RHS, -1, rref, nullptr);
    3924           0 :         goto error;
    3925             :     }
    3926         322 :     ReservedRooted<JSObject*> obj(&rootObject0, &rref.toObject());
    3927         161 :     bool cond = false;
    3928         161 :     if (!HasInstance(cx, obj, REGS.stackHandleAt(-2), &cond))
    3929           0 :         goto error;
    3930         161 :     REGS.sp--;
    3931         161 :     REGS.sp[-1].setBoolean(cond);
    3932             : }
    3933         161 : END_CASE(JSOP_INSTANCEOF)
    3934             : 
    3935             : CASE(JSOP_DEBUGGER)
    3936             : {
    3937           0 :     RootedValue rval(cx);
    3938           0 :     switch (Debugger::onDebuggerStatement(cx, REGS.fp())) {
    3939             :       case JSTRAP_ERROR:
    3940           0 :         goto error;
    3941             :       case JSTRAP_CONTINUE:
    3942           0 :         break;
    3943             :       case JSTRAP_RETURN:
    3944           0 :         if (!ForcedReturn(cx, REGS))
    3945           0 :             goto error;
    3946           0 :         goto successful_return_continuation;
    3947             :       case JSTRAP_THROW:
    3948           0 :         goto error;
    3949             :       default:;
    3950             :     }
    3951             : }
    3952           0 : END_CASE(JSOP_DEBUGGER)
    3953             : 
    3954             : CASE(JSOP_PUSHLEXICALENV)
    3955             : {
    3956         950 :     ReservedRooted<Scope*> scope(&rootScope0, script->getScope(REGS.pc));
    3957             : 
    3958             :     // Create block environment and push on scope chain.
    3959         475 :     if (!REGS.fp()->pushLexicalEnvironment(cx, scope.as<LexicalScope>()))
    3960           0 :         goto error;
    3961             : }
    3962         475 : END_CASE(JSOP_PUSHLEXICALENV)
    3963             : 
    3964             : CASE(JSOP_POPLEXICALENV)
    3965             : {
    3966             : #ifdef DEBUG
    3967             :     // Pop block from scope chain.
    3968         424 :     Scope* scope = script->lookupScope(REGS.pc);
    3969         424 :     MOZ_ASSERT(scope);
    3970         424 :     MOZ_ASSERT(scope->is<LexicalScope>());
    3971         424 :     MOZ_ASSERT(scope->as<LexicalScope>().hasEnvironment());
    3972             : #endif
    3973             : 
    3974         424 :     if (MOZ_UNLIKELY(cx->compartment()->isDebuggee()))
    3975           0 :         DebugEnvironments::onPopLexical(cx, REGS.fp(), REGS.pc);
    3976             : 
    3977             :     // Pop block from scope chain.
    3978         424 :     REGS.fp()->popOffEnvironmentChain<LexicalEnvironmentObject>();
    3979             : }
    3980         424 : END_CASE(JSOP_POPLEXICALENV)
    3981             : 
    3982             : CASE(JSOP_DEBUGLEAVELEXICALENV)
    3983             : {
    3984        2137 :     MOZ_ASSERT(script->lookupScope(REGS.pc));
    3985        2137 :     MOZ_ASSERT(script->lookupScope(REGS.pc)->is<LexicalScope>());
    3986        2137 :     MOZ_ASSERT(!script->lookupScope(REGS.pc)->as<LexicalScope>().hasEnvironment());
    3987             : 
    3988             :     // FIXME: This opcode should not be necessary.  The debugger shouldn't need
    3989             :     // help from bytecode to do its job.  See bug 927782.
    3990             : 
    3991        2137 :     if (MOZ_UNLIKELY(cx->compartment()->isDebuggee()))
    3992           0 :         DebugEnvironments::onPopLexical(cx, REGS.fp(), REGS.pc);
    3993             : }
    3994        2137 : END_CASE(JSOP_DEBUGLEAVELEXICALENV)
    3995             : 
    3996             : CASE(JSOP_FRESHENLEXICALENV)
    3997             : {
    3998           0 :     if (MOZ_UNLIKELY(cx->compartment()->isDebuggee()))
    3999           0 :         DebugEnvironments::onPopLexical(cx, REGS.fp(), REGS.pc);
    4000             : 
    4001           0 :     if (!REGS.fp()->freshenLexicalEnvironment(cx))
    4002           0 :         goto error;
    4003             : }
    4004           0 : END_CASE(JSOP_FRESHENLEXICALENV)
    4005             : 
    4006             : CASE(JSOP_RECREATELEXICALENV)
    4007             : {
    4008          73 :     if (MOZ_UNLIKELY(cx->compartment()->isDebuggee()))
    4009           0 :         DebugEnvironments::onPopLexical(cx, REGS.fp(), REGS.pc);
    4010             : 
    4011          73 :     if (!REGS.fp()->recreateLexicalEnvironment(cx))
    4012           0 :         goto error;
    4013             : }
    4014          73 : END_CASE(JSOP_RECREATELEXICALENV)
    4015             : 
    4016             : CASE(JSOP_PUSHVARENV)
    4017             : {
    4018          64 :     ReservedRooted<Scope*> scope(&rootScope0, script->getScope(REGS.pc));
    4019             : 
    4020          32 :     if (!REGS.fp()->pushVarEnvironment(cx, scope))
    4021           0 :         goto error;
    4022             : }
    4023          32 : END_CASE(JSOP_PUSHVARENV)
    4024             : 
    4025             : CASE(JSOP_POPVARENV)
    4026             : {
    4027             : #ifdef DEBUG
    4028           0 :     Scope* scope = script->lookupScope(REGS.pc);
    4029           0 :     MOZ_ASSERT(scope);
    4030           0 :     MOZ_ASSERT(scope->is<VarScope>());
    4031           0 :     MOZ_ASSERT(scope->as<VarScope>().hasEnvironment());
    4032             : #endif
    4033             : 
    4034           0 :     if (MOZ_UNLIKELY(cx->compartment()->isDebuggee()))
    4035           0 :         DebugEnvironments::onPopVar(cx, REGS.fp(), REGS.pc);
    4036             : 
    4037           0 :     REGS.fp()->popOffEnvironmentChain<VarEnvironmentObject>();
    4038             : }
    4039           0 : END_CASE(JSOP_POPVARENV)
    4040             : 
    4041             : CASE(JSOP_GENERATOR)
    4042             : {
    4043          72 :     MOZ_ASSERT(!cx->isExceptionPending());
    4044          72 :     MOZ_ASSERT(REGS.stackDepth() == 0);
    4045          72 :     JSObject* obj = GeneratorObject::create(cx, REGS.fp());
    4046          72 :     if (!obj)
    4047           0 :         goto error;
    4048          72 :     PUSH_OBJECT(*obj);
    4049             : }
    4050          72 : END_CASE(JSOP_GENERATOR)
    4051             : 
    4052             : CASE(JSOP_INITIALYIELD)
    4053             : {
    4054          72 :     MOZ_ASSERT(!cx->isExceptionPending());
    4055          72 :     MOZ_ASSERT(REGS.fp()->isFunctionFrame());
    4056          72 :     ReservedRooted<JSObject*> obj(&rootObject0, &REGS.sp[-1].toObject());
    4057          72 :     POP_RETURN_VALUE();
    4058          72 :     MOZ_ASSERT(REGS.stackDepth() == 0);
    4059          72 :     if (!GeneratorObject::initialSuspend(cx, obj, REGS.fp(), REGS.pc))
    4060           0 :         goto error;
    4061          72 :     goto successful_return_continuation;
    4062             : }
    4063             : 
    4064             : CASE(JSOP_YIELD)
    4065             : CASE(JSOP_AWAIT)
    4066             : {
    4067         130 :     MOZ_ASSERT(!cx->isExceptionPending());
    4068         130 :     MOZ_ASSERT(REGS.fp()->isFunctionFrame());
    4069         130 :     ReservedRooted<JSObject*> obj(&rootObject0, &REGS.sp[-1].toObject());
    4070         260 :     if (!GeneratorObject::normalSuspend(cx, obj, REGS.fp(), REGS.pc,
    4071         260 :                                         REGS.spForStackDepth(0), REGS.stackDepth() - 2))
    4072             :     {
    4073           0 :         goto error;
    4074             :     }
    4075             : 
    4076         130 :     REGS.sp--;
    4077         130 :     POP_RETURN_VALUE();
    4078             : 
    4079         130 :     goto successful_return_continuation;
    4080             : }
    4081             : 
    4082             : CASE(JSOP_RESUME)
    4083             : {
    4084             :     {
    4085         395 :         ReservedRooted<JSObject*> gen(&rootObject0, &REGS.sp[-2].toObject());
    4086         395 :         ReservedRooted<Value> val(&rootValue0, REGS.sp[-1]);
    4087             :         // popInlineFrame expects there to be an additional value on the stack
    4088             :         // to pop off, so leave "gen" on the stack.
    4089             : 
    4090         198 :         GeneratorObject::ResumeKind resumeKind = GeneratorObject::getResumeKind(REGS.pc);
    4091         198 :         bool ok = GeneratorObject::resume(cx, activation, gen, val, resumeKind);
    4092         198 :         SET_SCRIPT(REGS.fp()->script());
    4093             : 
    4094         198 :         TraceLoggerThread* logger = TraceLoggerForCurrentThread(cx);
    4095         395 :         TraceLoggerEvent scriptEvent(TraceLogger_Scripts, script);
    4096         198 :         TraceLogStartEvent(logger, scriptEvent);
    4097         198 :         TraceLogStartEvent(logger, TraceLogger_Interpreter);
    4098             : 
    4099         198 :         if (!ok)
    4100           1 :             goto error;
    4101             :     }
    4102         197 :     ADVANCE_AND_DISPATCH(0);
    4103             : }
    4104             : 
    4105             : CASE(JSOP_DEBUGAFTERYIELD)
    4106             : {
    4107             :     // No-op in the interpreter, as GeneratorObject::resume takes care of
    4108             :     // fixing up InterpreterFrames.
    4109         197 :     MOZ_ASSERT_IF(REGS.fp()->script()->isDebuggee(), REGS.fp()->isDebuggee());
    4110             : }
    4111         197 : END_CASE(JSOP_DEBUGAFTERYIELD)
    4112             : 
    4113             : CASE(JSOP_FINALYIELDRVAL)
    4114             : {
    4115          47 :     ReservedRooted<JSObject*> gen(&rootObject0, &REGS.sp[-1].toObject());
    4116          47 :     REGS.sp--;
    4117             : 
    4118          47 :     if (!GeneratorObject::finalSuspend(cx, gen)) {
    4119           0 :         interpReturnOK = false;
    4120           0 :         goto return_continuation;
    4121             :     }
    4122             : 
    4123          47 :     goto successful_return_continuation;
    4124             : }
    4125             : 
    4126             : CASE(JSOP_ARRAYPUSH)
    4127             : {
    4128           0 :     ReservedRooted<JSObject*> obj(&rootObject0, &REGS.sp[-1].toObject());
    4129           0 :     if (!NewbornArrayPush(cx, obj, REGS.sp[-2]))
    4130           0 :         goto error;
    4131           0 :     REGS.sp -= 2;
    4132             : }
    4133           0 : END_CASE(JSOP_ARRAYPUSH)
    4134             : 
    4135             : CASE(JSOP_CHECKCLASSHERITAGE)
    4136             : {
    4137          32 :     HandleValue heritage = REGS.stackHandleAt(-1);
    4138             : 
    4139          32 :     if (!CheckClassHeritageOperation(cx, heritage))
    4140           0 :         goto error;
    4141             : }
    4142          32 : END_CASE(JSOP_CHECKCLASSHERITAGE)
    4143             : 
    4144             : CASE(JSOP_BUILTINPROTO)
    4145             : {
    4146           6 :     ReservedRooted<JSObject*> builtin(&rootObject0);
    4147           3 :     MOZ_ASSERT(GET_UINT8(REGS.pc) < JSProto_LIMIT);
    4148           3 :     JSProtoKey key = static_cast<JSProtoKey>(GET_UINT8(REGS.pc));
    4149           3 :     if (!GetBuiltinPrototype(cx, key, &builtin))
    4150           0 :         goto error;
    4151           3 :     PUSH_OBJECT(*builtin);
    4152             : }
    4153           3 : END_CASE(JSOP_BUILTINPROTO)
    4154             : 
    4155             : CASE(JSOP_FUNWITHPROTO)
    4156             : {
    4157          58 :     ReservedRooted<JSObject*> proto(&rootObject1, &REGS.sp[-1].toObject());
    4158             : 
    4159             :     /* Load the specified function object literal. */
    4160          58 :     ReservedRooted<JSFunction*> fun(&rootFunction0, script->getFunction(GET_UINT32_INDEX(REGS.pc)));
    4161             : 
    4162          29 :     JSObject* obj = FunWithProtoOperation(cx, fun, REGS.fp()->environmentChain(), proto);
    4163          29 :     if (!obj)
    4164           0 :         goto error;
    4165             : 
    4166          29 :     REGS.sp[-1].setObject(*obj);
    4167             : }
    4168          29 : END_CASE(JSOP_FUNWITHPROTO)
    4169             : 
    4170             : CASE(JSOP_OBJWITHPROTO)
    4171             : {
    4172          32 :     JSObject* obj = ObjectWithProtoOperation(cx, REGS.stackHandleAt(-1));
    4173          32 :     if (!obj)
    4174           0 :         goto error;
    4175             : 
    4176          32 :     REGS.sp[-1].setObject(*obj);
    4177             : }
    4178          32 : END_CASE(JSOP_OBJWITHPROTO)
    4179             : 
    4180             : CASE(JSOP_INITHOMEOBJECT)
    4181             : {
    4182          19 :     unsigned skipOver = GET_UINT8(REGS.pc);
    4183          19 :     MOZ_ASSERT(REGS.stackDepth() >= skipOver + 2);
    4184             : 
    4185             :     /* Load the function to be initialized */
    4186          38 :     ReservedRooted<JSFunction*> func(&rootFunction0, &REGS.sp[-1].toObject().as<JSFunction>());
    4187          19 :     MOZ_ASSERT(func->allowSuperProperty());
    4188             : 
    4189             :     /* Load the home object */
    4190          38 :     ReservedRooted<JSObject*> obj(&rootObject0);
    4191          19 :     obj = &REGS.sp[int(-2 - skipOver)].toObject();
    4192          19 :     MOZ_ASSERT(obj->is<PlainObject>() || obj->is<UnboxedPlainObject>() || obj->is<JSFunction>());
    4193             : 
    4194          19 :     func->setExtendedSlot(FunctionExtended::METHOD_HOMEOBJECT_SLOT, ObjectValue(*obj));
    4195             : }
    4196          19 : END_CASE(JSOP_INITHOMEOBJECT)
    4197             : 
    4198             : CASE(JSOP_SUPERBASE)
    4199             : {
    4200           5 :     JSFunction& superEnvFunc = GetSuperEnvFunction(cx, REGS);
    4201           5 :     MOZ_ASSERT(superEnvFunc.allowSuperProperty());
    4202           5 :     MOZ_ASSERT(superEnvFunc.nonLazyScript()->needsHomeObject());
    4203           5 :     const Value& homeObjVal = superEnvFunc.getExtendedSlot(FunctionExtended::METHOD_HOMEOBJECT_SLOT);
    4204             : 
    4205          10 :     ReservedRooted<JSObject*> homeObj(&rootObject0, &homeObjVal.toObject());
    4206          10 :     ReservedRooted<JSObject*> superBase(&rootObject1);
    4207           5 :     superBase = HomeObjectSuperBase(cx, homeObj);
    4208           5 :     if (!superBase)
    4209           0 :         goto error;
    4210             : 
    4211           5 :     PUSH_OBJECT(*superBase);
    4212             : }
    4213           5 : END_CASE(JSOP_SUPERBASE)
    4214             : 
    4215             : CASE(JSOP_NEWTARGET)
    4216         619 :     PUSH_COPY(REGS.fp()->newTarget());
    4217         619 :     MOZ_ASSERT(REGS.sp[-1].isObject() || REGS.sp[-1].isUndefined());
    4218         619 : END_CASE(JSOP_NEWTARGET)
    4219             : 
    4220             : CASE(JSOP_SUPERFUN)
    4221             : {
    4222          58 :     ReservedRooted<JSObject*> superEnvFunc(&rootObject0, &GetSuperEnvFunction(cx, REGS));
    4223          58 :     ReservedRooted<JSObject*> superFun(&rootObject1);
    4224          29 :     superFun = SuperFunOperation(cx, superEnvFunc);
    4225          29 :     if (!superFun)
    4226           0 :         goto error;
    4227             : 
    4228          29 :     PUSH_OBJECT(*superFun);
    4229             : }
    4230          29 : END_CASE(JSOP_SUPERFUN)
    4231             : 
    4232             : CASE(JSOP_DERIVEDCONSTRUCTOR)
    4233             : {
    4234           3 :     MOZ_ASSERT(REGS.sp[-1].isObject());
    4235           6 :     ReservedRooted<JSObject*> proto(&rootObject0, &REGS.sp[-1].toObject());
    4236             : 
    4237           3 :     JSFunction* constructor = MakeDefaultConstructor(cx, script, REGS.pc, proto);
    4238           3 :     if (!constructor)
    4239           0 :         goto error;
    4240             : 
    4241           3 :     REGS.sp[-1].setObject(*constructor);
    4242             : }
    4243           3 : END_CASE(JSOP_DERIVEDCONSTRUCTOR)
    4244             : 
    4245             : CASE(JSOP_CLASSCONSTRUCTOR)
    4246             : {
    4247           0 :     JSFunction* constructor = MakeDefaultConstructor(cx, script, REGS.pc, nullptr);
    4248           0 :     if (!constructor)
    4249           0 :         goto error;
    4250           0 :     PUSH_OBJECT(*constructor);
    4251             : }
    4252           0 : END_CASE(JSOP_CLASSCONSTRUCTOR)
    4253             : 
    4254             : CASE(JSOP_CHECKOBJCOERCIBLE)
    4255             : {
    4256         634 :     ReservedRooted<Value> checkVal(&rootValue0, REGS.sp[-1]);
    4257         317 :     if (checkVal.isNullOrUndefined() && !ToObjectFromStack(cx, checkVal))
    4258           0 :         goto error;
    4259             : }
    4260         317 : END_CASE(JSOP_CHECKOBJCOERCIBLE)
    4261             : 
    4262             : CASE(JSOP_DEBUGCHECKSELFHOSTED)
    4263             : {
    4264             : #ifdef DEBUG
    4265         308 :     ReservedRooted<Value> checkVal(&rootValue0, REGS.sp[-1]);
    4266         154 :     if (!Debug_CheckSelfHosted(cx, checkVal))
    4267           0 :         goto error;
    4268             : #endif
    4269             : }
    4270         154 : END_CASE(JSOP_DEBUGCHECKSELFHOSTED)
    4271             : 
    4272             : CASE(JSOP_IS_CONSTRUCTING)
    4273         953 :     PUSH_MAGIC(JS_IS_CONSTRUCTING);
    4274         953 : END_CASE(JSOP_IS_CONSTRUCTING)
    4275             : 
    4276             : DEFAULT()
    4277             : {
    4278             :     char numBuf[12];
    4279           0 :     SprintfLiteral(numBuf, "%d", *REGS.pc);
    4280           0 :     JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_BAD_BYTECODE, numBuf);
    4281           0 :     goto error;
    4282             : }
    4283             : 
    4284             : } /* interpreter loop */
    4285             : 
    4286             :     MOZ_CRASH("Interpreter loop exited via fallthrough");
    4287             : 
    4288             :   error:
    4289          78 :     switch (HandleError(cx, REGS)) {
    4290             :       case SuccessfulReturnContinuation:
    4291           0 :         goto successful_return_continuation;
    4292             : 
    4293             :       case ErrorReturnContinuation:
    4294          12 :         interpReturnOK = false;
    4295          12 :         goto return_continuation;
    4296             : 
    4297             :       case CatchContinuation:
    4298          66 :         ADVANCE_AND_DISPATCH(0);
    4299             : 
    4300             :       case FinallyContinuation: {
    4301             :         /*
    4302             :          * Push (true, exception) pair for finally to indicate that [retsub]
    4303             :          * should rethrow the exception.
    4304             :          */
    4305           0 :         ReservedRooted<Value> exception(&rootValue0);
    4306           0 :         if (!cx->getPendingException(&exception)) {
    4307           0 :             interpReturnOK = false;
    4308           0 :             goto return_continuation;
    4309             :         }
    4310           0 :         PUSH_BOOLEAN(true);
    4311           0 :         PUSH_COPY(exception);
    4312           0 :         cx->clearPendingException();
    4313             :       }
    4314           0 :       ADVANCE_AND_DISPATCH(0);
    4315             :     }
    4316             : 
    4317           0 :     MOZ_CRASH("Invalid HandleError continuation");
    4318             : 
    4319             :   exit:
    4320       10325 :     if (MOZ_LIKELY(!frameHalfInitialized)) {
    4321       10325 :         interpReturnOK = Debugger::onLeaveFrame(cx, REGS.fp(), REGS.pc, interpReturnOK);
    4322             : 
    4323       10325 :         REGS.fp()->epilogue(cx, REGS.pc);
    4324             :     }
    4325             : 
    4326       10325 :     gc::MaybeVerifyBarriers(cx, true);
    4327             : 
    4328       10325 :     TraceLogStopEvent(logger, TraceLogger_Engine);
    4329       10325 :     TraceLogStopEvent(logger, scriptEvent);
    4330             : 
    4331             :     /*
    4332             :      * This path is used when it's guaranteed the method can be finished
    4333             :      * inside the JIT.
    4334             :      */
    4335             :   leave_on_safe_point:
    4336             : 
    4337       10419 :     if (interpReturnOK)
    4338       10408 :         state.setReturnValue(activation.entryFrame()->returnValue());
    4339             : 
    4340       10419 :     return interpReturnOK;
    4341             : 
    4342             :   prologue_error:
    4343           0 :     interpReturnOK = false;
    4344           0 :     frameHalfInitialized = true;
    4345           0 :     goto prologue_return_continuation;
    4346             : }
    4347             : 
    4348             : bool
    4349          84 : js::Throw(JSContext* cx, HandleValue v)
    4350             : {
    4351          84 :     MOZ_ASSERT(!cx->isExceptionPending());
    4352          84 :     cx->setPendingException(v);
    4353          84 :     return false;
    4354             : }
    4355             : 
    4356             : bool
    4357           0 : js::ThrowingOperation(JSContext* cx, HandleValue v)
    4358             : {
    4359             :     // Like js::Throw, but returns |true| instead of |false| to continue
    4360             :     // execution instead of calling the (JIT) exception handler.
    4361             : 
    4362           0 :     MOZ_ASSERT(!cx->isExceptionPending());
    4363           0 :     cx->setPendingException(v);
    4364           0 :     return true;
    4365             : }
    4366             : 
    4367             : bool
    4368       37549 : js::GetProperty(JSContext* cx, HandleValue v, HandlePropertyName name, MutableHandleValue vp)
    4369             : {
    4370       37549 :     if (name == cx->names().length) {
    4371             :         // Fast path for strings, arrays and arguments.
    4372         209 :         if (GetLengthProperty(v, vp))
    4373         113 :             return true;
    4374             :     }
    4375             : 
    4376             :     // Optimize common cases like (2).toString() or "foo".valueOf() to not
    4377             :     // create a wrapper object.
    4378       37436 :     if (v.isPrimitive() && !v.isNullOrUndefined()) {
    4379             :         NativeObject* proto;
    4380         480 :         if (v.isNumber()) {
    4381          15 :             proto = GlobalObject::getOrCreateNumberPrototype(cx, cx->global());
    4382         465 :         } else if (v.isString()) {
    4383         465 :             proto = GlobalObject::getOrCreateStringPrototype(cx, cx->global());
    4384           0 :         } else if (v.isBoolean()) {
    4385           0 :             proto = GlobalObject::getOrCreateBooleanPrototype(cx, cx->global());
    4386             :         } else {
    4387           0 :             MOZ_ASSERT(v.isSymbol());
    4388           0 :             proto = GlobalObject::getOrCreateSymbolPrototype(cx, cx->global());
    4389             :         }
    4390         480 :         if (!proto)
    4391           0 :             return false;
    4392             : 
    4393         480 :         if (GetPropertyPure(cx, proto, NameToId(name), vp.address()))
    4394         480 :             return true;
    4395             :     }
    4396             : 
    4397       73912 :     RootedValue receiver(cx, v);
    4398       73912 :     RootedObject obj(cx, ToObjectFromStack(cx, v));
    4399       36956 :     if (!obj)
    4400           2 :         return false;
    4401             : 
    4402       36954 :     return GetProperty(cx, obj, receiver, name, vp);
    4403             : }
    4404             : 
    4405             : JSObject*
    4406       13898 : js::Lambda(JSContext* cx, HandleFunction fun, HandleObject parent)
    4407             : {
    4408       13898 :     MOZ_ASSERT(!fun->isArrow());
    4409             : 
    4410       27796 :     RootedObject clone(cx, CloneFunctionObjectIfNotSingleton(cx, fun, parent));
    4411       13898 :     if (!clone)
    4412           0 :         return nullptr;
    4413             : 
    4414       13898 :     MOZ_ASSERT(fun->global() == clone->global());
    4415       13898 :     return clone;
    4416             : }
    4417             : 
    4418             : JSObject*
    4419        1227 : js::LambdaArrow(JSContext* cx, HandleFunction fun, HandleObject parent, HandleValue newTargetv)
    4420             : {
    4421        1227 :     MOZ_ASSERT(fun->isArrow());
    4422             : 
    4423        2454 :     RootedObject clone(cx, CloneFunctionObjectIfNotSingleton(cx, fun, parent, nullptr,
    4424        2454 :                                                              TenuredObject));
    4425        1227 :     if (!clone)
    4426           0 :         return nullptr;
    4427             : 
    4428        1227 :     MOZ_ASSERT(clone->as<JSFunction>().isArrow());
    4429        1227 :     clone->as<JSFunction>().setExtendedSlot(0, newTargetv);
    4430             : 
    4431        1227 :     MOZ_ASSERT(fun->global() == clone->global());
    4432        1227 :     return clone;
    4433             : }
    4434             : 
    4435             : bool
    4436        2426 : js::DefFunOperation(JSContext* cx, HandleScript script, HandleObject envChain,
    4437             :                     HandleFunction fun)
    4438             : {
    4439             :     /*
    4440             :      * We define the function as a property of the variable object and not the
    4441             :      * current scope chain even for the case of function expression statements
    4442             :      * and functions defined by eval inside let or with blocks.
    4443             :      */
    4444        4852 :     RootedObject parent(cx, envChain);
    4445        7278 :     while (!parent->isQualifiedVarObj())
    4446        2426 :         parent = parent->enclosingEnvironment();
    4447             : 
    4448             :     /* ES5 10.5 (NB: with subsequent errata). */
    4449        4852 :     RootedPropertyName name(cx, fun->explicitName()->asPropertyName());
    4450             : 
    4451        4852 :     Rooted<PropertyResult> prop(cx);
    4452        4852 :     RootedObject pobj(cx);
    4453        2426 :     if (!LookupProperty(cx, parent, name, &pobj, &prop))
    4454           0 :         return false;
    4455             : 
    4456        4852 :     RootedValue rval(cx, ObjectValue(*fun));
    4457             : 
    4458             :     /*
    4459             :      * ECMA requires functions defined when entering Eval code to be
    4460             :      * impermanent.
    4461             :      */
    4462        2426 :     unsigned attrs = script->isActiveEval()
    4463        2426 :                      ? JSPROP_ENUMERATE
    4464        2426 :                      : JSPROP_ENUMERATE | JSPROP_PERMANENT;
    4465             : 
    4466             :     /* Steps 5d, 5f. */
    4467        2426 :     if (!prop || pobj != parent) {
    4468        2382 :         if (!DefineProperty(cx, parent, name, rval, nullptr, nullptr, attrs))
    4469           0 :             return false;
    4470             : 
    4471        2382 :         return parent->is<GlobalObject>() ? parent->compartment()->addToVarNames(cx, name) : true;
    4472             :     }
    4473             : 
    4474             :     /*
    4475             :      * Step 5e.
    4476             :      *
    4477             :      * A DebugEnvironmentProxy is okay here, and sometimes necessary. If
    4478             :      * Debugger.Frame.prototype.eval defines a function with the same name as an
    4479             :      * extant variable in the frame, the DebugEnvironmentProxy takes care of storing
    4480             :      * the function in the stack frame (for non-aliased variables) or on the
    4481             :      * scope object (for aliased).
    4482             :      */
    4483          44 :     MOZ_ASSERT(parent->isNative() || parent->is<DebugEnvironmentProxy>());
    4484          44 :     if (parent->is<GlobalObject>()) {
    4485          44 :         Shape* shape = prop.shape();
    4486          44 :         if (shape->configurable()) {
    4487          12 :             if (!DefineProperty(cx, parent, name, rval, nullptr, nullptr, attrs))
    4488           0 :                 return false;
    4489             :         } else {
    4490          32 :             MOZ_ASSERT(shape->isDataDescriptor());
    4491          32 :             MOZ_ASSERT(shape->writable());
    4492          32 :             MOZ_ASSERT(shape->enumerable());
    4493             :         }
    4494             : 
    4495             :         // Careful: the presence of a shape, even one appearing to derive from
    4496             :         // a variable declaration, doesn't mean it's in [[VarNames]].
    4497          44 :         if (!parent->compartment()->addToVarNames(cx, name))
    4498           0 :             return false;
    4499             :     }
    4500             : 
    4501             :     /*
    4502             :      * Non-global properties, and global properties which we aren't simply
    4503             :      * redefining, must be set.  First, this preserves their attributes.
    4504             :      * Second, this will produce warnings and/or errors as necessary if the
    4505             :      * specified Call object property is not writable (const).
    4506             :      */
    4507             : 
    4508             :     /* Step 5f. */
    4509          88 :     RootedId id(cx, NameToId(name));
    4510          44 :     return PutProperty(cx, parent, id, rval, script->strict());
    4511             : }
    4512             : 
    4513             : bool
    4514           0 : js::ThrowMsgOperation(JSContext* cx, const unsigned errorNum)
    4515             : {
    4516           0 :     JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, errorNum);
    4517           0 :     return false;
    4518             : }
    4519             : 
    4520             : bool
    4521        1981 : js::GetAndClearException(JSContext* cx, MutableHandleValue res)
    4522             : {
    4523        1981 :     if (!cx->getPendingException(res))
    4524           0 :         return false;
    4525        1981 :     cx->clearPendingException();
    4526             : 
    4527             :     // Allow interrupting deeply nested exception handling.
    4528        1981 :     return CheckForInterrupt(cx);
    4529             : }
    4530             : 
    4531             : template <bool strict>
    4532             : bool
    4533          28 : js::DeletePropertyJit(JSContext* cx, HandleValue v, HandlePropertyName name, bool* bp)
    4534             : {
    4535          56 :     RootedObject obj(cx, ToObjectFromStack(cx, v));
    4536          28 :     if (!obj)
    4537           0 :         return false;
    4538             : 
    4539          56 :     RootedId id(cx, NameToId(name));
    4540          28 :     ObjectOpResult result;
    4541          28 :     if (!DeleteProperty(cx, obj, id, result))
    4542           0 :         return false;
    4543             : 
    4544             :     if (strict) {
    4545          28 :         if (!result)
    4546           0 :             return result.reportError(cx, obj, id);
    4547          28 :         *bp = true;
    4548             :     } else {
    4549           0 :         *bp = result.ok();
    4550             :     }
    4551          28 :     return true;
    4552             : }
    4553             : 
    4554             : template bool js::DeletePropertyJit<true> (JSContext* cx, HandleValue val, HandlePropertyName name,
    4555             :                                            bool* bp);
    4556             : template bool js::DeletePropertyJit<false>(JSContext* cx, HandleValue val, HandlePropertyName name,
    4557             :                                            bool* bp);
    4558             : 
    4559             : template <bool strict>
    4560             : bool
    4561         293 : js::DeleteElementJit(JSContext* cx, HandleValue val, HandleValue index, bool* bp)
    4562             : {
    4563         586 :     RootedObject obj(cx, ToObjectFromStack(cx, val));
    4564         293 :     if (!obj)
    4565           0 :         return false;
    4566             : 
    4567         586 :     RootedId id(cx);
    4568         293 :     if (!ToPropertyKey(cx, index, &id))
    4569           0 :         return false;
    4570         293 :     ObjectOpResult result;
    4571         293 :     if (!DeleteProperty(cx, obj, id, result))
    4572           0 :         return false;
    4573             : 
    4574             :     if (strict) {
    4575           0 :         if (!result)
    4576           0 :             return result.reportError(cx, obj, id);
    4577           0 :         *bp = true;
    4578             :     } else {
    4579         293 :         *bp = result.ok();
    4580             :     }
    4581         293 :     return true;
    4582             : }
    4583             : 
    4584             : template bool js::DeleteElementJit<true> (JSContext*, HandleValue, HandleValue, bool* succeeded);
    4585             : template bool js::DeleteElementJit<false>(JSContext*, HandleValue, HandleValue, bool* succeeded);
    4586             : 
    4587             : bool
    4588           0 : js::GetElement(JSContext* cx, MutableHandleValue lref, HandleValue rref, MutableHandleValue vp)
    4589             : {
    4590           0 :     return GetElementOperation(cx, JSOP_GETELEM, lref, rref, vp);
    4591             : }
    4592             : 
    4593             : bool
    4594           0 : js::CallElement(JSContext* cx, MutableHandleValue lref, HandleValue rref, MutableHandleValue res)
    4595             : {
    4596           0 :     return GetElementOperation(cx, JSOP_CALLELEM, lref, rref, res);
    4597             : }
    4598             : 
    4599             : bool
    4600           0 : js::SetObjectElement(JSContext* cx, HandleObject obj, HandleValue index, HandleValue value,
    4601             :                      bool strict)
    4602             : {
    4603           0 :     RootedId id(cx);
    4604           0 :     if (!ToPropertyKey(cx, index, &id))
    4605           0 :         return false;
    4606           0 :     RootedValue receiver(cx, ObjectValue(*obj));
    4607           0 :     return SetObjectElementOperation(cx, obj, id, value, receiver, strict);
    4608             : }
    4609             : 
    4610             : bool
    4611           0 : js::SetObjectElement(JSContext* cx, HandleObject obj, HandleValue index, HandleValue value,
    4612             :                      bool strict, HandleScript script, jsbytecode* pc)
    4613             : {
    4614           0 :     MOZ_ASSERT(pc);
    4615           0 :     RootedId id(cx);
    4616           0 :     if (!ToPropertyKey(cx, index, &id))
    4617           0 :         return false;
    4618           0 :     RootedValue receiver(cx, ObjectValue(*obj));
    4619           0 :     return SetObjectElementOperation(cx, obj, id, value, receiver, strict, script, pc);
    4620             : }
    4621             : 
    4622             : bool
    4623           0 : js::SetObjectElement(JSContext* cx, HandleObject obj, HandleValue index, HandleValue value,
    4624             :                      HandleValue receiver, bool strict)
    4625             : {
    4626           0 :     RootedId id(cx);
    4627           0 :     if (!ToPropertyKey(cx, index, &id))
    4628           0 :         return false;
    4629           0 :     return SetObjectElementOperation(cx, obj, id, value, receiver, strict);
    4630             : }
    4631             : 
    4632             : bool
    4633        1145 : js::SetObjectElement(JSContext* cx, HandleObject obj, HandleValue index, HandleValue value,
    4634             :                      HandleValue receiver, bool strict, HandleScript script, jsbytecode* pc)
    4635             : {
    4636        1145 :     MOZ_ASSERT(pc);
    4637        2290 :     RootedId id(cx);
    4638        1145 :     if (!ToPropertyKey(cx, index, &id))
    4639           0 :         return false;
    4640        1145 :     return SetObjectElementOperation(cx, obj, id, value, receiver, strict, script, pc);
    4641             : }
    4642             : 
    4643             : bool
    4644           0 : js::InitElementArray(JSContext* cx, jsbytecode* pc, HandleObject obj, uint32_t index, HandleValue value)
    4645             : {
    4646           0 :     return InitArrayElemOperation(cx, pc, obj, index, value);
    4647             : }
    4648             : 
    4649             : bool
    4650         203 : js::AddValues(JSContext* cx, MutableHandleValue lhs, MutableHandleValue rhs, MutableHandleValue res)
    4651             : {
    4652         203 :     return AddOperation(cx, lhs, rhs, res);
    4653             : }
    4654             : 
    4655             : bool
    4656          34 : js::SubValues(JSContext* cx, MutableHandleValue lhs, MutableHandleValue rhs, MutableHandleValue res)
    4657             : {
    4658          34 :     return SubOperation(cx, lhs, rhs, res);
    4659             : }
    4660             : 
    4661             : bool
    4662           0 : js::MulValues(JSContext* cx, MutableHandleValue lhs, MutableHandleValue rhs, MutableHandleValue res)
    4663             : {
    4664           0 :     return MulOperation(cx, lhs, rhs, res);
    4665             : }
    4666             : 
    4667             : bool
    4668           1 : js::DivValues(JSContext* cx, MutableHandleValue lhs, MutableHandleValue rhs, MutableHandleValue res)
    4669             : {
    4670           1 :     return DivOperation(cx, lhs, rhs, res);
    4671             : }
    4672             : 
    4673             : bool
    4674           0 : js::ModValues(JSContext* cx, MutableHandleValue lhs, MutableHandleValue rhs, MutableHandleValue res)
    4675             : {
    4676           0 :     return ModOperation(cx, lhs, rhs, res);
    4677             : }
    4678             : 
    4679             : bool
    4680           0 : js::UrshValues(JSContext* cx, MutableHandleValue lhs, MutableHandleValue rhs, MutableHandleValue res)
    4681             : {
    4682           0 :     return UrshOperation(cx, lhs, rhs, res);
    4683             : }
    4684             : 
    4685             : bool
    4686           0 : js::AtomicIsLockFree(JSContext* cx, HandleValue in, int* out)
    4687             : {
    4688             :     int i;
    4689           0 :     if (!ToInt32(cx, in, &i))
    4690           0 :         return false;
    4691           0 :     *out = js::jit::AtomicOperations::isLockfree(i);
    4692           0 :     return true;
    4693             : }
    4694             : 
    4695             : bool
    4696           0 : js::DeleteNameOperation(JSContext* cx, HandlePropertyName name, HandleObject scopeObj,
    4697             :                         MutableHandleValue res)
    4698             : {
    4699           0 :     RootedObject scope(cx), pobj(cx);
    4700           0 :     Rooted<PropertyResult> prop(cx);
    4701           0 :     if (!LookupName(cx, name, scopeObj, &scope, &pobj, &prop))
    4702           0 :         return false;
    4703             : 
    4704           0 :     if (!scope) {
    4705             :         // Return true for non-existent names.
    4706           0 :         res.setBoolean(true);
    4707           0 :         return true;
    4708             :     }
    4709             : 
    4710           0 :     ObjectOpResult result;
    4711           0 :     RootedId id(cx, NameToId(name));
    4712           0 :     if (!DeleteProperty(cx, scope, id, result))
    4713           0 :         return false;
    4714             : 
    4715           0 :     bool status = result.ok();
    4716           0 :     res.setBoolean(status);
    4717             : 
    4718           0 :     if (status) {
    4719             :         // Deleting a name from the global object removes it from [[VarNames]].
    4720           0 :         if (pobj == scope && scope->is<GlobalObject>())
    4721           0 :             scope->compartment()->removeFromVarNames(name);
    4722             :     }
    4723             : 
    4724           0 :     return true;
    4725             : }
    4726             : 
    4727             : bool
    4728         404 : js::ImplicitThisOperation(JSContext* cx, HandleObject scopeObj, HandlePropertyName name,
    4729             :                           MutableHandleValue res)
    4730             : {
    4731         808 :     RootedObject obj(cx);
    4732         404 :     if (!LookupNameWithGlobalDefault(cx, name, scopeObj, &obj))
    4733           0 :         return false;
    4734             : 
    4735         404 :     res.set(ComputeImplicitThis(obj));
    4736         404 :     return true;
    4737             : }
    4738             : 
    4739             : bool
    4740           8 : js::RunOnceScriptPrologue(JSContext* cx, HandleScript script)
    4741             : {
    4742           8 :     MOZ_ASSERT(script->treatAsRunOnce());
    4743             : 
    4744           8 :     if (!script->hasRunOnce()) {
    4745           8 :         script->setHasRunOnce();
    4746           8 :         return true;
    4747             :     }
    4748             : 
    4749             :     // Force instantiation of the script's function's group to ensure the flag
    4750             :     // is preserved in type information.
    4751           0 :     RootedFunction fun(cx, script->functionNonDelazifying());
    4752           0 :     if (!JSObject::getGroup(cx, fun))
    4753           0 :         return false;
    4754             : 
    4755           0 :     MarkObjectGroupFlags(cx, script->functionNonDelazifying(), OBJECT_FLAG_RUNONCE_INVALIDATED);
    4756           0 :     return true;
    4757             : }
    4758             : 
    4759             : unsigned
    4760       14189 : js::GetInitDataPropAttrs(JSOp op)
    4761             : {
    4762       14189 :     switch (op) {
    4763             :       case JSOP_INITPROP:
    4764       13799 :         return JSPROP_ENUMERATE;
    4765             :       case JSOP_INITLOCKEDPROP:
    4766          64 :         return JSPROP_PERMANENT | JSPROP_READONLY;
    4767             :       case JSOP_INITHIDDENPROP:
    4768             :         // Non-enumerable, but writable and configurable
    4769         326 :         return 0;
    4770             :       default:;
    4771             :     }
    4772           0 :     MOZ_CRASH("Unknown data initprop");
    4773             : }
    4774             : 
    4775             : bool
    4776        1025 : js::InitGetterSetterOperation(JSContext* cx, jsbytecode* pc, HandleObject obj, HandleId id,
    4777             :                               HandleObject val)
    4778             : {
    4779        1025 :     MOZ_ASSERT(val->isCallable());
    4780             :     GetterOp getter;
    4781             :     SetterOp setter;
    4782        1025 :     unsigned attrs = JSPROP_SHARED;
    4783             : 
    4784        1025 :     JSOp op = JSOp(*pc);
    4785             : 
    4786        1025 :     if (!IsHiddenInitOp(op))
    4787        1000 :         attrs |= JSPROP_ENUMERATE;
    4788             : 
    4789        1025 :     if (op == JSOP_INITPROP_GETTER || op == JSOP_INITELEM_GETTER ||
    4790         107 :         op == JSOP_INITHIDDENPROP_GETTER || op == JSOP_INITHIDDENELEM_GETTER)
    4791             :     {
    4792         918 :         getter = CastAsGetterOp(val);
    4793         918 :         setter = nullptr;
    4794         918 :         attrs |= JSPROP_GETTER;
    4795             :     } else {
    4796         107 :         MOZ_ASSERT(op == JSOP_INITPROP_SETTER || op == JSOP_INITELEM_SETTER ||
    4797             :                    op == JSOP_INITHIDDENPROP_SETTER || op == JSOP_INITHIDDENELEM_SETTER);
    4798         107 :         getter = nullptr;
    4799         107 :         setter = CastAsSetterOp(val);
    4800         107 :         attrs |= JSPROP_SETTER;
    4801             :     }
    4802             : 
    4803        2050 :     RootedValue scratch(cx);
    4804        2050 :     return DefineProperty(cx, obj, id, scratch, getter, setter, attrs);
    4805             : }
    4806             : 
    4807             : bool
    4808        1025 : js::InitGetterSetterOperation(JSContext* cx, jsbytecode* pc, HandleObject obj,
    4809             :                               HandlePropertyName name, HandleObject val)
    4810             : {
    4811        2050 :     RootedId id(cx, NameToId(name));
    4812        2050 :     return InitGetterSetterOperation(cx, pc, obj, id, val);
    4813             : }
    4814             : 
    4815             : bool
    4816           0 : js::InitGetterSetterOperation(JSContext* cx, jsbytecode* pc, HandleObject obj, HandleValue idval,
    4817             :                               HandleObject val)
    4818             : {
    4819           0 :     RootedId id(cx);
    4820           0 :     if (!ToPropertyKey(cx, idval, &id))
    4821           0 :         return false;
    4822             : 
    4823           0 :     return InitGetterSetterOperation(cx, pc, obj, id, val);
    4824             : }
    4825             : 
    4826             : bool
    4827          50 : js::SpreadCallOperation(JSContext* cx, HandleScript script, jsbytecode* pc, HandleValue thisv,
    4828             :                         HandleValue callee, HandleValue arr, HandleValue newTarget, MutableHandleValue res)
    4829             : {
    4830         100 :     RootedArrayObject aobj(cx, &arr.toObject().as<ArrayObject>());
    4831          50 :     uint32_t length = aobj->length();
    4832          50 :     JSOp op = JSOp(*pc);
    4833          50 :     bool constructing = op == JSOP_SPREADNEW || op == JSOP_SPREADSUPERCALL;
    4834             : 
    4835             :     // {Construct,Invoke}Args::init does this too, but this gives us a better
    4836             :     // error message.
    4837          50 :     if (length > ARGS_LENGTH_MAX) {
    4838           0 :         JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr,
    4839             :                                   constructing ? JSMSG_TOO_MANY_CON_SPREADARGS
    4840           0 :                                                : JSMSG_TOO_MANY_FUN_SPREADARGS);
    4841           0 :         return false;
    4842             :     }
    4843             : 
    4844             :     // Do our own checks for the callee being a function, as Invoke uses the
    4845             :     // expression decompiler to decompile the callee stack operand based on
    4846             :     // the number of arguments. Spread operations have the callee at sp - 3
    4847             :     // when not constructing, and sp - 4 when constructing.
    4848          50 :     if (callee.isPrimitive()) {
    4849           0 :         return ReportIsNotFunction(cx, callee, 2 + constructing,
    4850           0 :                                    constructing ? CONSTRUCT : NO_CONSTRUCT);
    4851             :     }
    4852             : 
    4853          50 :     if (MOZ_UNLIKELY(!callee.toObject().is<JSFunction>()) && !callee.toObject().callHook()) {
    4854           0 :         return ReportIsNotFunction(cx, callee, 2 + constructing,
    4855           0 :                                    constructing ? CONSTRUCT : NO_CONSTRUCT);
    4856             :     }
    4857             : 
    4858             : #ifdef DEBUG
    4859             :     // The object must be an array with dense elements and no holes. Baseline's
    4860             :     // optimized spread call stubs rely on this.
    4861          50 :     MOZ_ASSERT(!aobj->isIndexed());
    4862          50 :     MOZ_ASSERT(aobj->getDenseInitializedLength() == aobj->length());
    4863         169 :     for (size_t i = 0; i < aobj->length(); i++)
    4864         119 :         MOZ_ASSERT(!aobj->getDenseElement(i).isMagic(JS_ELEMENTS_HOLE));
    4865             : #endif
    4866             : 
    4867          50 :     if (constructing) {
    4868           0 :         if (!StackCheckIsConstructorCalleeNewTarget(cx, callee, newTarget))
    4869           0 :             return false;
    4870             : 
    4871           0 :         ConstructArgs cargs(cx);
    4872           0 :         if (!cargs.init(cx, length))
    4873           0 :             return false;
    4874             : 
    4875           0 :         if (!GetElements(cx, aobj, length, cargs.array()))
    4876           0 :             return false;
    4877             : 
    4878           0 :         RootedObject obj(cx);
    4879           0 :         if (!Construct(cx, callee, cargs, newTarget, &obj))
    4880           0 :             return false;
    4881           0 :         res.setObject(*obj);
    4882             :     } else {
    4883         100 :         InvokeArgs args(cx);
    4884          50 :         if (!args.init(cx, length))
    4885           0 :             return false;
    4886             : 
    4887          50 :         if (!GetElements(cx, aobj, length, args.array()))
    4888           0 :             return false;
    4889             : 
    4890         150 :         if ((op == JSOP_SPREADEVAL || op == JSOP_STRICTSPREADEVAL) &&
    4891          50 :             cx->global()->valueIsEval(callee))
    4892             :         {
    4893           0 :             if (!DirectEval(cx, args.get(0), res))
    4894           0 :                 return false;
    4895             :         } else {
    4896          50 :             MOZ_ASSERT(op == JSOP_SPREADCALL ||
    4897             :                        op == JSOP_SPREADEVAL ||
    4898             :                        op == JSOP_STRICTSPREADEVAL,
    4899             :                        "bad spread opcode");
    4900             : 
    4901          50 :             if (!Call(cx, callee, thisv, args, res))
    4902           0 :                 return false;
    4903             :         }
    4904             :     }
    4905             : 
    4906          50 :     TypeScript::Monitor(cx, script, pc, res);
    4907          50 :     return true;
    4908             : }
    4909             : 
    4910             : bool
    4911           0 : js::OptimizeSpreadCall(JSContext* cx, HandleValue arg, bool* optimized)
    4912             : {
    4913             :     // Optimize spread call by skipping spread operation when following
    4914             :     // conditions are met:
    4915             :     //   * the argument is an array
    4916             :     //   * the array has no hole
    4917             :     //   * array[@@iterator] is not modified
    4918             :     //   * the array's prototype is Array.prototype
    4919             :     //   * Array.prototype[@@iterator] is not modified
    4920             :     //   * %ArrayIteratorPrototype%.next is not modified
    4921           0 :     if (!arg.isObject()) {
    4922           0 :         *optimized = false;
    4923           0 :         return true;
    4924             :     }
    4925             : 
    4926           0 :     RootedObject obj(cx, &arg.toObject());
    4927           0 :     if (!IsPackedArray(obj)) {
    4928           0 :         *optimized = false;
    4929           0 :         return true;
    4930             :     }
    4931             : 
    4932           0 :     ForOfPIC::Chain* stubChain = ForOfPIC::getOrCreate(cx);
    4933           0 :     if (!stubChain)
    4934           0 :         return false;
    4935             : 
    4936           0 :     return stubChain->tryOptimizeArray(cx, obj.as<ArrayObject>(), optimized);
    4937             : }
    4938             : 
    4939             : JSObject*
    4940        4211 : js::NewObjectOperation(JSContext* cx, HandleScript script, jsbytecode* pc,
    4941             :                        NewObjectKind newKind /* = GenericObject */)
    4942             : {
    4943        4211 :     MOZ_ASSERT(newKind != SingletonObject);
    4944             : 
    4945        8422 :     RootedObjectGroup group(cx);
    4946        4211 :     if (ObjectGroup::useSingletonForAllocationSite(script, pc, JSProto_Object)) {
    4947        1307 :         newKind = SingletonObject;
    4948             :     } else {
    4949        2904 :         group = ObjectGroup::allocationSiteGroup(cx, script, pc, JSProto_Object);
    4950        2904 :         if (!group)
    4951           0 :             return nullptr;
    4952        2904 :         if (group->maybePreliminaryObjects()) {
    4953        2314 :             group->maybePreliminaryObjects()->maybeAnalyze(cx, group);
    4954        2314 :             if (group->maybeUnboxedLayout())
    4955          19 :                 group->maybeUnboxedLayout()->setAllocationSite(script, pc);
    4956             :         }
    4957             : 
    4958        2904 :         if (group->shouldPreTenure() || group->maybePreliminaryObjects())
    4959        2270 :             newKind = TenuredObject;
    4960             : 
    4961        2904 :         if (group->maybeUnboxedLayout())
    4962          52 :             return UnboxedPlainObject::create(cx, group, newKind);
    4963             :     }
    4964             : 
    4965        8318 :     RootedObject obj(cx);
    4966             : 
    4967        4159 :     if (*pc == JSOP_NEWOBJECT) {
    4968        7350 :         RootedPlainObject baseObject(cx, &script->getObject(pc)->as<PlainObject>());
    4969        3675 :         obj = CopyInitializerObject(cx, baseObject, newKind);
    4970             :     } else {
    4971         484 :         MOZ_ASSERT(*pc == JSOP_NEWINIT);
    4972         484 :         MOZ_ASSERT(GET_UINT8(pc) == JSProto_Object);
    4973         484 :         obj = NewBuiltinClassInstance<PlainObject>(cx, newKind);
    4974             :     }
    4975             : 
    4976        4159 :     if (!obj)
    4977           0 :         return nullptr;
    4978             : 
    4979        4159 :     if (newKind == SingletonObject) {
    4980        1307 :         if (!JSObject::setSingleton(cx, obj))
    4981           0 :             return nullptr;
    4982             :     } else {
    4983        2852 :         obj->setGroup(group);
    4984             : 
    4985        2852 :         if (PreliminaryObjectArray* preliminaryObjects = group->maybePreliminaryObjects())
    4986        2270 :             preliminaryObjects->registerNewObject(obj);
    4987             :     }
    4988             : 
    4989        4159 :     return obj;
    4990             : }
    4991             : 
    4992             : JSObject*
    4993          32 : js::NewObjectOperationWithTemplate(JSContext* cx, HandleObject templateObject)
    4994             : {
    4995             :     // This is an optimized version of NewObjectOperation for use when the
    4996             :     // object is not a singleton and has had its preliminary objects analyzed,
    4997             :     // with the template object a copy of the object to create.
    4998          32 :     MOZ_ASSERT(!templateObject->isSingleton());
    4999             : 
    5000          32 :     NewObjectKind newKind = templateObject->group()->shouldPreTenure() ? TenuredObject : GenericObject;
    5001             : 
    5002          32 :     if (templateObject->group()->maybeUnboxedLayout()) {
    5003           0 :         RootedObjectGroup group(cx, templateObject->group());
    5004           0 :         return UnboxedPlainObject::create(cx, group, newKind);
    5005             :     }
    5006             : 
    5007          32 :     JSObject* obj = CopyInitializerObject(cx, templateObject.as<PlainObject>(), newKind);
    5008          32 :     if (!obj)
    5009           0 :         return nullptr;
    5010             : 
    5011          32 :     obj->setGroup(templateObject->group());
    5012          32 :     return obj;
    5013             : }
    5014             : 
    5015             : JSObject*
    5016         988 : js::NewArrayOperation(JSContext* cx, HandleScript script, jsbytecode* pc, uint32_t length,
    5017             :                       NewObjectKind newKind /* = GenericObject */)
    5018             : {
    5019         988 :     MOZ_ASSERT(newKind != SingletonObject);
    5020             : 
    5021        1976 :     RootedObjectGroup group(cx);
    5022         988 :     if (ObjectGroup::useSingletonForAllocationSite(script, pc, JSProto_Array)) {
    5023           0 :         newKind = SingletonObject;
    5024             :     } else {
    5025         988 :         group = ObjectGroup::allocationSiteGroup(cx, script, pc, JSProto_Array);
    5026         988 :         if (!group)
    5027           0 :             return nullptr;
    5028         988 :         if (group->maybePreliminaryObjects())
    5029           0 :             group->maybePreliminaryObjects()->maybeAnalyze(cx, group);
    5030             : 
    5031         988 :         if (group->shouldPreTenure() || group->maybePreliminaryObjects())
    5032           0 :             newKind = TenuredObject;
    5033             : 
    5034         988 :         if (group->maybeUnboxedLayout())
    5035           0 :             return UnboxedArrayObject::create(cx, group, length, newKind);
    5036             :     }
    5037             : 
    5038         988 :     ArrayObject* obj = NewDenseFullyAllocatedArray(cx, length, nullptr, newKind);
    5039         988 :     if (!obj)
    5040           0 :         return nullptr;
    5041             : 
    5042         988 :     if (newKind == SingletonObject) {
    5043           0 :         MOZ_ASSERT(obj->isSingleton());
    5044             :     } else {
    5045         988 :         obj->setGroup(group);
    5046             : 
    5047         988 :         if (PreliminaryObjectArray* preliminaryObjects = group->maybePreliminaryObjects())
    5048           0 :             preliminaryObjects->registerNewObject(obj);
    5049             :     }
    5050             : 
    5051         988 :     return obj;
    5052             : }
    5053             : 
    5054             : JSObject*
    5055        1146 : js::NewArrayOperationWithTemplate(JSContext* cx, HandleObject templateObject)
    5056             : {
    5057        1146 :     MOZ_ASSERT(!templateObject->isSingleton());
    5058             : 
    5059        1146 :     NewObjectKind newKind = templateObject->group()->shouldPreTenure() ? TenuredObject : GenericObject;
    5060             : 
    5061        1146 :     if (templateObject->is<UnboxedArrayObject>()) {
    5062           0 :         uint32_t length = templateObject->as<UnboxedArrayObject>().length();
    5063           0 :         RootedObjectGroup group(cx, templateObject->group());
    5064           0 :         return UnboxedArrayObject::create(cx, group, length, newKind);
    5065             :     }
    5066             : 
    5067        2292 :     ArrayObject* obj = NewDenseFullyAllocatedArray(cx, templateObject->as<ArrayObject>().length(),
    5068        1146 :                                                    nullptr, newKind);
    5069        1146 :     if (!obj)
    5070           0 :         return nullptr;
    5071             : 
    5072        1146 :     MOZ_ASSERT(obj->lastProperty() == templateObject->as<ArrayObject>().lastProperty());
    5073        1146 :     obj->setGroup(templateObject->group());
    5074        1146 :     return obj;
    5075             : }
    5076             : 
    5077             : void
    5078           0 : js::ReportRuntimeLexicalError(JSContext* cx, unsigned errorNumber, HandleId id)
    5079             : {
    5080           0 :     MOZ_ASSERT(errorNumber == JSMSG_UNINITIALIZED_LEXICAL ||
    5081             :                errorNumber == JSMSG_BAD_CONST_ASSIGN);
    5082           0 :     JSAutoByteString printable;
    5083           0 :     if (ValueToPrintable(cx, IdToValue(id), &printable))
    5084           0 :         JS_ReportErrorNumberLatin1(cx, GetErrorMessage, nullptr, errorNumber, printable.ptr());
    5085           0 : }
    5086             : 
    5087             : void
    5088           0 : js::ReportRuntimeLexicalError(JSContext* cx, unsigned errorNumber, HandlePropertyName name)
    5089             : {
    5090           0 :     RootedId id(cx, NameToId(name));
    5091           0 :     ReportRuntimeLexicalError(cx, errorNumber, id);
    5092           0 : }
    5093             : 
    5094             : void
    5095           0 : js::ReportRuntimeLexicalError(JSContext* cx, unsigned errorNumber,
    5096             :                               HandleScript script, jsbytecode* pc)
    5097             : {
    5098           0 :     JSOp op = JSOp(*pc);
    5099           0 :     MOZ_ASSERT(op == JSOP_CHECKLEXICAL ||
    5100             :                op == JSOP_CHECKALIASEDLEXICAL ||
    5101             :                op == JSOP_THROWSETCONST ||
    5102             :                op == JSOP_THROWSETALIASEDCONST ||
    5103             :                op == JSOP_THROWSETCALLEE ||
    5104             :                op == JSOP_GETIMPORT);
    5105             : 
    5106           0 :     RootedPropertyName name(cx);
    5107             : 
    5108           0 :     if (op == JSOP_THROWSETCALLEE) {
    5109           0 :         name = script->functionNonDelazifying()->explicitName()->asPropertyName();
    5110           0 :     } else if (IsLocalOp(op)) {
    5111           0 :         name = FrameSlotName(script, pc)->asPropertyName();
    5112           0 :     } else if (IsAtomOp(op)) {
    5113           0 :         name = script->getName(pc);
    5114             :     } else {
    5115           0 :         MOZ_ASSERT(IsAliasedVarOp(op));
    5116           0 :         name = EnvironmentCoordinateName(cx->caches().envCoordinateNameCache, script, pc);
    5117             :     }
    5118             : 
    5119           0 :     ReportRuntimeLexicalError(cx, errorNumber, name);
    5120           0 : }
    5121             : 
    5122             : void
    5123           0 : js::ReportRuntimeRedeclaration(JSContext* cx, HandlePropertyName name, const char* redeclKind)
    5124             : {
    5125           0 :     JSAutoByteString printable;
    5126           0 :     if (AtomToPrintableString(cx, name, &printable)) {
    5127           0 :         JS_ReportErrorNumberLatin1(cx, GetErrorMessage, nullptr, JSMSG_REDECLARED_VAR,
    5128           0 :                                    redeclKind, printable.ptr());
    5129             :     }
    5130           0 : }
    5131             : 
    5132             : bool
    5133           0 : js::ThrowCheckIsObject(JSContext* cx, CheckIsObjectKind kind)
    5134             : {
    5135           0 :     switch (kind) {
    5136             :       case CheckIsObjectKind::IteratorNext:
    5137             :         JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr,
    5138           0 :                                   JSMSG_ITER_METHOD_RETURNED_PRIMITIVE, "next");
    5139           0 :         break;
    5140             :       case CheckIsObjectKind::IteratorReturn:
    5141             :         JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr,
    5142           0 :                                   JSMSG_ITER_METHOD_RETURNED_PRIMITIVE, "return");
    5143           0 :         break;
    5144             :       case CheckIsObjectKind::IteratorThrow:
    5145             :         JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr,
    5146           0 :                                   JSMSG_ITER_METHOD_RETURNED_PRIMITIVE, "throw");
    5147           0 :         break;
    5148             :       case CheckIsObjectKind::GetIterator:
    5149           0 :         JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_GET_ITER_RETURNED_PRIMITIVE);
    5150           0 :         break;
    5151             :       case CheckIsObjectKind::GetAsyncIterator:
    5152             :         JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr,
    5153           0 :                                   JSMSG_GET_ASYNC_ITER_RETURNED_PRIMITIVE);
    5154           0 :         break;
    5155             :       default:
    5156           0 :         MOZ_CRASH("Unknown kind");
    5157             :     }
    5158           0 :     return false;
    5159             : }
    5160             : 
    5161             : bool
    5162           0 : js::ThrowCheckIsCallable(JSContext* cx, CheckIsCallableKind kind)
    5163             : {
    5164           0 :     switch (kind) {
    5165             :       case CheckIsCallableKind::IteratorReturn:
    5166           0 :         JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_RETURN_NOT_CALLABLE);
    5167           0 :         break;
    5168             :       default:
    5169           0 :         MOZ_CRASH("Unknown kind");
    5170             :     }
    5171           0 :     return false;
    5172             : }
    5173             : 
    5174             : bool
    5175           0 : js::ThrowUninitializedThis(JSContext* cx, AbstractFramePtr frame)
    5176             : {
    5177           0 :     RootedFunction fun(cx);
    5178           0 :     if (frame.isFunctionFrame()) {
    5179           0 :         fun = frame.callee();
    5180             :     } else {
    5181             :         Scope* startingScope;
    5182           0 :         if (frame.isDebuggerEvalFrame()) {
    5183           0 :             AbstractFramePtr evalInFramePrev = frame.asInterpreterFrame()->evalInFramePrev();
    5184           0 :             startingScope = evalInFramePrev.script()->bodyScope();
    5185             :         } else {
    5186           0 :             MOZ_ASSERT(frame.isEvalFrame());
    5187           0 :             MOZ_ASSERT(frame.script()->isDirectEvalInFunction());
    5188           0 :             startingScope = frame.script()->enclosingScope();
    5189             :         }
    5190             : 
    5191           0 :         for (ScopeIter si(startingScope); si; si++) {
    5192           0 :             if (si.scope()->is<FunctionScope>()) {
    5193           0 :                 fun = si.scope()->as<FunctionScope>().canonicalFunction();
    5194           0 :                 break;
    5195             :             }
    5196             :         }
    5197           0 :         MOZ_ASSERT(fun);
    5198             :     }
    5199             : 
    5200           0 :     if (fun->isDerivedClassConstructor()) {
    5201           0 :         const char* name = "anonymous";
    5202           0 :         JSAutoByteString str;
    5203           0 :         if (fun->explicitName()) {
    5204           0 :             if (!AtomToPrintableString(cx, fun->explicitName(), &str))
    5205           0 :                 return false;
    5206           0 :             name = str.ptr();
    5207             :         }
    5208             : 
    5209           0 :         JS_ReportErrorNumberLatin1(cx, GetErrorMessage, nullptr, JSMSG_UNINITIALIZED_THIS, name);
    5210           0 :         return false;
    5211             :     }
    5212             : 
    5213           0 :     MOZ_ASSERT(fun->isArrow());
    5214           0 :     JS_ReportErrorNumberUTF8(cx, GetErrorMessage, nullptr, JSMSG_UNINITIALIZED_THIS_ARROW);
    5215           0 :     return false;
    5216             : }
    5217             : 
    5218             : JSObject*
    5219           5 : js::HomeObjectSuperBase(JSContext* cx, HandleObject homeObj)
    5220             : {
    5221          10 :     RootedObject superBase(cx);
    5222             : 
    5223           5 :     if (!GetPrototype(cx, homeObj, &superBase))
    5224           0 :         return nullptr;
    5225             : 
    5226           5 :     if (!superBase) {
    5227             :         JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_CANT_CONVERT_TO,
    5228           0 :                                   "null", "object");
    5229           0 :         return nullptr;
    5230             :     }
    5231             : 
    5232           5 :     return superBase;
    5233             : }
    5234             : 
    5235             : JSObject*
    5236          29 : js::SuperFunOperation(JSContext* cx, HandleObject callee)
    5237             : {
    5238          29 :     MOZ_ASSERT(callee->as<JSFunction>().isClassConstructor());
    5239          29 :     MOZ_ASSERT(callee->as<JSFunction>().nonLazyScript()->isDerivedClassConstructor());
    5240             : 
    5241          58 :     RootedObject superFun(cx);
    5242             : 
    5243          29 :     if (!GetPrototype(cx, callee, &superFun))
    5244           0 :         return nullptr;
    5245             : 
    5246          58 :     RootedValue superFunVal(cx, UndefinedValue());
    5247          29 :     if (!superFun)
    5248           0 :         superFunVal = NullValue();
    5249          29 :     else if (!superFun->isConstructor())
    5250           0 :         superFunVal = ObjectValue(*superFun);
    5251             : 
    5252          29 :     if (superFunVal.isObjectOrNull()) {
    5253           0 :         ReportIsNotFunction(cx, superFunVal, JSDVG_IGNORE_STACK, CONSTRUCT);
    5254           0 :         return nullptr;
    5255             :     }
    5256             : 
    5257          29 :     return superFun;
    5258             : }
    5259             : 
    5260             : bool
    5261           0 : js::ThrowInitializedThis(JSContext* cx, AbstractFramePtr frame)
    5262             : {
    5263           0 :     JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_REINIT_THIS);
    5264           0 :     return false;
    5265             : }
    5266             : 
    5267             : bool
    5268           0 : js::SetPropertySuper(JSContext* cx, HandleObject obj, HandleValue receiver,
    5269             :                      HandlePropertyName name, HandleValue rval, bool strict)
    5270             : {
    5271           0 :     RootedId id(cx, NameToId(name));
    5272           0 :     ObjectOpResult result;
    5273           0 :     if (!SetProperty(cx, obj, id, rval, receiver, result))
    5274           0 :         return false;
    5275             : 
    5276           0 :     return result.checkStrictErrorOrWarning(cx, obj, id, strict);
    5277             : }

Generated by: LCOV version 1.13