LCOV - code coverage report
Current view: top level - js/src/jit - VMFunctions.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 168 765 22.0 %
Date: 2018-08-07 16:42:27 Functions: 0 0 -
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             : #include "jit/VMFunctions.h"
       8             : 
       9             : #include "builtin/TypedObject.h"
      10             : #include "frontend/BytecodeCompiler.h"
      11             : #include "jit/arm/Simulator-arm.h"
      12             : #include "jit/BaselineIC.h"
      13             : #include "jit/JitFrames.h"
      14             : #include "jit/JitRealm.h"
      15             : #include "jit/mips32/Simulator-mips32.h"
      16             : #include "jit/mips64/Simulator-mips64.h"
      17             : #include "vm/ArrayObject.h"
      18             : #include "vm/Debugger.h"
      19             : #include "vm/Interpreter.h"
      20             : #include "vm/SelfHosting.h"
      21             : #include "vm/TraceLogging.h"
      22             : 
      23             : #include "jit/BaselineFrame-inl.h"
      24             : #include "jit/JitFrames-inl.h"
      25             : #include "vm/Debugger-inl.h"
      26             : #include "vm/Interpreter-inl.h"
      27             : #include "vm/NativeObject-inl.h"
      28             : #include "vm/StringObject-inl.h"
      29             : #include "vm/TypeInference-inl.h"
      30             : #include "vm/UnboxedObject-inl.h"
      31             : 
      32             : using namespace js;
      33             : using namespace js::jit;
      34             : 
      35             : namespace js {
      36             : namespace jit {
      37             : 
      38             : // Statics are initialized to null.
      39             : /* static */ VMFunction* VMFunction::functions;
      40             : 
      41           0 : AutoDetectInvalidation::AutoDetectInvalidation(JSContext* cx, MutableHandleValue rval)
      42             :   : cx_(cx),
      43           0 :     ionScript_(GetTopJitJSScript(cx)->ionScript()),
      44             :     rval_(rval),
      45           0 :     disabled_(false)
      46           0 : { }
      47             : 
      48             : bool
      49           0 : InvokeFunction(JSContext* cx, HandleObject obj, bool constructing, bool ignoresReturnValue,
      50             :                uint32_t argc, Value* argv, MutableHandleValue rval)
      51             : {
      52           0 :     TraceLoggerThread* logger = TraceLoggerForCurrentThread(cx);
      53           0 :     TraceLogStartEvent(logger, TraceLogger_Call);
      54             : 
      55           0 :     AutoArrayRooter argvRoot(cx, argc + 1 + constructing, argv);
      56             : 
      57             :     // Data in the argument vector is arranged for a JIT -> JIT call.
      58           0 :     RootedValue thisv(cx, argv[0]);
      59           0 :     Value* argvWithoutThis = argv + 1;
      60             : 
      61           0 :     RootedValue fval(cx, ObjectValue(*obj));
      62           0 :     if (constructing) {
      63           0 :         if (!IsConstructor(fval)) {
      64           0 :             ReportValueError(cx, JSMSG_NOT_CONSTRUCTOR, JSDVG_IGNORE_STACK, fval, nullptr);
      65           0 :             return false;
      66             :         }
      67             : 
      68           0 :         ConstructArgs cargs(cx);
      69           0 :         if (!cargs.init(cx, argc))
      70             :             return false;
      71             : 
      72           0 :         for (uint32_t i = 0; i < argc; i++)
      73           0 :             cargs[i].set(argvWithoutThis[i]);
      74             : 
      75           0 :         RootedValue newTarget(cx, argvWithoutThis[argc]);
      76             : 
      77             :         // If |this| hasn't been created, or is JS_UNINITIALIZED_LEXICAL,
      78             :         // we can use normal construction code without creating an extraneous
      79             :         // object.
      80           0 :         if (thisv.isMagic()) {
      81           0 :             MOZ_ASSERT(thisv.whyMagic() == JS_IS_CONSTRUCTING ||
      82             :                        thisv.whyMagic() == JS_UNINITIALIZED_LEXICAL);
      83             : 
      84           0 :             RootedObject obj(cx);
      85           0 :             if (!Construct(cx, fval, cargs, newTarget, &obj))
      86             :                 return false;
      87             : 
      88           0 :             rval.setObject(*obj);
      89           0 :             return true;
      90             :         }
      91             : 
      92             :         // Otherwise the default |this| has already been created.  We could
      93             :         // almost perform a *call* at this point, but we'd break |new.target|
      94             :         // in the function.  So in this one weird case we call a one-off
      95             :         // construction path that *won't* set |this| to JS_IS_CONSTRUCTING.
      96           0 :         return InternalConstructWithProvidedThis(cx, fval, thisv, cargs, newTarget, rval);
      97             :     }
      98             : 
      99           0 :     InvokeArgsMaybeIgnoresReturnValue args(cx, ignoresReturnValue);
     100           0 :     if (!args.init(cx, argc))
     101             :         return false;
     102             : 
     103           0 :     for (size_t i = 0; i < argc; i++)
     104           0 :         args[i].set(argvWithoutThis[i]);
     105             : 
     106           0 :     return Call(cx, fval, thisv, args, rval);
     107             : }
     108             : 
     109             : bool
     110           0 : InvokeFunctionShuffleNewTarget(JSContext* cx, HandleObject obj, uint32_t numActualArgs,
     111             :                                uint32_t numFormalArgs, Value* argv, MutableHandleValue rval)
     112             : {
     113           0 :     MOZ_ASSERT(numFormalArgs > numActualArgs);
     114           0 :     argv[1 + numActualArgs] = argv[1 + numFormalArgs];
     115           0 :     return InvokeFunction(cx, obj, true, false, numActualArgs, argv, rval);
     116             : }
     117             : 
     118             : bool
     119           0 : InvokeFromInterpreterStub(JSContext* cx, InterpreterStubExitFrameLayout* frame)
     120             : {
     121           0 :     JitFrameLayout* jsFrame = frame->jsFrame();
     122           0 :     CalleeToken token = jsFrame->calleeToken();
     123             : 
     124           0 :     Value* argv = jsFrame->argv();
     125           0 :     uint32_t numActualArgs = jsFrame->numActualArgs();
     126           0 :     bool constructing = CalleeTokenIsConstructing(token);
     127           0 :     RootedFunction fun(cx, CalleeTokenToFunction(token));
     128             : 
     129             :     // Ensure new.target immediately follows the actual arguments (the arguments
     130             :     // rectifier added padding). See also InvokeFunctionShuffleNewTarget.
     131           0 :     if (constructing && numActualArgs < fun->nargs())
     132           0 :         argv[1 + numActualArgs] = argv[1 + fun->nargs()];
     133             : 
     134           0 :     RootedValue rval(cx);
     135           0 :     if (!InvokeFunction(cx, fun, constructing,
     136             :                         /* ignoresReturnValue = */ false,
     137             :                         numActualArgs, argv, &rval))
     138             :     {
     139             :         return false;
     140             :     }
     141             : 
     142             :     // Overwrite |this| with the return value.
     143           0 :     argv[0] = rval;
     144           0 :     return true;
     145             : }
     146             : 
     147             : #ifdef JS_SIMULATOR
     148             : static bool
     149             : CheckSimulatorRecursionLimitWithExtra(JSContext* cx, uint32_t extra)
     150             : {
     151             :     if (cx->simulator()->overRecursedWithExtra(extra)) {
     152             :         ReportOverRecursed(cx);
     153             :         return false;
     154             :     }
     155             :     return true;
     156             : }
     157             : #endif
     158             : 
     159             : bool
     160           0 : CheckOverRecursed(JSContext* cx)
     161             : {
     162             :     // We just failed the jitStackLimit check. There are two possible reasons:
     163             :     //  - jitStackLimit was the real stack limit and we're over-recursed
     164             :     //  - jitStackLimit was set to UINTPTR_MAX by JSRuntime::requestInterrupt
     165             :     //    and we need to call JSRuntime::handleInterrupt.
     166             : #ifdef JS_SIMULATOR
     167             :     if (!CheckSimulatorRecursionLimitWithExtra(cx, 0))
     168             :         return false;
     169             : #else
     170           0 :     if (!CheckRecursionLimit(cx))
     171             :         return false;
     172             : #endif
     173           0 :     gc::MaybeVerifyBarriers(cx);
     174           0 :     return cx->handleInterrupt();
     175             : }
     176             : 
     177             : // This function can get called in two contexts.  In the usual context, it's
     178             : // called with earlyCheck=false, after the env chain has been initialized on
     179             : // a baseline frame.  In this case, it's ok to throw an exception, so a failed
     180             : // stack check returns false, and a successful stack check promps a check for
     181             : // an interrupt from the runtime, which may also cause a false return.
     182             : //
     183             : // In the second case, it's called with earlyCheck=true, prior to frame
     184             : // initialization.  An exception cannot be thrown in this instance, so instead
     185             : // an error flag is set on the frame and true returned.
     186             : bool
     187           0 : CheckOverRecursedWithExtra(JSContext* cx, BaselineFrame* frame,
     188             :                            uint32_t extra, uint32_t earlyCheck)
     189             : {
     190           0 :     MOZ_ASSERT_IF(earlyCheck, !frame->overRecursed());
     191             : 
     192             :     // See |CheckOverRecursed| above.  This is a variant of that function which
     193             :     // accepts an argument holding the extra stack space needed for the Baseline
     194             :     // frame that's about to be pushed.
     195             :     uint8_t spDummy;
     196           0 :     uint8_t* checkSp = (&spDummy) - extra;
     197           0 :     if (earlyCheck) {
     198             : #ifdef JS_SIMULATOR
     199             :         (void)checkSp;
     200             :         if (!CheckSimulatorRecursionLimitWithExtra(cx, extra))
     201             :             frame->setOverRecursed();
     202             : #else
     203           0 :         if (!CheckRecursionLimitWithStackPointer(cx, checkSp))
     204           0 :             frame->setOverRecursed();
     205             : #endif
     206             :         return true;
     207             :     }
     208             : 
     209             :     // The OVERRECURSED flag may have already been set on the frame by an
     210             :     // early over-recursed check.  If so, throw immediately.
     211           0 :     if (frame->overRecursed())
     212             :         return false;
     213             : 
     214             : #ifdef JS_SIMULATOR
     215             :     if (!CheckSimulatorRecursionLimitWithExtra(cx, extra))
     216             :         return false;
     217             : #else
     218           0 :     if (!CheckRecursionLimitWithStackPointer(cx, checkSp))
     219             :         return false;
     220             : #endif
     221             : 
     222           0 :     gc::MaybeVerifyBarriers(cx);
     223           0 :     return cx->handleInterrupt();
     224             : }
     225             : 
     226             : JSObject*
     227           0 : BindVar(JSContext* cx, HandleObject envChain)
     228             : {
     229           0 :     JSObject* obj = envChain;
     230           0 :     while (!obj->isQualifiedVarObj())
     231           0 :         obj = obj->enclosingEnvironment();
     232           0 :     MOZ_ASSERT(obj);
     233           0 :     return obj;
     234             : }
     235             : 
     236             : bool
     237           0 : DefVar(JSContext* cx, HandlePropertyName dn, unsigned attrs, HandleObject envChain)
     238             : {
     239             :     // Given the ScopeChain, extract the VarObj.
     240           0 :     RootedObject obj(cx, BindVar(cx, envChain));
     241           0 :     return DefVarOperation(cx, obj, dn, attrs);
     242             : }
     243             : 
     244             : bool
     245           0 : DefLexical(JSContext* cx, HandlePropertyName dn, unsigned attrs, HandleObject envChain)
     246             : {
     247             :     // Find the extensible lexical scope.
     248             :     Rooted<LexicalEnvironmentObject*> lexicalEnv(cx,
     249           0 :         &NearestEnclosingExtensibleLexicalEnvironment(envChain));
     250             : 
     251             :     // Find the variables object.
     252           0 :     RootedObject varObj(cx, BindVar(cx, envChain));
     253           0 :     return DefLexicalOperation(cx, lexicalEnv, varObj, dn, attrs);
     254             : }
     255             : 
     256             : bool
     257           0 : DefGlobalLexical(JSContext* cx, HandlePropertyName dn, unsigned attrs)
     258             : {
     259           0 :     Rooted<LexicalEnvironmentObject*> globalLexical(cx, &cx->global()->lexicalEnvironment());
     260           0 :     return DefLexicalOperation(cx, globalLexical, cx->global(), dn, attrs);
     261             : }
     262             : 
     263             : bool
     264           0 : MutatePrototype(JSContext* cx, HandlePlainObject obj, HandleValue value)
     265             : {
     266           0 :     if (!value.isObjectOrNull())
     267             :         return true;
     268             : 
     269           0 :     RootedObject newProto(cx, value.toObjectOrNull());
     270           0 :     return SetPrototype(cx, obj, newProto);
     271             : }
     272             : 
     273             : template<bool Equal>
     274             : bool
     275           0 : LooselyEqual(JSContext* cx, MutableHandleValue lhs, MutableHandleValue rhs, bool* res)
     276             : {
     277           0 :     if (!js::LooselyEqual(cx, lhs, rhs, res))
     278             :         return false;
     279             :     if (!Equal)
     280           0 :         *res = !*res;
     281           0 :     return true;
     282             : }
     283             : 
     284             : template bool LooselyEqual<true>(JSContext* cx, MutableHandleValue lhs, MutableHandleValue rhs, bool* res);
     285             : template bool LooselyEqual<false>(JSContext* cx, MutableHandleValue lhs, MutableHandleValue rhs, bool* res);
     286             : 
     287             : template<bool Equal>
     288             : bool
     289           0 : StrictlyEqual(JSContext* cx, MutableHandleValue lhs, MutableHandleValue rhs, bool* res)
     290             : {
     291           0 :     if (!js::StrictlyEqual(cx, lhs, rhs, res))
     292             :         return false;
     293             :     if (!Equal)
     294           0 :         *res = !*res;
     295           0 :     return true;
     296             : }
     297             : 
     298             : template bool StrictlyEqual<true>(JSContext* cx, MutableHandleValue lhs, MutableHandleValue rhs, bool* res);
     299             : template bool StrictlyEqual<false>(JSContext* cx, MutableHandleValue lhs, MutableHandleValue rhs, bool* res);
     300             : 
     301             : bool
     302           0 : LessThan(JSContext* cx, MutableHandleValue lhs, MutableHandleValue rhs, bool* res)
     303             : {
     304           0 :     return LessThanOperation(cx, lhs, rhs, res);
     305             : }
     306             : 
     307             : bool
     308           0 : LessThanOrEqual(JSContext* cx, MutableHandleValue lhs, MutableHandleValue rhs, bool* res)
     309             : {
     310           0 :     return LessThanOrEqualOperation(cx, lhs, rhs, res);
     311             : }
     312             : 
     313             : bool
     314           0 : GreaterThan(JSContext* cx, MutableHandleValue lhs, MutableHandleValue rhs, bool* res)
     315             : {
     316           0 :     return GreaterThanOperation(cx, lhs, rhs, res);
     317             : }
     318             : 
     319             : bool
     320           0 : GreaterThanOrEqual(JSContext* cx, MutableHandleValue lhs, MutableHandleValue rhs, bool* res)
     321             : {
     322           0 :     return GreaterThanOrEqualOperation(cx, lhs, rhs, res);
     323             : }
     324             : 
     325             : template<bool Equal>
     326             : bool
     327           0 : StringsEqual(JSContext* cx, HandleString lhs, HandleString rhs, bool* res)
     328             : {
     329           0 :     if (!js::EqualStrings(cx, lhs, rhs, res))
     330             :         return false;
     331             :     if (!Equal)
     332           0 :         *res = !*res;
     333           0 :     return true;
     334             : }
     335             : 
     336             : template bool StringsEqual<true>(JSContext* cx, HandleString lhs, HandleString rhs, bool* res);
     337             : template bool StringsEqual<false>(JSContext* cx, HandleString lhs, HandleString rhs, bool* res);
     338             : 
     339             : typedef bool (*StringCompareFn)(JSContext*, HandleString, HandleString, bool*);
     340           1 : const VMFunction StringsEqualInfo =
     341           3 :     FunctionInfo<StringCompareFn>(jit::StringsEqual<true>, "StringsEqual");
     342           1 : const VMFunction StringsNotEqualInfo =
     343           0 :     FunctionInfo<StringCompareFn>(jit::StringsEqual<false>, "StringsEqual");
     344             : 
     345         201 : bool StringSplitHelper(JSContext* cx, HandleString str, HandleString sep,
     346             :                        HandleObjectGroup group, uint32_t limit,
     347             :                        MutableHandleValue result)
     348             : {
     349         201 :     JSObject* resultObj = str_split_string(cx, group, str, sep, limit);
     350         201 :     if (!resultObj)
     351             :         return false;
     352             : 
     353           0 :     result.setObject(*resultObj);
     354         201 :     return true;
     355             : }
     356             : 
     357             : 
     358             : bool
     359           0 : ArrayPopDense(JSContext* cx, HandleObject obj, MutableHandleValue rval)
     360             : {
     361           0 :     MOZ_ASSERT(obj->is<ArrayObject>());
     362             : 
     363           0 :     AutoDetectInvalidation adi(cx, rval);
     364             : 
     365           0 :     JS::AutoValueArray<2> argv(cx);
     366           0 :     argv[0].setUndefined();
     367           0 :     argv[1].setObject(*obj);
     368           0 :     if (!js::array_pop(cx, 0, argv.begin()))
     369             :         return false;
     370             : 
     371             :     // If the result is |undefined|, the array was probably empty and we
     372             :     // have to monitor the return value.
     373           0 :     rval.set(argv[0]);
     374           0 :     if (rval.isUndefined())
     375           0 :         TypeScript::Monitor(cx, rval);
     376             :     return true;
     377             : }
     378             : 
     379             : bool
     380           0 : ArrayPushDense(JSContext* cx, HandleArrayObject arr, HandleValue v, uint32_t* length)
     381             : {
     382           6 :     *length = arr->length();
     383           6 :     DenseElementResult result = arr->setOrExtendDenseElements(cx, *length, v.address(), 1,
     384           3 :                                                               ShouldUpdateTypes::DontUpdate);
     385           3 :     if (result != DenseElementResult::Incomplete) {
     386           3 :         (*length)++;
     387           3 :         return result == DenseElementResult::Success;
     388             :     }
     389             : 
     390             :     // AutoDetectInvalidation uses GetTopJitJSScript(cx)->ionScript(), but it's
     391             :     // possible the setOrExtendDenseElements call already invalidated the
     392             :     // IonScript. JSJitFrameIter::ionScript works when the script is invalidated
     393             :     // so we use that instead.
     394           0 :     JSJitFrameIter frame(cx->activation()->asJit());
     395           0 :     MOZ_ASSERT(frame.type() == JitFrame_Exit);
     396           0 :     ++frame;
     397           0 :     IonScript* ionScript = frame.ionScript();
     398             : 
     399           0 :     JS::AutoValueArray<3> argv(cx);
     400           0 :     AutoDetectInvalidation adi(cx, argv[0], ionScript);
     401           0 :     argv[0].setUndefined();
     402           0 :     argv[1].setObject(*arr);
     403           0 :     argv[2].set(v);
     404           0 :     if (!js::array_push(cx, 1, argv.begin()))
     405             :         return false;
     406             : 
     407           0 :     if (argv[0].isInt32()) {
     408           0 :         *length = argv[0].toInt32();
     409           0 :         return true;
     410             :     }
     411             : 
     412             :     // array_push changed the length to be larger than INT32_MAX. In this case
     413             :     // OBJECT_FLAG_LENGTH_OVERFLOW was set, TI invalidated the script, and the
     414             :     // AutoDetectInvalidation instance on the stack will replace *length with
     415             :     // the actual return value during bailout.
     416           0 :     MOZ_ASSERT(adi.shouldSetReturnOverride());
     417           0 :     MOZ_ASSERT(argv[0].toDouble() == double(INT32_MAX) + 1);
     418           0 :     *length = 0;
     419           0 :     return true;
     420             : }
     421             : 
     422             : bool
     423           0 : ArrayShiftDense(JSContext* cx, HandleObject obj, MutableHandleValue rval)
     424             : {
     425           0 :     MOZ_ASSERT(obj->is<ArrayObject>());
     426             : 
     427           0 :     AutoDetectInvalidation adi(cx, rval);
     428             : 
     429           0 :     JS::AutoValueArray<2> argv(cx);
     430           0 :     argv[0].setUndefined();
     431           0 :     argv[1].setObject(*obj);
     432           0 :     if (!js::array_shift(cx, 0, argv.begin()))
     433             :         return false;
     434             : 
     435             :     // If the result is |undefined|, the array was probably empty and we
     436             :     // have to monitor the return value.
     437           0 :     rval.set(argv[0]);
     438           0 :     if (rval.isUndefined())
     439           0 :         TypeScript::Monitor(cx, rval);
     440             :     return true;
     441             : }
     442             : 
     443             : JSString*
     444           0 : ArrayJoin(JSContext* cx, HandleObject array, HandleString sep)
     445             : {
     446           0 :     JS::AutoValueArray<3> argv(cx);
     447           0 :     argv[0].setUndefined();
     448           0 :     argv[1].setObject(*array);
     449           0 :     argv[2].setString(sep);
     450           0 :     if (!js::array_join(cx, 1, argv.begin()))
     451             :         return nullptr;
     452           0 :     return argv[0].toString();
     453             : }
     454             : 
     455             : bool
     456         235 : SetArrayLength(JSContext* cx, HandleObject obj, HandleValue value, bool strict)
     457             : {
     458         235 :     Handle<ArrayObject*> array = obj.as<ArrayObject>();
     459             : 
     460        1175 :     RootedId id(cx, NameToId(cx->names().length));
     461         235 :     ObjectOpResult result;
     462             : 
     463             :     // SetArrayLength is called by IC stubs for SetProp and SetElem on arrays'
     464             :     // "length" property.
     465             :     //
     466             :     // ArraySetLength below coerces |value| before checking for length being
     467             :     // writable, and in the case of illegal values, will throw RangeError even
     468             :     // when "length" is not writable. This is incorrect observable behavior,
     469             :     // as a regular [[Set]] operation will check for "length" being
     470             :     // writable before attempting any assignment.
     471             :     //
     472             :     // So, perform ArraySetLength if and only if "length" is writable.
     473         470 :     if (array->lengthIsWritable()) {
     474           0 :         if (!ArraySetLength(cx, array, id, JSPROP_PERMANENT, value, result))
     475             :             return false;
     476             :     } else {
     477           0 :         MOZ_ALWAYS_TRUE(result.fail(JSMSG_READ_ONLY));
     478             :     }
     479             : 
     480         470 :     return result.checkStrictErrorOrWarning(cx, obj, id, strict);
     481             : }
     482             : 
     483             : bool
     484           0 : CharCodeAt(JSContext* cx, HandleString str, int32_t index, uint32_t* code)
     485             : {
     486             :     char16_t c;
     487           0 :     if (!str->getChar(cx, index, &c))
     488             :         return false;
     489           0 :     *code = c;
     490           0 :     return true;
     491             : }
     492             : 
     493             : JSFlatString*
     494           0 : StringFromCharCode(JSContext* cx, int32_t code)
     495             : {
     496           0 :     char16_t c = char16_t(code);
     497             : 
     498           0 :     if (StaticStrings::hasUnit(c))
     499           0 :         return cx->staticStrings().getUnit(c);
     500             : 
     501           0 :     return NewStringCopyNDontDeflate<CanGC>(cx, &c, 1);
     502             : }
     503             : 
     504             : JSString*
     505           0 : StringFromCodePoint(JSContext* cx, int32_t codePoint)
     506             : {
     507           0 :     RootedValue rval(cx, Int32Value(codePoint));
     508           0 :     if (!str_fromCodePoint_one_arg(cx, rval, &rval))
     509             :         return nullptr;
     510             : 
     511           0 :     return rval.toString();
     512             : }
     513             : 
     514             : bool
     515           6 : SetProperty(JSContext* cx, HandleObject obj, HandlePropertyName name, HandleValue value,
     516             :             bool strict, jsbytecode* pc)
     517             : {
     518          18 :     RootedId id(cx, NameToId(name));
     519             : 
     520           0 :     JSOp op = JSOp(*pc);
     521             : 
     522           0 :     if (op == JSOP_SETALIASEDVAR || op == JSOP_INITALIASEDLEXICAL) {
     523             :         // Aliased var assigns ignore readonly attributes on the property, as
     524             :         // required for initializing 'const' closure variables.
     525           0 :         Shape* shape = obj->as<NativeObject>().lookup(cx, name);
     526           0 :         MOZ_ASSERT(shape && shape->isDataProperty());
     527           0 :         obj->as<NativeObject>().setSlotWithType(cx, shape, value);
     528           0 :         return true;
     529             :     }
     530             : 
     531           0 :     RootedValue receiver(cx, ObjectValue(*obj));
     532           6 :     ObjectOpResult result;
     533          12 :     if (MOZ_LIKELY(!obj->getOpsSetProperty())) {
     534           6 :         if (op == JSOP_SETNAME || op == JSOP_STRICTSETNAME ||
     535           6 :             op == JSOP_SETGNAME || op == JSOP_STRICTSETGNAME)
     536             :         {
     537           0 :             if (!NativeSetProperty<Unqualified>(cx, obj.as<NativeObject>(), id, value, receiver,
     538             :                                                 result))
     539             :             {
     540             :                 return false;
     541             :             }
     542             :         } else {
     543          12 :             if (!NativeSetProperty<Qualified>(cx, obj.as<NativeObject>(), id, value, receiver,
     544             :                                               result))
     545             :             {
     546             :                 return false;
     547             :             }
     548             :         }
     549             :     } else {
     550           0 :         if (!SetProperty(cx, obj, id, value, receiver, result))
     551             :             return false;
     552             :     }
     553           0 :     return result.checkStrictErrorOrWarning(cx, obj, id, strict);
     554             : }
     555             : 
     556             : bool
     557          13 : InterruptCheck(JSContext* cx)
     558             : {
     559           0 :     gc::MaybeVerifyBarriers(cx);
     560             : 
     561           0 :     return CheckForInterrupt(cx);
     562             : }
     563             : 
     564             : void*
     565           0 : MallocWrapper(JS::Zone* zone, size_t nbytes)
     566             : {
     567           0 :     AutoUnsafeCallWithABI unsafe;
     568           0 :     return zone->pod_malloc<uint8_t>(nbytes);
     569             : }
     570             : 
     571             : JSObject*
     572           3 : NewCallObject(JSContext* cx, HandleShape shape, HandleObjectGroup group)
     573             : {
     574           3 :     JSObject* obj = CallObject::create(cx, shape, group);
     575           0 :     if (!obj)
     576             :         return nullptr;
     577             : 
     578             :     // The JIT creates call objects in the nursery, so elides barriers for
     579             :     // the initializing writes. The interpreter, however, may have allocated
     580             :     // the call object tenured, so barrier as needed before re-entering.
     581           3 :     if (!IsInsideNursery(obj))
     582           0 :         cx->runtime()->gc.storeBuffer().putWholeCell(obj);
     583             : 
     584             :     return obj;
     585             : }
     586             : 
     587             : JSObject*
     588           0 : NewSingletonCallObject(JSContext* cx, HandleShape shape)
     589             : {
     590           0 :     JSObject* obj = CallObject::createSingleton(cx, shape);
     591           0 :     if (!obj)
     592             :         return nullptr;
     593             : 
     594             :     // The JIT creates call objects in the nursery, so elides barriers for
     595             :     // the initializing writes. The interpreter, however, may have allocated
     596             :     // the call object tenured, so barrier as needed before re-entering.
     597           0 :     MOZ_ASSERT(!IsInsideNursery(obj),
     598             :                "singletons are created in the tenured heap");
     599           0 :     cx->runtime()->gc.storeBuffer().putWholeCell(obj);
     600             : 
     601           0 :     return obj;
     602             : }
     603             : 
     604             : JSObject*
     605           0 : NewStringObject(JSContext* cx, HandleString str)
     606             : {
     607           0 :     return StringObject::create(cx, str);
     608             : }
     609             : 
     610             : bool
     611         562 : OperatorIn(JSContext* cx, HandleValue key, HandleObject obj, bool* out)
     612             : {
     613           0 :     RootedId id(cx);
     614        1686 :     return ToPropertyKey(cx, key, &id) &&
     615           0 :            HasProperty(cx, obj, id, out);
     616             : }
     617             : 
     618             : bool
     619           0 : OperatorInI(JSContext* cx, uint32_t index, HandleObject obj, bool* out)
     620             : {
     621           0 :     RootedValue key(cx, Int32Value(index));
     622           0 :     return OperatorIn(cx, key, obj, out);
     623             : }
     624             : 
     625             : bool
     626           0 : GetIntrinsicValue(JSContext* cx, HandlePropertyName name, MutableHandleValue rval)
     627             : {
     628           0 :     if (!GlobalObject::getIntrinsicValue(cx, cx->global(), name, rval))
     629             :         return false;
     630             : 
     631             :     // This function is called when we try to compile a cold getintrinsic
     632             :     // op. MCallGetIntrinsicValue has an AliasSet of None for optimization
     633             :     // purposes, as its side effect is not observable from JS. We are
     634             :     // guaranteed to bail out after this function, but because of its AliasSet,
     635             :     // type info will not be reflowed. Manually monitor here.
     636           0 :     TypeScript::Monitor(cx, rval);
     637             : 
     638           0 :     return true;
     639             : }
     640             : 
     641             : bool
     642           0 : CreateThis(JSContext* cx, HandleObject callee, HandleObject newTarget, MutableHandleValue rval)
     643             : {
     644           0 :     rval.set(MagicValue(JS_IS_CONSTRUCTING));
     645             : 
     646           0 :     if (callee->is<JSFunction>()) {
     647           0 :         RootedFunction fun(cx, &callee->as<JSFunction>());
     648        9848 :         if (fun->isInterpreted() && fun->isConstructor()) {
     649        2462 :             JSScript* script = JSFunction::getOrCreateScript(cx, fun);
     650        4924 :             AutoKeepTypeScripts keepTypes(cx);
     651        2462 :             if (!script || !script->ensureHasTypes(cx, keepTypes))
     652           0 :                 return false;
     653        2462 :             if (!js::CreateThis(cx, fun, script, newTarget, GenericObject, rval))
     654             :                 return false;
     655             :         }
     656             :     }
     657             : 
     658             :     return true;
     659             : }
     660             : 
     661             : void
     662           0 : GetDynamicName(JSContext* cx, JSObject* envChain, JSString* str, Value* vp)
     663             : {
     664             :     // Lookup a string on the env chain, returning either the value found or
     665             :     // undefined through rval. This function is infallible, and cannot GC or
     666             :     // invalidate.
     667             : 
     668           0 :     AutoUnsafeCallWithABI unsafe;
     669             : 
     670             :     JSAtom* atom;
     671           0 :     if (str->isAtom()) {
     672           0 :         atom = &str->asAtom();
     673             :     } else {
     674           0 :         atom = AtomizeString(cx, str);
     675           0 :         if (!atom) {
     676             :             vp->setUndefined();
     677           0 :             return;
     678             :         }
     679             :     }
     680             : 
     681           0 :     if (!frontend::IsIdentifier(atom) || frontend::IsKeyword(atom)) {
     682             :         vp->setUndefined();
     683             :         return;
     684             :     }
     685             : 
     686           0 :     PropertyResult prop;
     687           0 :     JSObject* scope = nullptr;
     688           0 :     JSObject* pobj = nullptr;
     689           0 :     if (LookupNameNoGC(cx, atom->asPropertyName(), envChain, &scope, &pobj, &prop)) {
     690           0 :         if (FetchNameNoGC(pobj, prop, MutableHandleValue::fromMarkedLocation(vp)))
     691             :             return;
     692             :     }
     693             : 
     694           0 :     vp->setUndefined();
     695             : }
     696             : 
     697             : void
     698        1582 : PostWriteBarrier(JSRuntime* rt, js::gc::Cell* cell)
     699             : {
     700        3164 :     AutoUnsafeCallWithABI unsafe;
     701        1582 :     MOZ_ASSERT(!IsInsideNursery(cell));
     702        4746 :     rt->gc.storeBuffer().putWholeCell(cell);
     703           0 : }
     704             : 
     705             : static const size_t MAX_WHOLE_CELL_BUFFER_SIZE = 4096;
     706             : 
     707             : template <IndexInBounds InBounds>
     708             : void
     709         117 : PostWriteElementBarrier(JSRuntime* rt, JSObject* obj, int32_t index)
     710             : {
     711         122 :     AutoUnsafeCallWithABI unsafe;
     712             : 
     713         117 :     MOZ_ASSERT(!IsInsideNursery(obj));
     714             : 
     715             :     if (InBounds == IndexInBounds::Yes) {
     716           1 :         MOZ_ASSERT(uint32_t(index) < obj->as<NativeObject>().getDenseInitializedLength());
     717             :     } else {
     718          81 :         if (MOZ_UNLIKELY(!obj->is<NativeObject>() ||
     719             :                          index < 0 ||
     720             :                          uint32_t(index) >= NativeObject::MAX_DENSE_ELEMENTS_COUNT))
     721             :         {
     722           0 :             rt->gc.storeBuffer().putWholeCell(obj);
     723         112 :             return;
     724             :         }
     725             :     }
     726             : 
     727           0 :     NativeObject* nobj = &obj->as<NativeObject>();
     728         117 :     if (nobj->isInWholeCellBuffer())
     729             :         return;
     730             : 
     731           0 :     if (nobj->getDenseInitializedLength() > MAX_WHOLE_CELL_BUFFER_SIZE
     732             : #ifdef JS_GC_ZEAL
     733          10 :          || rt->hasZealMode(gc::ZealMode::ElementsBarrier)
     734             : #endif
     735             :         )
     736             :     {
     737           0 :         rt->gc.storeBuffer().putSlot(nobj, HeapSlot::Element,
     738             :                                      nobj->unshiftedIndex(index),
     739             :                                      1);
     740           0 :         return;
     741             :     }
     742             : 
     743          15 :     rt->gc.storeBuffer().putWholeCell(obj);
     744             : }
     745             : 
     746             : template void
     747             : PostWriteElementBarrier<IndexInBounds::Yes>(JSRuntime* rt, JSObject* obj, int32_t index);
     748             : 
     749             : template void
     750             : PostWriteElementBarrier<IndexInBounds::Maybe>(JSRuntime* rt, JSObject* obj, int32_t index);
     751             : 
     752             : void
     753           0 : PostGlobalWriteBarrier(JSRuntime* rt, JSObject* obj)
     754             : {
     755           0 :     MOZ_ASSERT(obj->is<GlobalObject>());
     756           0 :     if (!obj->realm()->globalWriteBarriered) {
     757           0 :         PostWriteBarrier(rt, obj);
     758           0 :         obj->realm()->globalWriteBarriered = 1;
     759             :     }
     760           0 : }
     761             : 
     762             : int32_t
     763           2 : GetIndexFromString(JSString* str)
     764             : {
     765             :     // We shouldn't GC here as this is called directly from IC code.
     766           0 :     AutoUnsafeCallWithABI unsafe;
     767             : 
     768           2 :     if (!str->isFlat())
     769             :         return -1;
     770             : 
     771             :     uint32_t index;
     772           2 :     if (!str->asFlat().isIndex(&index) || index > INT32_MAX)
     773             :         return -1;
     774             : 
     775           2 :     return int32_t(index);
     776             : }
     777             : 
     778             : JSObject*
     779           0 : WrapObjectPure(JSContext* cx, JSObject* obj)
     780             : {
     781             :     // IC code calls this directly so we shouldn't GC.
     782       17886 :     AutoUnsafeCallWithABI unsafe;
     783             : 
     784        8943 :     MOZ_ASSERT(obj);
     785       17886 :     MOZ_ASSERT(cx->compartment() != obj->compartment());
     786             : 
     787             :     // From: Compartment::getNonWrapperObjectForCurrentCompartment
     788             :     // Note that if the object is same-compartment, but has been wrapped into a
     789             :     // different compartment, we need to unwrap it and return the bare same-
     790             :     // compartment object. Note again that windows are always wrapped by a
     791             :     // WindowProxy even when same-compartment so take care not to strip this
     792             :     // particular wrapper.
     793        8943 :     obj = UncheckedUnwrap(obj, /* stopAtWindowProxy = */ true);
     794       17886 :     if (cx->compartment() == obj->compartment()) {
     795          10 :         MOZ_ASSERT(!IsWindow(obj));
     796           0 :         JS::ExposeObjectToActiveJS(obj);
     797           0 :         return obj;
     798             :     }
     799             : 
     800             :     // Try to Lookup an existing wrapper for this object. We assume that
     801             :     // if we can find such a wrapper, not calling preWrap is correct.
     802       17876 :     if (WrapperMap::Ptr p = cx->compartment()->lookupWrapper(obj)) {
     803       17812 :         JSObject* wrapped = &p->value().get().toObject();
     804             : 
     805             :         // Ensure the wrapper is still exposed.
     806        8906 :         JS::ExposeObjectToActiveJS(wrapped);
     807        8906 :         return wrapped;
     808             :     }
     809             : 
     810           0 :     return nullptr;
     811             : }
     812             : 
     813             : bool
     814           0 : DebugPrologue(JSContext* cx, BaselineFrame* frame, jsbytecode* pc, bool* mustReturn)
     815             : {
     816           0 :     *mustReturn = false;
     817             : 
     818           0 :     switch (Debugger::onEnterFrame(cx, frame)) {
     819             :       case ResumeMode::Continue:
     820             :         return true;
     821             : 
     822             :       case ResumeMode::Return:
     823             :         // The script is going to return immediately, so we have to call the
     824             :         // debug epilogue handler as well.
     825           0 :         MOZ_ASSERT(frame->hasReturnValue());
     826           0 :         *mustReturn = true;
     827           0 :         return jit::DebugEpilogue(cx, frame, pc, true);
     828             : 
     829             :       case ResumeMode::Throw:
     830             :       case ResumeMode::Terminate:
     831           0 :         return false;
     832             : 
     833             :       default:
     834           0 :         MOZ_CRASH("bad Debugger::onEnterFrame resume mode");
     835             :     }
     836             : }
     837             : 
     838             : bool
     839           0 : DebugEpilogueOnBaselineReturn(JSContext* cx, BaselineFrame* frame, jsbytecode* pc)
     840             : {
     841           0 :     if (!DebugEpilogue(cx, frame, pc, true)) {
     842             :         // DebugEpilogue popped the frame by updating packedExitFP, so run the
     843             :         // stop event here before we enter the exception handler.
     844           0 :         TraceLoggerThread* logger = TraceLoggerForCurrentThread(cx);
     845           0 :         TraceLogStopEvent(logger, TraceLogger_Baseline);
     846             :         TraceLogStopEvent(logger, TraceLogger_Scripts);
     847             :         return false;
     848             :     }
     849             : 
     850             :     return true;
     851             : }
     852             : 
     853             : bool
     854          35 : DebugEpilogue(JSContext* cx, BaselineFrame* frame, jsbytecode* pc, bool ok)
     855             : {
     856             :     // If Debugger::onLeaveFrame returns |true| we have to return the frame's
     857             :     // return value. If it returns |false|, the debugger threw an exception.
     858             :     // In both cases we have to pop debug scopes.
     859           0 :     ok = Debugger::onLeaveFrame(cx, frame, pc, ok);
     860             : 
     861             :     // Unwind to the outermost environment and set pc to the end of the
     862             :     // script, regardless of error.
     863          70 :     EnvironmentIter ei(cx, frame, pc);
     864          35 :     UnwindAllEnvironmentsInFrame(cx, ei);
     865           0 :     JSScript* script = frame->script();
     866           0 :     frame->setOverridePc(script->lastPC());
     867             : 
     868          35 :     if (!ok) {
     869             :         // Pop this frame by updating packedExitFP, so that the exception
     870             :         // handling code will start at the previous frame.
     871          35 :         JitFrameLayout* prefix = frame->framePrefix();
     872          35 :         EnsureBareExitFrame(cx->activation()->asJit(), prefix);
     873           0 :         return false;
     874             :     }
     875             : 
     876             :     // Clear the override pc. This is not necessary for correctness: the frame
     877             :     // will return immediately, but this simplifies the check we emit in debug
     878             :     // builds after each callVM, to ensure this flag is not set.
     879           0 :     frame->clearOverridePc();
     880           0 :     return true;
     881             : }
     882             : 
     883             : void
     884           0 : FrameIsDebuggeeCheck(BaselineFrame* frame)
     885             : {
     886           0 :     AutoUnsafeCallWithABI unsafe;
     887           0 :     if (frame->script()->isDebuggee())
     888           0 :         frame->setIsDebuggee();
     889           0 : }
     890             : 
     891             : JSObject*
     892           0 : CreateGenerator(JSContext* cx, BaselineFrame* frame)
     893             : {
     894         459 :     return GeneratorObject::create(cx, frame);
     895             : }
     896             : 
     897             : bool
     898           0 : NormalSuspend(JSContext* cx, HandleObject obj, BaselineFrame* frame, jsbytecode* pc,
     899             :               uint32_t stackDepth)
     900             : {
     901          73 :     MOZ_ASSERT(*pc == JSOP_YIELD || *pc == JSOP_AWAIT);
     902             : 
     903             :     // Return value is still on the stack.
     904           0 :     MOZ_ASSERT(stackDepth >= 1);
     905             : 
     906             :     // The expression stack slots are stored on the stack in reverse order, so
     907             :     // we copy them to a Vector and pass a pointer to that instead. We use
     908             :     // stackDepth - 1 because we don't want to include the return value.
     909           0 :     AutoValueVector exprStack(cx);
     910         146 :     if (!exprStack.reserve(stackDepth - 1))
     911             :         return false;
     912             : 
     913           0 :     size_t firstSlot = frame->numValueSlots() - stackDepth;
     914         457 :     for (size_t i = 0; i < stackDepth - 1; i++)
     915         768 :         exprStack.infallibleAppend(*frame->valueSlot(firstSlot + i));
     916             : 
     917           0 :     MOZ_ASSERT(exprStack.length() == stackDepth - 1);
     918             : 
     919           0 :     return GeneratorObject::normalSuspend(cx, obj, frame, pc, exprStack.begin(), stackDepth - 1);
     920             : }
     921             : 
     922             : bool
     923         498 : FinalSuspend(JSContext* cx, HandleObject obj, jsbytecode* pc)
     924             : {
     925           0 :     MOZ_ASSERT(*pc == JSOP_FINALYIELDRVAL);
     926         498 :     GeneratorObject::finalSuspend(obj);
     927         498 :     return true;
     928             : }
     929             : 
     930             : bool
     931        1006 : InterpretResume(JSContext* cx, HandleObject obj, HandleValue val, HandlePropertyName kind,
     932             :                 MutableHandleValue rval)
     933             : {
     934           0 :     MOZ_ASSERT(obj->is<GeneratorObject>());
     935             : 
     936           0 :     FixedInvokeArgs<3> args(cx);
     937             : 
     938        2012 :     args[0].setObject(*obj);
     939        1006 :     args[1].set(val);
     940        2012 :     args[2].setString(kind);
     941             : 
     942        2012 :     return CallSelfHostedFunction(cx, cx->names().InterpretGeneratorResume, UndefinedHandleValue,
     943        2012 :                                   args, rval);
     944             : }
     945             : 
     946             : bool
     947           0 : DebugAfterYield(JSContext* cx, BaselineFrame* frame)
     948             : {
     949             :     // The BaselineFrame has just been constructed by JSOP_RESUME in the
     950             :     // caller. We need to set its debuggee flag as necessary.
     951           0 :     if (frame->script()->isDebuggee())
     952           0 :         frame->setIsDebuggee();
     953           9 :     return true;
     954             : }
     955             : 
     956             : bool
     957           0 : GeneratorThrowOrReturn(JSContext* cx, BaselineFrame* frame, Handle<GeneratorObject*> genObj,
     958             :                        HandleValue arg, uint32_t resumeKind)
     959             : {
     960             :     // Set the frame's pc to the current resume pc, so that frame iterators
     961             :     // work. This function always returns false, so we're guaranteed to enter
     962             :     // the exception handler where we will clear the pc.
     963           0 :     JSScript* script = frame->script();
     964           9 :     uint32_t offset = script->yieldAndAwaitOffsets()[genObj->yieldAndAwaitIndex()];
     965           9 :     frame->setOverridePc(script->offsetToPC(offset));
     966             : 
     967           0 :     MOZ_ALWAYS_TRUE(DebugAfterYield(cx, frame));
     968           9 :     MOZ_ALWAYS_FALSE(js::GeneratorThrowOrReturn(cx, frame, genObj, arg, resumeKind));
     969           0 :     return false;
     970             : }
     971             : 
     972             : bool
     973           0 : CheckGlobalOrEvalDeclarationConflicts(JSContext* cx, BaselineFrame* frame)
     974             : {
     975           0 :     RootedScript script(cx, frame->script());
     976           0 :     RootedObject envChain(cx, frame->environmentChain());
     977           0 :     RootedObject varObj(cx, BindVar(cx, envChain));
     978             : 
     979           0 :     if (script->isForEval()) {
     980             :         // Strict eval and eval in parameter default expressions have their
     981             :         // own call objects.
     982             :         //
     983             :         // Non-strict eval may introduce 'var' bindings that conflict with
     984             :         // lexical bindings in an enclosing lexical scope.
     985           0 :         if (!script->bodyScope()->hasEnvironment()) {
     986           0 :             MOZ_ASSERT(!script->strict() &&
     987             :                        (!script->enclosingScope()->is<FunctionScope>() ||
     988             :                         !script->enclosingScope()->as<FunctionScope>().hasParameterExprs()));
     989           0 :             if (!CheckEvalDeclarationConflicts(cx, script, envChain, varObj))
     990             :                 return false;
     991             :         }
     992             :     } else {
     993             :         Rooted<LexicalEnvironmentObject*> lexicalEnv(cx,
     994           0 :             &NearestEnclosingExtensibleLexicalEnvironment(envChain));
     995           0 :         if (!CheckGlobalDeclarationConflicts(cx, script, lexicalEnv, varObj))
     996           0 :             return false;
     997             :     }
     998             : 
     999             :     return true;
    1000             : }
    1001             : 
    1002             : bool
    1003           0 : GlobalNameConflictsCheckFromIon(JSContext* cx, HandleScript script)
    1004             : {
    1005           0 :     Rooted<LexicalEnvironmentObject*> globalLexical(cx, &cx->global()->lexicalEnvironment());
    1006           0 :     return CheckGlobalDeclarationConflicts(cx, script, globalLexical, cx->global());
    1007             : }
    1008             : 
    1009             : bool
    1010           0 : InitFunctionEnvironmentObjects(JSContext* cx, BaselineFrame* frame)
    1011             : {
    1012           0 :     return frame->initFunctionEnvironmentObjects(cx);
    1013             : }
    1014             : 
    1015             : bool
    1016           0 : NewArgumentsObject(JSContext* cx, BaselineFrame* frame, MutableHandleValue res)
    1017             : {
    1018          61 :     ArgumentsObject* obj = ArgumentsObject::createExpected(cx, frame);
    1019          61 :     if (!obj)
    1020             :         return false;
    1021         122 :     res.setObject(*obj);
    1022           0 :     return true;
    1023             : }
    1024             : 
    1025             : JSObject*
    1026           0 : CopyLexicalEnvironmentObject(JSContext* cx, HandleObject env, bool copySlots)
    1027             : {
    1028           0 :     Handle<LexicalEnvironmentObject*> lexicalEnv = env.as<LexicalEnvironmentObject>();
    1029             : 
    1030           0 :     if (copySlots)
    1031           0 :         return LexicalEnvironmentObject::clone(cx, lexicalEnv);
    1032             : 
    1033           0 :     return LexicalEnvironmentObject::recreate(cx, lexicalEnv);
    1034             : }
    1035             : 
    1036             : JSObject*
    1037           0 : InitRestParameter(JSContext* cx, uint32_t length, Value* rest, HandleObject templateObj,
    1038             :                   HandleObject objRes)
    1039             : {
    1040           0 :     if (objRes) {
    1041           0 :         Rooted<ArrayObject*> arrRes(cx, &objRes->as<ArrayObject>());
    1042             : 
    1043           0 :         MOZ_ASSERT(!arrRes->getDenseInitializedLength());
    1044           0 :         MOZ_ASSERT(arrRes->group() == templateObj->group());
    1045             : 
    1046             :         // Fast path: we managed to allocate the array inline; initialize the
    1047             :         // slots.
    1048           0 :         if (length > 0) {
    1049           0 :             if (!arrRes->ensureElements(cx, length))
    1050             :                 return nullptr;
    1051           0 :             arrRes->initDenseElements(rest, length);
    1052           0 :             arrRes->setLengthInt32(length);
    1053             :         }
    1054           0 :         return arrRes;
    1055             :     }
    1056             : 
    1057             :     NewObjectKind newKind;
    1058             :     {
    1059           0 :         AutoSweepObjectGroup sweep(templateObj->group());
    1060           0 :         newKind = templateObj->group()->shouldPreTenure(sweep) ? TenuredObject : GenericObject;
    1061             :     }
    1062           0 :     ArrayObject* arrRes = NewDenseCopiedArray(cx, length, rest, nullptr, newKind);
    1063           0 :     if (arrRes)
    1064           0 :         arrRes->setGroup(templateObj->group());
    1065             :     return arrRes;
    1066             : }
    1067             : 
    1068             : bool
    1069           0 : HandleDebugTrap(JSContext* cx, BaselineFrame* frame, uint8_t* retAddr, bool* mustReturn)
    1070             : {
    1071           0 :     *mustReturn = false;
    1072             : 
    1073           0 :     RootedScript script(cx, frame->script());
    1074           0 :     jsbytecode* pc = script->baselineScript()->icEntryFromReturnAddress(retAddr).pc(script);
    1075             : 
    1076           0 :     if (*pc == JSOP_DEBUGAFTERYIELD) {
    1077             :         // JSOP_DEBUGAFTERYIELD will set the frame's debuggee flag, but if we
    1078             :         // set a breakpoint there we have to do it now.
    1079           0 :         MOZ_ASSERT(!frame->isDebuggee());
    1080           0 :         if (!DebugAfterYield(cx, frame))
    1081             :             return false;
    1082             :     }
    1083             : 
    1084           0 :     MOZ_ASSERT(frame->isDebuggee());
    1085           0 :     MOZ_ASSERT(script->stepModeEnabled() || script->hasBreakpointsAt(pc));
    1086             : 
    1087           0 :     RootedValue rval(cx);
    1088           0 :     ResumeMode resumeMode = ResumeMode::Continue;
    1089             : 
    1090           0 :     if (script->stepModeEnabled())
    1091           0 :         resumeMode = Debugger::onSingleStep(cx, &rval);
    1092             : 
    1093           0 :     if (resumeMode == ResumeMode::Continue && script->hasBreakpointsAt(pc))
    1094           0 :         resumeMode = Debugger::onTrap(cx, &rval);
    1095             : 
    1096           0 :     switch (resumeMode) {
    1097             :       case ResumeMode::Continue:
    1098             :         break;
    1099             : 
    1100             :       case ResumeMode::Terminate:
    1101             :         return false;
    1102             : 
    1103             :       case ResumeMode::Return:
    1104           0 :         *mustReturn = true;
    1105           0 :         frame->setReturnValue(rval);
    1106           0 :         return jit::DebugEpilogue(cx, frame, pc, true);
    1107             : 
    1108             :       case ResumeMode::Throw:
    1109           0 :         cx->setPendingException(rval);
    1110           0 :         return false;
    1111             : 
    1112             :       default:
    1113           0 :         MOZ_CRASH("Invalid step/breakpoint resume mode");
    1114             :     }
    1115             : 
    1116           0 :     return true;
    1117             : }
    1118             : 
    1119             : bool
    1120           0 : OnDebuggerStatement(JSContext* cx, BaselineFrame* frame, jsbytecode* pc, bool* mustReturn)
    1121             : {
    1122           0 :     *mustReturn = false;
    1123             : 
    1124           0 :     switch (Debugger::onDebuggerStatement(cx, frame)) {
    1125             :       case ResumeMode::Continue:
    1126             :         return true;
    1127             : 
    1128             :       case ResumeMode::Return:
    1129           0 :         *mustReturn = true;
    1130           0 :         return jit::DebugEpilogue(cx, frame, pc, true);
    1131             : 
    1132             :       case ResumeMode::Throw:
    1133             :       case ResumeMode::Terminate:
    1134           0 :         return false;
    1135             : 
    1136             :       default:
    1137           0 :         MOZ_CRASH("Invalid OnDebuggerStatement resume mode");
    1138             :     }
    1139             : }
    1140             : 
    1141             : bool
    1142           0 : GlobalHasLiveOnDebuggerStatement(JSContext* cx)
    1143             : {
    1144           0 :     AutoUnsafeCallWithABI unsafe;
    1145           0 :     return cx->realm()->isDebuggee() &&
    1146           0 :            Debugger::hasLiveHook(cx->global(), Debugger::OnDebuggerStatement);
    1147             : }
    1148             : 
    1149             : bool
    1150           0 : PushLexicalEnv(JSContext* cx, BaselineFrame* frame, Handle<LexicalScope*> scope)
    1151             : {
    1152           0 :     return frame->pushLexicalEnvironment(cx, scope);
    1153             : }
    1154             : 
    1155             : bool
    1156        2362 : PopLexicalEnv(JSContext* cx, BaselineFrame* frame)
    1157             : {
    1158        2362 :     frame->popOffEnvironmentChain<LexicalEnvironmentObject>();
    1159           0 :     return true;
    1160             : }
    1161             : 
    1162             : bool
    1163           0 : DebugLeaveThenPopLexicalEnv(JSContext* cx, BaselineFrame* frame, jsbytecode* pc)
    1164             : {
    1165           0 :     MOZ_ALWAYS_TRUE(DebugLeaveLexicalEnv(cx, frame, pc));
    1166           0 :     frame->popOffEnvironmentChain<LexicalEnvironmentObject>();
    1167           0 :     return true;
    1168             : }
    1169             : 
    1170             : bool
    1171           0 : FreshenLexicalEnv(JSContext* cx, BaselineFrame* frame)
    1172             : {
    1173           0 :     return frame->freshenLexicalEnvironment(cx);
    1174             : }
    1175             : 
    1176             : bool
    1177           0 : DebugLeaveThenFreshenLexicalEnv(JSContext* cx, BaselineFrame* frame, jsbytecode* pc)
    1178             : {
    1179           0 :     MOZ_ALWAYS_TRUE(DebugLeaveLexicalEnv(cx, frame, pc));
    1180           0 :     return frame->freshenLexicalEnvironment(cx);
    1181             : }
    1182             : 
    1183             : bool
    1184           0 : RecreateLexicalEnv(JSContext* cx, BaselineFrame* frame)
    1185             : {
    1186           0 :     return frame->recreateLexicalEnvironment(cx);
    1187             : }
    1188             : 
    1189             : bool
    1190           0 : DebugLeaveThenRecreateLexicalEnv(JSContext* cx, BaselineFrame* frame, jsbytecode* pc)
    1191             : {
    1192           0 :     MOZ_ALWAYS_TRUE(DebugLeaveLexicalEnv(cx, frame, pc));
    1193           0 :     return frame->recreateLexicalEnvironment(cx);
    1194             : }
    1195             : 
    1196             : bool
    1197           0 : DebugLeaveLexicalEnv(JSContext* cx, BaselineFrame* frame, jsbytecode* pc)
    1198             : {
    1199           0 :     MOZ_ASSERT(frame->script()->baselineScript()->hasDebugInstrumentation());
    1200           0 :     if (cx->realm()->isDebuggee())
    1201           0 :         DebugEnvironments::onPopLexical(cx, frame, pc);
    1202           0 :     return true;
    1203             : }
    1204             : 
    1205             : bool
    1206           0 : PushVarEnv(JSContext* cx, BaselineFrame* frame, HandleScope scope)
    1207             : {
    1208           0 :     return frame->pushVarEnvironment(cx, scope);
    1209             : }
    1210             : 
    1211             : bool
    1212           0 : PopVarEnv(JSContext* cx, BaselineFrame* frame)
    1213             : {
    1214           0 :     frame->popOffEnvironmentChain<VarEnvironmentObject>();
    1215           0 :     return true;
    1216             : }
    1217             : 
    1218             : bool
    1219           0 : EnterWith(JSContext* cx, BaselineFrame* frame, HandleValue val, Handle<WithScope*> templ)
    1220             : {
    1221           0 :     return EnterWithOperation(cx, frame, val, templ);
    1222             : }
    1223             : 
    1224             : bool
    1225           0 : LeaveWith(JSContext* cx, BaselineFrame* frame)
    1226             : {
    1227           0 :     if (MOZ_UNLIKELY(frame->isDebuggee()))
    1228           0 :         DebugEnvironments::onPopWith(frame);
    1229           0 :     frame->popOffEnvironmentChain<WithEnvironmentObject>();
    1230           0 :     return true;
    1231             : }
    1232             : 
    1233             : bool
    1234         195 : InitBaselineFrameForOsr(BaselineFrame* frame, InterpreterFrame* interpFrame,
    1235             :                         uint32_t numStackValues)
    1236             : {
    1237         195 :     return frame->initForOsr(interpFrame, numStackValues);
    1238             : }
    1239             : 
    1240             : JSObject*
    1241           0 : CreateDerivedTypedObj(JSContext* cx, HandleObject descr,
    1242             :                       HandleObject owner, int32_t offset)
    1243             : {
    1244           0 :     MOZ_ASSERT(descr->is<TypeDescr>());
    1245           0 :     MOZ_ASSERT(owner->is<TypedObject>());
    1246           0 :     Rooted<TypeDescr*> descr1(cx, &descr->as<TypeDescr>());
    1247           0 :     Rooted<TypedObject*> owner1(cx, &owner->as<TypedObject>());
    1248           0 :     return OutlineTypedObject::createDerived(cx, descr1, owner1, offset);
    1249             : }
    1250             : 
    1251             : JSString*
    1252           0 : StringReplace(JSContext* cx, HandleString string, HandleString pattern, HandleString repl)
    1253             : {
    1254           0 :     MOZ_ASSERT(string);
    1255           0 :     MOZ_ASSERT(pattern);
    1256           0 :     MOZ_ASSERT(repl);
    1257             : 
    1258           0 :     return str_replace_string_raw(cx, string, pattern, repl);
    1259             : }
    1260             : 
    1261             : bool
    1262           0 : RecompileImpl(JSContext* cx, bool force)
    1263             : {
    1264           0 :     MOZ_ASSERT(cx->currentlyRunningInJit());
    1265           0 :     JitActivationIterator activations(cx);
    1266           0 :     JSJitFrameIter frame(activations->asJit());
    1267             : 
    1268           0 :     MOZ_ASSERT(frame.type() == JitFrame_Exit);
    1269           0 :     ++frame;
    1270             : 
    1271           0 :     RootedScript script(cx, frame.script());
    1272           0 :     MOZ_ASSERT(script->hasIonScript());
    1273             : 
    1274           0 :     if (!IsIonEnabled(cx))
    1275             :         return true;
    1276             : 
    1277           0 :     MethodStatus status = Recompile(cx, script, nullptr, nullptr, force);
    1278           0 :     if (status == Method_Error)
    1279             :         return false;
    1280             : 
    1281           0 :     return true;
    1282             : }
    1283             : 
    1284             : bool
    1285           0 : ForcedRecompile(JSContext* cx)
    1286             : {
    1287           0 :     return RecompileImpl(cx, /* force = */ true);
    1288             : }
    1289             : 
    1290             : bool
    1291           0 : Recompile(JSContext* cx)
    1292             : {
    1293           0 :     return RecompileImpl(cx, /* force = */ false);
    1294             : }
    1295             : 
    1296             : bool
    1297         402 : SetDenseElement(JSContext* cx, HandleNativeObject obj, int32_t index, HandleValue value,
    1298             :                 bool strict)
    1299             : {
    1300             :     // This function is called from Ion code for StoreElementHole's OOL path.
    1301             :     // In this case we know the object is native and that no type changes are
    1302             :     // needed.
    1303             : 
    1304           0 :     DenseElementResult result = obj->setOrExtendDenseElements(cx, index, value.address(), 1,
    1305         402 :                                                               ShouldUpdateTypes::DontUpdate);
    1306         402 :     if (result != DenseElementResult::Incomplete)
    1307         402 :         return result == DenseElementResult::Success;
    1308             : 
    1309           0 :     RootedValue indexVal(cx, Int32Value(index));
    1310           0 :     return SetObjectElement(cx, obj, indexVal, value, strict);
    1311             : }
    1312             : 
    1313             : void
    1314           0 : AutoDetectInvalidation::setReturnOverride()
    1315             : {
    1316           0 :     cx_->setIonReturnOverride(rval_.get());
    1317           0 : }
    1318             : 
    1319             : void
    1320           0 : AssertValidObjectPtr(JSContext* cx, JSObject* obj)
    1321             : {
    1322           0 :     AutoUnsafeCallWithABI unsafe;
    1323             : #ifdef DEBUG
    1324             :     // Check what we can, so that we'll hopefully assert/crash if we get a
    1325             :     // bogus object (pointer).
    1326           0 :     MOZ_ASSERT(obj->compartment() == cx->compartment());
    1327           0 :     MOZ_ASSERT(obj->zoneFromAnyThread() == cx->zone());
    1328           0 :     MOZ_ASSERT(obj->runtimeFromMainThread() == cx->runtime());
    1329             : 
    1330           0 :     MOZ_ASSERT_IF(!obj->hasLazyGroup() && obj->maybeShape(),
    1331             :                   obj->group()->clasp() == obj->maybeShape()->getObjectClass());
    1332             : 
    1333           0 :     if (obj->isTenured()) {
    1334           0 :         MOZ_ASSERT(obj->isAligned());
    1335           0 :         gc::AllocKind kind = obj->asTenured().getAllocKind();
    1336           0 :         MOZ_ASSERT(gc::IsObjectAllocKind(kind));
    1337             :     }
    1338             : #endif
    1339           0 : }
    1340             : 
    1341             : void
    1342           0 : AssertValidObjectOrNullPtr(JSContext* cx, JSObject* obj)
    1343             : {
    1344           0 :     AutoUnsafeCallWithABI unsafe;
    1345           0 :     if (obj)
    1346           0 :         AssertValidObjectPtr(cx, obj);
    1347           0 : }
    1348             : 
    1349             : void
    1350           0 : AssertValidStringPtr(JSContext* cx, JSString* str)
    1351             : {
    1352           0 :     AutoUnsafeCallWithABI unsafe;
    1353             : #ifdef DEBUG
    1354             :     // We can't closely inspect strings from another runtime.
    1355           0 :     if (str->runtimeFromAnyThread() != cx->runtime()) {
    1356           0 :         MOZ_ASSERT(str->isPermanentAtom());
    1357           0 :         return;
    1358             :     }
    1359             : 
    1360           0 :     if (str->isAtom())
    1361           0 :         MOZ_ASSERT(str->zone()->isAtomsZone());
    1362             :     else
    1363           0 :         MOZ_ASSERT(str->zone() == cx->zone());
    1364             : 
    1365           0 :     MOZ_ASSERT(str->isAligned());
    1366           0 :     MOZ_ASSERT(str->length() <= JSString::MAX_LENGTH);
    1367             : 
    1368           0 :     gc::AllocKind kind = str->getAllocKind();
    1369           0 :     if (str->isFatInline()) {
    1370           0 :         MOZ_ASSERT(kind == gc::AllocKind::FAT_INLINE_STRING ||
    1371             :                    kind == gc::AllocKind::FAT_INLINE_ATOM);
    1372           0 :     } else if (str->isExternal()) {
    1373           0 :         MOZ_ASSERT(kind == gc::AllocKind::EXTERNAL_STRING);
    1374           0 :     } else if (str->isAtom()) {
    1375           0 :         MOZ_ASSERT(kind == gc::AllocKind::ATOM);
    1376           0 :     } else if (str->isFlat()) {
    1377           0 :         MOZ_ASSERT(kind == gc::AllocKind::STRING ||
    1378             :                    kind == gc::AllocKind::FAT_INLINE_STRING ||
    1379             :                    kind == gc::AllocKind::EXTERNAL_STRING);
    1380             :     } else {
    1381           0 :         MOZ_ASSERT(kind == gc::AllocKind::STRING);
    1382             :     }
    1383             : #endif
    1384             : }
    1385             : 
    1386             : void
    1387           0 : AssertValidSymbolPtr(JSContext* cx, JS::Symbol* sym)
    1388             : {
    1389           0 :     AutoUnsafeCallWithABI unsafe;
    1390             : 
    1391             :     // We can't closely inspect symbols from another runtime.
    1392           0 :     if (sym->runtimeFromAnyThread() != cx->runtime()) {
    1393           0 :         MOZ_ASSERT(sym->isWellKnownSymbol());
    1394           0 :         return;
    1395             :     }
    1396             : 
    1397           0 :     MOZ_ASSERT(sym->zone()->isAtomsZone());
    1398           0 :     MOZ_ASSERT(sym->isAligned());
    1399           0 :     if (JSString* desc = sym->description()) {
    1400           0 :         MOZ_ASSERT(desc->isAtom());
    1401           0 :         AssertValidStringPtr(cx, desc);
    1402             :     }
    1403             : 
    1404           0 :     MOZ_ASSERT(sym->getAllocKind() == gc::AllocKind::SYMBOL);
    1405             : }
    1406             : 
    1407             : void
    1408           0 : AssertValidValue(JSContext* cx, Value* v)
    1409             : {
    1410           0 :     AutoUnsafeCallWithABI unsafe;
    1411           0 :     if (v->isObject())
    1412           0 :         AssertValidObjectPtr(cx, &v->toObject());
    1413           0 :     else if (v->isString())
    1414           0 :         AssertValidStringPtr(cx, v->toString());
    1415           0 :     else if (v->isSymbol())
    1416           0 :         AssertValidSymbolPtr(cx, v->toSymbol());
    1417           0 : }
    1418             : 
    1419             : bool
    1420           9 : ObjectIsCallable(JSObject* obj)
    1421             : {
    1422          18 :     AutoUnsafeCallWithABI unsafe;
    1423           0 :     return obj->isCallable();
    1424             : }
    1425             : 
    1426             : bool
    1427           0 : ObjectIsConstructor(JSObject* obj)
    1428             : {
    1429           0 :     AutoUnsafeCallWithABI unsafe;
    1430           0 :     return obj->isConstructor();
    1431             : }
    1432             : 
    1433             : void
    1434           0 : MarkValueFromJit(JSRuntime* rt, Value* vp)
    1435             : {
    1436           0 :     AutoUnsafeCallWithABI unsafe;
    1437           0 :     TraceManuallyBarrieredEdge(&rt->gc.marker, vp, "write barrier");
    1438           0 : }
    1439             : 
    1440             : void
    1441           0 : MarkStringFromJit(JSRuntime* rt, JSString** stringp)
    1442             : {
    1443           0 :     AutoUnsafeCallWithABI unsafe;
    1444           0 :     MOZ_ASSERT(*stringp);
    1445           0 :     TraceManuallyBarrieredEdge(&rt->gc.marker, stringp, "write barrier");
    1446           0 : }
    1447             : 
    1448             : void
    1449           0 : MarkObjectFromJit(JSRuntime* rt, JSObject** objp)
    1450             : {
    1451           0 :     AutoUnsafeCallWithABI unsafe;
    1452           0 :     MOZ_ASSERT(*objp);
    1453           0 :     TraceManuallyBarrieredEdge(&rt->gc.marker, objp, "write barrier");
    1454           0 : }
    1455             : 
    1456             : void
    1457           0 : MarkShapeFromJit(JSRuntime* rt, Shape** shapep)
    1458             : {
    1459           0 :     AutoUnsafeCallWithABI unsafe;
    1460           0 :     TraceManuallyBarrieredEdge(&rt->gc.marker, shapep, "write barrier");
    1461           0 : }
    1462             : 
    1463             : void
    1464           0 : MarkObjectGroupFromJit(JSRuntime* rt, ObjectGroup** groupp)
    1465             : {
    1466           0 :     AutoUnsafeCallWithABI unsafe;
    1467           0 :     TraceManuallyBarrieredEdge(&rt->gc.marker, groupp, "write barrier");
    1468           0 : }
    1469             : 
    1470             : bool
    1471           0 : ThrowRuntimeLexicalError(JSContext* cx, unsigned errorNumber)
    1472             : {
    1473           0 :     ScriptFrameIter iter(cx);
    1474           0 :     RootedScript script(cx, iter.script());
    1475           0 :     ReportRuntimeLexicalError(cx, errorNumber, script, iter.pc());
    1476           0 :     return false;
    1477             : }
    1478             : 
    1479             : bool
    1480           0 : ThrowBadDerivedReturn(JSContext* cx, HandleValue v)
    1481             : {
    1482           0 :     ReportValueError(cx, JSMSG_BAD_DERIVED_RETURN, JSDVG_IGNORE_STACK, v, nullptr);
    1483           0 :     return false;
    1484             : }
    1485             : 
    1486             : bool
    1487           0 : BaselineThrowUninitializedThis(JSContext* cx, BaselineFrame* frame)
    1488             : {
    1489           0 :     return ThrowUninitializedThis(cx, frame);
    1490             : }
    1491             : 
    1492             : bool
    1493           0 : BaselineThrowInitializedThis(JSContext* cx)
    1494             : {
    1495           0 :     return ThrowInitializedThis(cx);
    1496             : }
    1497             : 
    1498             : 
    1499             : bool
    1500           0 : ThrowObjectCoercible(JSContext* cx, HandleValue v)
    1501             : {
    1502           0 :     MOZ_ASSERT(v.isUndefined() || v.isNull());
    1503           0 :     MOZ_ALWAYS_FALSE(ToObjectSlow(cx, v, true));
    1504           0 :     return false;
    1505             : }
    1506             : 
    1507             : bool
    1508           0 : BaselineGetFunctionThis(JSContext* cx, BaselineFrame* frame, MutableHandleValue res)
    1509             : {
    1510           0 :     return GetFunctionThis(cx, frame, res);
    1511             : }
    1512             : 
    1513             : bool
    1514           0 : CallNativeGetter(JSContext* cx, HandleFunction callee, HandleObject obj,
    1515             :                  MutableHandleValue result)
    1516             : {
    1517        4478 :     MOZ_ASSERT(callee->isNative());
    1518           0 :     JSNative natfun = callee->native();
    1519             : 
    1520        4478 :     JS::AutoValueArray<2> vp(cx);
    1521           0 :     vp[0].setObject(*callee.get());
    1522           0 :     vp[1].setObject(*obj.get());
    1523             : 
    1524        2239 :     if (!natfun(cx, 0, vp.begin()))
    1525             :         return false;
    1526             : 
    1527        4478 :     result.set(vp[0]);
    1528           0 :     return true;
    1529             : }
    1530             : 
    1531             : bool
    1532           0 : CallNativeSetter(JSContext* cx, HandleFunction callee, HandleObject obj, HandleValue rhs)
    1533             : {
    1534           0 :     MOZ_ASSERT(callee->isNative());
    1535           0 :     JSNative natfun = callee->native();
    1536             : 
    1537           0 :     JS::AutoValueArray<3> vp(cx);
    1538           0 :     vp[0].setObject(*callee.get());
    1539           0 :     vp[1].setObject(*obj.get());
    1540           0 :     vp[2].set(rhs);
    1541             : 
    1542           0 :     return natfun(cx, 1, vp.begin());
    1543             : }
    1544             : 
    1545             : bool
    1546           0 : EqualStringsHelper(JSString* str1, JSString* str2)
    1547             : {
    1548             :     // IC code calls this directly so we shouldn't GC.
    1549        1960 :     AutoUnsafeCallWithABI unsafe;
    1550             : 
    1551           0 :     MOZ_ASSERT(str1->isAtom());
    1552           0 :     MOZ_ASSERT(!str2->isAtom());
    1553        2940 :     MOZ_ASSERT(str1->length() == str2->length());
    1554             : 
    1555             :     // ensureLinear is intentionally called with a nullptr to avoid OOM
    1556             :     // reporting; if it fails, we will continue to the next stub.
    1557         980 :     JSLinearString* str2Linear = str2->ensureLinear(nullptr);
    1558         980 :     if (!str2Linear)
    1559             :         return false;
    1560             : 
    1561           0 :     return EqualChars(&str1->asLinear(), str2Linear);
    1562             : }
    1563             : 
    1564             : bool
    1565           0 : CheckIsCallable(JSContext* cx, HandleValue v, CheckIsCallableKind kind)
    1566             : {
    1567           0 :     if (!IsCallable(v))
    1568           0 :         return ThrowCheckIsCallable(cx, kind);
    1569             : 
    1570             :     return true;
    1571             : }
    1572             : 
    1573             : template <bool HandleMissing>
    1574             : static MOZ_ALWAYS_INLINE bool
    1575           0 : GetNativeDataProperty(JSContext* cx, NativeObject* obj, jsid id, Value* vp)
    1576             : {
    1577             :     // Fast path used by megamorphic IC stubs. Unlike our other property
    1578             :     // lookup paths, this is optimized to be as fast as possible for simple
    1579             :     // data property lookups.
    1580             : 
    1581           0 :     AutoUnsafeCallWithABI unsafe;
    1582             : 
    1583       19738 :     MOZ_ASSERT(JSID_IS_ATOM(id) || JSID_IS_SYMBOL(id));
    1584             : 
    1585           0 :     while (true) {
    1586       55910 :         if (Shape* shape = obj->lastProperty()->search(cx, id)) {
    1587       13702 :             if (!shape->isDataProperty())
    1588             :                 return false;
    1589             : 
    1590           0 :             *vp = obj->getSlot(shape->slot());
    1591       13689 :             return true;
    1592             :         }
    1593             : 
    1594             :         // Property not found. Watch out for Class hooks.
    1595           0 :         if (MOZ_UNLIKELY(!obj->is<PlainObject>())) {
    1596        2085 :             if (ClassMayResolveId(cx->names(), obj->getClass(), id, obj))
    1597             :                 return false;
    1598             :         }
    1599             : 
    1600       14243 :         JSObject* proto = obj->staticPrototype();
    1601       14243 :         if (!proto) {
    1602             :             if (HandleMissing) {
    1603           0 :                 vp->setUndefined();
    1604        5481 :                 return true;
    1605             :             }
    1606             :             return false;
    1607             :         }
    1608             : 
    1609        8217 :         if (!proto->isNative())
    1610             :             return false;
    1611           0 :         obj = &proto->as<NativeObject>();
    1612             :     }
    1613             : }
    1614             : 
    1615             : template <bool HandleMissing>
    1616             : bool
    1617        9818 : GetNativeDataProperty(JSContext* cx, JSObject* obj, PropertyName* name, Value* vp)
    1618             : {
    1619             :     // Condition checked by caller.
    1620        9818 :     MOZ_ASSERT(obj->isNative());
    1621        9818 :     return GetNativeDataProperty<HandleMissing>(cx, &obj->as<NativeObject>(), NameToId(name), vp);
    1622             : }
    1623             : 
    1624             : template bool
    1625             : GetNativeDataProperty<true>(JSContext* cx, JSObject* obj, PropertyName* name, Value* vp);
    1626             : 
    1627             : template bool
    1628             : GetNativeDataProperty<false>(JSContext* cx, JSObject* obj, PropertyName* name, Value* vp);
    1629             : 
    1630             : static MOZ_ALWAYS_INLINE bool
    1631       23359 : ValueToAtomOrSymbol(JSContext* cx, Value& idVal, jsid* id)
    1632             : {
    1633           0 :     AutoUnsafeCallWithABI unsafe;
    1634             : 
    1635           0 :     if (MOZ_LIKELY(idVal.isString())) {
    1636           0 :         JSString* s = idVal.toString();
    1637             :         JSAtom* atom;
    1638       46710 :         if (s->isAtom()) {
    1639           0 :             atom = &s->asAtom();
    1640             :         } else {
    1641           0 :             atom = AtomizeString(cx, s);
    1642         752 :             if (!atom)
    1643             :                 return false;
    1644             :         }
    1645       23355 :         *id = AtomToId(atom);
    1646           4 :     } else if (idVal.isSymbol()) {
    1647           4 :         *id = SYMBOL_TO_JSID(idVal.toSymbol());
    1648             :     } else {
    1649           0 :         if (!ValueToIdPure(idVal, id))
    1650             :             return false;
    1651             :     }
    1652             : 
    1653             :     // Watch out for ids that may be stored in dense elements.
    1654             :     static_assert(NativeObject::MAX_DENSE_ELEMENTS_COUNT < JSID_INT_MAX,
    1655             :                   "All dense elements must have integer jsids");
    1656       23359 :     if (MOZ_UNLIKELY(JSID_IS_INT(*id)))
    1657             :         return false;
    1658             : 
    1659       23357 :     return true;
    1660             : }
    1661             : 
    1662             : template <bool HandleMissing>
    1663             : bool
    1664        9921 : GetNativeDataPropertyByValue(JSContext* cx, JSObject* obj, Value* vp)
    1665             : {
    1666           0 :     AutoUnsafeCallWithABI unsafe;
    1667             : 
    1668             :     // Condition checked by caller.
    1669        9921 :     MOZ_ASSERT(obj->isNative());
    1670             : 
    1671             :     // vp[0] contains the id, result will be stored in vp[1].
    1672           0 :     Value idVal = vp[0];
    1673        9921 :     jsid id;
    1674        9921 :     if (!ValueToAtomOrSymbol(cx, idVal, &id))
    1675             :         return false;
    1676             : 
    1677        9920 :     Value* res = vp + 1;
    1678        9920 :     return GetNativeDataProperty<HandleMissing>(cx, &obj->as<NativeObject>(), id, res);
    1679             : }
    1680             : 
    1681             : template bool
    1682             : GetNativeDataPropertyByValue<true>(JSContext* cx, JSObject* obj, Value* vp);
    1683             : 
    1684             : template bool
    1685             : GetNativeDataPropertyByValue<false>(JSContext* cx, JSObject* obj, Value* vp);
    1686             : 
    1687             : template <bool NeedsTypeBarrier>
    1688             : bool
    1689           2 : SetNativeDataProperty(JSContext* cx, JSObject* obj, PropertyName* name, Value* val)
    1690             : {
    1691           0 :     AutoUnsafeCallWithABI unsafe;
    1692             : 
    1693           0 :     if (MOZ_UNLIKELY(!obj->isNative()))
    1694             :         return false;
    1695             : 
    1696           2 :     NativeObject* nobj = &obj->as<NativeObject>();
    1697           4 :     Shape* shape = nobj->lastProperty()->search(cx, NameToId(name));
    1698           4 :     if (!shape ||
    1699           0 :         !shape->isDataProperty() ||
    1700             :         !shape->writable())
    1701             :     {
    1702             :         return false;
    1703             :     }
    1704             : 
    1705           4 :     if (NeedsTypeBarrier && !HasTypePropertyId(nobj, NameToId(name), *val))
    1706             :         return false;
    1707             : 
    1708           2 :     nobj->setSlot(shape->slot(), *val);
    1709           2 :     return true;
    1710             : }
    1711             : 
    1712             : template bool
    1713             : SetNativeDataProperty<true>(JSContext* cx, JSObject* obj, PropertyName* name, Value* val);
    1714             : 
    1715             : template bool
    1716             : SetNativeDataProperty<false>(JSContext* cx, JSObject* obj, PropertyName* name, Value* val);
    1717             : 
    1718             : bool
    1719        1330 : ObjectHasGetterSetter(JSContext* cx, JSObject* objArg, Shape* propShape)
    1720             : {
    1721           0 :     AutoUnsafeCallWithABI unsafe;
    1722             : 
    1723        1330 :     MOZ_ASSERT(propShape->hasGetterObject() || propShape->hasSetterObject());
    1724             : 
    1725             :     // Window objects may require outerizing (passing the WindowProxy to the
    1726             :     // getter/setter), so we don't support them here.
    1727        2659 :     if (MOZ_UNLIKELY(!objArg->isNative() || IsWindow(objArg)))
    1728             :         return false;
    1729             : 
    1730        1329 :     NativeObject* nobj = &objArg->as<NativeObject>();
    1731           0 :     jsid id = propShape->propid();
    1732             : 
    1733             :     while (true) {
    1734        4022 :         if (Shape* shape = nobj->lastProperty()->search(cx, id)) {
    1735        1329 :             if (shape == propShape)
    1736             :                 return true;
    1737        2664 :             if (shape->getterOrUndefined() == propShape->getterOrUndefined() &&
    1738           0 :                 shape->setterOrUndefined() == propShape->setterOrUndefined())
    1739             :             {
    1740             :                 return true;
    1741             :             }
    1742         888 :             return false;
    1743             :         }
    1744             : 
    1745             :         // Property not found. Watch out for Class hooks.
    1746           0 :         if (!nobj->is<PlainObject>()) {
    1747        1974 :             if (ClassMayResolveId(cx->names(), nobj->getClass(), id, nobj))
    1748             :                 return false;
    1749             :         }
    1750             : 
    1751           0 :         JSObject* proto = nobj->staticPrototype();
    1752           0 :         if (!proto)
    1753             :             return false;
    1754             : 
    1755         682 :         if (!proto->isNative())
    1756             :             return false;
    1757           0 :         nobj = &proto->as<NativeObject>();
    1758         682 :     }
    1759             : }
    1760             : 
    1761             : template <bool HasOwn>
    1762             : bool
    1763           0 : HasNativeDataProperty(JSContext* cx, JSObject* obj, Value* vp)
    1764             : {
    1765       26876 :     AutoUnsafeCallWithABI unsafe;
    1766             : 
    1767             :     // vp[0] contains the id, result will be stored in vp[1].
    1768           0 :     Value idVal = vp[0];
    1769           0 :     jsid id;
    1770           0 :     if (!ValueToAtomOrSymbol(cx, idVal, &id))
    1771             :         return false;
    1772             : 
    1773       14734 :     do {
    1774       21013 :         if (obj->isNative()) {
    1775       35054 :             if (obj->as<NativeObject>().lastProperty()->search(cx, id)) {
    1776           0 :                 vp[1].setBoolean(true);
    1777        4252 :                 return true;
    1778             :             }
    1779             : 
    1780             :             // Fail if there's a resolve hook, unless the mayResolve hook tells
    1781             :             // us the resolve hook won't define a property with this id.
    1782       26550 :             if (MOZ_UNLIKELY(ClassMayResolveId(cx->names(), obj->getClass(), id, obj)))
    1783             :                 return false;
    1784           1 :         } else if (obj->is<UnboxedPlainObject>()) {
    1785           1 :             if (obj->as<UnboxedPlainObject>().containsUnboxedOrExpandoProperty(cx, id)) {
    1786           1 :                 vp[1].setBoolean(true);
    1787        1847 :                 return true;
    1788             :             }
    1789           0 :         } else if (obj->is<TypedObject>()) {
    1790           0 :             if (obj->as<TypedObject>().typeDescr().hasProperty(cx->names(), id)) {
    1791           0 :                 vp[1].setBoolean(true);
    1792           0 :                 return true;
    1793             :             }
    1794             :         } else {
    1795             :             return false;
    1796             :         }
    1797             : 
    1798             :         // If implementing Object.hasOwnProperty, don't follow protochain.
    1799             :         if (HasOwn)
    1800             :             break;
    1801             : 
    1802             :         // Get prototype. Objects that may allow dynamic prototypes are already
    1803             :         // filtered out above.
    1804       14734 :         obj = obj->staticPrototype();
    1805             :     } while (obj);
    1806             : 
    1807             :     // Missing property.
    1808       14676 :     vp[1].setBoolean(false);
    1809        7338 :     return true;
    1810             : }
    1811             : 
    1812             : template bool
    1813             : HasNativeDataProperty<true>(JSContext* cx, JSObject* obj, Value* vp);
    1814             : 
    1815             : template bool
    1816             : HasNativeDataProperty<false>(JSContext* cx, JSObject* obj, Value* vp);
    1817             : 
    1818             : 
    1819             : bool
    1820           0 : HasNativeElement(JSContext* cx, NativeObject* obj, int32_t index, Value* vp)
    1821             : {
    1822           0 :     AutoUnsafeCallWithABI unsafe;
    1823             : 
    1824           0 :     MOZ_ASSERT(obj->getClass()->isNative());
    1825           0 :     MOZ_ASSERT(!obj->getOpsHasProperty());
    1826           0 :     MOZ_ASSERT(!obj->getOpsLookupProperty());
    1827           0 :     MOZ_ASSERT(!obj->getOpsGetOwnPropertyDescriptor());
    1828             : 
    1829           0 :     if (MOZ_UNLIKELY(index < 0))
    1830             :         return false;
    1831             : 
    1832           0 :     if (obj->containsDenseElement(index)) {
    1833           0 :         vp[0].setBoolean(true);
    1834           0 :         return true;
    1835             :     }
    1836             : 
    1837           0 :     jsid id = INT_TO_JSID(index);
    1838           0 :     if (obj->lastProperty()->search(cx, id)) {
    1839           0 :         vp[0].setBoolean(true);
    1840           0 :         return true;
    1841             :     }
    1842             : 
    1843             :     // Fail if there's a resolve hook, unless the mayResolve hook tells
    1844             :     // us the resolve hook won't define a property with this id.
    1845           0 :     if (MOZ_UNLIKELY(ClassMayResolveId(cx->names(), obj->getClass(), id, obj)))
    1846             :         return false;
    1847             :     // TypedArrayObject are also native and contain indexed properties.
    1848           0 :     if (MOZ_UNLIKELY(obj->is<TypedArrayObject>())) {
    1849           0 :         vp[0].setBoolean(uint32_t(index) < obj->as<TypedArrayObject>().length());
    1850           0 :         return true;
    1851             :     }
    1852             : 
    1853           0 :     vp[0].setBoolean(false);
    1854           0 :     return true;
    1855             : }
    1856             : 
    1857             : JSString*
    1858         528 : TypeOfObject(JSObject* obj, JSRuntime* rt)
    1859             : {
    1860           0 :     AutoUnsafeCallWithABI unsafe;
    1861         528 :     JSType type = js::TypeOfObject(obj);
    1862           0 :     return TypeName(type, *rt->commonNames);
    1863             : }
    1864             : 
    1865             : bool
    1866           0 : GetPrototypeOf(JSContext* cx, HandleObject target, MutableHandleValue rval)
    1867             : {
    1868           0 :     MOZ_ASSERT(target->hasDynamicPrototype());
    1869             : 
    1870           0 :     RootedObject proto(cx);
    1871           0 :     if (!GetPrototype(cx, target, &proto))
    1872             :         return false;
    1873           0 :     rval.setObjectOrNull(proto);
    1874             :     return true;
    1875             : }
    1876             : 
    1877             : void
    1878           0 : CloseIteratorFromIon(JSContext* cx, JSObject* obj)
    1879             : {
    1880           0 :     CloseIterator(obj);
    1881             : }
    1882             : 
    1883             : typedef bool (*SetObjectElementFn)(JSContext*, HandleObject, HandleValue,
    1884             :                                    HandleValue, HandleValue, bool);
    1885             : const VMFunction SetObjectElementInfo =
    1886             :     FunctionInfo<SetObjectElementFn>(js::SetObjectElement, "SetObjectElement");
    1887             : 
    1888             : } // namespace jit
    1889             : } // namespace js

Generated by: LCOV version 1.13-14-ga5dd952