LCOV - code coverage report
Current view: top level - js/src/jit - BaselineCompiler.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 1823 2563 71.1 %
Date: 2017-07-14 16:53:18 Functions: 208 274 75.9 %
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/BaselineCompiler.h"
       8             : 
       9             : #include "mozilla/Casting.h"
      10             : #include "mozilla/SizePrintfMacros.h"
      11             : 
      12             : #include "jsfun.h"
      13             : 
      14             : #include "jit/BaselineIC.h"
      15             : #include "jit/BaselineJIT.h"
      16             : #include "jit/FixedList.h"
      17             : #include "jit/IonAnalysis.h"
      18             : #include "jit/JitcodeMap.h"
      19             : #include "jit/JitSpewer.h"
      20             : #include "jit/Linker.h"
      21             : #ifdef JS_ION_PERF
      22             : # include "jit/PerfSpewer.h"
      23             : #endif
      24             : #include "jit/SharedICHelpers.h"
      25             : #include "jit/VMFunctions.h"
      26             : #include "js/UniquePtr.h"
      27             : #include "vm/AsyncFunction.h"
      28             : #include "vm/AsyncIteration.h"
      29             : #include "vm/EnvironmentObject.h"
      30             : #include "vm/Interpreter.h"
      31             : #include "vm/TraceLogging.h"
      32             : #include "vtune/VTuneWrapper.h"
      33             : 
      34             : #include "jsscriptinlines.h"
      35             : 
      36             : #include "jit/BaselineFrameInfo-inl.h"
      37             : #include "jit/MacroAssembler-inl.h"
      38             : #include "vm/Interpreter-inl.h"
      39             : #include "vm/NativeObject-inl.h"
      40             : 
      41             : using namespace js;
      42             : using namespace js::jit;
      43             : 
      44             : using mozilla::AssertedCast;
      45             : 
      46         628 : BaselineCompiler::BaselineCompiler(JSContext* cx, TempAllocator& alloc, JSScript* script)
      47             :   : BaselineCompilerSpecific(cx, alloc, script),
      48             :     yieldAndAwaitOffsets_(cx),
      49         628 :     modifiesArguments_(false)
      50             : {
      51         628 : }
      52             : 
      53             : bool
      54         628 : BaselineCompiler::init()
      55             : {
      56         628 :     if (!analysis_.init(alloc_, cx->caches().gsnCache))
      57           0 :         return false;
      58             : 
      59         628 :     if (!labels_.init(alloc_, script->length()))
      60           0 :         return false;
      61             : 
      62      164786 :     for (size_t i = 0; i < script->length(); i++)
      63      164158 :         new (&labels_[i]) Label();
      64             : 
      65         628 :     if (!frame.init(alloc_))
      66           0 :         return false;
      67             : 
      68         628 :     return true;
      69             : }
      70             : 
      71             : bool
      72       61179 : BaselineCompiler::addPCMappingEntry(bool addIndexEntry)
      73             : {
      74             :     // Don't add multiple entries for a single pc.
      75       61179 :     size_t nentries = pcMappingEntries_.length();
      76       61179 :     if (nentries > 0 && pcMappingEntries_[nentries - 1].pcOffset == script->pcToOffset(pc))
      77           0 :         return true;
      78             : 
      79       61179 :     PCMappingEntry entry;
      80       61179 :     entry.pcOffset = script->pcToOffset(pc);
      81       61179 :     entry.nativeOffset = masm.currentOffset();
      82       61179 :     entry.slotInfo = getStackTopSlotInfo();
      83       61179 :     entry.addIndexEntry = addIndexEntry;
      84             : 
      85       61179 :     return pcMappingEntries_.append(entry);
      86             : }
      87             : 
      88             : MethodStatus
      89         628 : BaselineCompiler::compile()
      90             : {
      91        1884 :     JitSpew(JitSpew_BaselineScripts, "Baseline compiling script %s:%" PRIuSIZE " (%p)",
      92        1884 :             script->filename(), script->lineno(), script);
      93             : 
      94        1256 :     JitSpew(JitSpew_Codegen, "# Emitting baseline code for script %s:%" PRIuSIZE,
      95        1884 :             script->filename(), script->lineno());
      96             : 
      97         628 :     TraceLoggerThread* logger = TraceLoggerForCurrentThread(cx);
      98        1256 :     TraceLoggerEvent scriptEvent(TraceLogger_AnnotateScripts, script);
      99        1256 :     AutoTraceLog logScript(logger, scriptEvent);
     100        1256 :     AutoTraceLog logCompile(logger, TraceLogger_BaselineCompilation);
     101             : 
     102         628 :     if (!script->ensureHasTypes(cx) || !script->ensureHasAnalyzedArgsUsage(cx))
     103           0 :         return Method_Error;
     104             : 
     105             :     // When code coverage is only enabled for optimizations, or when a Debugger
     106             :     // set the collectCoverageInfo flag, we have to create the ScriptCounts if
     107             :     // they do not exist.
     108         628 :     if (!script->hasScriptCounts() && cx->compartment()->collectCoverage()) {
     109         613 :         if (!script->initScriptCounts(cx))
     110           0 :             return Method_Error;
     111             :     }
     112             : 
     113             :     // Pin analysis info during compilation.
     114        1256 :     AutoEnterAnalysis autoEnterAnalysis(cx);
     115             : 
     116         628 :     MOZ_ASSERT(!script->hasBaselineScript());
     117             : 
     118         628 :     if (!emitPrologue())
     119           0 :         return Method_Error;
     120             : 
     121         628 :     MethodStatus status = emitBody();
     122         628 :     if (status != Method_Compiled)
     123           1 :         return status;
     124             : 
     125         627 :     if (!emitEpilogue())
     126           0 :         return Method_Error;
     127             : 
     128         627 :     if (!emitOutOfLinePostBarrierSlot())
     129           0 :         return Method_Error;
     130             : 
     131        1254 :     Linker linker(masm);
     132         627 :     if (masm.oom()) {
     133           0 :         ReportOutOfMemory(cx);
     134           0 :         return Method_Error;
     135             :     }
     136             : 
     137        1254 :     AutoFlushICache afc("Baseline");
     138         627 :     JitCode* code = linker.newCode<CanGC>(cx, BASELINE_CODE);
     139         627 :     if (!code)
     140           0 :         return Method_Error;
     141             : 
     142        1254 :     Rooted<EnvironmentObject*> templateEnv(cx);
     143         627 :     if (script->functionNonDelazifying()) {
     144        1244 :         RootedFunction fun(cx, script->functionNonDelazifying());
     145             : 
     146         622 :         if (fun->needsNamedLambdaEnvironment()) {
     147           0 :             templateEnv = NamedLambdaObject::createTemplateObject(cx, fun, gc::TenuredHeap);
     148           0 :             if (!templateEnv)
     149           0 :                 return Method_Error;
     150             :         }
     151             : 
     152         622 :         if (fun->needsCallObject()) {
     153         130 :             RootedScript scriptRoot(cx, script);
     154         130 :             templateEnv = CallObject::createTemplateObject(cx, scriptRoot, templateEnv,
     155          65 :                                                            gc::TenuredHeap);
     156          65 :             if (!templateEnv)
     157           0 :                 return Method_Error;
     158             :         }
     159             :     }
     160             : 
     161             :     // Encode the pc mapping table. See PCMappingIndexEntry for
     162             :     // more information.
     163        1254 :     Vector<PCMappingIndexEntry> pcMappingIndexEntries(cx);
     164        1254 :     CompactBufferWriter pcEntries;
     165         627 :     uint32_t previousOffset = 0;
     166             : 
     167       61805 :     for (size_t i = 0; i < pcMappingEntries_.length(); i++) {
     168       61178 :         PCMappingEntry& entry = pcMappingEntries_[i];
     169             : 
     170       61178 :         if (entry.addIndexEntry) {
     171             :             PCMappingIndexEntry indexEntry;
     172        1132 :             indexEntry.pcOffset = entry.pcOffset;
     173        1132 :             indexEntry.nativeOffset = entry.nativeOffset;
     174        1132 :             indexEntry.bufferOffset = pcEntries.length();
     175        1132 :             if (!pcMappingIndexEntries.append(indexEntry)) {
     176           0 :                 ReportOutOfMemory(cx);
     177           0 :                 return Method_Error;
     178             :             }
     179        1132 :             previousOffset = entry.nativeOffset;
     180             :         }
     181             : 
     182             :         // Use the high bit of the SlotInfo byte to indicate the
     183             :         // native code offset (relative to the previous op) > 0 and
     184             :         // comes next in the buffer.
     185       61178 :         MOZ_ASSERT((entry.slotInfo.toByte() & 0x80) == 0);
     186             : 
     187       61178 :         if (entry.nativeOffset == previousOffset) {
     188       15359 :             pcEntries.writeByte(entry.slotInfo.toByte());
     189             :         } else {
     190       45819 :             MOZ_ASSERT(entry.nativeOffset > previousOffset);
     191       45819 :             pcEntries.writeByte(0x80 | entry.slotInfo.toByte());
     192       45819 :             pcEntries.writeUnsigned(entry.nativeOffset - previousOffset);
     193             :         }
     194             : 
     195       61178 :         previousOffset = entry.nativeOffset;
     196             :     }
     197             : 
     198         627 :     if (pcEntries.oom()) {
     199           0 :         ReportOutOfMemory(cx);
     200           0 :         return Method_Error;
     201             :     }
     202             : 
     203             :     // Note: There is an extra entry in the bytecode type map for the search hint, see below.
     204         627 :     size_t bytecodeTypeMapEntries = script->nTypeSets() + 1;
     205             :     UniquePtr<BaselineScript> baselineScript(
     206         627 :         BaselineScript::New(script, prologueOffset_.offset(),
     207         627 :                             epilogueOffset_.offset(),
     208         627 :                             profilerEnterFrameToggleOffset_.offset(),
     209         627 :                             profilerExitFrameToggleOffset_.offset(),
     210         627 :                             postDebugPrologueOffset_.offset(),
     211             :                             icEntries_.length(),
     212             :                             pcMappingIndexEntries.length(),
     213             :                             pcEntries.length(),
     214             :                             bytecodeTypeMapEntries,
     215             :                             yieldAndAwaitOffsets_.length(),
     216             :                             traceLoggerToggleOffsets_.length()),
     217        4389 :         JS::DeletePolicy<BaselineScript>(cx->runtime()));
     218         627 :     if (!baselineScript) {
     219           0 :         ReportOutOfMemory(cx);
     220           0 :         return Method_Error;
     221             :     }
     222             : 
     223         627 :     baselineScript->setMethod(code);
     224         627 :     baselineScript->setTemplateEnvironment(templateEnv);
     225             : 
     226        1254 :     JitSpew(JitSpew_BaselineScripts, "Created BaselineScript %p (raw %p) for %s:%" PRIuSIZE,
     227         627 :             (void*) baselineScript.get(), (void*) code->raw(),
     228        1881 :             script->filename(), script->lineno());
     229             : 
     230         627 :     MOZ_ASSERT(pcMappingIndexEntries.length() > 0);
     231         627 :     baselineScript->copyPCMappingIndexEntries(&pcMappingIndexEntries[0]);
     232             : 
     233         627 :     MOZ_ASSERT(pcEntries.length() > 0);
     234         627 :     baselineScript->copyPCMappingEntries(pcEntries);
     235             : 
     236             :     // Copy IC entries
     237         627 :     if (icEntries_.length())
     238         627 :         baselineScript->copyICEntries(script, &icEntries_[0], masm);
     239             : 
     240             :     // Adopt fallback stubs from the compiler into the baseline script.
     241         627 :     baselineScript->adoptFallbackStubs(&stubSpace_);
     242             : 
     243             :     // If profiler instrumentation is enabled, toggle instrumentation on.
     244         627 :     if (cx->runtime()->jitRuntime()->isProfilerInstrumentationEnabled(cx->runtime()))
     245           0 :         baselineScript->toggleProfilerInstrumentation(true);
     246             : 
     247             :     // Patch IC loads using IC entries.
     248       19968 :     for (size_t i = 0; i < icLoadLabels_.length(); i++) {
     249       19341 :         CodeOffset label = icLoadLabels_[i].label;
     250       19341 :         size_t icEntry = icLoadLabels_[i].icEntry;
     251       19341 :         BaselineICEntry* entryAddr = &(baselineScript->icEntry(icEntry));
     252       38682 :         Assembler::PatchDataWithValueCheck(CodeLocationLabel(code, label),
     253             :                                            ImmPtr(entryAddr),
     254       19341 :                                            ImmPtr((void*)-1));
     255             :     }
     256             : 
     257         627 :     if (modifiesArguments_)
     258          69 :         baselineScript->setModifiesArguments();
     259             : 
     260             : #ifdef JS_TRACE_LOGGING
     261             :     // Initialize the tracelogger instrumentation.
     262         627 :     baselineScript->initTraceLogger(cx->runtime(), script, traceLoggerToggleOffsets_);
     263             : #endif
     264             : 
     265         627 :     uint32_t* bytecodeMap = baselineScript->bytecodeTypeMap();
     266         627 :     FillBytecodeTypeMap(script, bytecodeMap);
     267             : 
     268             :     // The last entry in the last index found, and is used to avoid binary
     269             :     // searches for the sought entry when queries are in linear order.
     270         627 :     bytecodeMap[script->nTypeSets()] = 0;
     271             : 
     272         627 :     baselineScript->copyYieldAndAwaitEntries(script, yieldAndAwaitOffsets_);
     273             : 
     274         627 :     if (compileDebugInstrumentation_)
     275           0 :         baselineScript->setHasDebugInstrumentation();
     276             : 
     277             :     // Always register a native => bytecode mapping entry, since profiler can be
     278             :     // turned on with baseline jitcode on stack, and baseline jitcode cannot be invalidated.
     279             :     {
     280        1881 :         JitSpew(JitSpew_Profiling, "Added JitcodeGlobalEntry for baseline script %s:%" PRIuSIZE " (%p)",
     281        1881 :                     script->filename(), script->lineno(), baselineScript.get());
     282             : 
     283             :         // Generate profiling string.
     284         627 :         char* str = JitcodeGlobalEntry::createScriptString(cx, script);
     285         627 :         if (!str)
     286           0 :             return Method_Error;
     287             : 
     288             :         JitcodeGlobalEntry::BaselineEntry entry;
     289         627 :         entry.init(code, code->raw(), code->rawEnd(), script, str);
     290             : 
     291         627 :         JitcodeGlobalTable* globalTable = cx->runtime()->jitRuntime()->getJitcodeGlobalTable();
     292         627 :         if (!globalTable->addEntry(entry, cx->runtime())) {
     293           0 :             entry.destroy();
     294           0 :             ReportOutOfMemory(cx);
     295           0 :             return Method_Error;
     296             :         }
     297             : 
     298             :         // Mark the jitcode as having a bytecode map.
     299         627 :         code->setHasBytecodeMap();
     300             :     }
     301             : 
     302         627 :     script->setBaselineScript(cx->runtime(), baselineScript.release());
     303             : 
     304             : #ifdef JS_ION_PERF
     305             :     writePerfSpewerBaselineProfile(script, code);
     306             : #endif
     307             : 
     308             : #ifdef MOZ_VTUNE
     309         627 :     vtune::MarkScript(code, script, "baseline");
     310             : #endif
     311             : 
     312         627 :     return Method_Compiled;
     313             : }
     314             : 
     315             : void
     316         628 : BaselineCompiler::emitInitializeLocals()
     317             : {
     318             :     // Initialize all locals to |undefined|. Lexical bindings are temporal
     319             :     // dead zoned in bytecode.
     320             : 
     321         628 :     size_t n = frame.nlocals();
     322         628 :     if (n == 0)
     323         189 :         return;
     324             : 
     325             :     // Use R0 to minimize code size. If the number of locals to push is <
     326             :     // LOOP_UNROLL_FACTOR, then the initialization pushes are emitted directly
     327             :     // and inline.  Otherwise, they're emitted in a partially unrolled loop.
     328             :     static const size_t LOOP_UNROLL_FACTOR = 4;
     329         439 :     size_t toPushExtra = n % LOOP_UNROLL_FACTOR;
     330             : 
     331         439 :     masm.moveValue(UndefinedValue(), R0);
     332             : 
     333             :     // Handle any extra pushes left over by the optional unrolled loop below.
     334        1134 :     for (size_t i = 0; i < toPushExtra; i++)
     335         695 :         masm.pushValue(R0);
     336             : 
     337             :     // Partially unrolled loop of pushes.
     338         439 :     if (n >= LOOP_UNROLL_FACTOR) {
     339         177 :         size_t toPush = n - toPushExtra;
     340         177 :         MOZ_ASSERT(toPush % LOOP_UNROLL_FACTOR == 0);
     341         177 :         MOZ_ASSERT(toPush >= LOOP_UNROLL_FACTOR);
     342         177 :         masm.move32(Imm32(toPush), R1.scratchReg());
     343             :         // Emit unrolled loop with 4 pushes per iteration.
     344         354 :         Label pushLoop;
     345         177 :         masm.bind(&pushLoop);
     346         885 :         for (size_t i = 0; i < LOOP_UNROLL_FACTOR; i++)
     347         708 :             masm.pushValue(R0);
     348         354 :         masm.branchSub32(Assembler::NonZero,
     349         177 :                          Imm32(LOOP_UNROLL_FACTOR), R1.scratchReg(), &pushLoop);
     350             :     }
     351             : }
     352             : 
     353             : bool
     354         628 : BaselineCompiler::emitPrologue()
     355             : {
     356             : #ifdef JS_USE_LINK_REGISTER
     357             :     // Push link register from generateEnterJIT()'s BLR.
     358             :     masm.pushReturnAddress();
     359             :     masm.checkStackAlignment();
     360             : #endif
     361         628 :     emitProfilerEnterFrame();
     362             : 
     363         628 :     masm.push(BaselineFrameReg);
     364         628 :     masm.moveStackPtrTo(BaselineFrameReg);
     365         628 :     masm.subFromStackPtr(Imm32(BaselineFrame::Size()));
     366             : 
     367             :     // Initialize BaselineFrame. For eval scripts, the scope chain
     368             :     // is passed in R1, so we have to be careful not to clobber it.
     369             : 
     370             :     // Initialize BaselineFrame::flags.
     371         628 :     masm.store32(Imm32(0), frame.addressOfFlags());
     372             : 
     373             :     // Handle env chain pre-initialization (in case GC gets run
     374             :     // during stack check).  For global and eval scripts, the env
     375             :     // chain is in R1.  For function scripts, the env chain is in
     376             :     // the callee, nullptr is stored for now so that GC doesn't choke
     377             :     // on a bogus EnvironmentChain value in the frame.
     378         628 :     if (function())
     379         623 :         masm.storePtr(ImmPtr(nullptr), frame.addressOfEnvironmentChain());
     380             :     else
     381           5 :         masm.storePtr(R1.scratchReg(), frame.addressOfEnvironmentChain());
     382             : 
     383             :     // Functions with a large number of locals require two stack checks.
     384             :     // The VMCall for a fallible stack check can only occur after the
     385             :     // env chain has been initialized, as that is required for proper
     386             :     // exception handling if the VMCall returns false.  The env chain
     387             :     // initialization can only happen after the UndefinedValues for the
     388             :     // local slots have been pushed.
     389             :     // However by that time, the stack might have grown too much.
     390             :     // In these cases, we emit an extra, early, infallible check
     391             :     // before pushing the locals.  The early check sets a flag on the
     392             :     // frame if the stack check fails (but otherwise doesn't throw an
     393             :     // exception).  If the flag is set, then the jitcode skips past
     394             :     // the pushing of the locals, and directly to env chain initialization
     395             :     // followed by the actual stack check, which will throw the correct
     396             :     // exception.
     397        1256 :     Label earlyStackCheckFailed;
     398         628 :     if (needsEarlyStackCheck()) {
     399           0 :         if (!emitStackCheck(/* earlyCheck = */ true))
     400           0 :             return false;
     401           0 :         masm.branchTest32(Assembler::NonZero,
     402           0 :                           frame.addressOfFlags(),
     403             :                           Imm32(BaselineFrame::OVER_RECURSED),
     404           0 :                           &earlyStackCheckFailed);
     405             :     }
     406             : 
     407         628 :     emitInitializeLocals();
     408             : 
     409         628 :     if (needsEarlyStackCheck())
     410           0 :         masm.bind(&earlyStackCheckFailed);
     411             : 
     412             : #ifdef JS_TRACE_LOGGING
     413         628 :     if (!emitTraceLoggerEnter())
     414           0 :         return false;
     415             : #endif
     416             : 
     417             :     // Record the offset of the prologue, because Ion can bailout before
     418             :     // the env chain is initialized.
     419         628 :     prologueOffset_ = CodeOffset(masm.currentOffset());
     420             : 
     421             :     // When compiling with Debugger instrumentation, set the debuggeeness of
     422             :     // the frame before any operation that can call into the VM.
     423         628 :     emitIsDebuggeeCheck();
     424             : 
     425             :     // Initialize the env chain before any operation that may
     426             :     // call into the VM and trigger a GC.
     427         628 :     if (!initEnvironmentChain())
     428           0 :         return false;
     429             : 
     430         628 :     if (!emitStackCheck())
     431           0 :         return false;
     432             : 
     433         628 :     if (!emitDebugPrologue())
     434           0 :         return false;
     435             : 
     436         628 :     if (!emitWarmUpCounterIncrement())
     437           0 :         return false;
     438             : 
     439         628 :     if (!emitArgumentTypeChecks())
     440           0 :         return false;
     441             : 
     442         628 :     return true;
     443             : }
     444             : 
     445             : bool
     446         627 : BaselineCompiler::emitEpilogue()
     447             : {
     448             :     // Record the offset of the epilogue, so we can do early return from
     449             :     // Debugger handlers during on-stack recompile.
     450         627 :     epilogueOffset_ = CodeOffset(masm.currentOffset());
     451             : 
     452         627 :     masm.bind(&return_);
     453             : 
     454             : #ifdef JS_TRACE_LOGGING
     455         627 :     if (!emitTraceLoggerExit())
     456           0 :         return false;
     457             : #endif
     458             : 
     459         627 :     masm.moveToStackPtr(BaselineFrameReg);
     460         627 :     masm.pop(BaselineFrameReg);
     461             : 
     462         627 :     emitProfilerExitFrame();
     463             : 
     464         627 :     masm.ret();
     465         627 :     return true;
     466             : }
     467             : 
     468             : // On input:
     469             : //  R2.scratchReg() contains object being written to.
     470             : //  Called with the baseline stack synced, except for R0 which is preserved.
     471             : //  All other registers are usable as scratch.
     472             : // This calls:
     473             : //    void PostWriteBarrier(JSRuntime* rt, JSObject* obj);
     474             : bool
     475         627 : BaselineCompiler::emitOutOfLinePostBarrierSlot()
     476             : {
     477         627 :     masm.bind(&postBarrierSlot_);
     478             : 
     479         627 :     Register objReg = R2.scratchReg();
     480         627 :     AllocatableGeneralRegisterSet regs(GeneralRegisterSet::All());
     481         627 :     regs.take(R0);
     482         627 :     regs.take(objReg);
     483         627 :     regs.take(BaselineFrameReg);
     484         627 :     Register scratch = regs.takeAny();
     485             : #if defined(JS_CODEGEN_ARM) || defined(JS_CODEGEN_ARM64)
     486             :     // On ARM, save the link register before calling.  It contains the return
     487             :     // address.  The |masm.ret()| later will pop this into |pc| to return.
     488             :     masm.push(lr);
     489             : #elif defined(JS_CODEGEN_MIPS32) || defined(JS_CODEGEN_MIPS64)
     490             :     masm.push(ra);
     491             : #endif
     492         627 :     masm.pushValue(R0);
     493             : 
     494         627 :     masm.setupUnalignedABICall(scratch);
     495         627 :     masm.movePtr(ImmPtr(cx->runtime()), scratch);
     496         627 :     masm.passABIArg(scratch);
     497         627 :     masm.passABIArg(objReg);
     498         627 :     masm.callWithABI(JS_FUNC_TO_DATA_PTR(void*, PostWriteBarrier));
     499             : 
     500         627 :     masm.popValue(R0);
     501         627 :     masm.ret();
     502         627 :     return true;
     503             : }
     504             : 
     505             : bool
     506       19345 : BaselineCompiler::emitIC(ICStub* stub, ICEntry::Kind kind)
     507             : {
     508       19345 :     BaselineICEntry* entry = allocateICEntry(stub, kind);
     509       19345 :     if (!entry)
     510           0 :         return false;
     511             : 
     512       19345 :     CodeOffset patchOffset;
     513       19345 :     EmitCallIC(&patchOffset, masm);
     514       19345 :     entry->setReturnOffset(CodeOffset(masm.currentOffset()));
     515       19345 :     if (!addICLoadLabel(patchOffset))
     516           0 :         return false;
     517             : 
     518       19345 :     return true;
     519             : }
     520             : 
     521             : typedef bool (*CheckOverRecursedWithExtraFn)(JSContext*, BaselineFrame*, uint32_t, uint32_t);
     522           3 : static const VMFunction CheckOverRecursedWithExtraInfo =
     523           6 :     FunctionInfo<CheckOverRecursedWithExtraFn>(CheckOverRecursedWithExtra,
     524             :                                                "CheckOverRecursedWithExtra");
     525             : 
     526             : bool
     527         628 : BaselineCompiler::emitStackCheck(bool earlyCheck)
     528             : {
     529        1256 :     Label skipCall;
     530         628 :     uint32_t slotsSize = script->nslots() * sizeof(Value);
     531         628 :     uint32_t tolerance = earlyCheck ? slotsSize : 0;
     532             : 
     533         628 :     masm.moveStackPtrTo(R1.scratchReg());
     534             : 
     535             :     // If this is the early stack check, locals haven't been pushed yet.  Adjust the
     536             :     // stack pointer to account for the locals that would be pushed before performing
     537             :     // the guard around the vmcall to the stack check.
     538         628 :     if (earlyCheck)
     539           0 :         masm.subPtr(Imm32(tolerance), R1.scratchReg());
     540             : 
     541             :     // If this is the late stack check for a frame which contains an early stack check,
     542             :     // then the early stack check might have failed and skipped past the pushing of locals
     543             :     // on the stack.
     544             :     //
     545             :     // If this is a possibility, then the OVER_RECURSED flag should be checked, and the
     546             :     // VMCall to CheckOverRecursed done unconditionally if it's set.
     547        1256 :     Label forceCall;
     548         628 :     if (!earlyCheck && needsEarlyStackCheck()) {
     549           0 :         masm.branchTest32(Assembler::NonZero,
     550           0 :                           frame.addressOfFlags(),
     551             :                           Imm32(BaselineFrame::OVER_RECURSED),
     552           0 :                           &forceCall);
     553             :     }
     554             : 
     555         628 :     void* contextAddr = cx->zone()->group()->addressOfOwnerContext();
     556         628 :     masm.loadPtr(AbsoluteAddress(contextAddr), R0.scratchReg());
     557        1256 :     masm.branchPtr(Assembler::BelowOrEqual,
     558        1256 :                    Address(R0.scratchReg(), offsetof(JSContext, jitStackLimit)), R1.scratchReg(),
     559         628 :                    &skipCall);
     560             : 
     561         628 :     if (!earlyCheck && needsEarlyStackCheck())
     562           0 :         masm.bind(&forceCall);
     563             : 
     564         628 :     prepareVMCall();
     565         628 :     pushArg(Imm32(earlyCheck));
     566         628 :     pushArg(Imm32(tolerance));
     567         628 :     masm.loadBaselineFramePtr(BaselineFrameReg, R1.scratchReg());
     568         628 :     pushArg(R1.scratchReg());
     569             : 
     570         628 :     CallVMPhase phase = POST_INITIALIZE;
     571         628 :     if (earlyCheck)
     572           0 :         phase = PRE_INITIALIZE;
     573         628 :     else if (needsEarlyStackCheck())
     574           0 :         phase = CHECK_OVER_RECURSED;
     575             : 
     576         628 :     if (!callVMNonOp(CheckOverRecursedWithExtraInfo, phase))
     577           0 :         return false;
     578             : 
     579         628 :     icEntries_.back().setFakeKind(earlyCheck
     580             :                                   ? ICEntry::Kind_EarlyStackCheck
     581         628 :                                   : ICEntry::Kind_StackCheck);
     582             : 
     583         628 :     masm.bind(&skipCall);
     584         628 :     return true;
     585             : }
     586             : 
     587             : void
     588         628 : BaselineCompiler::emitIsDebuggeeCheck()
     589             : {
     590         628 :     if (compileDebugInstrumentation_) {
     591           0 :         masm.Push(BaselineFrameReg);
     592           0 :         masm.setupUnalignedABICall(R0.scratchReg());
     593           0 :         masm.loadBaselineFramePtr(BaselineFrameReg, R0.scratchReg());
     594           0 :         masm.passABIArg(R0.scratchReg());
     595           0 :         masm.callWithABI(JS_FUNC_TO_DATA_PTR(void*, jit::FrameIsDebuggeeCheck));
     596           0 :         masm.Pop(BaselineFrameReg);
     597             :     }
     598         628 : }
     599             : 
     600             : typedef bool (*DebugPrologueFn)(JSContext*, BaselineFrame*, jsbytecode*, bool*);
     601           3 : static const VMFunction DebugPrologueInfo =
     602           6 :     FunctionInfo<DebugPrologueFn>(jit::DebugPrologue, "DebugPrologue");
     603             : 
     604             : bool
     605         628 : BaselineCompiler::emitDebugPrologue()
     606             : {
     607         628 :     if (compileDebugInstrumentation_) {
     608             :         // Load pointer to BaselineFrame in R0.
     609           0 :         masm.loadBaselineFramePtr(BaselineFrameReg, R0.scratchReg());
     610             : 
     611           0 :         prepareVMCall();
     612           0 :         pushArg(ImmPtr(pc));
     613           0 :         pushArg(R0.scratchReg());
     614           0 :         if (!callVM(DebugPrologueInfo))
     615           0 :             return false;
     616             : 
     617             :         // Fix up the fake ICEntry appended by callVM for on-stack recompilation.
     618           0 :         icEntries_.back().setFakeKind(ICEntry::Kind_DebugPrologue);
     619             : 
     620             :         // If the stub returns |true|, we have to return the value stored in the
     621             :         // frame's return value slot.
     622           0 :         Label done;
     623           0 :         masm.branchTest32(Assembler::Zero, ReturnReg, ReturnReg, &done);
     624             :         {
     625           0 :             masm.loadValue(frame.addressOfReturnValue(), JSReturnOperand);
     626           0 :             masm.jump(&return_);
     627             :         }
     628           0 :         masm.bind(&done);
     629             :     }
     630             : 
     631         628 :     postDebugPrologueOffset_ = CodeOffset(masm.currentOffset());
     632             : 
     633         628 :     return true;
     634             : }
     635             : 
     636             : typedef bool (*CheckGlobalOrEvalDeclarationConflictsFn)(JSContext*, BaselineFrame*);
     637           3 : static const VMFunction CheckGlobalOrEvalDeclarationConflictsInfo =
     638           6 :     FunctionInfo<CheckGlobalOrEvalDeclarationConflictsFn>(jit::CheckGlobalOrEvalDeclarationConflicts,
     639             :                                                           "CheckGlobalOrEvalDeclarationConflicts");
     640             : 
     641             : typedef bool (*InitFunctionEnvironmentObjectsFn)(JSContext*, BaselineFrame*);
     642           3 : static const VMFunction InitFunctionEnvironmentObjectsInfo =
     643           6 :     FunctionInfo<InitFunctionEnvironmentObjectsFn>(jit::InitFunctionEnvironmentObjects,
     644             :                                                    "InitFunctionEnvironmentObjects");
     645             : 
     646             : bool
     647         628 : BaselineCompiler::initEnvironmentChain()
     648             : {
     649         628 :     CallVMPhase phase = POST_INITIALIZE;
     650         628 :     if (needsEarlyStackCheck())
     651           0 :         phase = CHECK_OVER_RECURSED;
     652             : 
     653        1256 :     RootedFunction fun(cx, function());
     654         628 :     if (fun) {
     655             :         // Use callee->environment as scope chain. Note that we do this also
     656             :         // for needsSomeEnvironmentObject functions, so that the scope chain
     657             :         // slot is properly initialized if the call triggers GC.
     658         623 :         Register callee = R0.scratchReg();
     659         623 :         Register scope = R1.scratchReg();
     660         623 :         masm.loadFunctionFromCalleeToken(frame.addressOfCalleeToken(), callee);
     661         623 :         masm.loadPtr(Address(callee, JSFunction::offsetOfEnvironment()), scope);
     662         623 :         masm.storePtr(scope, frame.addressOfEnvironmentChain());
     663             : 
     664         623 :         if (fun->needsFunctionEnvironmentObjects()) {
     665             :             // Call into the VM to create the proper environment objects.
     666          65 :             prepareVMCall();
     667             : 
     668          65 :             masm.loadBaselineFramePtr(BaselineFrameReg, R0.scratchReg());
     669          65 :             pushArg(R0.scratchReg());
     670             : 
     671          65 :             if (!callVMNonOp(InitFunctionEnvironmentObjectsInfo, phase))
     672           0 :                 return false;
     673             :         }
     674           5 :     } else if (module()) {
     675             :         // Modules use a pre-created scope object.
     676           0 :         Register scope = R1.scratchReg();
     677           0 :         masm.movePtr(ImmGCPtr(&module()->initialEnvironment()), scope);
     678           0 :         masm.storePtr(scope, frame.addressOfEnvironmentChain());
     679             :     } else {
     680             :         // EnvironmentChain pointer in BaselineFrame has already been initialized
     681             :         // in prologue, but we need to check for redeclaration errors.
     682             : 
     683           5 :         prepareVMCall();
     684           5 :         masm.loadBaselineFramePtr(BaselineFrameReg, R0.scratchReg());
     685           5 :         pushArg(R0.scratchReg());
     686             : 
     687           5 :         if (!callVMNonOp(CheckGlobalOrEvalDeclarationConflictsInfo, phase))
     688           0 :             return false;
     689             :     }
     690             : 
     691         628 :     return true;
     692             : }
     693             : 
     694             : typedef bool (*InterruptCheckFn)(JSContext*);
     695           3 : static const VMFunction InterruptCheckInfo =
     696           6 :     FunctionInfo<InterruptCheckFn>(InterruptCheck, "InterruptCheck");
     697             : 
     698             : bool
     699         295 : BaselineCompiler::emitInterruptCheck()
     700             : {
     701         295 :     frame.syncStack(0);
     702             : 
     703         590 :     Label done;
     704         295 :     void* context = cx->zone()->group()->addressOfOwnerContext();
     705         295 :     masm.loadPtr(AbsoluteAddress(context), R0.scratchReg());
     706         885 :     masm.branch32(Assembler::Equal,
     707         590 :                   Address(R0.scratchReg(), offsetof(JSContext, interrupt_)), Imm32(0),
     708         295 :                   &done);
     709             : 
     710         295 :     prepareVMCall();
     711         295 :     if (!callVM(InterruptCheckInfo))
     712           0 :         return false;
     713             : 
     714         295 :     masm.bind(&done);
     715         295 :     return true;
     716             : }
     717             : 
     718             : typedef bool (*IonCompileScriptForBaselineFn)(JSContext*, BaselineFrame*, jsbytecode*);
     719           3 : static const VMFunction IonCompileScriptForBaselineInfo =
     720           6 :     FunctionInfo<IonCompileScriptForBaselineFn>(IonCompileScriptForBaseline,
     721             :                                                 "IonCompileScriptForBaseline");
     722             : 
     723             : bool
     724         911 : BaselineCompiler::emitWarmUpCounterIncrement(bool allowOsr)
     725             : {
     726             :     // Emit no warm-up counter increments or bailouts if Ion is not
     727             :     // enabled, or if the script will never be Ion-compileable
     728             : 
     729         911 :     if (!ionCompileable_ && !ionOSRCompileable_)
     730          19 :         return true;
     731             : 
     732         892 :     frame.assertSyncedStack();
     733             : 
     734         892 :     Register scriptReg = R2.scratchReg();
     735         892 :     Register countReg = R0.scratchReg();
     736         892 :     Address warmUpCounterAddr(scriptReg, JSScript::offsetOfWarmUpCounter());
     737             : 
     738         892 :     masm.movePtr(ImmGCPtr(script), scriptReg);
     739         892 :     masm.load32(warmUpCounterAddr, countReg);
     740         892 :     masm.add32(Imm32(1), countReg);
     741         892 :     masm.store32(countReg, warmUpCounterAddr);
     742             : 
     743             :     // If this is a loop inside a catch or finally block, increment the warmup
     744             :     // counter but don't attempt OSR (Ion only compiles the try block).
     745         892 :     if (analysis_.info(pc).loopEntryInCatchOrFinally) {
     746           2 :         MOZ_ASSERT(JSOp(*pc) == JSOP_LOOPENTRY);
     747           2 :         return true;
     748             :     }
     749             : 
     750             :     // OSR not possible at this loop entry.
     751         890 :     if (!allowOsr) {
     752          25 :         MOZ_ASSERT(JSOp(*pc) == JSOP_LOOPENTRY);
     753          25 :         return true;
     754             :     }
     755             : 
     756        1730 :     Label skipCall;
     757             : 
     758         865 :     const OptimizationInfo* info = IonOptimizations.get(IonOptimizations.firstLevel());
     759         865 :     uint32_t warmUpThreshold = info->compilerWarmUpThreshold(script, pc);
     760         865 :     masm.branch32(Assembler::LessThan, countReg, Imm32(warmUpThreshold), &skipCall);
     761             : 
     762        2595 :     masm.branchPtr(Assembler::Equal,
     763        1730 :                    Address(scriptReg, JSScript::offsetOfIonScript()),
     764         865 :                    ImmPtr(ION_COMPILING_SCRIPT), &skipCall);
     765             : 
     766             :     // Try to compile and/or finish a compilation.
     767         865 :     if (JSOp(*pc) == JSOP_LOOPENTRY) {
     768             :         // During the loop entry we can try to OSR into ion.
     769             :         // The ic has logic for this.
     770         490 :         ICWarmUpCounter_Fallback::Compiler stubCompiler(cx);
     771         245 :         if (!emitNonOpIC(stubCompiler.getStub(&stubSpace_)))
     772           0 :             return false;
     773             :     } else {
     774             :         // To call stubs we need to have an opcode. This code handles the
     775             :         // prologue and there is no dedicatd opcode present. Therefore use an
     776             :         // annotated vm call.
     777         620 :         prepareVMCall();
     778             : 
     779         620 :         masm.Push(ImmPtr(pc));
     780         620 :         masm.PushBaselineFramePtr(BaselineFrameReg, R0.scratchReg());
     781             : 
     782         620 :         if (!callVM(IonCompileScriptForBaselineInfo))
     783           0 :             return false;
     784             : 
     785             :         // Annotate the ICEntry as warmup counter.
     786         620 :         icEntries_.back().setFakeKind(ICEntry::Kind_WarmupCounter);
     787             :     }
     788         865 :     masm.bind(&skipCall);
     789             : 
     790         865 :     return true;
     791             : }
     792             : 
     793             : bool
     794         628 : BaselineCompiler::emitArgumentTypeChecks()
     795             : {
     796         628 :     if (!function())
     797           5 :         return true;
     798             : 
     799         623 :     frame.pushThis();
     800         623 :     frame.popRegsAndSync(1);
     801             : 
     802        1246 :     ICTypeMonitor_Fallback::Compiler compiler(cx, uint32_t(0));
     803         623 :     if (!emitNonOpIC(compiler.getStub(&stubSpace_)))
     804           0 :         return false;
     805             : 
     806        1489 :     for (size_t i = 0; i < function()->nargs(); i++) {
     807         866 :         frame.pushArg(i);
     808         866 :         frame.popRegsAndSync(1);
     809             : 
     810        1732 :         ICTypeMonitor_Fallback::Compiler compiler(cx, i + 1);
     811         866 :         if (!emitNonOpIC(compiler.getStub(&stubSpace_)))
     812           0 :             return false;
     813             :     }
     814             : 
     815         623 :     return true;
     816             : }
     817             : 
     818             : bool
     819           0 : BaselineCompiler::emitDebugTrap()
     820             : {
     821           0 :     MOZ_ASSERT(compileDebugInstrumentation_);
     822           0 :     MOZ_ASSERT(frame.numUnsyncedSlots() == 0);
     823             : 
     824           0 :     bool enabled = script->stepModeEnabled() || script->hasBreakpointsAt(pc);
     825             : 
     826             :     // Emit patchable call to debug trap handler.
     827           0 :     JitCode* handler = cx->runtime()->jitRuntime()->debugTrapHandler(cx);
     828           0 :     if (!handler)
     829           0 :         return false;
     830           0 :     mozilla::DebugOnly<CodeOffset> offset = masm.toggledCall(handler, enabled);
     831             : 
     832             : #ifdef DEBUG
     833             :     // Patchable call offset has to match the pc mapping offset.
     834           0 :     PCMappingEntry& entry = pcMappingEntries_.back();
     835           0 :     MOZ_ASSERT((&offset)->offset() == entry.nativeOffset);
     836             : #endif
     837             : 
     838             :     // Add an IC entry for the return offset -> pc mapping.
     839           0 :     return appendICEntry(ICEntry::Kind_DebugTrap, masm.currentOffset());
     840             : }
     841             : 
     842             : #ifdef JS_TRACE_LOGGING
     843             : bool
     844         628 : BaselineCompiler::emitTraceLoggerEnter()
     845             : {
     846         628 :     AllocatableRegisterSet regs(RegisterSet::Volatile());
     847         628 :     Register loggerReg = regs.takeAnyGeneral();
     848         628 :     Register scriptReg = regs.takeAnyGeneral();
     849             : 
     850        1256 :     Label noTraceLogger;
     851         628 :     if (!traceLoggerToggleOffsets_.append(masm.toggledJump(&noTraceLogger)))
     852           0 :         return false;
     853             : 
     854         628 :     masm.Push(loggerReg);
     855         628 :     masm.Push(scriptReg);
     856             : 
     857         628 :     masm.loadTraceLogger(loggerReg);
     858             : 
     859             :     // Script start.
     860         628 :     masm.movePtr(ImmGCPtr(script), scriptReg);
     861         628 :     masm.loadPtr(Address(scriptReg, JSScript::offsetOfBaselineScript()), scriptReg);
     862         628 :     Address scriptEvent(scriptReg, BaselineScript::offsetOfTraceLoggerScriptEvent());
     863         628 :     masm.computeEffectiveAddress(scriptEvent, scriptReg);
     864         628 :     masm.tracelogStartEvent(loggerReg, scriptReg);
     865             : 
     866             :     // Engine start.
     867         628 :     masm.tracelogStartId(loggerReg, TraceLogger_Baseline, /* force = */ true);
     868             : 
     869         628 :     masm.Pop(scriptReg);
     870         628 :     masm.Pop(loggerReg);
     871             : 
     872         628 :     masm.bind(&noTraceLogger);
     873             : 
     874         628 :     return true;
     875             : }
     876             : 
     877             : bool
     878         627 : BaselineCompiler::emitTraceLoggerExit()
     879             : {
     880         627 :     AllocatableRegisterSet regs(RegisterSet::Volatile());
     881         627 :     Register loggerReg = regs.takeAnyGeneral();
     882             : 
     883        1254 :     Label noTraceLogger;
     884         627 :     if (!traceLoggerToggleOffsets_.append(masm.toggledJump(&noTraceLogger)))
     885           0 :         return false;
     886             : 
     887         627 :     masm.Push(loggerReg);
     888         627 :     masm.loadTraceLogger(loggerReg);
     889             : 
     890         627 :     masm.tracelogStopId(loggerReg, TraceLogger_Baseline, /* force = */ true);
     891         627 :     masm.tracelogStopId(loggerReg, TraceLogger_Scripts, /* force = */ true);
     892             : 
     893         627 :     masm.Pop(loggerReg);
     894             : 
     895         627 :     masm.bind(&noTraceLogger);
     896             : 
     897         627 :     return true;
     898             : }
     899             : 
     900             : bool
     901           4 : BaselineCompiler::emitTraceLoggerResume(Register baselineScript, AllocatableGeneralRegisterSet& regs)
     902             : {
     903           4 :     Register scriptId = regs.takeAny();
     904           4 :     Register loggerReg = regs.takeAny();
     905             : 
     906           8 :     Label noTraceLogger;
     907           4 :     if (!traceLoggerToggleOffsets_.append(masm.toggledJump(&noTraceLogger)))
     908           0 :         return false;
     909             : 
     910           4 :     masm.loadTraceLogger(loggerReg);
     911             : 
     912           4 :     Address scriptEvent(baselineScript, BaselineScript::offsetOfTraceLoggerScriptEvent());
     913           4 :     masm.computeEffectiveAddress(scriptEvent, scriptId);
     914           4 :     masm.tracelogStartEvent(loggerReg, scriptId);
     915           4 :     masm.tracelogStartId(loggerReg, TraceLogger_Baseline, /* force = */ true);
     916             : 
     917           4 :     regs.add(loggerReg);
     918           4 :     regs.add(scriptId);
     919             : 
     920           4 :     masm.bind(&noTraceLogger);
     921             : 
     922           4 :     return true;
     923             : }
     924             : #endif
     925             : 
     926             : void
     927         628 : BaselineCompiler::emitProfilerEnterFrame()
     928             : {
     929             :     // Store stack position to lastProfilingFrame variable, guarded by a toggled jump.
     930             :     // Starts off initially disabled.
     931        1256 :     Label noInstrument;
     932         628 :     CodeOffset toggleOffset = masm.toggledJump(&noInstrument);
     933         628 :     masm.profilerEnterFrame(masm.getStackPointer(), R0.scratchReg());
     934         628 :     masm.bind(&noInstrument);
     935             : 
     936             :     // Store the start offset in the appropriate location.
     937         628 :     MOZ_ASSERT(!profilerEnterFrameToggleOffset_.bound());
     938         628 :     profilerEnterFrameToggleOffset_ = toggleOffset;
     939         628 : }
     940             : 
     941             : void
     942         627 : BaselineCompiler::emitProfilerExitFrame()
     943             : {
     944             :     // Store previous frame to lastProfilingFrame variable, guarded by a toggled jump.
     945             :     // Starts off initially disabled.
     946        1254 :     Label noInstrument;
     947         627 :     CodeOffset toggleOffset = masm.toggledJump(&noInstrument);
     948         627 :     masm.profilerExitFrame();
     949         627 :     masm.bind(&noInstrument);
     950             : 
     951             :     // Store the start offset in the appropriate location.
     952         627 :     MOZ_ASSERT(!profilerExitFrameToggleOffset_.bound());
     953         627 :     profilerExitFrameToggleOffset_ = toggleOffset;
     954         627 : }
     955             : 
     956             : MethodStatus
     957         628 : BaselineCompiler::emitBody()
     958             : {
     959         628 :     MOZ_ASSERT(pc == script->code());
     960             : 
     961         628 :     bool lastOpUnreachable = false;
     962         628 :     uint32_t emittedOps = 0;
     963        1256 :     mozilla::DebugOnly<jsbytecode*> prevpc = pc;
     964             : 
     965             :     while (true) {
     966       61896 :         JSOp op = JSOp(*pc);
     967      123792 :         JitSpew(JitSpew_BaselineOp, "Compiling op @ %d: %s",
     968      123792 :                 int(script->pcToOffset(pc)), CodeName[op]);
     969             : 
     970       61896 :         BytecodeInfo* info = analysis_.maybeInfo(pc);
     971             : 
     972             :         // Skip unreachable ops.
     973       61896 :         if (!info) {
     974             :             // Test if last instructions and stop emitting in that case.
     975         717 :             pc += GetBytecodeLength(pc);
     976         717 :             if (pc >= script->codeEnd())
     977         455 :                 break;
     978             : 
     979         262 :             lastOpUnreachable = true;
     980         262 :             prevpc = pc;
     981         262 :             continue;
     982             :         }
     983             : 
     984             :         // Fully sync the stack if there are incoming jumps.
     985       61179 :         if (info->jumpTarget) {
     986        6481 :             frame.syncStack(0);
     987        6481 :             frame.setStackDepth(info->stackDepth);
     988             :         }
     989             : 
     990             :         // Always sync in debug mode.
     991       61179 :         if (compileDebugInstrumentation_)
     992           0 :             frame.syncStack(0);
     993             : 
     994             :         // At the beginning of any op, at most the top 2 stack-values are unsynced.
     995       61179 :         if (frame.stackDepth() > 2)
     996       19511 :             frame.syncStack(2);
     997             : 
     998       61179 :         frame.assertValidState(*info);
     999             : 
    1000       61179 :         masm.bind(labelOf(pc));
    1001             : 
    1002             :         // Add a PC -> native mapping entry for the current op. These entries are
    1003             :         // used when we need the native code address for a given pc, for instance
    1004             :         // for bailouts from Ion, the debugger and exception handling. See
    1005             :         // PCMappingIndexEntry for more information.
    1006       61179 :         bool addIndexEntry = (pc == script->code() || lastOpUnreachable || emittedOps > 100);
    1007       61179 :         if (addIndexEntry)
    1008        1133 :             emittedOps = 0;
    1009       61179 :         if (!addPCMappingEntry(addIndexEntry)) {
    1010           0 :             ReportOutOfMemory(cx);
    1011           0 :             return Method_Error;
    1012             :         }
    1013             : 
    1014             :         // Emit traps for breakpoints and step mode.
    1015       61179 :         if (compileDebugInstrumentation_ && !emitDebugTrap())
    1016           0 :             return Method_Error;
    1017             : 
    1018       61179 :         switch (op) {
    1019             :           // ===== NOT Yet Implemented =====
    1020             :           case JSOP_FORCEINTERPRETER:
    1021             :             // Intentionally not implemented.
    1022             :           case JSOP_SETINTRINSIC:
    1023             :             // Run-once opcode during self-hosting initialization.
    1024             :           case JSOP_UNUSED222:
    1025             :           case JSOP_UNUSED223:
    1026             :           case JSOP_LIMIT:
    1027             :             // === !! WARNING WARNING WARNING !! ===
    1028             :             // Do you really want to sacrifice performance by not implementing
    1029             :             // this operation in the BaselineCompiler?
    1030           1 :             JitSpew(JitSpew_BaselineAbort, "Unhandled op: %s", CodeName[op]);
    1031           1 :             return Method_CantCompile;
    1032             : 
    1033             : #define EMIT_OP(OP)                            \
    1034             :           case OP:                             \
    1035             :             if (!this->emit_##OP())            \
    1036             :                 return Method_Error;           \
    1037             :             break;
    1038         227 : OPCODE_LIST(EMIT_OP)
    1039             : #undef EMIT_OP
    1040             :         }
    1041             : 
    1042             :         // If the main instruction is not a jump target, then we emit the
    1043             :         //  corresponding code coverage counter.
    1044       61178 :         if (pc == script->main() && !BytecodeIsJumpTarget(op)) {
    1045         623 :             if (!emit_JSOP_JUMPTARGET())
    1046           0 :                 return Method_Error;
    1047             :         }
    1048             : 
    1049             :         // Test if last instructions and stop emitting in that case.
    1050       61178 :         pc += GetBytecodeLength(pc);
    1051       61178 :         if (pc >= script->codeEnd())
    1052         172 :             break;
    1053             : 
    1054       61006 :         emittedOps++;
    1055       61006 :         lastOpUnreachable = false;
    1056             : #ifdef DEBUG
    1057       61006 :         prevpc = pc;
    1058             : #endif
    1059       61268 :     }
    1060             : 
    1061         627 :     MOZ_ASSERT(JSOp(*prevpc) == JSOP_RETRVAL);
    1062         627 :     return Method_Compiled;
    1063             : }
    1064             : 
    1065             : bool
    1066         227 : BaselineCompiler::emit_JSOP_NOP()
    1067             : {
    1068         227 :     return true;
    1069             : }
    1070             : 
    1071             : bool
    1072          88 : BaselineCompiler::emit_JSOP_NOP_DESTRUCTURING()
    1073             : {
    1074          88 :     return true;
    1075             : }
    1076             : 
    1077             : bool
    1078         115 : BaselineCompiler::emit_JSOP_TRY_DESTRUCTURING_ITERCLOSE()
    1079             : {
    1080         115 :     return true;
    1081             : }
    1082             : 
    1083             : bool
    1084           0 : BaselineCompiler::emit_JSOP_LABEL()
    1085             : {
    1086           0 :     return true;
    1087             : }
    1088             : 
    1089             : bool
    1090        6754 : BaselineCompiler::emit_JSOP_POP()
    1091             : {
    1092        6754 :     frame.pop();
    1093        6754 :     return true;
    1094             : }
    1095             : 
    1096             : bool
    1097           2 : BaselineCompiler::emit_JSOP_POPN()
    1098             : {
    1099           2 :     frame.popn(GET_UINT16(pc));
    1100           2 :     return true;
    1101             : }
    1102             : 
    1103             : bool
    1104         599 : BaselineCompiler::emit_JSOP_DUPAT()
    1105             : {
    1106         599 :     frame.syncStack(0);
    1107             : 
    1108             :     // DUPAT takes a value on the stack and re-pushes it on top.  It's like
    1109             :     // GETLOCAL but it addresses from the top of the stack instead of from the
    1110             :     // stack frame.
    1111             : 
    1112         599 :     int depth = -(GET_UINT24(pc) + 1);
    1113         599 :     masm.loadValue(frame.addressOfStackValue(frame.peek(depth)), R0);
    1114         599 :     frame.push(R0);
    1115         599 :     return true;
    1116             : }
    1117             : 
    1118             : bool
    1119        2407 : BaselineCompiler::emit_JSOP_DUP()
    1120             : {
    1121             :     // Keep top stack value in R0, sync the rest so that we can use R1. We use
    1122             :     // separate registers because every register can be used by at most one
    1123             :     // StackValue.
    1124        2407 :     frame.popRegsAndSync(1);
    1125        2407 :     masm.moveValue(R0, R1);
    1126             : 
    1127             :     // inc/dec ops use DUP followed by ONE, ADD. Push R0 last to avoid a move.
    1128        2407 :     frame.push(R1);
    1129        2407 :     frame.push(R0);
    1130        2407 :     return true;
    1131             : }
    1132             : 
    1133             : bool
    1134           0 : BaselineCompiler::emit_JSOP_DUP2()
    1135             : {
    1136           0 :     frame.syncStack(0);
    1137             : 
    1138           0 :     masm.loadValue(frame.addressOfStackValue(frame.peek(-2)), R0);
    1139           0 :     masm.loadValue(frame.addressOfStackValue(frame.peek(-1)), R1);
    1140             : 
    1141           0 :     frame.push(R0);
    1142           0 :     frame.push(R1);
    1143           0 :     return true;
    1144             : }
    1145             : 
    1146             : bool
    1147        1725 : BaselineCompiler::emit_JSOP_SWAP()
    1148             : {
    1149             :     // Keep top stack values in R0 and R1.
    1150        1725 :     frame.popRegsAndSync(2);
    1151             : 
    1152        1725 :     frame.push(R1);
    1153        1725 :     frame.push(R0);
    1154        1725 :     return true;
    1155             : }
    1156             : 
    1157             : bool
    1158          96 : BaselineCompiler::emit_JSOP_PICK()
    1159             : {
    1160          96 :     frame.syncStack(0);
    1161             : 
    1162             :     // Pick takes a value on the stack and moves it to the top.
    1163             :     // For instance, pick 2:
    1164             :     //     before: A B C D E
    1165             :     //     after : A B D E C
    1166             : 
    1167             :     // First, move value at -(amount + 1) into R0.
    1168          96 :     int32_t depth = -(GET_INT8(pc) + 1);
    1169          96 :     masm.loadValue(frame.addressOfStackValue(frame.peek(depth)), R0);
    1170             : 
    1171             :     // Move the other values down.
    1172          96 :     depth++;
    1173         544 :     for (; depth < 0; depth++) {
    1174         224 :         Address source = frame.addressOfStackValue(frame.peek(depth));
    1175         224 :         Address dest = frame.addressOfStackValue(frame.peek(depth - 1));
    1176         224 :         masm.loadValue(source, R1);
    1177         224 :         masm.storeValue(R1, dest);
    1178             :     }
    1179             : 
    1180             :     // Push R0.
    1181          96 :     frame.pop();
    1182          96 :     frame.push(R0);
    1183          96 :     return true;
    1184             : }
    1185             : 
    1186             : bool
    1187         198 : BaselineCompiler::emit_JSOP_UNPICK()
    1188             : {
    1189         198 :     frame.syncStack(0);
    1190             : 
    1191             :     // Pick takes the top of the stack value and moves it under the nth value.
    1192             :     // For instance, unpick 2:
    1193             :     //     before: A B C D E
    1194             :     //     after : A B E C D
    1195             : 
    1196             :     // First, move value at -1 into R0.
    1197         198 :     masm.loadValue(frame.addressOfStackValue(frame.peek(-1)), R0);
    1198             : 
    1199             :     // Move the other values up.
    1200         198 :     int32_t depth = -(GET_INT8(pc) + 1);
    1201         565 :     for (int32_t i = -1; i > depth; i--) {
    1202         367 :         Address source = frame.addressOfStackValue(frame.peek(i - 1));
    1203         367 :         Address dest = frame.addressOfStackValue(frame.peek(i));
    1204         367 :         masm.loadValue(source, R1);
    1205         367 :         masm.storeValue(R1, dest);
    1206             :     }
    1207             : 
    1208             :     // Store R0 under the nth value.
    1209         198 :     Address dest = frame.addressOfStackValue(frame.peek(depth));
    1210         198 :     masm.storeValue(R0, dest);
    1211         198 :     return true;
    1212             : }
    1213             : 
    1214             : bool
    1215        1341 : BaselineCompiler::emit_JSOP_GOTO()
    1216             : {
    1217        1341 :     frame.syncStack(0);
    1218             : 
    1219        1341 :     jsbytecode* target = pc + GET_JUMP_OFFSET(pc);
    1220        1341 :     masm.jump(labelOf(target));
    1221        1341 :     return true;
    1222             : }
    1223             : 
    1224             : bool
    1225        1473 : BaselineCompiler::emitToBoolean()
    1226             : {
    1227        2946 :     Label skipIC;
    1228        1473 :     masm.branchTestBoolean(Assembler::Equal, R0, &skipIC);
    1229             : 
    1230             :     // Call IC
    1231        2946 :     ICToBool_Fallback::Compiler stubCompiler(cx);
    1232        1473 :     if (!emitOpIC(stubCompiler.getStub(&stubSpace_)))
    1233           0 :         return false;
    1234             : 
    1235        1473 :     masm.bind(&skipIC);
    1236        1473 :     return true;
    1237             : }
    1238             : 
    1239             : bool
    1240        2261 : BaselineCompiler::emitTest(bool branchIfTrue)
    1241             : {
    1242        2261 :     bool knownBoolean = frame.peek(-1)->isKnownBoolean();
    1243             : 
    1244             :     // Keep top stack value in R0.
    1245        2261 :     frame.popRegsAndSync(1);
    1246             : 
    1247        2261 :     if (!knownBoolean && !emitToBoolean())
    1248           0 :         return false;
    1249             : 
    1250             :     // IC will leave a BooleanValue in R0, just need to branch on it.
    1251        2261 :     masm.branchTestBooleanTruthy(branchIfTrue, R0, labelOf(pc + GET_JUMP_OFFSET(pc)));
    1252        2261 :     return true;
    1253             : }
    1254             : 
    1255             : bool
    1256        2136 : BaselineCompiler::emit_JSOP_IFEQ()
    1257             : {
    1258        2136 :     return emitTest(false);
    1259             : }
    1260             : 
    1261             : bool
    1262         125 : BaselineCompiler::emit_JSOP_IFNE()
    1263             : {
    1264         125 :     return emitTest(true);
    1265             : }
    1266             : 
    1267             : bool
    1268         333 : BaselineCompiler::emitAndOr(bool branchIfTrue)
    1269             : {
    1270         333 :     bool knownBoolean = frame.peek(-1)->isKnownBoolean();
    1271             : 
    1272             :     // AND and OR leave the original value on the stack.
    1273         333 :     frame.syncStack(0);
    1274             : 
    1275         333 :     masm.loadValue(frame.addressOfStackValue(frame.peek(-1)), R0);
    1276         333 :     if (!knownBoolean && !emitToBoolean())
    1277           0 :         return false;
    1278             : 
    1279         333 :     masm.branchTestBooleanTruthy(branchIfTrue, R0, labelOf(pc + GET_JUMP_OFFSET(pc)));
    1280         333 :     return true;
    1281             : }
    1282             : 
    1283             : bool
    1284         149 : BaselineCompiler::emit_JSOP_AND()
    1285             : {
    1286         149 :     return emitAndOr(false);
    1287             : }
    1288             : 
    1289             : bool
    1290         184 : BaselineCompiler::emit_JSOP_OR()
    1291             : {
    1292         184 :     return emitAndOr(true);
    1293             : }
    1294             : 
    1295             : bool
    1296         473 : BaselineCompiler::emit_JSOP_NOT()
    1297             : {
    1298         473 :     bool knownBoolean = frame.peek(-1)->isKnownBoolean();
    1299             : 
    1300             :     // Keep top stack value in R0.
    1301         473 :     frame.popRegsAndSync(1);
    1302             : 
    1303         473 :     if (!knownBoolean && !emitToBoolean())
    1304           0 :         return false;
    1305             : 
    1306         473 :     masm.notBoolean(R0);
    1307             : 
    1308         473 :     frame.push(R0, JSVAL_TYPE_BOOLEAN);
    1309         473 :     return true;
    1310             : }
    1311             : 
    1312             : bool
    1313         151 : BaselineCompiler::emit_JSOP_POS()
    1314             : {
    1315             :     // Keep top stack value in R0.
    1316         151 :     frame.popRegsAndSync(1);
    1317             : 
    1318             :     // Inline path for int32 and double.
    1319         302 :     Label done;
    1320         151 :     masm.branchTestNumber(Assembler::Equal, R0, &done);
    1321             : 
    1322             :     // Call IC.
    1323         302 :     ICToNumber_Fallback::Compiler stubCompiler(cx);
    1324         151 :     if (!emitOpIC(stubCompiler.getStub(&stubSpace_)))
    1325           0 :         return false;
    1326             : 
    1327         151 :     masm.bind(&done);
    1328         151 :     frame.push(R0);
    1329         151 :     return true;
    1330             : }
    1331             : 
    1332             : bool
    1333         283 : BaselineCompiler::emit_JSOP_LOOPHEAD()
    1334             : {
    1335         283 :     if (!emit_JSOP_JUMPTARGET())
    1336           0 :         return false;
    1337         283 :     return emitInterruptCheck();
    1338             : }
    1339             : 
    1340             : bool
    1341         283 : BaselineCompiler::emit_JSOP_LOOPENTRY()
    1342             : {
    1343         283 :     if (!emit_JSOP_JUMPTARGET())
    1344           0 :         return false;
    1345         283 :     frame.syncStack(0);
    1346         283 :     return emitWarmUpCounterIncrement(LoopEntryCanIonOsr(pc));
    1347             : }
    1348             : 
    1349             : bool
    1350          44 : BaselineCompiler::emit_JSOP_VOID()
    1351             : {
    1352          44 :     frame.pop();
    1353          44 :     frame.push(UndefinedValue());
    1354          44 :     return true;
    1355             : }
    1356             : 
    1357             : bool
    1358        2529 : BaselineCompiler::emit_JSOP_UNDEFINED()
    1359             : {
    1360             :     // If this ever changes, change what JSOP_GIMPLICITTHIS does too.
    1361        2529 :     frame.push(UndefinedValue());
    1362        2529 :     return true;
    1363             : }
    1364             : 
    1365             : bool
    1366           0 : BaselineCompiler::emit_JSOP_HOLE()
    1367             : {
    1368           0 :     frame.push(MagicValue(JS_ELEMENTS_HOLE));
    1369           0 :     return true;
    1370             : }
    1371             : 
    1372             : bool
    1373         229 : BaselineCompiler::emit_JSOP_NULL()
    1374             : {
    1375         229 :     frame.push(NullValue());
    1376         229 :     return true;
    1377             : }
    1378             : 
    1379             : typedef bool (*ThrowCheckIsObjectFn)(JSContext*, CheckIsObjectKind);
    1380           3 : static const VMFunction ThrowCheckIsObjectInfo =
    1381           6 :     FunctionInfo<ThrowCheckIsObjectFn>(ThrowCheckIsObject, "ThrowCheckIsObject");
    1382             : 
    1383             : bool
    1384         411 : BaselineCompiler::emit_JSOP_CHECKISOBJ()
    1385             : {
    1386         411 :     frame.syncStack(0);
    1387         411 :     masm.loadValue(frame.addressOfStackValue(frame.peek(-1)), R0);
    1388             : 
    1389         822 :     Label ok;
    1390         411 :     masm.branchTestObject(Assembler::Equal, R0, &ok);
    1391             : 
    1392         411 :     prepareVMCall();
    1393             : 
    1394         411 :     pushArg(Imm32(GET_UINT8(pc)));
    1395         411 :     if (!callVM(ThrowCheckIsObjectInfo))
    1396           0 :         return false;
    1397             : 
    1398         411 :     masm.bind(&ok);
    1399         411 :     return true;
    1400             : }
    1401             : 
    1402             : typedef bool (*CheckIsCallableFn)(JSContext*, HandleValue, CheckIsCallableKind);
    1403           3 : static const VMFunction CheckIsCallableInfo =
    1404           6 :     FunctionInfo<CheckIsCallableFn>(CheckIsCallable, "CheckIsCallable");
    1405             : 
    1406             : bool
    1407         108 : BaselineCompiler::emit_JSOP_CHECKISCALLABLE()
    1408             : {
    1409         108 :     frame.syncStack(0);
    1410         108 :     masm.loadValue(frame.addressOfStackValue(frame.peek(-1)), R0);
    1411             : 
    1412         108 :     prepareVMCall();
    1413             : 
    1414         108 :     pushArg(Imm32(GET_UINT8(pc)));
    1415         108 :     pushArg(R0);
    1416         108 :     if (!callVM(CheckIsCallableInfo))
    1417           0 :         return false;
    1418             : 
    1419         108 :     return true;
    1420             : }
    1421             : 
    1422             : typedef bool (*ThrowUninitializedThisFn)(JSContext*, BaselineFrame* frame);
    1423           3 : static const VMFunction ThrowUninitializedThisInfo =
    1424           6 :     FunctionInfo<ThrowUninitializedThisFn>(BaselineThrowUninitializedThis,
    1425             :                                            "BaselineThrowUninitializedThis");
    1426             : 
    1427             : typedef bool (*ThrowInitializedThisFn)(JSContext*, BaselineFrame* frame);
    1428           3 : static const VMFunction ThrowInitializedThisInfo =
    1429           6 :     FunctionInfo<ThrowInitializedThisFn>(BaselineThrowInitializedThis,
    1430             :                                          "BaselineThrowInitializedThis");
    1431             : 
    1432             : bool
    1433           6 : BaselineCompiler::emit_JSOP_CHECKTHIS()
    1434             : {
    1435           6 :     frame.syncStack(0);
    1436           6 :     masm.loadValue(frame.addressOfStackValue(frame.peek(-1)), R0);
    1437             : 
    1438           6 :     return emitCheckThis(R0);
    1439             : }
    1440             : 
    1441             : bool
    1442           1 : BaselineCompiler::emit_JSOP_CHECKTHISREINIT()
    1443             : {
    1444           1 :     frame.syncStack(0);
    1445           1 :     masm.loadValue(frame.addressOfStackValue(frame.peek(-1)), R0);
    1446             : 
    1447           1 :     return emitCheckThis(R0, /* reinit = */true);
    1448             : }
    1449             : 
    1450             : bool
    1451           8 : BaselineCompiler::emitCheckThis(ValueOperand val, bool reinit)
    1452             : {
    1453          16 :     Label thisOK;
    1454           8 :     if (reinit)
    1455           1 :         masm.branchTestMagic(Assembler::Equal, val, &thisOK);
    1456             :     else
    1457           7 :         masm.branchTestMagic(Assembler::NotEqual, val, &thisOK);
    1458             : 
    1459           8 :     prepareVMCall();
    1460             : 
    1461           8 :     masm.loadBaselineFramePtr(BaselineFrameReg, val.scratchReg());
    1462           8 :     pushArg(val.scratchReg());
    1463             : 
    1464           8 :     if (reinit) {
    1465           1 :         if (!callVM(ThrowInitializedThisInfo))
    1466           0 :             return false;
    1467             :     } else {
    1468           7 :         if (!callVM(ThrowUninitializedThisInfo))
    1469           0 :             return false;
    1470             :     }
    1471             : 
    1472           8 :     masm.bind(&thisOK);
    1473           8 :     return true;
    1474             : }
    1475             : 
    1476             : typedef bool (*ThrowBadDerivedReturnFn)(JSContext*, HandleValue);
    1477           3 : static const VMFunction ThrowBadDerivedReturnInfo =
    1478           6 :     FunctionInfo<ThrowBadDerivedReturnFn>(jit::ThrowBadDerivedReturn, "ThrowBadDerivedReturn");
    1479             : 
    1480             : bool
    1481           1 : BaselineCompiler::emit_JSOP_CHECKRETURN()
    1482             : {
    1483           1 :     MOZ_ASSERT(script->isDerivedClassConstructor());
    1484             : 
    1485             :     // Load |this| in R0, return value in R1.
    1486           1 :     frame.popRegsAndSync(1);
    1487           1 :     emitLoadReturnValue(R1);
    1488             : 
    1489           2 :     Label done, returnOK;
    1490           1 :     masm.branchTestObject(Assembler::Equal, R1, &done);
    1491           1 :     masm.branchTestUndefined(Assembler::Equal, R1, &returnOK);
    1492             : 
    1493           1 :     prepareVMCall();
    1494           1 :     pushArg(R1);
    1495           1 :     if (!callVM(ThrowBadDerivedReturnInfo))
    1496           0 :         return false;
    1497           1 :     masm.assumeUnreachable("Should throw on bad derived constructor return");
    1498             : 
    1499           1 :     masm.bind(&returnOK);
    1500             : 
    1501           1 :     if (!emitCheckThis(R0))
    1502           0 :         return false;
    1503             : 
    1504             :     // Store |this| in the return value slot.
    1505           1 :     masm.storeValue(R0, frame.addressOfReturnValue());
    1506           1 :     masm.or32(Imm32(BaselineFrame::HAS_RVAL), frame.addressOfFlags());
    1507             : 
    1508           1 :     masm.bind(&done);
    1509           1 :     return true;
    1510             : }
    1511             : 
    1512             : typedef bool (*GetFunctionThisFn)(JSContext*, BaselineFrame*, MutableHandleValue);
    1513           3 : static const VMFunction GetFunctionThisInfo =
    1514           6 :     FunctionInfo<GetFunctionThisFn>(jit::BaselineGetFunctionThis, "BaselineGetFunctionThis");
    1515             : 
    1516             : bool
    1517         301 : BaselineCompiler::emit_JSOP_FUNCTIONTHIS()
    1518             : {
    1519         301 :     MOZ_ASSERT(function());
    1520         301 :     MOZ_ASSERT(!function()->isArrow());
    1521             : 
    1522         301 :     frame.pushThis();
    1523             : 
    1524             :     // In strict mode code or self-hosted functions, |this| is left alone.
    1525         301 :     if (script->strict() || (function() && function()->isSelfHostedBuiltin()))
    1526         231 :         return true;
    1527             : 
    1528             :     // Load |thisv| in R0. Skip the call if it's already an object.
    1529         140 :     Label skipCall;
    1530          70 :     frame.popRegsAndSync(1);
    1531          70 :     masm.branchTestObject(Assembler::Equal, R0, &skipCall);
    1532             : 
    1533          70 :     prepareVMCall();
    1534          70 :     masm.loadBaselineFramePtr(BaselineFrameReg, R1.scratchReg());
    1535             : 
    1536          70 :     pushArg(R1.scratchReg());
    1537             : 
    1538          70 :     if (!callVM(GetFunctionThisInfo))
    1539           0 :         return false;
    1540             : 
    1541          70 :     masm.bind(&skipCall);
    1542          70 :     frame.push(R0);
    1543          70 :     return true;
    1544             : }
    1545             : 
    1546             : typedef bool (*GetNonSyntacticGlobalThisFn)(JSContext*, HandleObject, MutableHandleValue);
    1547           3 : static const VMFunction GetNonSyntacticGlobalThisInfo =
    1548           6 :     FunctionInfo<GetNonSyntacticGlobalThisFn>(js::GetNonSyntacticGlobalThis,
    1549             :                                               "GetNonSyntacticGlobalThis");
    1550             : 
    1551             : bool
    1552          19 : BaselineCompiler::emit_JSOP_GLOBALTHIS()
    1553             : {
    1554          19 :     frame.syncStack(0);
    1555             : 
    1556          19 :     if (!script->hasNonSyntacticScope()) {
    1557          19 :         LexicalEnvironmentObject* globalLexical = &script->global().lexicalEnvironment();
    1558          19 :         masm.moveValue(globalLexical->thisValue(), R0);
    1559          19 :         frame.push(R0);
    1560          19 :         return true;
    1561             :     }
    1562             : 
    1563           0 :     prepareVMCall();
    1564             : 
    1565           0 :     masm.loadPtr(frame.addressOfEnvironmentChain(), R0.scratchReg());
    1566           0 :     pushArg(R0.scratchReg());
    1567             : 
    1568           0 :     if (!callVM(GetNonSyntacticGlobalThisInfo))
    1569           0 :         return false;
    1570             : 
    1571           0 :     frame.push(R0);
    1572           0 :     return true;
    1573             : }
    1574             : 
    1575             : bool
    1576         270 : BaselineCompiler::emit_JSOP_TRUE()
    1577             : {
    1578         270 :     frame.push(BooleanValue(true));
    1579         270 :     return true;
    1580             : }
    1581             : 
    1582             : bool
    1583         289 : BaselineCompiler::emit_JSOP_FALSE()
    1584             : {
    1585         289 :     frame.push(BooleanValue(false));
    1586         289 :     return true;
    1587             : }
    1588             : 
    1589             : bool
    1590         670 : BaselineCompiler::emit_JSOP_ZERO()
    1591             : {
    1592         670 :     frame.push(Int32Value(0));
    1593         670 :     return true;
    1594             : }
    1595             : 
    1596             : bool
    1597         484 : BaselineCompiler::emit_JSOP_ONE()
    1598             : {
    1599         484 :     frame.push(Int32Value(1));
    1600         484 :     return true;
    1601             : }
    1602             : 
    1603             : bool
    1604         385 : BaselineCompiler::emit_JSOP_INT8()
    1605             : {
    1606         385 :     frame.push(Int32Value(GET_INT8(pc)));
    1607         385 :     return true;
    1608             : }
    1609             : 
    1610             : bool
    1611           2 : BaselineCompiler::emit_JSOP_INT32()
    1612             : {
    1613           2 :     frame.push(Int32Value(GET_INT32(pc)));
    1614           2 :     return true;
    1615             : }
    1616             : 
    1617             : bool
    1618          62 : BaselineCompiler::emit_JSOP_UINT16()
    1619             : {
    1620          62 :     frame.push(Int32Value(GET_UINT16(pc)));
    1621          62 :     return true;
    1622             : }
    1623             : 
    1624             : bool
    1625           2 : BaselineCompiler::emit_JSOP_UINT24()
    1626             : {
    1627           2 :     frame.push(Int32Value(GET_UINT24(pc)));
    1628           2 :     return true;
    1629             : }
    1630             : 
    1631             : bool
    1632          56 : BaselineCompiler::emit_JSOP_DOUBLE()
    1633             : {
    1634          56 :     frame.push(script->getConst(GET_UINT32_INDEX(pc)));
    1635          56 :     return true;
    1636             : }
    1637             : 
    1638             : bool
    1639        1108 : BaselineCompiler::emit_JSOP_STRING()
    1640             : {
    1641        1108 :     frame.push(StringValue(script->getAtom(pc)));
    1642        1108 :     return true;
    1643             : }
    1644             : 
    1645             : bool
    1646         166 : BaselineCompiler::emit_JSOP_SYMBOL()
    1647             : {
    1648         166 :     unsigned which = GET_UINT8(pc);
    1649         166 :     JS::Symbol* sym = cx->runtime()->wellKnownSymbols->get(which);
    1650         166 :     frame.push(SymbolValue(sym));
    1651         166 :     return true;
    1652             : }
    1653             : 
    1654             : typedef JSObject* (*DeepCloneObjectLiteralFn)(JSContext*, HandleObject, NewObjectKind);
    1655           3 : static const VMFunction DeepCloneObjectLiteralInfo =
    1656           6 :     FunctionInfo<DeepCloneObjectLiteralFn>(DeepCloneObjectLiteral, "DeepCloneObjectLiteral");
    1657             : 
    1658             : bool
    1659           0 : BaselineCompiler::emit_JSOP_OBJECT()
    1660             : {
    1661           0 :     JSCompartment* comp = cx->compartment();
    1662           0 :     if (comp->creationOptions().cloneSingletons()) {
    1663           0 :         RootedObject obj(cx, script->getObject(GET_UINT32_INDEX(pc)));
    1664           0 :         if (!obj)
    1665           0 :             return false;
    1666             : 
    1667           0 :         prepareVMCall();
    1668             : 
    1669           0 :         pushArg(ImmWord(TenuredObject));
    1670           0 :         pushArg(ImmGCPtr(obj));
    1671             : 
    1672           0 :         if (!callVM(DeepCloneObjectLiteralInfo))
    1673           0 :             return false;
    1674             : 
    1675             :         // Box and push return value.
    1676           0 :         masm.tagValue(JSVAL_TYPE_OBJECT, ReturnReg, R0);
    1677           0 :         frame.push(R0);
    1678           0 :         return true;
    1679             :     }
    1680             : 
    1681           0 :     comp->behaviors().setSingletonsAsValues();
    1682           0 :     frame.push(ObjectValue(*script->getObject(pc)));
    1683           0 :     return true;
    1684             : }
    1685             : 
    1686             : bool
    1687           1 : BaselineCompiler::emit_JSOP_CALLSITEOBJ()
    1688             : {
    1689           2 :     RootedObject cso(cx, script->getObject(pc));
    1690           2 :     RootedObject raw(cx, script->getObject(GET_UINT32_INDEX(pc) + 1));
    1691           1 :     if (!cso || !raw)
    1692           0 :         return false;
    1693             : 
    1694           1 :     if (!cx->compartment()->getTemplateLiteralObject(cx, raw, &cso))
    1695           0 :         return false;
    1696             : 
    1697           1 :     frame.push(ObjectValue(*cso));
    1698           1 :     return true;
    1699             : }
    1700             : 
    1701             : typedef JSObject* (*CloneRegExpObjectFn)(JSContext*, Handle<RegExpObject*>);
    1702           3 : static const VMFunction CloneRegExpObjectInfo =
    1703           6 :     FunctionInfo<CloneRegExpObjectFn>(CloneRegExpObject, "CloneRegExpObject");
    1704             : 
    1705             : bool
    1706          16 : BaselineCompiler::emit_JSOP_REGEXP()
    1707             : {
    1708          32 :     RootedObject reObj(cx, script->getRegExp(pc));
    1709             : 
    1710          16 :     prepareVMCall();
    1711          16 :     pushArg(ImmGCPtr(reObj));
    1712          16 :     if (!callVM(CloneRegExpObjectInfo))
    1713           0 :         return false;
    1714             : 
    1715             :     // Box and push return value.
    1716          16 :     masm.tagValue(JSVAL_TYPE_OBJECT, ReturnReg, R0);
    1717          16 :     frame.push(R0);
    1718          16 :     return true;
    1719             : }
    1720             : 
    1721             : typedef JSObject* (*LambdaFn)(JSContext*, HandleFunction, HandleObject);
    1722           3 : static const VMFunction LambdaInfo = FunctionInfo<LambdaFn>(js::Lambda, "Lambda");
    1723             : 
    1724             : bool
    1725         185 : BaselineCompiler::emit_JSOP_LAMBDA()
    1726             : {
    1727         370 :     RootedFunction fun(cx, script->getFunction(GET_UINT32_INDEX(pc)));
    1728             : 
    1729         185 :     prepareVMCall();
    1730         185 :     masm.loadPtr(frame.addressOfEnvironmentChain(), R0.scratchReg());
    1731             : 
    1732         185 :     pushArg(R0.scratchReg());
    1733         185 :     pushArg(ImmGCPtr(fun));
    1734             : 
    1735         185 :     if (!callVM(LambdaInfo))
    1736           0 :         return false;
    1737             : 
    1738             :     // Box and push return value.
    1739         185 :     masm.tagValue(JSVAL_TYPE_OBJECT, ReturnReg, R0);
    1740         185 :     frame.push(R0);
    1741         185 :     return true;
    1742             : }
    1743             : 
    1744             : typedef JSObject* (*LambdaArrowFn)(JSContext*, HandleFunction, HandleObject, HandleValue);
    1745           3 : static const VMFunction LambdaArrowInfo =
    1746           6 :     FunctionInfo<LambdaArrowFn>(js::LambdaArrow, "LambdaArrow");
    1747             : 
    1748             : bool
    1749          62 : BaselineCompiler::emit_JSOP_LAMBDA_ARROW()
    1750             : {
    1751             :     // Keep pushed newTarget in R0.
    1752          62 :     frame.popRegsAndSync(1);
    1753             : 
    1754         124 :     RootedFunction fun(cx, script->getFunction(GET_UINT32_INDEX(pc)));
    1755             : 
    1756          62 :     prepareVMCall();
    1757          62 :     masm.loadPtr(frame.addressOfEnvironmentChain(), R2.scratchReg());
    1758             : 
    1759          62 :     pushArg(R0);
    1760          62 :     pushArg(R2.scratchReg());
    1761          62 :     pushArg(ImmGCPtr(fun));
    1762             : 
    1763          62 :     if (!callVM(LambdaArrowInfo))
    1764           0 :         return false;
    1765             : 
    1766             :     // Box and push return value.
    1767          62 :     masm.tagValue(JSVAL_TYPE_OBJECT, ReturnReg, R0);
    1768          62 :     frame.push(R0);
    1769          62 :     return true;
    1770             : }
    1771             : 
    1772             : typedef bool (*SetFunNameFn)(JSContext*, HandleFunction, HandleValue, FunctionPrefixKind);
    1773           3 : static const VMFunction SetFunNameInfo =
    1774           6 :     FunctionInfo<SetFunNameFn>(js::SetFunctionNameIfNoOwnName, "SetFunName");
    1775             : 
    1776             : bool
    1777           0 : BaselineCompiler::emit_JSOP_SETFUNNAME()
    1778             : {
    1779           0 :     frame.popRegsAndSync(2);
    1780             : 
    1781           0 :     frame.push(R0);
    1782           0 :     frame.syncStack(0);
    1783             : 
    1784           0 :     FunctionPrefixKind prefixKind = FunctionPrefixKind(GET_UINT8(pc));
    1785           0 :     masm.unboxObject(R0, R0.scratchReg());
    1786             : 
    1787           0 :     prepareVMCall();
    1788             : 
    1789           0 :     pushArg(Imm32(int32_t(prefixKind)));
    1790           0 :     pushArg(R1);
    1791           0 :     pushArg(R0.scratchReg());
    1792           0 :     return callVM(SetFunNameInfo);
    1793             : }
    1794             : 
    1795             : void
    1796        3323 : BaselineCompiler::storeValue(const StackValue* source, const Address& dest,
    1797             :                              const ValueOperand& scratch)
    1798             : {
    1799        3323 :     switch (source->kind()) {
    1800             :       case StackValue::Constant:
    1801        1029 :         masm.storeValue(source->constant(), dest);
    1802        1029 :         break;
    1803             :       case StackValue::Register:
    1804        1648 :         masm.storeValue(source->reg(), dest);
    1805        1648 :         break;
    1806             :       case StackValue::LocalSlot:
    1807         116 :         masm.loadValue(frame.addressOfLocal(source->localSlot()), scratch);
    1808         116 :         masm.storeValue(scratch, dest);
    1809         116 :         break;
    1810             :       case StackValue::ArgSlot:
    1811          31 :         masm.loadValue(frame.addressOfArg(source->argSlot()), scratch);
    1812          31 :         masm.storeValue(scratch, dest);
    1813          31 :         break;
    1814             :       case StackValue::ThisSlot:
    1815         217 :         masm.loadValue(frame.addressOfThis(), scratch);
    1816         217 :         masm.storeValue(scratch, dest);
    1817         217 :         break;
    1818             :       case StackValue::EvalNewTargetSlot:
    1819           0 :         MOZ_ASSERT(script->isForEval());
    1820           0 :         masm.loadValue(frame.addressOfEvalNewTarget(), scratch);
    1821           0 :         masm.storeValue(scratch, dest);
    1822           0 :         break;
    1823             :       case StackValue::Stack:
    1824         282 :         masm.loadValue(frame.addressOfStackValue(source), scratch);
    1825         282 :         masm.storeValue(scratch, dest);
    1826         282 :         break;
    1827             :       default:
    1828           0 :         MOZ_CRASH("Invalid kind");
    1829             :     }
    1830        3323 : }
    1831             : 
    1832             : bool
    1833          22 : BaselineCompiler::emit_JSOP_BITOR()
    1834             : {
    1835          22 :     return emitBinaryArith();
    1836             : }
    1837             : 
    1838             : bool
    1839           0 : BaselineCompiler::emit_JSOP_BITXOR()
    1840             : {
    1841           0 :     return emitBinaryArith();
    1842             : }
    1843             : 
    1844             : bool
    1845          16 : BaselineCompiler::emit_JSOP_BITAND()
    1846             : {
    1847          16 :     return emitBinaryArith();
    1848             : }
    1849             : 
    1850             : bool
    1851           0 : BaselineCompiler::emit_JSOP_LSH()
    1852             : {
    1853           0 :     return emitBinaryArith();
    1854             : }
    1855             : 
    1856             : bool
    1857           1 : BaselineCompiler::emit_JSOP_RSH()
    1858             : {
    1859           1 :     return emitBinaryArith();
    1860             : }
    1861             : 
    1862             : bool
    1863           3 : BaselineCompiler::emit_JSOP_URSH()
    1864             : {
    1865           3 :     return emitBinaryArith();
    1866             : }
    1867             : 
    1868             : bool
    1869         546 : BaselineCompiler::emit_JSOP_ADD()
    1870             : {
    1871         546 :     return emitBinaryArith();
    1872             : }
    1873             : 
    1874             : bool
    1875          47 : BaselineCompiler::emit_JSOP_SUB()
    1876             : {
    1877          47 :     return emitBinaryArith();
    1878             : }
    1879             : 
    1880             : bool
    1881           9 : BaselineCompiler::emit_JSOP_MUL()
    1882             : {
    1883           9 :     return emitBinaryArith();
    1884             : }
    1885             : 
    1886             : bool
    1887           1 : BaselineCompiler::emit_JSOP_DIV()
    1888             : {
    1889           1 :     return emitBinaryArith();
    1890             : }
    1891             : 
    1892             : bool
    1893           0 : BaselineCompiler::emit_JSOP_MOD()
    1894             : {
    1895           0 :     return emitBinaryArith();
    1896             : }
    1897             : 
    1898             : bool
    1899           0 : BaselineCompiler::emit_JSOP_POW()
    1900             : {
    1901           0 :     return emitBinaryArith();
    1902             : }
    1903             : 
    1904             : bool
    1905         645 : BaselineCompiler::emitBinaryArith()
    1906             : {
    1907             :     // Keep top JSStack value in R0 and R2
    1908         645 :     frame.popRegsAndSync(2);
    1909             : 
    1910             :     // Call IC
    1911        1290 :     ICBinaryArith_Fallback::Compiler stubCompiler(cx, ICStubCompiler::Engine::Baseline);
    1912         645 :     if (!emitOpIC(stubCompiler.getStub(&stubSpace_)))
    1913           0 :         return false;
    1914             : 
    1915             :     // Mark R0 as pushed stack value.
    1916         645 :     frame.push(R0);
    1917         645 :     return true;
    1918             : }
    1919             : 
    1920             : bool
    1921           2 : BaselineCompiler::emitUnaryArith()
    1922             : {
    1923             :     // Keep top stack value in R0.
    1924           2 :     frame.popRegsAndSync(1);
    1925             : 
    1926             :     // Call IC
    1927           4 :     ICUnaryArith_Fallback::Compiler stubCompiler(cx, ICStubCompiler::Engine::Baseline);
    1928           2 :     if (!emitOpIC(stubCompiler.getStub(&stubSpace_)))
    1929           0 :         return false;
    1930             : 
    1931             :     // Mark R0 as pushed stack value.
    1932           2 :     frame.push(R0);
    1933           2 :     return true;
    1934             : }
    1935             : 
    1936             : bool
    1937           2 : BaselineCompiler::emit_JSOP_BITNOT()
    1938             : {
    1939           2 :     return emitUnaryArith();
    1940             : }
    1941             : 
    1942             : bool
    1943           0 : BaselineCompiler::emit_JSOP_NEG()
    1944             : {
    1945           0 :     return emitUnaryArith();
    1946             : }
    1947             : 
    1948             : bool
    1949         143 : BaselineCompiler::emit_JSOP_LT()
    1950             : {
    1951         143 :     return emitCompare();
    1952             : }
    1953             : 
    1954             : bool
    1955           9 : BaselineCompiler::emit_JSOP_LE()
    1956             : {
    1957           9 :     return emitCompare();
    1958             : }
    1959             : 
    1960             : bool
    1961          60 : BaselineCompiler::emit_JSOP_GT()
    1962             : {
    1963          60 :     return emitCompare();
    1964             : }
    1965             : 
    1966             : bool
    1967          73 : BaselineCompiler::emit_JSOP_GE()
    1968             : {
    1969          73 :     return emitCompare();
    1970             : }
    1971             : 
    1972             : bool
    1973         118 : BaselineCompiler::emit_JSOP_EQ()
    1974             : {
    1975         118 :     return emitCompare();
    1976             : }
    1977             : 
    1978             : bool
    1979         214 : BaselineCompiler::emit_JSOP_NE()
    1980             : {
    1981         214 :     return emitCompare();
    1982             : }
    1983             : 
    1984             : bool
    1985        1179 : BaselineCompiler::emitCompare()
    1986             : {
    1987             :     // CODEGEN
    1988             : 
    1989             :     // Keep top JSStack value in R0 and R1.
    1990        1179 :     frame.popRegsAndSync(2);
    1991             : 
    1992             :     // Call IC.
    1993        2358 :     ICCompare_Fallback::Compiler stubCompiler(cx, ICStubCompiler::Engine::Baseline);
    1994        1179 :     if (!emitOpIC(stubCompiler.getStub(&stubSpace_)))
    1995           0 :         return false;
    1996             : 
    1997             :     // Mark R0 as pushed stack value.
    1998        1179 :     frame.push(R0, JSVAL_TYPE_BOOLEAN);
    1999        1179 :     return true;
    2000             : }
    2001             : 
    2002             : bool
    2003         395 : BaselineCompiler::emit_JSOP_STRICTEQ()
    2004             : {
    2005         395 :     return emitCompare();
    2006             : }
    2007             : 
    2008             : bool
    2009         167 : BaselineCompiler::emit_JSOP_STRICTNE()
    2010             : {
    2011         167 :     return emitCompare();
    2012             : }
    2013             : 
    2014             : bool
    2015           6 : BaselineCompiler::emit_JSOP_CONDSWITCH()
    2016             : {
    2017           6 :     return true;
    2018             : }
    2019             : 
    2020             : bool
    2021          23 : BaselineCompiler::emit_JSOP_CASE()
    2022             : {
    2023          23 :     frame.popRegsAndSync(2);
    2024          23 :     frame.push(R0);
    2025          23 :     frame.syncStack(0);
    2026             : 
    2027             :     // Call IC.
    2028          46 :     ICCompare_Fallback::Compiler stubCompiler(cx, ICStubCompiler::Engine::Baseline);
    2029          23 :     if (!emitOpIC(stubCompiler.getStub(&stubSpace_)))
    2030           0 :         return false;
    2031             : 
    2032          23 :     Register payload = masm.extractInt32(R0, R0.scratchReg());
    2033          23 :     jsbytecode* target = pc + GET_JUMP_OFFSET(pc);
    2034             : 
    2035          46 :     Label done;
    2036          23 :     masm.branch32(Assembler::Equal, payload, Imm32(0), &done);
    2037             :     {
    2038             :         // Pop the switch value if the case matches.
    2039          23 :         masm.addToStackPtr(Imm32(sizeof(Value)));
    2040          23 :         masm.jump(labelOf(target));
    2041             :     }
    2042          23 :     masm.bind(&done);
    2043          23 :     return true;
    2044             : }
    2045             : 
    2046             : bool
    2047           6 : BaselineCompiler::emit_JSOP_DEFAULT()
    2048             : {
    2049           6 :     frame.pop();
    2050           6 :     return emit_JSOP_GOTO();
    2051             : }
    2052             : 
    2053             : bool
    2054           0 : BaselineCompiler::emit_JSOP_LINENO()
    2055             : {
    2056           0 :     return true;
    2057             : }
    2058             : 
    2059             : bool
    2060         138 : BaselineCompiler::emit_JSOP_NEWARRAY()
    2061             : {
    2062         138 :     frame.syncStack(0);
    2063             : 
    2064         138 :     uint32_t length = GET_UINT32(pc);
    2065         138 :     MOZ_ASSERT(length <= INT32_MAX,
    2066             :                "the bytecode emitter must fail to compile code that would "
    2067             :                "produce JSOP_NEWARRAY with a length exceeding int32_t range");
    2068             : 
    2069             :     // Pass length in R0.
    2070         138 :     masm.move32(Imm32(AssertedCast<int32_t>(length)), R0.scratchReg());
    2071             : 
    2072         138 :     ObjectGroup* group = ObjectGroup::allocationSiteGroup(cx, script, pc, JSProto_Array);
    2073         138 :     if (!group)
    2074           0 :         return false;
    2075             : 
    2076         276 :     ICNewArray_Fallback::Compiler stubCompiler(cx, group, ICStubCompiler::Engine::Baseline);
    2077         138 :     if (!emitOpIC(stubCompiler.getStub(&stubSpace_)))
    2078           0 :         return false;
    2079             : 
    2080         138 :     frame.push(R0);
    2081         138 :     return true;
    2082             : }
    2083             : 
    2084             : bool
    2085          27 : BaselineCompiler::emit_JSOP_SPREADCALLARRAY()
    2086             : {
    2087          27 :     return emit_JSOP_NEWARRAY();
    2088             : }
    2089             : 
    2090             : typedef JSObject* (*NewArrayCopyOnWriteFn)(JSContext*, HandleArrayObject, gc::InitialHeap);
    2091           3 : const VMFunction jit::NewArrayCopyOnWriteInfo =
    2092           6 :     FunctionInfo<NewArrayCopyOnWriteFn>(js::NewDenseCopyOnWriteArray, "NewDenseCopyOnWriteArray");
    2093             : 
    2094             : bool
    2095          29 : BaselineCompiler::emit_JSOP_NEWARRAY_COPYONWRITE()
    2096             : {
    2097          58 :     RootedScript scriptRoot(cx, script);
    2098          29 :     JSObject* obj = ObjectGroup::getOrFixupCopyOnWriteObject(cx, scriptRoot, pc);
    2099          29 :     if (!obj)
    2100           0 :         return false;
    2101             : 
    2102          29 :     prepareVMCall();
    2103             : 
    2104          29 :     pushArg(Imm32(gc::DefaultHeap));
    2105          29 :     pushArg(ImmGCPtr(obj));
    2106             : 
    2107          29 :     if (!callVM(NewArrayCopyOnWriteInfo))
    2108           0 :         return false;
    2109             : 
    2110             :     // Box and push return value.
    2111          29 :     masm.tagValue(JSVAL_TYPE_OBJECT, ReturnReg, R0);
    2112          29 :     frame.push(R0);
    2113          29 :     return true;
    2114             : }
    2115             : 
    2116             : bool
    2117         130 : BaselineCompiler::emit_JSOP_INITELEM_ARRAY()
    2118             : {
    2119             :     // Keep the object and rhs on the stack.
    2120         130 :     frame.syncStack(0);
    2121             : 
    2122             :     // Load object in R0, index in R1.
    2123         130 :     masm.loadValue(frame.addressOfStackValue(frame.peek(-2)), R0);
    2124         130 :     uint32_t index = GET_UINT32(pc);
    2125         130 :     MOZ_ASSERT(index <= INT32_MAX,
    2126             :                "the bytecode emitter must fail to compile code that would "
    2127             :                "produce JSOP_INITELEM_ARRAY with a length exceeding "
    2128             :                "int32_t range");
    2129         130 :     masm.moveValue(Int32Value(AssertedCast<int32_t>(index)), R1);
    2130             : 
    2131             :     // Call IC.
    2132         260 :     ICSetElem_Fallback::Compiler stubCompiler(cx);
    2133         130 :     if (!emitOpIC(stubCompiler.getStub(&stubSpace_)))
    2134           0 :         return false;
    2135             : 
    2136             :     // Pop the rhs, so that the object is on the top of the stack.
    2137         130 :     frame.pop();
    2138         130 :     return true;
    2139             : }
    2140             : 
    2141             : bool
    2142         202 : BaselineCompiler::emit_JSOP_NEWOBJECT()
    2143             : {
    2144         202 :     frame.syncStack(0);
    2145             : 
    2146         404 :     ICNewObject_Fallback::Compiler stubCompiler(cx, ICStubCompiler::Engine::Baseline);
    2147         202 :     if (!emitOpIC(stubCompiler.getStub(&stubSpace_)))
    2148           0 :         return false;
    2149             : 
    2150         202 :     frame.push(R0);
    2151         202 :     return true;
    2152             : }
    2153             : 
    2154             : bool
    2155          12 : BaselineCompiler::emit_JSOP_NEWINIT()
    2156             : {
    2157          12 :     frame.syncStack(0);
    2158          12 :     JSProtoKey key = JSProtoKey(GET_UINT8(pc));
    2159             : 
    2160          12 :     if (key == JSProto_Array) {
    2161             :         // Pass length in R0.
    2162           0 :         masm.move32(Imm32(0), R0.scratchReg());
    2163             : 
    2164           0 :         ObjectGroup* group = ObjectGroup::allocationSiteGroup(cx, script, pc, JSProto_Array);
    2165           0 :         if (!group)
    2166           0 :             return false;
    2167             : 
    2168           0 :         ICNewArray_Fallback::Compiler stubCompiler(cx, group, ICStubCompiler::Engine::Baseline);
    2169           0 :         if (!emitOpIC(stubCompiler.getStub(&stubSpace_)))
    2170           0 :             return false;
    2171             :     } else {
    2172          12 :         MOZ_ASSERT(key == JSProto_Object);
    2173             : 
    2174          24 :         ICNewObject_Fallback::Compiler stubCompiler(cx, ICStubCompiler::Engine::Baseline);
    2175          12 :         if (!emitOpIC(stubCompiler.getStub(&stubSpace_)))
    2176           0 :             return false;
    2177             :     }
    2178             : 
    2179          12 :     frame.push(R0);
    2180          12 :     return true;
    2181             : }
    2182             : 
    2183             : bool
    2184          41 : BaselineCompiler::emit_JSOP_INITELEM()
    2185             : {
    2186             :     // Store RHS in the scratch slot.
    2187          41 :     storeValue(frame.peek(-1), frame.addressOfScratchValue(), R2);
    2188          41 :     frame.pop();
    2189             : 
    2190             :     // Keep object and index in R0 and R1.
    2191          41 :     frame.popRegsAndSync(2);
    2192             : 
    2193             :     // Push the object to store the result of the IC.
    2194          41 :     frame.push(R0);
    2195          41 :     frame.syncStack(0);
    2196             : 
    2197             :     // Keep RHS on the stack.
    2198          41 :     frame.pushScratchValue();
    2199             : 
    2200             :     // Call IC.
    2201          82 :     ICSetElem_Fallback::Compiler stubCompiler(cx);
    2202          41 :     if (!emitOpIC(stubCompiler.getStub(&stubSpace_)))
    2203           0 :         return false;
    2204             : 
    2205             :     // Pop the rhs, so that the object is on the top of the stack.
    2206          41 :     frame.pop();
    2207          41 :     return true;
    2208             : }
    2209             : 
    2210             : bool
    2211           0 : BaselineCompiler::emit_JSOP_INITHIDDENELEM()
    2212             : {
    2213           0 :     return emit_JSOP_INITELEM();
    2214             : }
    2215             : 
    2216             : typedef bool (*MutateProtoFn)(JSContext* cx, HandlePlainObject obj, HandleValue newProto);
    2217           3 : static const VMFunction MutateProtoInfo =
    2218           6 :     FunctionInfo<MutateProtoFn>(MutatePrototype, "MutatePrototype");
    2219             : 
    2220             : bool
    2221           3 : BaselineCompiler::emit_JSOP_MUTATEPROTO()
    2222             : {
    2223             :     // Keep values on the stack for the decompiler.
    2224           3 :     frame.syncStack(0);
    2225             : 
    2226           3 :     masm.extractObject(frame.addressOfStackValue(frame.peek(-2)), R0.scratchReg());
    2227           3 :     masm.loadValue(frame.addressOfStackValue(frame.peek(-1)), R1);
    2228             : 
    2229           3 :     prepareVMCall();
    2230             : 
    2231           3 :     pushArg(R1);
    2232           3 :     pushArg(R0.scratchReg());
    2233             : 
    2234           3 :     if (!callVM(MutateProtoInfo))
    2235           0 :         return false;
    2236             : 
    2237           3 :     frame.pop();
    2238           3 :     return true;
    2239             : }
    2240             : 
    2241             : bool
    2242         465 : BaselineCompiler::emit_JSOP_INITPROP()
    2243             : {
    2244             :     // Load lhs in R0, rhs in R1.
    2245         465 :     frame.syncStack(0);
    2246         465 :     masm.loadValue(frame.addressOfStackValue(frame.peek(-2)), R0);
    2247         465 :     masm.loadValue(frame.addressOfStackValue(frame.peek(-1)), R1);
    2248             : 
    2249             :     // Call IC.
    2250         930 :     ICSetProp_Fallback::Compiler compiler(cx);
    2251         465 :     if (!emitOpIC(compiler.getStub(&stubSpace_)))
    2252           0 :         return false;
    2253             : 
    2254             :     // Leave the object on the stack.
    2255         465 :     frame.pop();
    2256         465 :     return true;
    2257             : }
    2258             : 
    2259             : bool
    2260           0 : BaselineCompiler::emit_JSOP_INITLOCKEDPROP()
    2261             : {
    2262           0 :     return emit_JSOP_INITPROP();
    2263             : }
    2264             : 
    2265             : bool
    2266           0 : BaselineCompiler::emit_JSOP_INITHIDDENPROP()
    2267             : {
    2268           0 :     return emit_JSOP_INITPROP();
    2269             : }
    2270             : 
    2271             : typedef bool (*NewbornArrayPushFn)(JSContext*, HandleObject, const Value&);
    2272           3 : static const VMFunction NewbornArrayPushInfo =
    2273           6 :     FunctionInfo<NewbornArrayPushFn>(NewbornArrayPush, "NewbornArrayPush");
    2274             : 
    2275             : bool
    2276           0 : BaselineCompiler::emit_JSOP_ARRAYPUSH()
    2277             : {
    2278             :     // Keep value in R0, object in R1.
    2279           0 :     frame.popRegsAndSync(2);
    2280           0 :     masm.unboxObject(R1, R1.scratchReg());
    2281             : 
    2282           0 :     prepareVMCall();
    2283             : 
    2284           0 :     pushArg(R0);
    2285           0 :     pushArg(R1.scratchReg());
    2286             : 
    2287           0 :     return callVM(NewbornArrayPushInfo);
    2288             : }
    2289             : 
    2290             : bool
    2291         650 : BaselineCompiler::emit_JSOP_GETELEM()
    2292             : {
    2293             :     // Keep top two stack values in R0 and R1.
    2294         650 :     frame.popRegsAndSync(2);
    2295             : 
    2296             :     // Call IC.
    2297        1300 :     ICGetElem_Fallback::Compiler stubCompiler(cx);
    2298         650 :     if (!emitOpIC(stubCompiler.getStub(&stubSpace_)))
    2299           0 :         return false;
    2300             : 
    2301             :     // Mark R0 as pushed stack value.
    2302         650 :     frame.push(R0);
    2303         650 :     return true;
    2304             : }
    2305             : 
    2306             : bool
    2307           0 : BaselineCompiler::emit_JSOP_GETELEM_SUPER()
    2308             : {
    2309             :     // Index -> R1, Receiver -> R2, Object -> R0
    2310           0 :     frame.popRegsAndSync(1);
    2311           0 :     masm.loadValue(frame.addressOfStackValue(frame.peek(-1)), R2);
    2312           0 :     masm.loadValue(frame.addressOfStackValue(frame.peek(-2)), R1);
    2313             : 
    2314             :     // Keep receiver on stack.
    2315           0 :     frame.popn(2);
    2316           0 :     frame.push(R2);
    2317           0 :     frame.syncStack(0);
    2318             : 
    2319           0 :     ICGetElem_Fallback::Compiler stubCompiler(cx, /* hasReceiver = */ true);
    2320           0 :     if (!emitOpIC(stubCompiler.getStub(&stubSpace_)))
    2321           0 :         return false;
    2322             : 
    2323           0 :     frame.pop();
    2324           0 :     frame.push(R0);
    2325           0 :     return true;
    2326             : }
    2327             : 
    2328             : bool
    2329         167 : BaselineCompiler::emit_JSOP_CALLELEM()
    2330             : {
    2331         167 :     return emit_JSOP_GETELEM();
    2332             : }
    2333             : 
    2334             : bool
    2335         170 : BaselineCompiler::emit_JSOP_SETELEM()
    2336             : {
    2337             :     // Store RHS in the scratch slot.
    2338         170 :     storeValue(frame.peek(-1), frame.addressOfScratchValue(), R2);
    2339         170 :     frame.pop();
    2340             : 
    2341             :     // Keep object and index in R0 and R1.
    2342         170 :     frame.popRegsAndSync(2);
    2343             : 
    2344             :     // Keep RHS on the stack.
    2345         170 :     frame.pushScratchValue();
    2346             : 
    2347             :     // Call IC.
    2348         340 :     ICSetElem_Fallback::Compiler stubCompiler(cx);
    2349         170 :     if (!emitOpIC(stubCompiler.getStub(&stubSpace_)))
    2350           0 :         return false;
    2351             : 
    2352         170 :     return true;
    2353             : }
    2354             : 
    2355             : bool
    2356          66 : BaselineCompiler::emit_JSOP_STRICTSETELEM()
    2357             : {
    2358          66 :     return emit_JSOP_SETELEM();
    2359             : }
    2360             : 
    2361             : typedef bool (*SetObjectElementFn)(JSContext*, HandleObject, HandleValue,
    2362             :                                   HandleValue, HandleValue, bool);
    2363           3 : static const VMFunction SetObjectElementInfo =
    2364           6 :     FunctionInfo<SetObjectElementFn>(js::SetObjectElement, "SetObjectElement");
    2365             : 
    2366             : bool
    2367           0 : BaselineCompiler::emit_JSOP_SETELEM_SUPER()
    2368             : {
    2369           0 :     bool strict = IsCheckStrictOp(JSOp(*pc));
    2370             : 
    2371             :     // Incoming stack is |propval, receiver, obj, rval|. We need to shuffle
    2372             :     // stack to leave rval when operation is complete.
    2373             : 
    2374             :     // Pop rval into R0, then load propval into R1 and replace with rval.
    2375           0 :     frame.popRegsAndSync(1);
    2376           0 :     masm.loadValue(frame.addressOfStackValue(frame.peek(-3)), R1);
    2377           0 :     masm.storeValue(R0, frame.addressOfStackValue(frame.peek(-3)));
    2378             : 
    2379           0 :     prepareVMCall();
    2380             : 
    2381           0 :     pushArg(Imm32(strict));
    2382           0 :     masm.loadValue(frame.addressOfStackValue(frame.peek(-2)), R2);
    2383           0 :     pushArg(R2); // receiver
    2384           0 :     pushArg(R0); // rval
    2385           0 :     pushArg(R1); // propval
    2386           0 :     masm.unboxObject(frame.addressOfStackValue(frame.peek(-1)), R0.scratchReg());
    2387           0 :     pushArg(R0.scratchReg()); // obj
    2388             : 
    2389           0 :     if (!callVM(SetObjectElementInfo))
    2390           0 :         return false;
    2391             : 
    2392           0 :     frame.popn(2);
    2393           0 :     return true;
    2394             : }
    2395             : 
    2396             : bool
    2397           0 : BaselineCompiler::emit_JSOP_STRICTSETELEM_SUPER()
    2398             : {
    2399           0 :     return emit_JSOP_SETELEM_SUPER();
    2400             : }
    2401             : 
    2402             : typedef bool (*DeleteElementFn)(JSContext*, HandleValue, HandleValue, bool*);
    2403           3 : static const VMFunction DeleteElementStrictInfo
    2404           6 :     = FunctionInfo<DeleteElementFn>(DeleteElementJit<true>, "DeleteElementStrict");
    2405           3 : static const VMFunction DeleteElementNonStrictInfo
    2406           6 :     = FunctionInfo<DeleteElementFn>(DeleteElementJit<false>, "DeleteElementNonStrict");
    2407             : 
    2408             : bool
    2409          11 : BaselineCompiler::emit_JSOP_DELELEM()
    2410             : {
    2411             :     // Keep values on the stack for the decompiler.
    2412          11 :     frame.syncStack(0);
    2413          11 :     masm.loadValue(frame.addressOfStackValue(frame.peek(-2)), R0);
    2414          11 :     masm.loadValue(frame.addressOfStackValue(frame.peek(-1)), R1);
    2415             : 
    2416          11 :     prepareVMCall();
    2417             : 
    2418          11 :     pushArg(R1);
    2419          11 :     pushArg(R0);
    2420             : 
    2421          11 :     bool strict = JSOp(*pc) == JSOP_STRICTDELELEM;
    2422          11 :     if (!callVM(strict ? DeleteElementStrictInfo : DeleteElementNonStrictInfo))
    2423           0 :         return false;
    2424             : 
    2425          11 :     masm.boxNonDouble(JSVAL_TYPE_BOOLEAN, ReturnReg, R1);
    2426          11 :     frame.popn(2);
    2427          11 :     frame.push(R1);
    2428          11 :     return true;
    2429             : }
    2430             : 
    2431             : bool
    2432           7 : BaselineCompiler::emit_JSOP_STRICTDELELEM()
    2433             : {
    2434           7 :     return emit_JSOP_DELELEM();
    2435             : }
    2436             : 
    2437             : bool
    2438          76 : BaselineCompiler::emit_JSOP_IN()
    2439             : {
    2440          76 :     frame.popRegsAndSync(2);
    2441             : 
    2442         152 :     ICIn_Fallback::Compiler stubCompiler(cx);
    2443          76 :     if (!emitOpIC(stubCompiler.getStub(&stubSpace_)))
    2444           0 :         return false;
    2445             : 
    2446          76 :     frame.push(R0);
    2447          76 :     return true;
    2448             : }
    2449             : 
    2450             : bool
    2451           0 : BaselineCompiler::emit_JSOP_HASOWN()
    2452             : {
    2453           0 :     frame.popRegsAndSync(2);
    2454             : 
    2455           0 :     ICHasOwn_Fallback::Compiler stubCompiler(cx);
    2456           0 :     if (!emitOpIC(stubCompiler.getStub(&stubSpace_)))
    2457           0 :         return false;
    2458             : 
    2459           0 :     frame.push(R0);
    2460           0 :     return true;
    2461             : }
    2462             : 
    2463             : bool
    2464        1583 : BaselineCompiler::emit_JSOP_GETGNAME()
    2465             : {
    2466        1583 :     if (script->hasNonSyntacticScope())
    2467           0 :         return emit_JSOP_GETNAME();
    2468             : 
    2469        3166 :     RootedPropertyName name(cx, script->getName(pc));
    2470             : 
    2471             :     // These names are non-configurable on the global and cannot be shadowed.
    2472        1583 :     if (name == cx->names().undefined) {
    2473          16 :         frame.push(UndefinedValue());
    2474          16 :         return true;
    2475             :     }
    2476        1567 :     if (name == cx->names().NaN) {
    2477           0 :         frame.push(cx->runtime()->NaNValue);
    2478           0 :         return true;
    2479             :     }
    2480        1567 :     if (name == cx->names().Infinity) {
    2481           0 :         frame.push(cx->runtime()->positiveInfinityValue);
    2482           0 :         return true;
    2483             :     }
    2484             : 
    2485        1567 :     frame.syncStack(0);
    2486             : 
    2487        1567 :     masm.movePtr(ImmGCPtr(&script->global().lexicalEnvironment()), R0.scratchReg());
    2488             : 
    2489             :     // Call IC.
    2490        3134 :     ICGetName_Fallback::Compiler stubCompiler(cx);
    2491        1567 :     if (!emitOpIC(stubCompiler.getStub(&stubSpace_)))
    2492           0 :         return false;
    2493             : 
    2494             :     // Mark R0 as pushed stack value.
    2495        1567 :     frame.push(R0);
    2496        1567 :     return true;
    2497             : }
    2498             : 
    2499             : bool
    2500          56 : BaselineCompiler::emit_JSOP_BINDGNAME()
    2501             : {
    2502          56 :     if (!script->hasNonSyntacticScope()) {
    2503             :         // We can bind name to the global lexical scope if the binding already
    2504             :         // exists, is initialized, and is writable (i.e., an initialized
    2505             :         // 'let') at compile time.
    2506          56 :         RootedPropertyName name(cx, script->getName(pc));
    2507          56 :         Rooted<LexicalEnvironmentObject*> env(cx, &script->global().lexicalEnvironment());
    2508          56 :         if (Shape* shape = env->lookup(cx, name)) {
    2509           0 :             if (shape->writable() &&
    2510           0 :                 !env->getSlot(shape->slot()).isMagic(JS_UNINITIALIZED_LEXICAL))
    2511             :             {
    2512           0 :                 frame.push(ObjectValue(*env));
    2513           0 :                 return true;
    2514             :             }
    2515          56 :         } else if (Shape* shape = script->global().lookup(cx, name)) {
    2516             :             // If the property does not currently exist on the global lexical
    2517             :             // scope, we can bind name to the global object if the property
    2518             :             // exists on the global and is non-configurable, as then it cannot
    2519             :             // be shadowed.
    2520          56 :             if (!shape->configurable()) {
    2521          56 :                 frame.push(ObjectValue(script->global()));
    2522          56 :                 return true;
    2523             :             }
    2524             :         }
    2525             : 
    2526             :         // Otherwise we have to use the dynamic scope chain.
    2527             :     }
    2528             : 
    2529           0 :     return emit_JSOP_BINDNAME();
    2530             : }
    2531             : 
    2532             : typedef JSObject* (*BindVarFn)(JSContext*, HandleObject);
    2533           3 : static const VMFunction BindVarInfo = FunctionInfo<BindVarFn>(jit::BindVar, "BindVar");
    2534             : 
    2535             : bool
    2536           0 : BaselineCompiler::emit_JSOP_BINDVAR()
    2537             : {
    2538           0 :     frame.syncStack(0);
    2539           0 :     masm.loadPtr(frame.addressOfEnvironmentChain(), R0.scratchReg());
    2540             : 
    2541           0 :     prepareVMCall();
    2542           0 :     pushArg(R0.scratchReg());
    2543             : 
    2544           0 :     if (!callVM(BindVarInfo))
    2545           0 :         return false;
    2546             : 
    2547           0 :     masm.tagValue(JSVAL_TYPE_OBJECT, ReturnReg, R0);
    2548           0 :     frame.push(R0);
    2549           0 :     return true;
    2550             : }
    2551             : 
    2552             : bool
    2553         742 : BaselineCompiler::emit_JSOP_SETPROP()
    2554             : {
    2555             :     // Keep lhs in R0, rhs in R1.
    2556         742 :     frame.popRegsAndSync(2);
    2557             : 
    2558             :     // Keep RHS on the stack.
    2559         742 :     frame.push(R1);
    2560         742 :     frame.syncStack(0);
    2561             : 
    2562             :     // Call IC.
    2563        1484 :     ICSetProp_Fallback::Compiler compiler(cx);
    2564         742 :     if (!emitOpIC(compiler.getStub(&stubSpace_)))
    2565           0 :         return false;
    2566             : 
    2567         742 :     return true;
    2568             : }
    2569             : 
    2570             : bool
    2571         482 : BaselineCompiler::emit_JSOP_STRICTSETPROP()
    2572             : {
    2573         482 :     return emit_JSOP_SETPROP();
    2574             : }
    2575             : 
    2576             : bool
    2577           0 : BaselineCompiler::emit_JSOP_SETNAME()
    2578             : {
    2579           0 :     return emit_JSOP_SETPROP();
    2580             : }
    2581             : 
    2582             : bool
    2583           0 : BaselineCompiler::emit_JSOP_STRICTSETNAME()
    2584             : {
    2585           0 :     return emit_JSOP_SETPROP();
    2586             : }
    2587             : 
    2588             : bool
    2589           3 : BaselineCompiler::emit_JSOP_SETGNAME()
    2590             : {
    2591           3 :     return emit_JSOP_SETPROP();
    2592             : }
    2593             : 
    2594             : bool
    2595          53 : BaselineCompiler::emit_JSOP_STRICTSETGNAME()
    2596             : {
    2597          53 :     return emit_JSOP_SETPROP();
    2598             : }
    2599             : 
    2600             : typedef bool (*SetPropertySuperFn)(JSContext*, HandleObject, HandleValue,
    2601             :                                    HandlePropertyName, HandleValue, bool);
    2602           3 : static const VMFunction SetPropertySuperInfo =
    2603           6 :     FunctionInfo<SetPropertySuperFn>(js::SetPropertySuper, "SetPropertySuper");
    2604             : 
    2605             : bool
    2606           0 : BaselineCompiler::emit_JSOP_SETPROP_SUPER()
    2607             : {
    2608           0 :     bool strict = IsCheckStrictOp(JSOp(*pc));
    2609             : 
    2610             :     // Incoming stack is |receiver, obj, rval|. We need to shuffle stack to
    2611             :     // leave rval when operation is complete.
    2612             : 
    2613             :     // Pop rval into R0, then load receiver into R1 and replace with rval.
    2614           0 :     frame.popRegsAndSync(1);
    2615           0 :     masm.loadValue(frame.addressOfStackValue(frame.peek(-2)), R1);
    2616           0 :     masm.storeValue(R0, frame.addressOfStackValue(frame.peek(-2)));
    2617             : 
    2618           0 :     prepareVMCall();
    2619             : 
    2620           0 :     pushArg(Imm32(strict));
    2621           0 :     pushArg(R0); // rval
    2622           0 :     pushArg(ImmGCPtr(script->getName(pc)));
    2623           0 :     pushArg(R1); // receiver
    2624           0 :     masm.unboxObject(frame.addressOfStackValue(frame.peek(-1)), R0.scratchReg());
    2625           0 :     pushArg(R0.scratchReg()); // obj
    2626             : 
    2627           0 :     if (!callVM(SetPropertySuperInfo))
    2628           0 :         return false;
    2629             : 
    2630           0 :     frame.pop();
    2631           0 :     return true;
    2632             : }
    2633             : 
    2634             : bool
    2635           0 : BaselineCompiler::emit_JSOP_STRICTSETPROP_SUPER()
    2636             : {
    2637           0 :     return emit_JSOP_SETPROP_SUPER();
    2638             : }
    2639             : 
    2640             : bool
    2641        3722 : BaselineCompiler::emit_JSOP_GETPROP()
    2642             : {
    2643             :     // Keep object in R0.
    2644        3722 :     frame.popRegsAndSync(1);
    2645             : 
    2646             :     // Call IC.
    2647        7444 :     ICGetProp_Fallback::Compiler compiler(cx, ICStubCompiler::Engine::Baseline);
    2648        3722 :     if (!emitOpIC(compiler.getStub(&stubSpace_)))
    2649           0 :         return false;
    2650             : 
    2651             :     // Mark R0 as pushed stack value.
    2652        3722 :     frame.push(R0);
    2653        3722 :     return true;
    2654             : }
    2655             : 
    2656             : bool
    2657        1428 : BaselineCompiler::emit_JSOP_CALLPROP()
    2658             : {
    2659        1428 :     return emit_JSOP_GETPROP();
    2660             : }
    2661             : 
    2662             : bool
    2663         230 : BaselineCompiler::emit_JSOP_LENGTH()
    2664             : {
    2665         230 :     return emit_JSOP_GETPROP();
    2666             : }
    2667             : 
    2668             : bool
    2669           0 : BaselineCompiler::emit_JSOP_GETBOUNDNAME()
    2670             : {
    2671           0 :     return emit_JSOP_GETPROP();
    2672             : }
    2673             : 
    2674             : bool
    2675           0 : BaselineCompiler::emit_JSOP_GETPROP_SUPER()
    2676             : {
    2677             :     // Receiver -> R1, Object -> R0
    2678           0 :     frame.popRegsAndSync(1);
    2679           0 :     masm.loadValue(frame.addressOfStackValue(frame.peek(-1)), R1);
    2680           0 :     frame.pop();
    2681             : 
    2682             :     ICGetProp_Fallback::Compiler compiler(cx, ICStubCompiler::Engine::Baseline,
    2683           0 :                                           /* hasReceiver = */ true);
    2684           0 :     if (!emitOpIC(compiler.getStub(&stubSpace_)))
    2685           0 :         return false;
    2686             : 
    2687           0 :     frame.push(R0);
    2688           0 :     return true;
    2689             : }
    2690             : 
    2691             : 
    2692             : typedef bool (*DeletePropertyFn)(JSContext*, HandleValue, HandlePropertyName, bool*);
    2693           3 : static const VMFunction DeletePropertyStrictInfo =
    2694           6 :     FunctionInfo<DeletePropertyFn>(DeletePropertyJit<true>, "DeletePropertyStrict");
    2695           3 : static const VMFunction DeletePropertyNonStrictInfo =
    2696           6 :     FunctionInfo<DeletePropertyFn>(DeletePropertyJit<false>, "DeletePropertyNonStrict");
    2697             : 
    2698             : bool
    2699           4 : BaselineCompiler::emit_JSOP_DELPROP()
    2700             : {
    2701             :     // Keep value on the stack for the decompiler.
    2702           4 :     frame.syncStack(0);
    2703           4 :     masm.loadValue(frame.addressOfStackValue(frame.peek(-1)), R0);
    2704             : 
    2705           4 :     prepareVMCall();
    2706             : 
    2707           4 :     pushArg(ImmGCPtr(script->getName(pc)));
    2708           4 :     pushArg(R0);
    2709             : 
    2710           4 :     bool strict = JSOp(*pc) == JSOP_STRICTDELPROP;
    2711           4 :     if (!callVM(strict ? DeletePropertyStrictInfo : DeletePropertyNonStrictInfo))
    2712           0 :         return false;
    2713             : 
    2714           4 :     masm.boxNonDouble(JSVAL_TYPE_BOOLEAN, ReturnReg, R1);
    2715           4 :     frame.pop();
    2716           4 :     frame.push(R1);
    2717           4 :     return true;
    2718             : }
    2719             : 
    2720             : bool
    2721           4 : BaselineCompiler::emit_JSOP_STRICTDELPROP()
    2722             : {
    2723           4 :     return emit_JSOP_DELPROP();
    2724             : }
    2725             : 
    2726             : void
    2727         957 : BaselineCompiler::getEnvironmentCoordinateObject(Register reg)
    2728             : {
    2729         957 :     EnvironmentCoordinate ec(pc);
    2730             : 
    2731         957 :     masm.loadPtr(frame.addressOfEnvironmentChain(), reg);
    2732        1252 :     for (unsigned i = ec.hops(); i; i--)
    2733         295 :         masm.extractObject(Address(reg, EnvironmentObject::offsetOfEnclosingEnvironment()), reg);
    2734         957 : }
    2735             : 
    2736             : Address
    2737         957 : BaselineCompiler::getEnvironmentCoordinateAddressFromObject(Register objReg, Register reg)
    2738             : {
    2739         957 :     EnvironmentCoordinate ec(pc);
    2740         957 :     Shape* shape = EnvironmentCoordinateToEnvironmentShape(script, pc);
    2741             : 
    2742         957 :     Address addr;
    2743         957 :     if (shape->numFixedSlots() <= ec.slot()) {
    2744          36 :         masm.loadPtr(Address(objReg, NativeObject::offsetOfSlots()), reg);
    2745          36 :         return Address(reg, (ec.slot() - shape->numFixedSlots()) * sizeof(Value));
    2746             :     }
    2747             : 
    2748         921 :     return Address(objReg, NativeObject::getFixedSlotOffset(ec.slot()));
    2749             : }
    2750             : 
    2751             : Address
    2752         802 : BaselineCompiler::getEnvironmentCoordinateAddress(Register reg)
    2753             : {
    2754         802 :     getEnvironmentCoordinateObject(reg);
    2755         802 :     return getEnvironmentCoordinateAddressFromObject(reg, reg);
    2756             : }
    2757             : 
    2758             : bool
    2759         719 : BaselineCompiler::emit_JSOP_GETALIASEDVAR()
    2760             : {
    2761         719 :     frame.syncStack(0);
    2762             : 
    2763         719 :     Address address = getEnvironmentCoordinateAddress(R0.scratchReg());
    2764         719 :     masm.loadValue(address, R0);
    2765             : 
    2766         719 :     if (ionCompileable_) {
    2767             :         // No need to monitor types if we know Ion can't compile this script.
    2768        1274 :         ICTypeMonitor_Fallback::Compiler compiler(cx, nullptr);
    2769         637 :         if (!emitOpIC(compiler.getStub(&stubSpace_)))
    2770           0 :             return false;
    2771             :     }
    2772             : 
    2773         719 :     frame.push(R0);
    2774         719 :     return true;
    2775             : }
    2776             : 
    2777             : bool
    2778         155 : BaselineCompiler::emit_JSOP_SETALIASEDVAR()
    2779             : {
    2780         155 :     JSScript* outerScript = EnvironmentCoordinateFunctionScript(script, pc);
    2781         155 :     if (outerScript && outerScript->treatAsRunOnce()) {
    2782             :         // Type updates for this operation might need to be tracked, so treat
    2783             :         // this as a SETPROP.
    2784             : 
    2785             :         // Load rhs into R1.
    2786           0 :         frame.syncStack(0);
    2787           0 :         masm.loadValue(frame.addressOfStackValue(frame.peek(-1)), R1);
    2788             : 
    2789             :         // Load and box lhs into R0.
    2790           0 :         getEnvironmentCoordinateObject(R2.scratchReg());
    2791           0 :         masm.tagValue(JSVAL_TYPE_OBJECT, R2.scratchReg(), R0);
    2792             : 
    2793             :         // Call SETPROP IC.
    2794           0 :         ICSetProp_Fallback::Compiler compiler(cx);
    2795           0 :         if (!emitOpIC(compiler.getStub(&stubSpace_)))
    2796           0 :             return false;
    2797             : 
    2798           0 :         return true;
    2799             :     }
    2800             : 
    2801             :     // Keep rvalue in R0.
    2802         155 :     frame.popRegsAndSync(1);
    2803         155 :     Register objReg = R2.scratchReg();
    2804             : 
    2805         155 :     getEnvironmentCoordinateObject(objReg);
    2806         155 :     Address address = getEnvironmentCoordinateAddressFromObject(objReg, R1.scratchReg());
    2807         155 :     masm.guardedCallPreBarrier(address, MIRType::Value);
    2808         155 :     masm.storeValue(R0, address);
    2809         155 :     frame.push(R0);
    2810             : 
    2811             :     // Only R0 is live at this point.
    2812             :     // Scope coordinate object is already in R2.scratchReg().
    2813         155 :     Register temp = R1.scratchReg();
    2814             : 
    2815         310 :     Label skipBarrier;
    2816         155 :     masm.branchPtrInNurseryChunk(Assembler::Equal, objReg, temp, &skipBarrier);
    2817         155 :     masm.branchValueIsNurseryObject(Assembler::NotEqual, R0, temp, &skipBarrier);
    2818             : 
    2819         155 :     masm.call(&postBarrierSlot_); // Won't clobber R0
    2820             : 
    2821         155 :     masm.bind(&skipBarrier);
    2822         155 :     return true;
    2823             : }
    2824             : 
    2825             : bool
    2826          89 : BaselineCompiler::emit_JSOP_GETNAME()
    2827             : {
    2828          89 :     frame.syncStack(0);
    2829             : 
    2830          89 :     masm.loadPtr(frame.addressOfEnvironmentChain(), R0.scratchReg());
    2831             : 
    2832             :     // Call IC.
    2833         178 :     ICGetName_Fallback::Compiler stubCompiler(cx);
    2834          89 :     if (!emitOpIC(stubCompiler.getStub(&stubSpace_)))
    2835           0 :         return false;
    2836             : 
    2837             :     // Mark R0 as pushed stack value.
    2838          89 :     frame.push(R0);
    2839          89 :     return true;
    2840             : }
    2841             : 
    2842             : bool
    2843           0 : BaselineCompiler::emit_JSOP_BINDNAME()
    2844             : {
    2845           0 :     frame.syncStack(0);
    2846             : 
    2847           0 :     if (*pc == JSOP_BINDGNAME && !script->hasNonSyntacticScope())
    2848           0 :         masm.movePtr(ImmGCPtr(&script->global().lexicalEnvironment()), R0.scratchReg());
    2849             :     else
    2850           0 :         masm.loadPtr(frame.addressOfEnvironmentChain(), R0.scratchReg());
    2851             : 
    2852             :     // Call IC.
    2853           0 :     ICBindName_Fallback::Compiler stubCompiler(cx);
    2854           0 :     if (!emitOpIC(stubCompiler.getStub(&stubSpace_)))
    2855           0 :         return false;
    2856             : 
    2857             :     // Mark R0 as pushed stack value.
    2858           0 :     frame.push(R0);
    2859           0 :     return true;
    2860             : }
    2861             : 
    2862             : typedef bool (*DeleteNameFn)(JSContext*, HandlePropertyName, HandleObject,
    2863             :                              MutableHandleValue);
    2864           3 : static const VMFunction DeleteNameInfo =
    2865           6 :     FunctionInfo<DeleteNameFn>(DeleteNameOperation, "DeleteNameOperation");
    2866             : 
    2867             : bool
    2868           0 : BaselineCompiler::emit_JSOP_DELNAME()
    2869             : {
    2870           0 :     frame.syncStack(0);
    2871           0 :     masm.loadPtr(frame.addressOfEnvironmentChain(), R0.scratchReg());
    2872             : 
    2873           0 :     prepareVMCall();
    2874             : 
    2875           0 :     pushArg(R0.scratchReg());
    2876           0 :     pushArg(ImmGCPtr(script->getName(pc)));
    2877             : 
    2878           0 :     if (!callVM(DeleteNameInfo))
    2879           0 :         return false;
    2880             : 
    2881           0 :     frame.push(R0);
    2882           0 :     return true;
    2883             : }
    2884             : 
    2885             : bool
    2886           0 : BaselineCompiler::emit_JSOP_GETIMPORT()
    2887             : {
    2888           0 :     ModuleEnvironmentObject* env = GetModuleEnvironmentForScript(script);
    2889           0 :     MOZ_ASSERT(env);
    2890             : 
    2891             :     ModuleEnvironmentObject* targetEnv;
    2892             :     Shape* shape;
    2893           0 :     MOZ_ALWAYS_TRUE(env->lookupImport(NameToId(script->getName(pc)), &targetEnv, &shape));
    2894             : 
    2895           0 :     EnsureTrackPropertyTypes(cx, targetEnv, shape->propid());
    2896             : 
    2897           0 :     frame.syncStack(0);
    2898             : 
    2899           0 :     uint32_t slot = shape->slot();
    2900           0 :     Register scratch = R0.scratchReg();
    2901           0 :     masm.movePtr(ImmGCPtr(targetEnv), scratch);
    2902           0 :     if (slot < targetEnv->numFixedSlots()) {
    2903           0 :         masm.loadValue(Address(scratch, NativeObject::getFixedSlotOffset(slot)), R0);
    2904             :     } else {
    2905           0 :         masm.loadPtr(Address(scratch, NativeObject::offsetOfSlots()), scratch);
    2906           0 :         masm.loadValue(Address(scratch, (slot - targetEnv->numFixedSlots()) * sizeof(Value)), R0);
    2907             :     }
    2908             : 
    2909             :     // Imports are initialized by this point except in rare circumstances, so
    2910             :     // don't emit a check unless we have to.
    2911           0 :     if (targetEnv->getSlot(shape->slot()).isMagic(JS_UNINITIALIZED_LEXICAL))
    2912           0 :         if (!emitUninitializedLexicalCheck(R0))
    2913           0 :             return false;
    2914             : 
    2915           0 :     if (ionCompileable_) {
    2916             :         // No need to monitor types if we know Ion can't compile this script.
    2917           0 :         ICTypeMonitor_Fallback::Compiler compiler(cx, nullptr);
    2918           0 :         if (!emitOpIC(compiler.getStub(&stubSpace_)))
    2919           0 :             return false;
    2920             :     }
    2921             : 
    2922           0 :     frame.push(R0);
    2923           0 :     return true;
    2924             : }
    2925             : 
    2926             : bool
    2927        1724 : BaselineCompiler::emit_JSOP_GETINTRINSIC()
    2928             : {
    2929        1724 :     frame.syncStack(0);
    2930             : 
    2931        3448 :     ICGetIntrinsic_Fallback::Compiler stubCompiler(cx);
    2932        1724 :     if (!emitOpIC(stubCompiler.getStub(&stubSpace_)))
    2933           0 :         return false;
    2934             : 
    2935        1724 :     frame.push(R0);
    2936        1724 :     return true;
    2937             : }
    2938             : 
    2939             : typedef bool (*DefVarFn)(JSContext*, HandlePropertyName, unsigned, HandleObject);
    2940           3 : static const VMFunction DefVarInfo = FunctionInfo<DefVarFn>(DefVar, "DefVar");
    2941             : 
    2942             : bool
    2943          28 : BaselineCompiler::emit_JSOP_DEFVAR()
    2944             : {
    2945          28 :     frame.syncStack(0);
    2946             : 
    2947          28 :     unsigned attrs = JSPROP_ENUMERATE;
    2948          28 :     if (!script->isForEval())
    2949          28 :         attrs |= JSPROP_PERMANENT;
    2950             :     MOZ_ASSERT(attrs <= UINT32_MAX);
    2951             : 
    2952          28 :     masm.loadPtr(frame.addressOfEnvironmentChain(), R0.scratchReg());
    2953             : 
    2954          28 :     prepareVMCall();
    2955             : 
    2956          28 :     pushArg(R0.scratchReg());
    2957          28 :     pushArg(Imm32(attrs));
    2958          28 :     pushArg(ImmGCPtr(script->getName(pc)));
    2959             : 
    2960          28 :     return callVM(DefVarInfo);
    2961             : }
    2962             : 
    2963             : typedef bool (*DefLexicalFn)(JSContext*, HandlePropertyName, unsigned, HandleObject);
    2964           3 : static const VMFunction DefLexicalInfo = FunctionInfo<DefLexicalFn>(DefLexical, "DefLexical");
    2965             : 
    2966             : bool
    2967          17 : BaselineCompiler::emit_JSOP_DEFCONST()
    2968             : {
    2969          17 :     return emit_JSOP_DEFLET();
    2970             : }
    2971             : 
    2972             : bool
    2973          19 : BaselineCompiler::emit_JSOP_DEFLET()
    2974             : {
    2975          19 :     frame.syncStack(0);
    2976             : 
    2977          19 :     unsigned attrs = JSPROP_ENUMERATE | JSPROP_PERMANENT;
    2978          19 :     if (*pc == JSOP_DEFCONST)
    2979          17 :         attrs |= JSPROP_READONLY;
    2980             :     MOZ_ASSERT(attrs <= UINT32_MAX);
    2981             : 
    2982          19 :     masm.loadPtr(frame.addressOfEnvironmentChain(), R0.scratchReg());
    2983             : 
    2984          19 :     prepareVMCall();
    2985             : 
    2986          19 :     pushArg(R0.scratchReg());
    2987          19 :     pushArg(Imm32(attrs));
    2988          19 :     pushArg(ImmGCPtr(script->getName(pc)));
    2989             : 
    2990          19 :     return callVM(DefLexicalInfo);
    2991             : }
    2992             : 
    2993             : typedef bool (*DefFunOperationFn)(JSContext*, HandleScript, HandleObject, HandleFunction);
    2994           3 : static const VMFunction DefFunOperationInfo =
    2995           6 :     FunctionInfo<DefFunOperationFn>(DefFunOperation, "DefFunOperation");
    2996             : 
    2997             : bool
    2998          11 : BaselineCompiler::emit_JSOP_DEFFUN()
    2999             : {
    3000          11 :     frame.popRegsAndSync(1);
    3001          11 :     masm.unboxObject(R0, R0.scratchReg());
    3002          11 :     masm.loadPtr(frame.addressOfEnvironmentChain(), R1.scratchReg());
    3003             : 
    3004          11 :     prepareVMCall();
    3005             : 
    3006          11 :     pushArg(R0.scratchReg());
    3007          11 :     pushArg(R1.scratchReg());
    3008          11 :     pushArg(ImmGCPtr(script));
    3009             : 
    3010          11 :     return callVM(DefFunOperationInfo);
    3011             : }
    3012             : 
    3013             : typedef bool (*InitPropGetterSetterFn)(JSContext*, jsbytecode*, HandleObject, HandlePropertyName,
    3014             :                                        HandleObject);
    3015           3 : static const VMFunction InitPropGetterSetterInfo =
    3016           6 :     FunctionInfo<InitPropGetterSetterFn>(InitGetterSetterOperation,
    3017             :                                          "InitPropGetterSetterOperation");
    3018             : 
    3019             : bool
    3020          24 : BaselineCompiler::emitInitPropGetterSetter()
    3021             : {
    3022          24 :     MOZ_ASSERT(JSOp(*pc) == JSOP_INITPROP_GETTER ||
    3023             :                JSOp(*pc) == JSOP_INITHIDDENPROP_GETTER ||
    3024             :                JSOp(*pc) == JSOP_INITPROP_SETTER ||
    3025             :                JSOp(*pc) == JSOP_INITHIDDENPROP_SETTER);
    3026             : 
    3027             :     // Keep values on the stack for the decompiler.
    3028          24 :     frame.syncStack(0);
    3029             : 
    3030          24 :     prepareVMCall();
    3031             : 
    3032          24 :     masm.extractObject(frame.addressOfStackValue(frame.peek(-1)), R0.scratchReg());
    3033          24 :     masm.extractObject(frame.addressOfStackValue(frame.peek(-2)), R1.scratchReg());
    3034             : 
    3035          24 :     pushArg(R0.scratchReg());
    3036          24 :     pushArg(ImmGCPtr(script->getName(pc)));
    3037          24 :     pushArg(R1.scratchReg());
    3038          24 :     pushArg(ImmPtr(pc));
    3039             : 
    3040          24 :     if (!callVM(InitPropGetterSetterInfo))
    3041           0 :         return false;
    3042             : 
    3043          24 :     frame.pop();
    3044          24 :     return true;
    3045             : }
    3046             : 
    3047             : bool
    3048          23 : BaselineCompiler::emit_JSOP_INITPROP_GETTER()
    3049             : {
    3050          23 :     return emitInitPropGetterSetter();
    3051             : }
    3052             : 
    3053             : bool
    3054           0 : BaselineCompiler::emit_JSOP_INITHIDDENPROP_GETTER()
    3055             : {
    3056           0 :     return emitInitPropGetterSetter();
    3057             : }
    3058             : 
    3059             : bool
    3060           1 : BaselineCompiler::emit_JSOP_INITPROP_SETTER()
    3061             : {
    3062           1 :     return emitInitPropGetterSetter();
    3063             : }
    3064             : 
    3065             : bool
    3066           0 : BaselineCompiler::emit_JSOP_INITHIDDENPROP_SETTER()
    3067             : {
    3068           0 :     return emitInitPropGetterSetter();
    3069             : }
    3070             : 
    3071             : typedef bool (*InitElemGetterSetterFn)(JSContext*, jsbytecode*, HandleObject, HandleValue,
    3072             :                                        HandleObject);
    3073           3 : static const VMFunction InitElemGetterSetterInfo =
    3074           6 :     FunctionInfo<InitElemGetterSetterFn>(InitGetterSetterOperation,
    3075             :                                          "InitElemGetterSetterOperation");
    3076             : 
    3077             : bool
    3078           0 : BaselineCompiler::emitInitElemGetterSetter()
    3079             : {
    3080           0 :     MOZ_ASSERT(JSOp(*pc) == JSOP_INITELEM_GETTER ||
    3081             :                JSOp(*pc) == JSOP_INITHIDDENELEM_GETTER ||
    3082             :                JSOp(*pc) == JSOP_INITELEM_SETTER ||
    3083             :                JSOp(*pc) == JSOP_INITHIDDENELEM_SETTER);
    3084             : 
    3085             :     // Load index and value in R0 and R1, but keep values on the stack for the
    3086             :     // decompiler.
    3087           0 :     frame.syncStack(0);
    3088           0 :     masm.loadValue(frame.addressOfStackValue(frame.peek(-2)), R0);
    3089           0 :     masm.extractObject(frame.addressOfStackValue(frame.peek(-1)), R1.scratchReg());
    3090             : 
    3091           0 :     prepareVMCall();
    3092             : 
    3093           0 :     pushArg(R1.scratchReg());
    3094           0 :     pushArg(R0);
    3095           0 :     masm.extractObject(frame.addressOfStackValue(frame.peek(-3)), R0.scratchReg());
    3096           0 :     pushArg(R0.scratchReg());
    3097           0 :     pushArg(ImmPtr(pc));
    3098             : 
    3099           0 :     if (!callVM(InitElemGetterSetterInfo))
    3100           0 :         return false;
    3101             : 
    3102           0 :     frame.popn(2);
    3103           0 :     return true;
    3104             : }
    3105             : 
    3106             : bool
    3107           0 : BaselineCompiler::emit_JSOP_INITELEM_GETTER()
    3108             : {
    3109           0 :     return emitInitElemGetterSetter();
    3110             : }
    3111             : 
    3112             : bool
    3113           0 : BaselineCompiler::emit_JSOP_INITHIDDENELEM_GETTER()
    3114             : {
    3115           0 :     return emitInitElemGetterSetter();
    3116             : }
    3117             : 
    3118             : bool
    3119           0 : BaselineCompiler::emit_JSOP_INITELEM_SETTER()
    3120             : {
    3121           0 :     return emitInitElemGetterSetter();
    3122             : }
    3123             : 
    3124             : bool
    3125           0 : BaselineCompiler::emit_JSOP_INITHIDDENELEM_SETTER()
    3126             : {
    3127           0 :     return emitInitElemGetterSetter();
    3128             : }
    3129             : 
    3130             : bool
    3131          31 : BaselineCompiler::emit_JSOP_INITELEM_INC()
    3132             : {
    3133             :     // Keep the object and rhs on the stack.
    3134          31 :     frame.syncStack(0);
    3135             : 
    3136             :     // Load object in R0, index in R1.
    3137          31 :     masm.loadValue(frame.addressOfStackValue(frame.peek(-3)), R0);
    3138          31 :     masm.loadValue(frame.addressOfStackValue(frame.peek(-2)), R1);
    3139             : 
    3140             :     // Call IC.
    3141          62 :     ICSetElem_Fallback::Compiler stubCompiler(cx);
    3142          31 :     if (!emitOpIC(stubCompiler.getStub(&stubSpace_)))
    3143           0 :         return false;
    3144             : 
    3145             :     // Pop the rhs
    3146          31 :     frame.pop();
    3147             : 
    3148             :     // Increment index
    3149          31 :     Address indexAddr = frame.addressOfStackValue(frame.peek(-1));
    3150             : #ifdef DEBUG
    3151          62 :     Label isInt32;
    3152          31 :     masm.branchTestInt32(Assembler::Equal, indexAddr, &isInt32);
    3153          31 :     masm.assumeUnreachable("INITELEM_INC index must be Int32");
    3154          31 :     masm.bind(&isInt32);
    3155             : #endif
    3156          31 :     masm.incrementInt32Value(indexAddr);
    3157          31 :     return true;
    3158             : }
    3159             : 
    3160             : bool
    3161        5535 : BaselineCompiler::emit_JSOP_GETLOCAL()
    3162             : {
    3163        5535 :     frame.pushLocal(GET_LOCALNO(pc));
    3164        5535 :     return true;
    3165             : }
    3166             : 
    3167             : bool
    3168        2821 : BaselineCompiler::emit_JSOP_SETLOCAL()
    3169             : {
    3170             :     // Ensure no other StackValue refers to the old value, for instance i + (i = 3).
    3171             :     // This also allows us to use R0 as scratch below.
    3172        2821 :     frame.syncStack(1);
    3173             : 
    3174        2821 :     uint32_t local = GET_LOCALNO(pc);
    3175        2821 :     storeValue(frame.peek(-1), frame.addressOfLocal(local), R0);
    3176        2821 :     return true;
    3177             : }
    3178             : 
    3179             : bool
    3180        2021 : BaselineCompiler::emitFormalArgAccess(uint32_t arg, bool get)
    3181             : {
    3182             :     // Fast path: the script does not use |arguments| or formals don't
    3183             :     // alias the arguments object.
    3184        2021 :     if (!script->argumentsAliasesFormals()) {
    3185        2021 :         if (get) {
    3186        1910 :             frame.pushArg(arg);
    3187             :         } else {
    3188             :             // See the comment in emit_JSOP_SETLOCAL.
    3189         111 :             frame.syncStack(1);
    3190         111 :             storeValue(frame.peek(-1), frame.addressOfArg(arg), R0);
    3191             :         }
    3192             : 
    3193        2021 :         return true;
    3194             :     }
    3195             : 
    3196             :     // Sync so that we can use R0.
    3197           0 :     frame.syncStack(0);
    3198             : 
    3199             :     // If the script is known to have an arguments object, we can just use it.
    3200             :     // Else, we *may* have an arguments object (because we can't invalidate
    3201             :     // when needsArgsObj becomes |true|), so we have to test HAS_ARGS_OBJ.
    3202           0 :     Label done;
    3203           0 :     if (!script->needsArgsObj()) {
    3204           0 :         Label hasArgsObj;
    3205           0 :         masm.branchTest32(Assembler::NonZero, frame.addressOfFlags(),
    3206           0 :                           Imm32(BaselineFrame::HAS_ARGS_OBJ), &hasArgsObj);
    3207           0 :         if (get)
    3208           0 :             masm.loadValue(frame.addressOfArg(arg), R0);
    3209             :         else
    3210           0 :             storeValue(frame.peek(-1), frame.addressOfArg(arg), R0);
    3211           0 :         masm.jump(&done);
    3212           0 :         masm.bind(&hasArgsObj);
    3213             :     }
    3214             : 
    3215             :     // Load the arguments object data vector.
    3216           0 :     Register reg = R2.scratchReg();
    3217           0 :     masm.loadPtr(Address(BaselineFrameReg, BaselineFrame::reverseOffsetOfArgsObj()), reg);
    3218           0 :     masm.loadPrivate(Address(reg, ArgumentsObject::getDataSlotOffset()), reg);
    3219             : 
    3220             :     // Load/store the argument.
    3221           0 :     Address argAddr(reg, ArgumentsData::offsetOfArgs() + arg * sizeof(Value));
    3222           0 :     if (get) {
    3223           0 :         masm.loadValue(argAddr, R0);
    3224           0 :         frame.push(R0);
    3225             :     } else {
    3226           0 :         masm.guardedCallPreBarrier(argAddr, MIRType::Value);
    3227           0 :         masm.loadValue(frame.addressOfStackValue(frame.peek(-1)), R0);
    3228           0 :         masm.storeValue(R0, argAddr);
    3229             : 
    3230           0 :         MOZ_ASSERT(frame.numUnsyncedSlots() == 0);
    3231             : 
    3232           0 :         Register temp = R1.scratchReg();
    3233             : 
    3234             :         // Reload the arguments object
    3235           0 :         Register reg = R2.scratchReg();
    3236           0 :         masm.loadPtr(Address(BaselineFrameReg, BaselineFrame::reverseOffsetOfArgsObj()), reg);
    3237             : 
    3238           0 :         Label skipBarrier;
    3239             : 
    3240           0 :         masm.branchPtrInNurseryChunk(Assembler::Equal, reg, temp, &skipBarrier);
    3241           0 :         masm.branchValueIsNurseryObject(Assembler::NotEqual, R0, temp, &skipBarrier);
    3242             : 
    3243           0 :         masm.call(&postBarrierSlot_);
    3244             : 
    3245           0 :         masm.bind(&skipBarrier);
    3246             :     }
    3247             : 
    3248           0 :     masm.bind(&done);
    3249           0 :     return true;
    3250             : }
    3251             : 
    3252             : bool
    3253        1910 : BaselineCompiler::emit_JSOP_GETARG()
    3254             : {
    3255        1910 :     uint32_t arg = GET_ARGNO(pc);
    3256        1910 :     return emitFormalArgAccess(arg, /* get = */ true);
    3257             : }
    3258             : 
    3259             : bool
    3260         111 : BaselineCompiler::emit_JSOP_SETARG()
    3261             : {
    3262             :     // Ionmonkey can't inline functions with SETARG with magic arguments.
    3263         111 :     if (!script->argsObjAliasesFormals() && script->argumentsAliasesFormals())
    3264           0 :         script->setUninlineable();
    3265             : 
    3266         111 :     modifiesArguments_ = true;
    3267             : 
    3268         111 :     uint32_t arg = GET_ARGNO(pc);
    3269         111 :     return emitFormalArgAccess(arg, /* get = */ false);
    3270             : }
    3271             : 
    3272             : bool
    3273          64 : BaselineCompiler::emit_JSOP_NEWTARGET()
    3274             : {
    3275          64 :     if (script->isForEval()) {
    3276           0 :         frame.pushEvalNewTarget();
    3277           0 :         return true;
    3278             :     }
    3279             : 
    3280          64 :     MOZ_ASSERT(function());
    3281          64 :     frame.syncStack(0);
    3282             : 
    3283          64 :     if (function()->isArrow()) {
    3284             :         // Arrow functions store their |new.target| value in an
    3285             :         // extended slot.
    3286           7 :         Register scratch = R0.scratchReg();
    3287           7 :         masm.loadFunctionFromCalleeToken(frame.addressOfCalleeToken(), scratch);
    3288           7 :         masm.loadValue(Address(scratch, FunctionExtended::offsetOfArrowNewTargetSlot()), R0);
    3289           7 :         frame.push(R0);
    3290           7 :         return true;
    3291             :     }
    3292             : 
    3293             :     // if (isConstructing()) push(argv[Max(numActualArgs, numFormalArgs)])
    3294         114 :     Label notConstructing, done;
    3295         114 :     masm.branchTestPtr(Assembler::Zero, frame.addressOfCalleeToken(),
    3296          57 :                        Imm32(CalleeToken_FunctionConstructing), &notConstructing);
    3297             : 
    3298          57 :     Register argvLen = R0.scratchReg();
    3299             : 
    3300          57 :     Address actualArgs(BaselineFrameReg, BaselineFrame::offsetOfNumActualArgs());
    3301          57 :     masm.loadPtr(actualArgs, argvLen);
    3302             : 
    3303         114 :     Label useNFormals;
    3304             : 
    3305         114 :     masm.branchPtr(Assembler::Below, argvLen, Imm32(function()->nargs()),
    3306          57 :                    &useNFormals);
    3307             : 
    3308             :     {
    3309          57 :         BaseValueIndex newTarget(BaselineFrameReg, argvLen, BaselineFrame::offsetOfArg(0));
    3310          57 :         masm.loadValue(newTarget, R0);
    3311          57 :         masm.jump(&done);
    3312             :     }
    3313             : 
    3314          57 :     masm.bind(&useNFormals);
    3315             : 
    3316             :     {
    3317             :         Address newTarget(BaselineFrameReg,
    3318          57 :                           BaselineFrame::offsetOfArg(0) + (function()->nargs() * sizeof(Value)));
    3319          57 :         masm.loadValue(newTarget, R0);
    3320          57 :         masm.jump(&done);
    3321             :     }
    3322             : 
    3323             :     // else push(undefined)
    3324          57 :     masm.bind(&notConstructing);
    3325          57 :     masm.moveValue(UndefinedValue(), R0);
    3326             : 
    3327          57 :     masm.bind(&done);
    3328          57 :     frame.push(R0);
    3329             : 
    3330          57 :     return true;
    3331             : }
    3332             : 
    3333             : typedef bool (*ThrowRuntimeLexicalErrorFn)(JSContext* cx, unsigned);
    3334           3 : static const VMFunction ThrowRuntimeLexicalErrorInfo =
    3335           6 :     FunctionInfo<ThrowRuntimeLexicalErrorFn>(jit::ThrowRuntimeLexicalError,
    3336             :                                              "ThrowRuntimeLexicalError");
    3337             : 
    3338             : bool
    3339           0 : BaselineCompiler::emitThrowConstAssignment()
    3340             : {
    3341           0 :     prepareVMCall();
    3342           0 :     pushArg(Imm32(JSMSG_BAD_CONST_ASSIGN));
    3343           0 :     return callVM(ThrowRuntimeLexicalErrorInfo);
    3344             : }
    3345             : 
    3346             : bool
    3347           0 : BaselineCompiler::emit_JSOP_THROWSETCONST()
    3348             : {
    3349           0 :     return emitThrowConstAssignment();
    3350             : }
    3351             : 
    3352             : bool
    3353           0 : BaselineCompiler::emit_JSOP_THROWSETALIASEDCONST()
    3354             : {
    3355           0 :     return emitThrowConstAssignment();
    3356             : }
    3357             : 
    3358             : bool
    3359           0 : BaselineCompiler::emit_JSOP_THROWSETCALLEE()
    3360             : {
    3361           0 :     return emitThrowConstAssignment();
    3362             : }
    3363             : 
    3364             : bool
    3365          83 : BaselineCompiler::emitUninitializedLexicalCheck(const ValueOperand& val)
    3366             : {
    3367         166 :     Label done;
    3368          83 :     masm.branchTestMagicValue(Assembler::NotEqual, val, JS_UNINITIALIZED_LEXICAL, &done);
    3369             : 
    3370          83 :     prepareVMCall();
    3371          83 :     pushArg(Imm32(JSMSG_UNINITIALIZED_LEXICAL));
    3372          83 :     if (!callVM(ThrowRuntimeLexicalErrorInfo))
    3373           0 :         return false;
    3374             : 
    3375          83 :     masm.bind(&done);
    3376          83 :     return true;
    3377             : }
    3378             : 
    3379             : bool
    3380           0 : BaselineCompiler::emit_JSOP_CHECKLEXICAL()
    3381             : {
    3382           0 :     frame.syncStack(0);
    3383           0 :     masm.loadValue(frame.addressOfLocal(GET_LOCALNO(pc)), R0);
    3384           0 :     return emitUninitializedLexicalCheck(R0);
    3385             : }
    3386             : 
    3387             : bool
    3388        1202 : BaselineCompiler::emit_JSOP_INITLEXICAL()
    3389             : {
    3390        1202 :     return emit_JSOP_SETLOCAL();
    3391             : }
    3392             : 
    3393             : bool
    3394          19 : BaselineCompiler::emit_JSOP_INITGLEXICAL()
    3395             : {
    3396          19 :     frame.popRegsAndSync(1);
    3397          19 :     frame.push(ObjectValue(script->global().lexicalEnvironment()));
    3398          19 :     frame.push(R0);
    3399          19 :     return emit_JSOP_SETPROP();
    3400             : }
    3401             : 
    3402             : bool
    3403          83 : BaselineCompiler::emit_JSOP_CHECKALIASEDLEXICAL()
    3404             : {
    3405          83 :     frame.syncStack(0);
    3406          83 :     masm.loadValue(getEnvironmentCoordinateAddress(R0.scratchReg()), R0);
    3407          83 :     return emitUninitializedLexicalCheck(R0);
    3408             : }
    3409             : 
    3410             : bool
    3411          88 : BaselineCompiler::emit_JSOP_INITALIASEDLEXICAL()
    3412             : {
    3413          88 :     return emit_JSOP_SETALIASEDVAR();
    3414             : }
    3415             : 
    3416             : bool
    3417         475 : BaselineCompiler::emit_JSOP_UNINITIALIZED()
    3418             : {
    3419         475 :     frame.push(MagicValue(JS_UNINITIALIZED_LEXICAL));
    3420         475 :     return true;
    3421             : }
    3422             : 
    3423             : bool
    3424        3507 : BaselineCompiler::emitCall()
    3425             : {
    3426        3507 :     MOZ_ASSERT(IsCallPC(pc));
    3427             : 
    3428        3507 :     bool construct = JSOp(*pc) == JSOP_NEW || JSOp(*pc) == JSOP_SUPERCALL;
    3429        3507 :     uint32_t argc = GET_ARGC(pc);
    3430             : 
    3431        3507 :     frame.syncStack(0);
    3432        3507 :     masm.move32(Imm32(argc), R0.scratchReg());
    3433             : 
    3434             :     // Call IC
    3435             :     ICCall_Fallback::Compiler stubCompiler(cx, /* isConstructing = */ construct,
    3436        7014 :                                            /* isSpread = */ false);
    3437        3507 :     if (!emitOpIC(stubCompiler.getStub(&stubSpace_)))
    3438           0 :         return false;
    3439             : 
    3440             :     // Update FrameInfo.
    3441        3507 :     frame.popn(2 + argc + construct);
    3442        3507 :     frame.push(R0);
    3443        3507 :     return true;
    3444             : }
    3445             : 
    3446             : bool
    3447          27 : BaselineCompiler::emitSpreadCall()
    3448             : {
    3449          27 :     MOZ_ASSERT(IsCallPC(pc));
    3450             : 
    3451          27 :     frame.syncStack(0);
    3452          27 :     masm.move32(Imm32(1), R0.scratchReg());
    3453             : 
    3454             :     // Call IC
    3455          27 :     bool construct = JSOp(*pc) == JSOP_SPREADNEW || JSOp(*pc) == JSOP_SPREADSUPERCALL;
    3456             :     ICCall_Fallback::Compiler stubCompiler(cx, /* isConstructing = */ construct,
    3457          54 :                                            /* isSpread = */ true);
    3458          27 :     if (!emitOpIC(stubCompiler.getStub(&stubSpace_)))
    3459           0 :         return false;
    3460             : 
    3461             :     // Update FrameInfo.
    3462          27 :     frame.popn(3 + construct);
    3463          27 :     frame.push(R0);
    3464          27 :     return true;
    3465             : }
    3466             : 
    3467             : bool
    3468        2251 : BaselineCompiler::emit_JSOP_CALL()
    3469             : {
    3470        2251 :     return emitCall();
    3471             : }
    3472             : 
    3473             : bool
    3474         923 : BaselineCompiler::emit_JSOP_CALL_IGNORES_RV()
    3475             : {
    3476         923 :     return emitCall();
    3477             : }
    3478             : 
    3479             : bool
    3480         166 : BaselineCompiler::emit_JSOP_CALLITER()
    3481             : {
    3482         166 :     return emitCall();
    3483             : }
    3484             : 
    3485             : bool
    3486         139 : BaselineCompiler::emit_JSOP_NEW()
    3487             : {
    3488         139 :     return emitCall();
    3489             : }
    3490             : 
    3491             : bool
    3492           1 : BaselineCompiler::emit_JSOP_SUPERCALL()
    3493             : {
    3494           1 :     return emitCall();
    3495             : }
    3496             : 
    3497             : bool
    3498           3 : BaselineCompiler::emit_JSOP_FUNCALL()
    3499             : {
    3500           3 :     return emitCall();
    3501             : }
    3502             : 
    3503             : bool
    3504          24 : BaselineCompiler::emit_JSOP_FUNAPPLY()
    3505             : {
    3506          24 :     return emitCall();
    3507             : }
    3508             : 
    3509             : bool
    3510           0 : BaselineCompiler::emit_JSOP_EVAL()
    3511             : {
    3512           0 :     return emitCall();
    3513             : }
    3514             : 
    3515             : bool
    3516           0 : BaselineCompiler::emit_JSOP_STRICTEVAL()
    3517             : {
    3518           0 :     return emitCall();
    3519             : }
    3520             : 
    3521             : bool
    3522          27 : BaselineCompiler::emit_JSOP_SPREADCALL()
    3523             : {
    3524          27 :     return emitSpreadCall();
    3525             : }
    3526             : 
    3527             : bool
    3528           0 : BaselineCompiler::emit_JSOP_SPREADNEW()
    3529             : {
    3530           0 :     return emitSpreadCall();
    3531             : }
    3532             : 
    3533             : bool
    3534           0 : BaselineCompiler::emit_JSOP_SPREADSUPERCALL()
    3535             : {
    3536           0 :     return emitSpreadCall();
    3537             : }
    3538             : 
    3539             : bool
    3540           0 : BaselineCompiler::emit_JSOP_SPREADEVAL()
    3541             : {
    3542           0 :     return emitSpreadCall();
    3543             : }
    3544             : 
    3545             : bool
    3546           0 : BaselineCompiler::emit_JSOP_STRICTSPREADEVAL()
    3547             : {
    3548           0 :     return emitSpreadCall();
    3549             : }
    3550             : 
    3551             : typedef bool (*OptimizeSpreadCallFn)(JSContext*, HandleValue, bool*);
    3552           3 : static const VMFunction OptimizeSpreadCallInfo =
    3553           6 :     FunctionInfo<OptimizeSpreadCallFn>(OptimizeSpreadCall, "OptimizeSpreadCall");
    3554             : 
    3555             : bool
    3556           0 : BaselineCompiler::emit_JSOP_OPTIMIZE_SPREADCALL()
    3557             : {
    3558           0 :     frame.syncStack(0);
    3559           0 :     masm.loadValue(frame.addressOfStackValue(frame.peek(-1)), R0);
    3560             : 
    3561           0 :     prepareVMCall();
    3562           0 :     pushArg(R0);
    3563             : 
    3564           0 :     if (!callVM(OptimizeSpreadCallInfo))
    3565           0 :         return false;
    3566             : 
    3567           0 :     masm.boxNonDouble(JSVAL_TYPE_BOOLEAN, ReturnReg, R0);
    3568           0 :     frame.push(R0);
    3569           0 :     return true;
    3570             : }
    3571             : 
    3572             : typedef bool (*ImplicitThisFn)(JSContext*, HandleObject, HandlePropertyName,
    3573             :                                MutableHandleValue);
    3574           3 : static const VMFunction ImplicitThisInfo =
    3575           6 :     FunctionInfo<ImplicitThisFn>(ImplicitThisOperation, "ImplicitThisOperation");
    3576             : 
    3577             : bool
    3578          24 : BaselineCompiler::emit_JSOP_IMPLICITTHIS()
    3579             : {
    3580          24 :     frame.syncStack(0);
    3581          24 :     masm.loadPtr(frame.addressOfEnvironmentChain(), R0.scratchReg());
    3582             : 
    3583          24 :     prepareVMCall();
    3584             : 
    3585          24 :     pushArg(ImmGCPtr(script->getName(pc)));
    3586          24 :     pushArg(R0.scratchReg());
    3587             : 
    3588          24 :     if (!callVM(ImplicitThisInfo))
    3589           0 :         return false;
    3590             : 
    3591          24 :     frame.push(R0);
    3592          24 :     return true;
    3593             : }
    3594             : 
    3595             : bool
    3596         120 : BaselineCompiler::emit_JSOP_GIMPLICITTHIS()
    3597             : {
    3598         120 :     if (!script->hasNonSyntacticScope()) {
    3599          96 :         frame.push(UndefinedValue());
    3600          96 :         return true;
    3601             :     }
    3602             : 
    3603          24 :     return emit_JSOP_IMPLICITTHIS();
    3604             : }
    3605             : 
    3606             : bool
    3607          10 : BaselineCompiler::emit_JSOP_INSTANCEOF()
    3608             : {
    3609          10 :     frame.popRegsAndSync(2);
    3610             : 
    3611          20 :     ICInstanceOf_Fallback::Compiler stubCompiler(cx);
    3612          10 :     if (!emitOpIC(stubCompiler.getStub(&stubSpace_)))
    3613           0 :         return false;
    3614             : 
    3615          10 :     frame.push(R0);
    3616          10 :     return true;
    3617             : }
    3618             : 
    3619             : bool
    3620         101 : BaselineCompiler::emit_JSOP_TYPEOF()
    3621             : {
    3622         101 :     frame.popRegsAndSync(1);
    3623             : 
    3624         202 :     ICTypeOf_Fallback::Compiler stubCompiler(cx);
    3625         101 :     if (!emitOpIC(stubCompiler.getStub(&stubSpace_)))
    3626           0 :         return false;
    3627             : 
    3628         101 :     frame.push(R0);
    3629         101 :     return true;
    3630             : }
    3631             : 
    3632             : bool
    3633          19 : BaselineCompiler::emit_JSOP_TYPEOFEXPR()
    3634             : {
    3635          19 :     return emit_JSOP_TYPEOF();
    3636             : }
    3637             : 
    3638             : typedef bool (*ThrowMsgFn)(JSContext*, const unsigned);
    3639           3 : static const VMFunction ThrowMsgInfo =
    3640           6 :     FunctionInfo<ThrowMsgFn>(js::ThrowMsgOperation, "ThrowMsgOperation");
    3641             : 
    3642             : bool
    3643           2 : BaselineCompiler::emit_JSOP_THROWMSG()
    3644             : {
    3645           2 :     prepareVMCall();
    3646           2 :     pushArg(Imm32(GET_UINT16(pc)));
    3647           2 :     return callVM(ThrowMsgInfo);
    3648             : }
    3649             : 
    3650             : typedef bool (*ThrowFn)(JSContext*, HandleValue);
    3651           3 : static const VMFunction ThrowInfo = FunctionInfo<ThrowFn>(js::Throw, "Throw");
    3652             : 
    3653             : bool
    3654         169 : BaselineCompiler::emit_JSOP_THROW()
    3655             : {
    3656             :     // Keep value to throw in R0.
    3657         169 :     frame.popRegsAndSync(1);
    3658             : 
    3659         169 :     prepareVMCall();
    3660         169 :     pushArg(R0);
    3661             : 
    3662         169 :     return callVM(ThrowInfo);
    3663             : }
    3664             : 
    3665             : typedef bool (*ThrowingFn)(JSContext*, HandleValue);
    3666           3 : static const VMFunction ThrowingInfo =
    3667           6 :     FunctionInfo<ThrowingFn>(js::ThrowingOperation, "ThrowingOperation");
    3668             : 
    3669             : bool
    3670           0 : BaselineCompiler::emit_JSOP_THROWING()
    3671             : {
    3672             :     // Keep value to throw in R0.
    3673           0 :     frame.popRegsAndSync(1);
    3674             : 
    3675           0 :     prepareVMCall();
    3676           0 :     pushArg(R0);
    3677             : 
    3678           0 :     return callVM(ThrowingInfo);
    3679             : }
    3680             : 
    3681             : bool
    3682         264 : BaselineCompiler::emit_JSOP_TRY()
    3683             : {
    3684         264 :     if (!emit_JSOP_JUMPTARGET())
    3685           0 :         return false;
    3686             : 
    3687             :     // Ionmonkey can't inline function with JSOP_TRY.
    3688         264 :     script->setUninlineable();
    3689         264 :     return true;
    3690             : }
    3691             : 
    3692             : bool
    3693          12 : BaselineCompiler::emit_JSOP_FINALLY()
    3694             : {
    3695             :     // JSOP_FINALLY has a def count of 2, but these values are already on the
    3696             :     // stack (they're pushed by JSOP_GOSUB). Update the compiler's stack state.
    3697          12 :     frame.setStackDepth(frame.stackDepth() + 2);
    3698             : 
    3699             :     // To match the interpreter, emit an interrupt check at the start of the
    3700             :     // finally block.
    3701          12 :     return emitInterruptCheck();
    3702             : }
    3703             : 
    3704             : bool
    3705           5 : BaselineCompiler::emit_JSOP_GOSUB()
    3706             : {
    3707             :     // Push |false| so that RETSUB knows the value on top of the
    3708             :     // stack is not an exception but the offset to the op following
    3709             :     // this GOSUB.
    3710           5 :     frame.push(BooleanValue(false));
    3711             : 
    3712           5 :     int32_t nextOffset = script->pcToOffset(GetNextPc(pc));
    3713           5 :     frame.push(Int32Value(nextOffset));
    3714             : 
    3715             :     // Jump to the finally block.
    3716           5 :     frame.syncStack(0);
    3717           5 :     jsbytecode* target = pc + GET_JUMP_OFFSET(pc);
    3718           5 :     masm.jump(labelOf(target));
    3719           5 :     return true;
    3720             : }
    3721             : 
    3722             : bool
    3723          12 : BaselineCompiler::emit_JSOP_RETSUB()
    3724             : {
    3725          12 :     frame.popRegsAndSync(2);
    3726             : 
    3727          24 :     ICRetSub_Fallback::Compiler stubCompiler(cx);
    3728          24 :     return emitOpIC(stubCompiler.getStub(&stubSpace_));
    3729             : }
    3730             : 
    3731             : typedef bool (*PushLexicalEnvFn)(JSContext*, BaselineFrame*, Handle<LexicalScope*>);
    3732           3 : static const VMFunction PushLexicalEnvInfo =
    3733           6 :     FunctionInfo<PushLexicalEnvFn>(jit::PushLexicalEnv, "PushLexicalEnv");
    3734             : 
    3735             : bool
    3736          48 : BaselineCompiler::emit_JSOP_PUSHLEXICALENV()
    3737             : {
    3738          48 :     LexicalScope& scope = script->getScope(pc)->as<LexicalScope>();
    3739             : 
    3740             :     // Call a stub to push the block on the block chain.
    3741          48 :     prepareVMCall();
    3742          48 :     masm.loadBaselineFramePtr(BaselineFrameReg, R0.scratchReg());
    3743             : 
    3744          48 :     pushArg(ImmGCPtr(&scope));
    3745          48 :     pushArg(R0.scratchReg());
    3746             : 
    3747          48 :     return callVM(PushLexicalEnvInfo);
    3748             : }
    3749             : 
    3750             : typedef bool (*PopLexicalEnvFn)(JSContext*, BaselineFrame*);
    3751           3 : static const VMFunction PopLexicalEnvInfo =
    3752           6 :     FunctionInfo<PopLexicalEnvFn>(jit::PopLexicalEnv, "PopLexicalEnv");
    3753             : 
    3754             : typedef bool (*DebugLeaveThenPopLexicalEnvFn)(JSContext*, BaselineFrame*, jsbytecode*);
    3755           3 : static const VMFunction DebugLeaveThenPopLexicalEnvInfo =
    3756           6 :     FunctionInfo<DebugLeaveThenPopLexicalEnvFn>(jit::DebugLeaveThenPopLexicalEnv,
    3757             :                                                 "DebugLeaveThenPopLexicalEnv");
    3758             : 
    3759             : bool
    3760          57 : BaselineCompiler::emit_JSOP_POPLEXICALENV()
    3761             : {
    3762          57 :     prepareVMCall();
    3763             : 
    3764          57 :     masm.loadBaselineFramePtr(BaselineFrameReg, R0.scratchReg());
    3765             : 
    3766          57 :     if (compileDebugInstrumentation_) {
    3767           0 :         pushArg(ImmPtr(pc));
    3768           0 :         pushArg(R0.scratchReg());
    3769           0 :         return callVM(DebugLeaveThenPopLexicalEnvInfo);
    3770             :     }
    3771             : 
    3772          57 :     pushArg(R0.scratchReg());
    3773          57 :     return callVM(PopLexicalEnvInfo);
    3774             : }
    3775             : 
    3776             : typedef bool (*FreshenLexicalEnvFn)(JSContext*, BaselineFrame*);
    3777           3 : static const VMFunction FreshenLexicalEnvInfo =
    3778           6 :     FunctionInfo<FreshenLexicalEnvFn>(jit::FreshenLexicalEnv, "FreshenLexicalEnv");
    3779             : 
    3780             : typedef bool (*DebugLeaveThenFreshenLexicalEnvFn)(JSContext*, BaselineFrame*, jsbytecode*);
    3781           3 : static const VMFunction DebugLeaveThenFreshenLexicalEnvInfo =
    3782           6 :     FunctionInfo<DebugLeaveThenFreshenLexicalEnvFn>(jit::DebugLeaveThenFreshenLexicalEnv,
    3783             :                                                     "DebugLeaveThenFreshenLexicalEnv");
    3784             : 
    3785             : bool
    3786           0 : BaselineCompiler::emit_JSOP_FRESHENLEXICALENV()
    3787             : {
    3788           0 :     prepareVMCall();
    3789             : 
    3790           0 :     masm.loadBaselineFramePtr(BaselineFrameReg, R0.scratchReg());
    3791             : 
    3792           0 :     if (compileDebugInstrumentation_) {
    3793           0 :         pushArg(ImmPtr(pc));
    3794           0 :         pushArg(R0.scratchReg());
    3795           0 :         return callVM(DebugLeaveThenFreshenLexicalEnvInfo);
    3796             :     }
    3797             : 
    3798           0 :     pushArg(R0.scratchReg());
    3799           0 :     return callVM(FreshenLexicalEnvInfo);
    3800             : }
    3801             : 
    3802             : 
    3803             : typedef bool (*RecreateLexicalEnvFn)(JSContext*, BaselineFrame*);
    3804           3 : static const VMFunction RecreateLexicalEnvInfo =
    3805           6 :     FunctionInfo<RecreateLexicalEnvFn>(jit::RecreateLexicalEnv, "RecreateLexicalEnv");
    3806             : 
    3807             : typedef bool (*DebugLeaveThenRecreateLexicalEnvFn)(JSContext*, BaselineFrame*, jsbytecode*);
    3808           3 : static const VMFunction DebugLeaveThenRecreateLexicalEnvInfo =
    3809           6 :     FunctionInfo<DebugLeaveThenRecreateLexicalEnvFn>(jit::DebugLeaveThenRecreateLexicalEnv,
    3810             :                                                      "DebugLeaveThenRecreateLexicalEnv");
    3811             : 
    3812             : bool
    3813          14 : BaselineCompiler::emit_JSOP_RECREATELEXICALENV()
    3814             : {
    3815          14 :     prepareVMCall();
    3816             : 
    3817          14 :     masm.loadBaselineFramePtr(BaselineFrameReg, R0.scratchReg());
    3818             : 
    3819          14 :     if (compileDebugInstrumentation_) {
    3820           0 :         pushArg(ImmPtr(pc));
    3821           0 :         pushArg(R0.scratchReg());
    3822           0 :         return callVM(DebugLeaveThenRecreateLexicalEnvInfo);
    3823             :     }
    3824             : 
    3825          14 :     pushArg(R0.scratchReg());
    3826          14 :     return callVM(RecreateLexicalEnvInfo);
    3827             : }
    3828             : 
    3829             : typedef bool (*DebugLeaveLexicalEnvFn)(JSContext*, BaselineFrame*, jsbytecode*);
    3830           3 : static const VMFunction DebugLeaveLexicalEnvInfo =
    3831           6 :     FunctionInfo<DebugLeaveLexicalEnvFn>(jit::DebugLeaveLexicalEnv, "DebugLeaveLexicalEnv");
    3832             : 
    3833             : bool
    3834         412 : BaselineCompiler::emit_JSOP_DEBUGLEAVELEXICALENV()
    3835             : {
    3836         412 :     if (!compileDebugInstrumentation_)
    3837         412 :         return true;
    3838             : 
    3839           0 :     prepareVMCall();
    3840           0 :     masm.loadBaselineFramePtr(BaselineFrameReg, R0.scratchReg());
    3841           0 :     pushArg(ImmPtr(pc));
    3842           0 :     pushArg(R0.scratchReg());
    3843             : 
    3844           0 :     return callVM(DebugLeaveLexicalEnvInfo);
    3845             : }
    3846             : 
    3847             : typedef bool (*PushVarEnvFn)(JSContext*, BaselineFrame*, HandleScope);
    3848           3 : static const VMFunction PushVarEnvInfo =
    3849           6 :     FunctionInfo<PushVarEnvFn>(jit::PushVarEnv, "PushVarEnv");
    3850             : 
    3851             : bool
    3852           1 : BaselineCompiler::emit_JSOP_PUSHVARENV()
    3853             : {
    3854           1 :     prepareVMCall();
    3855           1 :     masm.loadBaselineFramePtr(BaselineFrameReg, R0.scratchReg());
    3856           1 :     pushArg(ImmGCPtr(script->getScope(pc)));
    3857           1 :     pushArg(R0.scratchReg());
    3858             : 
    3859           1 :     return callVM(PushVarEnvInfo);
    3860             : }
    3861             : 
    3862             : typedef bool (*PopVarEnvFn)(JSContext*, BaselineFrame*);
    3863           3 : static const VMFunction PopVarEnvInfo =
    3864           6 :     FunctionInfo<PopVarEnvFn>(jit::PopVarEnv, "PopVarEnv");
    3865             : 
    3866             : bool
    3867           0 : BaselineCompiler::emit_JSOP_POPVARENV()
    3868             : {
    3869           0 :     prepareVMCall();
    3870           0 :     masm.loadBaselineFramePtr(BaselineFrameReg, R0.scratchReg());
    3871           0 :     pushArg(R0.scratchReg());
    3872             : 
    3873           0 :     return callVM(PopVarEnvInfo);
    3874             : }
    3875             : 
    3876             : typedef bool (*EnterWithFn)(JSContext*, BaselineFrame*, HandleValue, Handle<WithScope*>);
    3877           3 : static const VMFunction EnterWithInfo =
    3878           6 :     FunctionInfo<EnterWithFn>(jit::EnterWith, "EnterWith");
    3879             : 
    3880             : bool
    3881           0 : BaselineCompiler::emit_JSOP_ENTERWITH()
    3882             : {
    3883           0 :     WithScope& withScope = script->getScope(pc)->as<WithScope>();
    3884             : 
    3885             :     // Pop "with" object to R0.
    3886           0 :     frame.popRegsAndSync(1);
    3887             : 
    3888             :     // Call a stub to push the object onto the scope chain.
    3889           0 :     prepareVMCall();
    3890           0 :     masm.loadBaselineFramePtr(BaselineFrameReg, R1.scratchReg());
    3891             : 
    3892           0 :     pushArg(ImmGCPtr(&withScope));
    3893           0 :     pushArg(R0);
    3894           0 :     pushArg(R1.scratchReg());
    3895             : 
    3896           0 :     return callVM(EnterWithInfo);
    3897             : }
    3898             : 
    3899             : typedef bool (*LeaveWithFn)(JSContext*, BaselineFrame*);
    3900           3 : static const VMFunction LeaveWithInfo =
    3901           6 :     FunctionInfo<LeaveWithFn>(jit::LeaveWith, "LeaveWith");
    3902             : 
    3903             : bool
    3904           0 : BaselineCompiler::emit_JSOP_LEAVEWITH()
    3905             : {
    3906             :     // Call a stub to pop the with object from the scope chain.
    3907           0 :     prepareVMCall();
    3908             : 
    3909           0 :     masm.loadBaselineFramePtr(BaselineFrameReg, R0.scratchReg());
    3910           0 :     pushArg(R0.scratchReg());
    3911             : 
    3912           0 :     return callVM(LeaveWithInfo);
    3913             : }
    3914             : 
    3915             : typedef bool (*GetAndClearExceptionFn)(JSContext*, MutableHandleValue);
    3916           3 : static const VMFunction GetAndClearExceptionInfo =
    3917           6 :     FunctionInfo<GetAndClearExceptionFn>(GetAndClearException, "GetAndClearException");
    3918             : 
    3919             : bool
    3920         260 : BaselineCompiler::emit_JSOP_EXCEPTION()
    3921             : {
    3922         260 :     prepareVMCall();
    3923             : 
    3924         260 :     if (!callVM(GetAndClearExceptionInfo))
    3925           0 :         return false;
    3926             : 
    3927         260 :     frame.push(R0);
    3928         260 :     return true;
    3929             : }
    3930             : 
    3931             : typedef bool (*OnDebuggerStatementFn)(JSContext*, BaselineFrame*, jsbytecode* pc, bool*);
    3932           3 : static const VMFunction OnDebuggerStatementInfo =
    3933           6 :     FunctionInfo<OnDebuggerStatementFn>(jit::OnDebuggerStatement, "OnDebuggerStatement");
    3934             : 
    3935             : bool
    3936           0 : BaselineCompiler::emit_JSOP_DEBUGGER()
    3937             : {
    3938           0 :     prepareVMCall();
    3939           0 :     pushArg(ImmPtr(pc));
    3940             : 
    3941           0 :     frame.assertSyncedStack();
    3942           0 :     masm.loadBaselineFramePtr(BaselineFrameReg, R0.scratchReg());
    3943           0 :     pushArg(R0.scratchReg());
    3944             : 
    3945           0 :     if (!callVM(OnDebuggerStatementInfo))
    3946           0 :         return false;
    3947             : 
    3948             :     // If the stub returns |true|, return the frame's return value.
    3949           0 :     Label done;
    3950           0 :     masm.branchTest32(Assembler::Zero, ReturnReg, ReturnReg, &done);
    3951             :     {
    3952           0 :         masm.loadValue(frame.addressOfReturnValue(), JSReturnOperand);
    3953           0 :         masm.jump(&return_);
    3954             :     }
    3955           0 :     masm.bind(&done);
    3956           0 :     return true;
    3957             : }
    3958             : 
    3959             : typedef bool (*DebugEpilogueFn)(JSContext*, BaselineFrame*, jsbytecode*);
    3960           3 : static const VMFunction DebugEpilogueInfo =
    3961           6 :     FunctionInfo<DebugEpilogueFn>(jit::DebugEpilogueOnBaselineReturn,
    3962             :                                   "DebugEpilogueOnBaselineReturn");
    3963             : 
    3964             : bool
    3965        1130 : BaselineCompiler::emitReturn()
    3966             : {
    3967        1130 :     if (compileDebugInstrumentation_) {
    3968             :         // Move return value into the frame's rval slot.
    3969           0 :         masm.storeValue(JSReturnOperand, frame.addressOfReturnValue());
    3970           0 :         masm.or32(Imm32(BaselineFrame::HAS_RVAL), frame.addressOfFlags());
    3971             : 
    3972             :         // Load BaselineFrame pointer in R0.
    3973           0 :         frame.syncStack(0);
    3974           0 :         masm.loadBaselineFramePtr(BaselineFrameReg, R0.scratchReg());
    3975             : 
    3976           0 :         prepareVMCall();
    3977           0 :         pushArg(ImmPtr(pc));
    3978           0 :         pushArg(R0.scratchReg());
    3979           0 :         if (!callVM(DebugEpilogueInfo))
    3980           0 :             return false;
    3981             : 
    3982             :         // Fix up the fake ICEntry appended by callVM for on-stack recompilation.
    3983           0 :         icEntries_.back().setFakeKind(ICEntry::Kind_DebugEpilogue);
    3984             : 
    3985           0 :         masm.loadValue(frame.addressOfReturnValue(), JSReturnOperand);
    3986             :     }
    3987             : 
    3988             :     // Only emit the jump if this JSOP_RETRVAL is not the last instruction.
    3989             :     // Not needed for last instruction, because last instruction flows
    3990             :     // into return label.
    3991        1130 :     if (pc + GetBytecodeLength(pc) < script->codeEnd())
    3992         958 :         masm.jump(&return_);
    3993             : 
    3994        1130 :     return true;
    3995             : }
    3996             : 
    3997             : bool
    3998         816 : BaselineCompiler::emit_JSOP_RETURN()
    3999             : {
    4000         816 :     MOZ_ASSERT(frame.stackDepth() == 1);
    4001             : 
    4002         816 :     frame.popValue(JSReturnOperand);
    4003         816 :     return emitReturn();
    4004             : }
    4005             : 
    4006             : void
    4007           7 : BaselineCompiler::emitLoadReturnValue(ValueOperand val)
    4008             : {
    4009          14 :     Label done, noRval;
    4010          14 :     masm.branchTest32(Assembler::Zero, frame.addressOfFlags(),
    4011           7 :                       Imm32(BaselineFrame::HAS_RVAL), &noRval);
    4012           7 :     masm.loadValue(frame.addressOfReturnValue(), val);
    4013           7 :     masm.jump(&done);
    4014             : 
    4015           7 :     masm.bind(&noRval);
    4016           7 :     masm.moveValue(UndefinedValue(), val);
    4017             : 
    4018           7 :     masm.bind(&done);
    4019           7 : }
    4020             : 
    4021             : bool
    4022         290 : BaselineCompiler::emit_JSOP_RETRVAL()
    4023             : {
    4024         290 :     MOZ_ASSERT(frame.stackDepth() == 0);
    4025             : 
    4026         290 :     masm.moveValue(UndefinedValue(), JSReturnOperand);
    4027             : 
    4028         290 :     if (!script->noScriptRval()) {
    4029             :         // Return the value in the return value slot, if any.
    4030         570 :         Label done;
    4031         285 :         Address flags = frame.addressOfFlags();
    4032         285 :         masm.branchTest32(Assembler::Zero, flags, Imm32(BaselineFrame::HAS_RVAL), &done);
    4033         285 :         masm.loadValue(frame.addressOfReturnValue(), JSReturnOperand);
    4034         285 :         masm.bind(&done);
    4035             :     }
    4036             : 
    4037         290 :     return emitReturn();
    4038             : }
    4039             : 
    4040             : typedef bool (*ToIdFn)(JSContext*, HandleScript, jsbytecode*, HandleValue, MutableHandleValue);
    4041           3 : static const VMFunction ToIdInfo = FunctionInfo<ToIdFn>(js::ToIdOperation, "ToIdOperation");
    4042             : 
    4043             : bool
    4044           1 : BaselineCompiler::emit_JSOP_TOID()
    4045             : {
    4046             :     // Load index in R0, but keep values on the stack for the decompiler.
    4047           1 :     frame.syncStack(0);
    4048           1 :     masm.loadValue(frame.addressOfStackValue(frame.peek(-1)), R0);
    4049             : 
    4050             :     // No-op if index is int32.
    4051           2 :     Label done;
    4052           1 :     masm.branchTestInt32(Assembler::Equal, R0, &done);
    4053             : 
    4054           1 :     prepareVMCall();
    4055             : 
    4056           1 :     pushArg(R0);
    4057           1 :     pushArg(ImmPtr(pc));
    4058           1 :     pushArg(ImmGCPtr(script));
    4059             : 
    4060           1 :     if (!callVM(ToIdInfo))
    4061           0 :         return false;
    4062             : 
    4063           1 :     masm.bind(&done);
    4064           1 :     frame.pop(); // Pop index.
    4065           1 :     frame.push(R0);
    4066           1 :     return true;
    4067             : }
    4068             : 
    4069             : typedef JSObject* (*ToAsyncFn)(JSContext*, HandleFunction);
    4070           3 : static const VMFunction ToAsyncInfo = FunctionInfo<ToAsyncFn>(js::WrapAsyncFunction, "ToAsync");
    4071             : 
    4072             : bool
    4073           4 : BaselineCompiler::emit_JSOP_TOASYNC()
    4074             : {
    4075           4 :     frame.syncStack(0);
    4076           4 :     masm.unboxObject(frame.addressOfStackValue(frame.peek(-1)), R0.scratchReg());
    4077             : 
    4078           4 :     prepareVMCall();
    4079           4 :     pushArg(R0.scratchReg());
    4080             : 
    4081           4 :     if (!callVM(ToAsyncInfo))
    4082           0 :         return false;
    4083             : 
    4084           4 :     masm.tagValue(JSVAL_TYPE_OBJECT, ReturnReg, R0);
    4085           4 :     frame.pop();
    4086           4 :     frame.push(R0);
    4087           4 :     return true;
    4088             : }
    4089             : 
    4090             : typedef JSObject* (*ToAsyncGenFn)(JSContext*, HandleFunction);
    4091           3 : static const VMFunction ToAsyncGenInfo =
    4092           6 :     FunctionInfo<ToAsyncGenFn>(js::WrapAsyncGenerator, "ToAsyncGen");
    4093             : 
    4094             : bool
    4095           0 : BaselineCompiler::emit_JSOP_TOASYNCGEN()
    4096             : {
    4097           0 :     frame.syncStack(0);
    4098           0 :     masm.unboxObject(frame.addressOfStackValue(frame.peek(-1)), R0.scratchReg());
    4099             : 
    4100           0 :     prepareVMCall();
    4101           0 :     pushArg(R0.scratchReg());
    4102             : 
    4103           0 :     if (!callVM(ToAsyncGenInfo))
    4104           0 :         return false;
    4105             : 
    4106           0 :     masm.tagValue(JSVAL_TYPE_OBJECT, ReturnReg, R0);
    4107           0 :     frame.pop();
    4108           0 :     frame.push(R0);
    4109           0 :     return true;
    4110             : }
    4111             : 
    4112             : typedef JSObject* (*ToAsyncIterFn)(JSContext*, HandleObject);
    4113           3 : static const VMFunction ToAsyncIterInfo =
    4114           6 :     FunctionInfo<ToAsyncIterFn>(js::CreateAsyncFromSyncIterator, "ToAsyncIter");
    4115             : 
    4116             : bool
    4117           0 : BaselineCompiler::emit_JSOP_TOASYNCITER()
    4118             : {
    4119           0 :     frame.syncStack(0);
    4120           0 :     masm.unboxObject(frame.addressOfStackValue(frame.peek(-1)), R0.scratchReg());
    4121             : 
    4122           0 :     prepareVMCall();
    4123           0 :     pushArg(R0.scratchReg());
    4124             : 
    4125           0 :     if (!callVM(ToAsyncIterInfo))
    4126           0 :         return false;
    4127             : 
    4128           0 :     masm.tagValue(JSVAL_TYPE_OBJECT, ReturnReg, R0);
    4129           0 :     frame.pop();
    4130           0 :     frame.push(R0);
    4131           0 :     return true;
    4132             : }
    4133             : 
    4134             : typedef bool (*ThrowObjectCoercibleFn)(JSContext*, HandleValue);
    4135           3 : static const VMFunction ThrowObjectCoercibleInfo =
    4136           6 :     FunctionInfo<ThrowObjectCoercibleFn>(ThrowObjectCoercible, "ThrowObjectCoercible");
    4137             : 
    4138             : bool
    4139          17 : BaselineCompiler::emit_JSOP_CHECKOBJCOERCIBLE()
    4140             : {
    4141          17 :     frame.syncStack(0);
    4142          17 :     masm.loadValue(frame.addressOfStackValue(frame.peek(-1)), R0);
    4143             : 
    4144          34 :     Label fail, done;
    4145             : 
    4146          17 :     masm.branchTestUndefined(Assembler::Equal, R0, &fail);
    4147          17 :     masm.branchTestNull(Assembler::NotEqual, R0, &done);
    4148             : 
    4149          17 :     masm.bind(&fail);
    4150          17 :     prepareVMCall();
    4151             : 
    4152          17 :     pushArg(R0);
    4153             : 
    4154          17 :     if (!callVM(ThrowObjectCoercibleInfo))
    4155           0 :         return false;
    4156             : 
    4157          17 :     masm.bind(&done);
    4158          17 :     return true;
    4159             : }
    4160             : 
    4161             : typedef JSString* (*ToStringFn)(JSContext*, HandleValue);
    4162           3 : static const VMFunction ToStringInfo = FunctionInfo<ToStringFn>(ToStringSlow, "ToStringSlow");
    4163             : 
    4164             : bool
    4165          21 : BaselineCompiler::emit_JSOP_TOSTRING()
    4166             : {
    4167             :     // Keep top stack value in R0.
    4168          21 :     frame.popRegsAndSync(1);
    4169             : 
    4170             :     // Inline path for string.
    4171          42 :     Label done;
    4172          21 :     masm.branchTestString(Assembler::Equal, R0, &done);
    4173             : 
    4174          21 :     prepareVMCall();
    4175             : 
    4176          21 :     pushArg(R0);
    4177             : 
    4178             :     // Call ToStringSlow which doesn't handle string inputs.
    4179          21 :     if (!callVM(ToStringInfo))
    4180           0 :         return false;
    4181             : 
    4182          21 :     masm.tagValue(JSVAL_TYPE_STRING, ReturnReg, R0);
    4183             : 
    4184          21 :     masm.bind(&done);
    4185          21 :     frame.push(R0);
    4186          21 :     return true;
    4187             : }
    4188             : 
    4189             : bool
    4190          11 : BaselineCompiler::emit_JSOP_TABLESWITCH()
    4191             : {
    4192          11 :     frame.popRegsAndSync(1);
    4193             : 
    4194             :     // Call IC.
    4195          22 :     ICTableSwitch::Compiler compiler(cx, pc);
    4196          22 :     return emitOpIC(compiler.getStub(&stubSpace_));
    4197             : }
    4198             : 
    4199             : bool
    4200          20 : BaselineCompiler::emit_JSOP_ITER()
    4201             : {
    4202          20 :     frame.popRegsAndSync(1);
    4203             : 
    4204          40 :     ICIteratorNew_Fallback::Compiler compiler(cx);
    4205          20 :     if (!emitOpIC(compiler.getStub(&stubSpace_)))
    4206           0 :         return false;
    4207             : 
    4208          20 :     frame.push(R0);
    4209          20 :     return true;
    4210             : }
    4211             : 
    4212             : bool
    4213          20 : BaselineCompiler::emit_JSOP_MOREITER()
    4214             : {
    4215          20 :     frame.syncStack(0);
    4216          20 :     masm.loadValue(frame.addressOfStackValue(frame.peek(-1)), R0);
    4217             : 
    4218          40 :     ICIteratorMore_Fallback::Compiler compiler(cx);
    4219          20 :     if (!emitOpIC(compiler.getStub(&stubSpace_)))
    4220           0 :         return false;
    4221             : 
    4222          20 :     frame.push(R0);
    4223          20 :     return true;
    4224             : }
    4225             : 
    4226             : bool
    4227          28 : BaselineCompiler::emitIsMagicValue()
    4228             : {
    4229          28 :     frame.syncStack(0);
    4230             : 
    4231          56 :     Label isMagic, done;
    4232          56 :     masm.branchTestMagic(Assembler::Equal, frame.addressOfStackValue(frame.peek(-1)),
    4233          28 :                          &isMagic);
    4234          28 :     masm.moveValue(BooleanValue(false), R0);
    4235          28 :     masm.jump(&done);
    4236             : 
    4237          28 :     masm.bind(&isMagic);
    4238          28 :     masm.moveValue(BooleanValue(true), R0);
    4239             : 
    4240          28 :     masm.bind(&done);
    4241          28 :     frame.push(R0, JSVAL_TYPE_BOOLEAN);
    4242          56 :     return true;
    4243             : }
    4244             : 
    4245             : bool
    4246          20 : BaselineCompiler::emit_JSOP_ISNOITER()
    4247             : {
    4248          20 :     return emitIsMagicValue();
    4249             : }
    4250             : 
    4251             : bool
    4252          20 : BaselineCompiler::emit_JSOP_ENDITER()
    4253             : {
    4254          20 :     if (!emit_JSOP_JUMPTARGET())
    4255           0 :         return false;
    4256          20 :     frame.popRegsAndSync(1);
    4257             : 
    4258          40 :     ICIteratorClose_Fallback::Compiler compiler(cx);
    4259          20 :     return emitOpIC(compiler.getStub(&stubSpace_));
    4260             : }
    4261             : 
    4262             : bool
    4263           8 : BaselineCompiler::emit_JSOP_ISGENCLOSING()
    4264             : {
    4265           8 :     return emitIsMagicValue();
    4266             : }
    4267             : 
    4268             : bool
    4269           6 : BaselineCompiler::emit_JSOP_GETRVAL()
    4270             : {
    4271           6 :     frame.syncStack(0);
    4272             : 
    4273           6 :     emitLoadReturnValue(R0);
    4274             : 
    4275           6 :     frame.push(R0);
    4276           6 :     return true;
    4277             : }
    4278             : 
    4279             : bool
    4280         180 : BaselineCompiler::emit_JSOP_SETRVAL()
    4281             : {
    4282             :     // Store to the frame's return value slot.
    4283         180 :     storeValue(frame.peek(-1), frame.addressOfReturnValue(), R2);
    4284         180 :     masm.or32(Imm32(BaselineFrame::HAS_RVAL), frame.addressOfFlags());
    4285         180 :     frame.pop();
    4286         180 :     return true;
    4287             : }
    4288             : 
    4289             : bool
    4290           2 : BaselineCompiler::emit_JSOP_CALLEE()
    4291             : {
    4292           2 :     MOZ_ASSERT(function());
    4293           2 :     frame.syncStack(0);
    4294           2 :     masm.loadFunctionFromCalleeToken(frame.addressOfCalleeToken(), R0.scratchReg());
    4295           2 :     masm.tagValue(JSVAL_TYPE_OBJECT, R0.scratchReg(), R0);
    4296           2 :     frame.push(R0);
    4297           2 :     return true;
    4298             : }
    4299             : 
    4300             : void
    4301           1 : BaselineCompiler::getThisEnvironmentCallee(Register reg)
    4302             : {
    4303             :     // Directly load callee from frame if we have a HomeObject
    4304           1 :     if (function() && function()->allowSuperProperty()) {
    4305           1 :         masm.loadFunctionFromCalleeToken(frame.addressOfCalleeToken(), reg);
    4306           1 :         return;
    4307             :     }
    4308             : 
    4309             :     // Locate environment chain
    4310           0 :     masm.loadPtr(frame.addressOfEnvironmentChain(), reg);
    4311             : 
    4312             :     // Walk environment chain until first non-arrow CallObject
    4313           0 :     for (ScopeIter si(script->innermostScope(pc)); si; si++) {
    4314             : 
    4315             :         // Find first non-arrow FunctionScope
    4316           0 :         if (si.hasSyntacticEnvironment() && si.scope()->is<FunctionScope>()) {
    4317           0 :             JSFunction* fn = si.scope()->as<FunctionScope>().canonicalFunction();
    4318             : 
    4319           0 :             if (!fn->isArrow())
    4320           0 :                 break;
    4321             :         }
    4322             : 
    4323             :         // Traverse environment chain
    4324           0 :         if (si.scope()->hasEnvironment()) {
    4325           0 :             Address nextAddr(reg, EnvironmentObject::offsetOfEnclosingEnvironment());
    4326           0 :             masm.unboxObject(nextAddr, reg);
    4327             :         }
    4328             :     }
    4329             : 
    4330             :     // Load callee
    4331           0 :     masm.unboxObject(Address(reg, CallObject::offsetOfCallee()), reg);
    4332             : }
    4333             : 
    4334             : typedef JSObject* (*HomeObjectSuperBaseFn)(JSContext*, HandleObject);
    4335           3 : static const VMFunction HomeObjectSuperBaseInfo =
    4336           6 :     FunctionInfo<HomeObjectSuperBaseFn>(HomeObjectSuperBase, "HomeObjectSuperBase");
    4337             : 
    4338             : bool
    4339           0 : BaselineCompiler::emit_JSOP_SUPERBASE()
    4340             : {
    4341           0 :     frame.syncStack(0);
    4342             : 
    4343           0 :     Register scratch = R0.scratchReg();
    4344           0 :     Register proto = R1.scratchReg();
    4345             : 
    4346             :     // Lookup callee object of environment containing [[ThisValue]]
    4347           0 :     getThisEnvironmentCallee(scratch);
    4348             : 
    4349             :     // Load [[HomeObject]]
    4350           0 :     Address homeObjAddr(scratch, FunctionExtended::offsetOfMethodHomeObjectSlot());
    4351             : #ifdef DEBUG
    4352           0 :     Label isObject;
    4353           0 :     masm.branchTestObject(Assembler::Equal, homeObjAddr, &isObject);
    4354           0 :     masm.assumeUnreachable("[[HomeObject]] must be Object");
    4355           0 :     masm.bind(&isObject);
    4356             : #endif
    4357           0 :     masm.unboxObject(homeObjAddr, scratch);
    4358             : 
    4359             :     // Load prototype from [[HomeObject]]
    4360           0 :     masm.loadObjProto(scratch, proto);
    4361             : 
    4362           0 :     Label hasProto;
    4363           0 :     MOZ_ASSERT(uintptr_t(TaggedProto::LazyProto) == 1);
    4364           0 :     masm.branchPtr(Assembler::Above, proto, ImmWord(1), &hasProto);
    4365             : 
    4366             :     // Use VMCall for missing or lazy proto
    4367           0 :     prepareVMCall();
    4368           0 :     pushArg(scratch);  // [[HomeObject]]
    4369           0 :     if (!callVM(HomeObjectSuperBaseInfo))
    4370           0 :         return false;
    4371           0 :     masm.movePtr(ReturnReg, proto);
    4372             : 
    4373             :     // Box prototype and return
    4374           0 :     masm.bind(&hasProto);
    4375           0 :     masm.tagValue(JSVAL_TYPE_OBJECT, proto, R1);
    4376           0 :     frame.push(R1);
    4377           0 :     return true;
    4378             : }
    4379             : 
    4380             : typedef JSObject* (*SuperFunOperationFn)(JSContext*, HandleObject);
    4381           3 : static const VMFunction SuperFunOperationInfo =
    4382           6 :     FunctionInfo<SuperFunOperationFn>(SuperFunOperation, "SuperFunOperation");
    4383             : 
    4384             : bool
    4385           1 : BaselineCompiler::emit_JSOP_SUPERFUN()
    4386             : {
    4387           1 :     frame.syncStack(0);
    4388             : 
    4389           1 :     Register callee = R0.scratchReg();
    4390           1 :     Register proto = R1.scratchReg();
    4391           1 :     Register scratch = R2.scratchReg();
    4392             : 
    4393             :     // Lookup callee object of environment containing [[ThisValue]]
    4394           1 :     getThisEnvironmentCallee(callee);
    4395             : 
    4396             :     // Load prototype of callee
    4397           1 :     masm.loadObjProto(callee, proto);
    4398             : 
    4399             :     // Use VMCall for missing or lazy proto
    4400           2 :     Label needVMCall;
    4401           1 :     MOZ_ASSERT(uintptr_t(TaggedProto::LazyProto) == 1);
    4402           1 :     masm.branchPtr(Assembler::BelowOrEqual, proto, ImmWord(1), &needVMCall);
    4403             : 
    4404             :     // Use VMCall for non-JSFunction objects (eg. Proxy)
    4405           1 :     masm.branchTestObjClass(Assembler::NotEqual, proto, scratch, &JSFunction::class_, &needVMCall);
    4406             : 
    4407             :     // Use VMCall if not constructor
    4408           1 :     masm.load16ZeroExtend(Address(proto, JSFunction::offsetOfFlags()), scratch);
    4409           1 :     masm.branchTest32(Assembler::Zero, scratch, Imm32(JSFunction::CONSTRUCTOR), &needVMCall);
    4410             : 
    4411             :     // Valid constructor
    4412           2 :     Label hasSuperFun;
    4413           1 :     masm.jump(&hasSuperFun);
    4414             : 
    4415             :     // Slow path VM Call
    4416           1 :     masm.bind(&needVMCall);
    4417           1 :     prepareVMCall();
    4418           1 :     pushArg(callee);
    4419           1 :     if (!callVM(SuperFunOperationInfo))
    4420           0 :         return false;
    4421           1 :     masm.movePtr(ReturnReg, proto);
    4422             : 
    4423             :     // Box prototype and return
    4424           1 :     masm.bind(&hasSuperFun);
    4425           1 :     masm.tagValue(JSVAL_TYPE_OBJECT, proto, R1);
    4426           1 :     frame.push(R1);
    4427           1 :     return true;
    4428             : }
    4429             : 
    4430             : typedef bool (*NewArgumentsObjectFn)(JSContext*, BaselineFrame*, MutableHandleValue);
    4431           3 : static const VMFunction NewArgumentsObjectInfo =
    4432           6 :     FunctionInfo<NewArgumentsObjectFn>(jit::NewArgumentsObject, "NewArgumentsObject");
    4433             : 
    4434             : bool
    4435          45 : BaselineCompiler::emit_JSOP_ARGUMENTS()
    4436             : {
    4437          45 :     frame.syncStack(0);
    4438             : 
    4439          90 :     Label done;
    4440          45 :     if (!script->argumentsHasVarBinding() || !script->needsArgsObj()) {
    4441             :         // We assume the script does not need an arguments object. However, this
    4442             :         // assumption can be invalidated later, see argumentsOptimizationFailed
    4443             :         // in JSScript. Because we can't invalidate baseline JIT code, we set a
    4444             :         // flag on BaselineScript when that happens and guard on it here.
    4445          41 :         masm.moveValue(MagicValue(JS_OPTIMIZED_ARGUMENTS), R0);
    4446             : 
    4447             :         // Load script->baseline.
    4448          41 :         Register scratch = R1.scratchReg();
    4449          41 :         masm.movePtr(ImmGCPtr(script), scratch);
    4450          41 :         masm.loadPtr(Address(scratch, JSScript::offsetOfBaselineScript()), scratch);
    4451             : 
    4452             :         // If we don't need an arguments object, skip the VM call.
    4453          82 :         masm.branchTest32(Assembler::Zero, Address(scratch, BaselineScript::offsetOfFlags()),
    4454          41 :                           Imm32(BaselineScript::NEEDS_ARGS_OBJ), &done);
    4455             :     }
    4456             : 
    4457          45 :     prepareVMCall();
    4458             : 
    4459          45 :     masm.loadBaselineFramePtr(BaselineFrameReg, R0.scratchReg());
    4460          45 :     pushArg(R0.scratchReg());
    4461             : 
    4462          45 :     if (!callVM(NewArgumentsObjectInfo))
    4463           0 :         return false;
    4464             : 
    4465          45 :     masm.bind(&done);
    4466          45 :     frame.push(R0);
    4467          45 :     return true;
    4468             : }
    4469             : 
    4470             : typedef bool (*RunOnceScriptPrologueFn)(JSContext*, HandleScript);
    4471           3 : static const VMFunction RunOnceScriptPrologueInfo =
    4472           6 :     FunctionInfo<RunOnceScriptPrologueFn>(js::RunOnceScriptPrologue, "RunOnceScriptPrologue");
    4473             : 
    4474             : bool
    4475           0 : BaselineCompiler::emit_JSOP_RUNONCE()
    4476             : {
    4477           0 :     frame.syncStack(0);
    4478             : 
    4479           0 :     prepareVMCall();
    4480             : 
    4481           0 :     masm.movePtr(ImmGCPtr(script), R0.scratchReg());
    4482           0 :     pushArg(R0.scratchReg());
    4483             : 
    4484           0 :     return callVM(RunOnceScriptPrologueInfo);
    4485             : }
    4486             : 
    4487             : bool
    4488          14 : BaselineCompiler::emit_JSOP_REST()
    4489             : {
    4490          14 :     frame.syncStack(0);
    4491             : 
    4492             :     JSObject* templateObject =
    4493          14 :         ObjectGroup::newArrayObject(cx, nullptr, 0, TenuredObject,
    4494          14 :                                     ObjectGroup::NewArrayKind::UnknownIndex);
    4495          14 :     if (!templateObject)
    4496           0 :         return false;
    4497             : 
    4498             :     // Call IC.
    4499          28 :     ICRest_Fallback::Compiler compiler(cx, &templateObject->as<ArrayObject>());
    4500          14 :     if (!emitOpIC(compiler.getStub(&stubSpace_)))
    4501           0 :         return false;
    4502             : 
    4503             :     // Mark R0 as pushed stack value.
    4504          14 :     frame.push(R0);
    4505          14 :     return true;
    4506             : }
    4507             : 
    4508             : typedef JSObject* (*CreateGeneratorFn)(JSContext*, BaselineFrame*);
    4509           3 : static const VMFunction CreateGeneratorInfo =
    4510           6 :     FunctionInfo<CreateGeneratorFn>(jit::CreateGenerator, "CreateGenerator");
    4511             : 
    4512             : bool
    4513           7 : BaselineCompiler::emit_JSOP_GENERATOR()
    4514             : {
    4515           7 :     MOZ_ASSERT(frame.stackDepth() == 0);
    4516             : 
    4517           7 :     masm.loadBaselineFramePtr(BaselineFrameReg, R0.scratchReg());
    4518             : 
    4519           7 :     prepareVMCall();
    4520           7 :     pushArg(R0.scratchReg());
    4521           7 :     if (!callVM(CreateGeneratorInfo))
    4522           0 :         return false;
    4523             : 
    4524           7 :     masm.tagValue(JSVAL_TYPE_OBJECT, ReturnReg, R0);
    4525           7 :     frame.push(R0);
    4526           7 :     return true;
    4527             : }
    4528             : 
    4529             : bool
    4530          17 : BaselineCompiler::addYieldAndAwaitOffset()
    4531             : {
    4532          17 :     MOZ_ASSERT(*pc == JSOP_INITIALYIELD || *pc == JSOP_YIELD || *pc == JSOP_AWAIT);
    4533             : 
    4534          17 :     uint32_t yieldAndAwaitIndex = GET_UINT24(pc);
    4535             : 
    4536          51 :     while (yieldAndAwaitIndex >= yieldAndAwaitOffsets_.length()) {
    4537          17 :         if (!yieldAndAwaitOffsets_.append(0))
    4538           0 :             return false;
    4539             :     }
    4540             : 
    4541             :     static_assert(JSOP_INITIALYIELD_LENGTH == JSOP_YIELD_LENGTH &&
    4542             :                   JSOP_INITIALYIELD_LENGTH == JSOP_AWAIT_LENGTH,
    4543             :                   "code below assumes INITIALYIELD and YIELD and AWAIT have same length");
    4544          17 :     yieldAndAwaitOffsets_[yieldAndAwaitIndex] = script->pcToOffset(pc + JSOP_YIELD_LENGTH);
    4545          17 :     return true;
    4546             : }
    4547             : 
    4548             : bool
    4549           7 : BaselineCompiler::emit_JSOP_INITIALYIELD()
    4550             : {
    4551           7 :     if (!addYieldAndAwaitOffset())
    4552           0 :         return false;
    4553             : 
    4554           7 :     frame.syncStack(0);
    4555           7 :     MOZ_ASSERT(frame.stackDepth() == 1);
    4556             : 
    4557           7 :     Register genObj = R2.scratchReg();
    4558           7 :     masm.unboxObject(frame.addressOfStackValue(frame.peek(-1)), genObj);
    4559             : 
    4560           7 :     MOZ_ASSERT(GET_UINT24(pc) == 0);
    4561          14 :     masm.storeValue(Int32Value(0),
    4562          21 :                     Address(genObj, GeneratorObject::offsetOfYieldAndAwaitIndexSlot()));
    4563             : 
    4564           7 :     Register envObj = R0.scratchReg();
    4565           7 :     Address envChainSlot(genObj, GeneratorObject::offsetOfEnvironmentChainSlot());
    4566           7 :     masm.loadPtr(frame.addressOfEnvironmentChain(), envObj);
    4567           7 :     masm.guardedCallPreBarrier(envChainSlot, MIRType::Value);
    4568           7 :     masm.storeValue(JSVAL_TYPE_OBJECT, envObj, envChainSlot);
    4569             : 
    4570           7 :     Register temp = R1.scratchReg();
    4571          14 :     Label skipBarrier;
    4572           7 :     masm.branchPtrInNurseryChunk(Assembler::Equal, genObj, temp, &skipBarrier);
    4573           7 :     masm.branchPtrInNurseryChunk(Assembler::NotEqual, envObj, temp, &skipBarrier);
    4574           7 :     masm.push(genObj);
    4575           7 :     MOZ_ASSERT(genObj == R2.scratchReg());
    4576           7 :     masm.call(&postBarrierSlot_);
    4577           7 :     masm.pop(genObj);
    4578           7 :     masm.bind(&skipBarrier);
    4579             : 
    4580           7 :     masm.tagValue(JSVAL_TYPE_OBJECT, genObj, JSReturnOperand);
    4581           7 :     return emitReturn();
    4582             : }
    4583             : 
    4584             : typedef bool (*NormalSuspendFn)(JSContext*, HandleObject, BaselineFrame*, jsbytecode*, uint32_t);
    4585           3 : static const VMFunction NormalSuspendInfo =
    4586           6 :     FunctionInfo<NormalSuspendFn>(jit::NormalSuspend, "NormalSuspend");
    4587             : 
    4588             : bool
    4589          10 : BaselineCompiler::emit_JSOP_YIELD()
    4590             : {
    4591          10 :     if (!addYieldAndAwaitOffset())
    4592           0 :         return false;
    4593             : 
    4594             :     // Store generator in R0.
    4595          10 :     frame.popRegsAndSync(1);
    4596             : 
    4597          10 :     Register genObj = R2.scratchReg();
    4598          10 :     masm.unboxObject(R0, genObj);
    4599             : 
    4600          10 :     MOZ_ASSERT(frame.stackDepth() >= 1);
    4601             : 
    4602          10 :     if (frame.stackDepth() == 1 && !script->isLegacyGenerator()) {
    4603             :         // If the expression stack is empty, we can inline the YIELD. Don't do
    4604             :         // this for legacy generators: we have to throw an exception if the
    4605             :         // generator is in the closing state, see GeneratorObject::suspend.
    4606             : 
    4607           2 :         masm.storeValue(Int32Value(GET_UINT24(pc)),
    4608           3 :                         Address(genObj, GeneratorObject::offsetOfYieldAndAwaitIndexSlot()));
    4609             : 
    4610           1 :         Register envObj = R0.scratchReg();
    4611           1 :         Address envChainSlot(genObj, GeneratorObject::offsetOfEnvironmentChainSlot());
    4612           1 :         masm.loadPtr(frame.addressOfEnvironmentChain(), envObj);
    4613           1 :         masm.guardedCallPreBarrier(envChainSlot, MIRType::Value);
    4614           1 :         masm.storeValue(JSVAL_TYPE_OBJECT, envObj, envChainSlot);
    4615             : 
    4616           1 :         Register temp = R1.scratchReg();
    4617           2 :         Label skipBarrier;
    4618           1 :         masm.branchPtrInNurseryChunk(Assembler::Equal, genObj, temp, &skipBarrier);
    4619           1 :         masm.branchPtrInNurseryChunk(Assembler::NotEqual, envObj, temp, &skipBarrier);
    4620           1 :         MOZ_ASSERT(genObj == R2.scratchReg());
    4621           1 :         masm.call(&postBarrierSlot_);
    4622           1 :         masm.bind(&skipBarrier);
    4623             :     } else {
    4624           9 :         masm.loadBaselineFramePtr(BaselineFrameReg, R1.scratchReg());
    4625             : 
    4626           9 :         prepareVMCall();
    4627           9 :         pushArg(Imm32(frame.stackDepth()));
    4628           9 :         pushArg(ImmPtr(pc));
    4629           9 :         pushArg(R1.scratchReg());
    4630           9 :         pushArg(genObj);
    4631             : 
    4632           9 :         if (!callVM(NormalSuspendInfo))
    4633           0 :             return false;
    4634             :     }
    4635             : 
    4636          10 :     masm.loadValue(frame.addressOfStackValue(frame.peek(-1)), JSReturnOperand);
    4637          10 :     return emitReturn();
    4638             : }
    4639             : 
    4640             : bool
    4641           4 : BaselineCompiler::emit_JSOP_AWAIT()
    4642             : {
    4643           4 :     return emit_JSOP_YIELD();
    4644             : }
    4645             : 
    4646             : typedef bool (*DebugAfterYieldFn)(JSContext*, BaselineFrame*);
    4647           3 : static const VMFunction DebugAfterYieldInfo =
    4648           6 :     FunctionInfo<DebugAfterYieldFn>(jit::DebugAfterYield, "DebugAfterYield");
    4649             : 
    4650             : bool
    4651          17 : BaselineCompiler::emit_JSOP_DEBUGAFTERYIELD()
    4652             : {
    4653          17 :     if (!compileDebugInstrumentation_)
    4654          17 :         return true;
    4655             : 
    4656           0 :     frame.assertSyncedStack();
    4657           0 :     masm.loadBaselineFramePtr(BaselineFrameReg, R0.scratchReg());
    4658           0 :     prepareVMCall();
    4659           0 :     pushArg(R0.scratchReg());
    4660           0 :     return callVM(DebugAfterYieldInfo);
    4661             : }
    4662             : 
    4663             : typedef bool (*FinalSuspendFn)(JSContext*, HandleObject, BaselineFrame*, jsbytecode*);
    4664           3 : static const VMFunction FinalSuspendInfo =
    4665           6 :     FunctionInfo<FinalSuspendFn>(jit::FinalSuspend, "FinalSuspend");
    4666             : 
    4667             : bool
    4668           7 : BaselineCompiler::emit_JSOP_FINALYIELDRVAL()
    4669             : {
    4670             :     // Store generator in R0, BaselineFrame pointer in R1.
    4671           7 :     frame.popRegsAndSync(1);
    4672           7 :     masm.unboxObject(R0, R0.scratchReg());
    4673           7 :     masm.loadBaselineFramePtr(BaselineFrameReg, R1.scratchReg());
    4674             : 
    4675           7 :     prepareVMCall();
    4676           7 :     pushArg(ImmPtr(pc));
    4677           7 :     pushArg(R1.scratchReg());
    4678           7 :     pushArg(R0.scratchReg());
    4679             : 
    4680           7 :     if (!callVM(FinalSuspendInfo))
    4681           0 :         return false;
    4682             : 
    4683           7 :     masm.loadValue(frame.addressOfReturnValue(), JSReturnOperand);
    4684           7 :     return emitReturn();
    4685             : }
    4686             : 
    4687             : typedef bool (*InterpretResumeFn)(JSContext*, HandleObject, HandleValue, HandlePropertyName,
    4688             :                                   MutableHandleValue);
    4689           3 : static const VMFunction InterpretResumeInfo =
    4690           6 :     FunctionInfo<InterpretResumeFn>(jit::InterpretResume, "InterpretResume");
    4691             : 
    4692             : typedef bool (*GeneratorThrowFn)(JSContext*, BaselineFrame*, Handle<GeneratorObject*>,
    4693             :                                  HandleValue, uint32_t);
    4694           3 : static const VMFunction GeneratorThrowInfo =
    4695           6 :     FunctionInfo<GeneratorThrowFn>(jit::GeneratorThrowOrClose, "GeneratorThrowOrClose", TailCall);
    4696             : 
    4697             : bool
    4698           4 : BaselineCompiler::emit_JSOP_RESUME()
    4699             : {
    4700           4 :     GeneratorObject::ResumeKind resumeKind = GeneratorObject::getResumeKind(pc);
    4701             : 
    4702           4 :     frame.syncStack(0);
    4703           4 :     masm.checkStackAlignment();
    4704             : 
    4705           4 :     AllocatableGeneralRegisterSet regs(GeneralRegisterSet::All());
    4706           4 :     regs.take(BaselineFrameReg);
    4707             : 
    4708             :     // Load generator object.
    4709           4 :     Register genObj = regs.takeAny();
    4710           4 :     masm.unboxObject(frame.addressOfStackValue(frame.peek(-2)), genObj);
    4711             : 
    4712             :     // Load callee.
    4713           4 :     Register callee = regs.takeAny();
    4714           4 :     masm.unboxObject(Address(genObj, GeneratorObject::offsetOfCalleeSlot()), callee);
    4715             : 
    4716             :     // Load the script. Note that we don't relazify generator scripts, so it's
    4717             :     // guaranteed to be non-lazy.
    4718           4 :     Register scratch1 = regs.takeAny();
    4719           4 :     masm.loadPtr(Address(callee, JSFunction::offsetOfNativeOrScript()), scratch1);
    4720             : 
    4721             :     // Load the BaselineScript or call a stub if we don't have one.
    4722           8 :     Label interpret;
    4723           4 :     masm.loadPtr(Address(scratch1, JSScript::offsetOfBaselineScript()), scratch1);
    4724           4 :     masm.branchPtr(Assembler::BelowOrEqual, scratch1, ImmPtr(BASELINE_DISABLED_SCRIPT), &interpret);
    4725             : 
    4726             : #ifdef JS_TRACE_LOGGING
    4727           4 :     if (!emitTraceLoggerResume(scratch1, regs))
    4728           0 :         return false;
    4729             : #endif
    4730             : 
    4731           4 :     Register constructing = regs.takeAny();
    4732           4 :     ValueOperand newTarget = regs.takeAnyValue();
    4733           4 :     masm.loadValue(Address(genObj, GeneratorObject::offsetOfNewTargetSlot()), newTarget);
    4734           4 :     masm.move32(Imm32(0), constructing);
    4735             :     {
    4736           8 :         Label notConstructing;
    4737           4 :         masm.branchTestObject(Assembler::NotEqual, newTarget, &notConstructing);
    4738           4 :         masm.pushValue(newTarget);
    4739           4 :         masm.move32(Imm32(CalleeToken_FunctionConstructing), constructing);
    4740           4 :         masm.bind(&notConstructing);
    4741             :     }
    4742           4 :     regs.add(newTarget);
    4743             : 
    4744             :     // Push |undefined| for all formals.
    4745           4 :     Register scratch2 = regs.takeAny();
    4746           8 :     Label loop, loopDone;
    4747           4 :     masm.load16ZeroExtend(Address(callee, JSFunction::offsetOfNargs()), scratch2);
    4748           4 :     masm.bind(&loop);
    4749           4 :     masm.branchTest32(Assembler::Zero, scratch2, scratch2, &loopDone);
    4750             :     {
    4751           4 :         masm.pushValue(UndefinedValue());
    4752           4 :         masm.sub32(Imm32(1), scratch2);
    4753           4 :         masm.jump(&loop);
    4754             :     }
    4755           4 :     masm.bind(&loopDone);
    4756             : 
    4757             :     // Push |undefined| for |this|.
    4758           4 :     masm.pushValue(UndefinedValue());
    4759             : 
    4760             :     // Update BaselineFrame frameSize field and create the frame descriptor.
    4761           8 :     masm.computeEffectiveAddress(Address(BaselineFrameReg, BaselineFrame::FramePointerOffset),
    4762           4 :                                  scratch2);
    4763           4 :     masm.subStackPtrFrom(scratch2);
    4764           4 :     masm.store32(scratch2, Address(BaselineFrameReg, BaselineFrame::reverseOffsetOfFrameSize()));
    4765           4 :     masm.makeFrameDescriptor(scratch2, JitFrame_BaselineJS, JitFrameLayout::Size());
    4766             : 
    4767           4 :     masm.Push(Imm32(0)); // actual argc
    4768             : 
    4769             :     // Duplicate PushCalleeToken with a variable instead.
    4770           4 :     masm.orPtr(constructing, callee);
    4771           4 :     masm.Push(callee);
    4772           4 :     masm.Push(scratch2); // frame descriptor
    4773             : 
    4774           4 :     regs.add(callee);
    4775           4 :     regs.add(constructing);
    4776             : 
    4777             :     // Load the return value.
    4778           4 :     ValueOperand retVal = regs.takeAnyValue();
    4779           4 :     masm.loadValue(frame.addressOfStackValue(frame.peek(-1)), retVal);
    4780             : 
    4781             :     // Push a fake return address on the stack. We will resume here when the
    4782             :     // generator returns.
    4783           8 :     Label genStart, returnTarget;
    4784             : #ifdef JS_USE_LINK_REGISTER
    4785             :     masm.call(&genStart);
    4786             : #else
    4787           4 :     masm.callAndPushReturnAddress(&genStart);
    4788             : #endif
    4789             : 
    4790             :     // Add an IC entry so the return offset -> pc mapping works.
    4791           4 :     if (!appendICEntry(ICEntry::Kind_Op, masm.currentOffset()))
    4792           0 :         return false;
    4793             : 
    4794           4 :     masm.jump(&returnTarget);
    4795           4 :     masm.bind(&genStart);
    4796             : #ifdef JS_USE_LINK_REGISTER
    4797             :     masm.pushReturnAddress();
    4798             : #endif
    4799             : 
    4800             :     // If profiler instrumentation is on, update lastProfilingFrame on
    4801             :     // current JitActivation
    4802             :     {
    4803           4 :         Register scratchReg = scratch2;
    4804           8 :         Label skip;
    4805           4 :         AbsoluteAddress addressOfEnabled(cx->runtime()->geckoProfiler().addressOfEnabled());
    4806           4 :         masm.branch32(Assembler::Equal, addressOfEnabled, Imm32(0), &skip);
    4807           4 :         masm.loadPtr(AbsoluteAddress(cx->addressOfProfilingActivation()), scratchReg);
    4808           4 :         masm.storePtr(masm.getStackPointer(),
    4809           8 :                       Address(scratchReg, JitActivation::offsetOfLastProfilingFrame()));
    4810           4 :         masm.bind(&skip);
    4811             :     }
    4812             : 
    4813             :     // Construct BaselineFrame.
    4814           4 :     masm.push(BaselineFrameReg);
    4815           4 :     masm.moveStackPtrTo(BaselineFrameReg);
    4816           4 :     masm.subFromStackPtr(Imm32(BaselineFrame::Size()));
    4817           4 :     masm.checkStackAlignment();
    4818             : 
    4819             :     // Store flags and env chain.
    4820           4 :     masm.store32(Imm32(BaselineFrame::HAS_INITIAL_ENV), frame.addressOfFlags());
    4821           4 :     masm.unboxObject(Address(genObj, GeneratorObject::offsetOfEnvironmentChainSlot()), scratch2);
    4822           4 :     masm.storePtr(scratch2, frame.addressOfEnvironmentChain());
    4823             : 
    4824             :     // Store the arguments object if there is one.
    4825           8 :     Label noArgsObj;
    4826           4 :     masm.unboxObject(Address(genObj, GeneratorObject::offsetOfArgsObjSlot()), scratch2);
    4827           4 :     masm.branchTestPtr(Assembler::Zero, scratch2, scratch2, &noArgsObj);
    4828             :     {
    4829           4 :         masm.storePtr(scratch2, frame.addressOfArgsObj());
    4830           4 :         masm.or32(Imm32(BaselineFrame::HAS_ARGS_OBJ), frame.addressOfFlags());
    4831             :     }
    4832           4 :     masm.bind(&noArgsObj);
    4833             : 
    4834             :     // Push expression slots if needed.
    4835           8 :     Label noExprStack;
    4836           4 :     Address exprStackSlot(genObj, GeneratorObject::offsetOfExpressionStackSlot());
    4837           4 :     masm.branchTestNull(Assembler::Equal, exprStackSlot, &noExprStack);
    4838             :     {
    4839           4 :         masm.unboxObject(exprStackSlot, scratch2);
    4840             : 
    4841           4 :         Register initLength = regs.takeAny();
    4842           4 :         masm.loadPtr(Address(scratch2, NativeObject::offsetOfElements()), scratch2);
    4843           4 :         masm.load32(Address(scratch2, ObjectElements::offsetOfInitializedLength()), initLength);
    4844             : 
    4845           8 :         Label loop, loopDone;
    4846           4 :         masm.bind(&loop);
    4847           4 :         masm.branchTest32(Assembler::Zero, initLength, initLength, &loopDone);
    4848             :         {
    4849           4 :             masm.pushValue(Address(scratch2, 0));
    4850           4 :             masm.addPtr(Imm32(sizeof(Value)), scratch2);
    4851           4 :             masm.sub32(Imm32(1), initLength);
    4852           4 :             masm.jump(&loop);
    4853             :         }
    4854           4 :         masm.bind(&loopDone);
    4855             : 
    4856           4 :         masm.guardedCallPreBarrier(exprStackSlot, MIRType::Value);
    4857           4 :         masm.storeValue(NullValue(), exprStackSlot);
    4858           4 :         regs.add(initLength);
    4859             :     }
    4860             : 
    4861           4 :     masm.bind(&noExprStack);
    4862           4 :     masm.pushValue(retVal);
    4863             : 
    4864           4 :     if (resumeKind == GeneratorObject::NEXT) {
    4865             :         // Determine the resume address based on the yieldAndAwaitIndex and the
    4866             :         // yieldAndAwaitIndex -> native table in the BaselineScript.
    4867           4 :         masm.load32(Address(scratch1, BaselineScript::offsetOfYieldEntriesOffset()), scratch2);
    4868           4 :         masm.addPtr(scratch2, scratch1);
    4869           8 :         masm.unboxInt32(Address(genObj, GeneratorObject::offsetOfYieldAndAwaitIndexSlot()),
    4870           4 :                         scratch2);
    4871           4 :         masm.loadPtr(BaseIndex(scratch1, scratch2, ScaleFromElemWidth(sizeof(uintptr_t))), scratch1);
    4872             : 
    4873             :         // Mark as running and jump to the generator's JIT code.
    4874           8 :         masm.storeValue(Int32Value(GeneratorObject::YIELD_AND_AWAIT_INDEX_RUNNING),
    4875          12 :                         Address(genObj, GeneratorObject::offsetOfYieldAndAwaitIndexSlot()));
    4876           4 :         masm.jump(scratch1);
    4877             :     } else {
    4878           0 :         MOZ_ASSERT(resumeKind == GeneratorObject::THROW || resumeKind == GeneratorObject::CLOSE);
    4879             : 
    4880             :         // Update the frame's frameSize field.
    4881           0 :         masm.computeEffectiveAddress(Address(BaselineFrameReg, BaselineFrame::FramePointerOffset),
    4882           0 :                                      scratch2);
    4883           0 :         masm.movePtr(scratch2, scratch1);
    4884           0 :         masm.subStackPtrFrom(scratch2);
    4885           0 :         masm.store32(scratch2, Address(BaselineFrameReg, BaselineFrame::reverseOffsetOfFrameSize()));
    4886           0 :         masm.loadBaselineFramePtr(BaselineFrameReg, scratch2);
    4887             : 
    4888           0 :         prepareVMCall();
    4889           0 :         pushArg(Imm32(resumeKind));
    4890           0 :         pushArg(retVal);
    4891           0 :         pushArg(genObj);
    4892           0 :         pushArg(scratch2);
    4893             : 
    4894           0 :         JitCode* code = cx->runtime()->jitRuntime()->getVMWrapper(GeneratorThrowInfo);
    4895           0 :         if (!code)
    4896           0 :             return false;
    4897             : 
    4898             :         // Create the frame descriptor.
    4899           0 :         masm.subStackPtrFrom(scratch1);
    4900           0 :         masm.makeFrameDescriptor(scratch1, JitFrame_BaselineJS, ExitFrameLayout::Size());
    4901             : 
    4902             :         // Push the frame descriptor and a dummy return address (it doesn't
    4903             :         // matter what we push here, frame iterators will use the frame pc
    4904             :         // set in jit::GeneratorThrowOrClose).
    4905           0 :         masm.push(scratch1);
    4906             : 
    4907             :         // On ARM64, the callee will push the return address.
    4908             : #ifndef JS_CODEGEN_ARM64
    4909           0 :         masm.push(ImmWord(0));
    4910             : #endif
    4911           0 :         masm.jump(code);
    4912             :     }
    4913             : 
    4914             :     // If the generator script has no JIT code, call into the VM.
    4915           4 :     masm.bind(&interpret);
    4916             : 
    4917           4 :     prepareVMCall();
    4918           4 :     if (resumeKind == GeneratorObject::NEXT) {
    4919           4 :         pushArg(ImmGCPtr(cx->names().next));
    4920           0 :     } else if (resumeKind == GeneratorObject::THROW) {
    4921           0 :         pushArg(ImmGCPtr(cx->names().throw_));
    4922             :     } else {
    4923           0 :         MOZ_ASSERT(resumeKind == GeneratorObject::CLOSE);
    4924           0 :         pushArg(ImmGCPtr(cx->names().close));
    4925             :     }
    4926             : 
    4927           4 :     masm.loadValue(frame.addressOfStackValue(frame.peek(-1)), retVal);
    4928           4 :     pushArg(retVal);
    4929           4 :     pushArg(genObj);
    4930             : 
    4931           4 :     if (!callVM(InterpretResumeInfo))
    4932           0 :         return false;
    4933             : 
    4934             :     // After the generator returns, we restore the stack pointer, push the
    4935             :     // return value and we're done.
    4936           4 :     masm.bind(&returnTarget);
    4937           4 :     masm.computeEffectiveAddress(frame.addressOfStackValue(frame.peek(-1)), masm.getStackPointer());
    4938           4 :     frame.popn(2);
    4939           4 :     frame.push(R0);
    4940           4 :     return true;
    4941             : }
    4942             : 
    4943             : typedef bool (*CheckSelfHostedFn)(JSContext*, HandleValue);
    4944           3 : static const VMFunction CheckSelfHostedInfo =
    4945           6 :     FunctionInfo<CheckSelfHostedFn>(js::Debug_CheckSelfHosted, "Debug_CheckSelfHosted");
    4946             : 
    4947             : bool
    4948          59 : BaselineCompiler::emit_JSOP_DEBUGCHECKSELFHOSTED()
    4949             : {
    4950             : #ifdef DEBUG
    4951          59 :     frame.syncStack(0);
    4952             : 
    4953          59 :     masm.loadValue(frame.addressOfStackValue(frame.peek(-1)), R0);
    4954             : 
    4955          59 :     prepareVMCall();
    4956          59 :     pushArg(R0);
    4957          59 :     if (!callVM(CheckSelfHostedInfo))
    4958           0 :         return false;
    4959             : #endif
    4960          59 :     return true;
    4961             : 
    4962             : }
    4963             : 
    4964             : bool
    4965         140 : BaselineCompiler::emit_JSOP_IS_CONSTRUCTING()
    4966             : {
    4967         140 :     frame.push(MagicValue(JS_IS_CONSTRUCTING));
    4968         140 :     return true;
    4969             : }
    4970             : 
    4971             : bool
    4972        7452 : BaselineCompiler::emit_JSOP_JUMPTARGET()
    4973             : {
    4974        7452 :     if (!script->hasScriptCounts())
    4975           0 :         return true;
    4976        7452 :     PCCounts* counts = script->maybeGetPCCounts(pc);
    4977        7452 :     uint64_t* counterAddr = &counts->numExec();
    4978        7452 :     masm.inc64(AbsoluteAddress(counterAddr));
    4979        7452 :     return true;
    4980             : }
    4981             : 
    4982             : typedef bool (*CheckClassHeritageOperationFn)(JSContext*, HandleValue);
    4983           3 : static const VMFunction CheckClassHeritageOperationInfo =
    4984           6 :     FunctionInfo<CheckClassHeritageOperationFn>(js::CheckClassHeritageOperation,
    4985             :                                                 "CheckClassHeritageOperation");
    4986             : 
    4987             : bool
    4988           0 : BaselineCompiler::emit_JSOP_CHECKCLASSHERITAGE()
    4989             : {
    4990           0 :     frame.syncStack(0);
    4991             : 
    4992             :     // Leave the heritage value on the stack.
    4993           0 :     masm.loadValue(frame.addressOfStackValue(frame.peek(-1)), R0);
    4994             : 
    4995           0 :     prepareVMCall();
    4996           0 :     pushArg(R0);
    4997           0 :     return callVM(CheckClassHeritageOperationInfo);
    4998             : }
    4999             : 
    5000             : bool
    5001           0 : BaselineCompiler::emit_JSOP_INITHOMEOBJECT()
    5002             : {
    5003           0 :     frame.syncStack(0);
    5004             : 
    5005             :     // Load HomeObject off stack
    5006           0 :     unsigned skipOver = GET_UINT8(pc);
    5007           0 :     MOZ_ASSERT(frame.stackDepth() >= skipOver + 2);
    5008           0 :     masm.loadValue(frame.addressOfStackValue(frame.peek(-2 - skipOver)), R0);
    5009             : 
    5010             :     // Load function off stack
    5011           0 :     Register func = R2.scratchReg();
    5012           0 :     masm.unboxObject(frame.addressOfStackValue(frame.peek(-1)), func);
    5013             : 
    5014             :     // Set HOMEOBJECT_SLOT
    5015           0 :     Address addr(func, FunctionExtended::offsetOfMethodHomeObjectSlot());
    5016             : #ifdef DEBUG
    5017           0 :     Label isUndefined;
    5018           0 :     masm.branchTestUndefined(Assembler::Equal, addr, &isUndefined);
    5019           0 :     masm.assumeUnreachable("INITHOMEOBJECT expects undefined slot");
    5020           0 :     masm.bind(&isUndefined);
    5021             : #endif
    5022           0 :     masm.storeValue(R0, addr);
    5023             : 
    5024           0 :     Register temp = R1.scratchReg();
    5025           0 :     Label skipBarrier;
    5026           0 :     masm.branchPtrInNurseryChunk(Assembler::Equal, func, temp, &skipBarrier);
    5027           0 :     masm.branchValueIsNurseryObject(Assembler::NotEqual, R0, temp, &skipBarrier);
    5028           0 :     masm.call(&postBarrierSlot_);
    5029           0 :     masm.bind(&skipBarrier);
    5030             : 
    5031           0 :     return true;
    5032             : }
    5033             : 
    5034             : bool
    5035           0 : BaselineCompiler::emit_JSOP_BUILTINPROTO()
    5036             : {
    5037             :     // The builtin prototype is a constant for a given global.
    5038           0 :     RootedObject builtin(cx);
    5039           0 :     JSProtoKey key = static_cast<JSProtoKey>(GET_UINT8(pc));
    5040           0 :     MOZ_ASSERT(key < JSProto_LIMIT);
    5041           0 :     if (!GetBuiltinPrototype(cx, key, &builtin))
    5042           0 :         return false;
    5043           0 :     frame.push(ObjectValue(*builtin));
    5044           0 :     return true;
    5045             : }
    5046             : 
    5047             : typedef JSObject* (*ObjectWithProtoOperationFn)(JSContext*, HandleValue);
    5048           3 : static const VMFunction ObjectWithProtoOperationInfo =
    5049           6 :     FunctionInfo<ObjectWithProtoOperationFn>(js::ObjectWithProtoOperation,
    5050             :                                              "ObjectWithProtoOperationInfo");
    5051             : 
    5052             : bool
    5053           0 : BaselineCompiler::emit_JSOP_OBJWITHPROTO()
    5054             : {
    5055           0 :     frame.syncStack(0);
    5056             : 
    5057             :     // Leave the proto value on the stack for the decompiler
    5058           0 :     masm.loadValue(frame.addressOfStackValue(frame.peek(-1)), R0);
    5059             : 
    5060           0 :     prepareVMCall();
    5061           0 :     pushArg(R0);
    5062           0 :     if (!callVM(ObjectWithProtoOperationInfo))
    5063           0 :         return false;
    5064             : 
    5065           0 :     masm.tagValue(JSVAL_TYPE_OBJECT, ReturnReg, R0);
    5066           0 :     frame.pop();
    5067           0 :     frame.push(R0);
    5068           0 :     return true;
    5069             : }
    5070             : 
    5071             : typedef JSObject* (*FunWithProtoFn)(JSContext*, HandleFunction, HandleObject, HandleObject);
    5072           3 : static const VMFunction FunWithProtoInfo =
    5073           6 :     FunctionInfo<FunWithProtoFn>(js::FunWithProtoOperation, "FunWithProtoOperation");
    5074             : 
    5075             : bool
    5076           0 : BaselineCompiler::emit_JSOP_FUNWITHPROTO()
    5077             : {
    5078           0 :     frame.popRegsAndSync(1);
    5079             : 
    5080           0 :     masm.unboxObject(R0, R0.scratchReg());
    5081           0 :     masm.loadPtr(frame.addressOfEnvironmentChain(), R1.scratchReg());
    5082             : 
    5083           0 :     prepareVMCall();
    5084           0 :     pushArg(R0.scratchReg());
    5085           0 :     pushArg(R1.scratchReg());
    5086           0 :     pushArg(ImmGCPtr(script->getFunction(GET_UINT32_INDEX(pc))));
    5087           0 :     if (!callVM(FunWithProtoInfo))
    5088           0 :         return false;
    5089             : 
    5090           0 :     masm.tagValue(JSVAL_TYPE_OBJECT, ReturnReg, R0);
    5091           0 :     frame.push(R0);
    5092           0 :     return true;
    5093             : }
    5094             : 
    5095             : typedef JSFunction* (*MakeDefaultConstructorFn)(JSContext*, HandleScript,
    5096             :                                                 jsbytecode*, HandleObject);
    5097           3 : static const VMFunction MakeDefaultConstructorInfo =
    5098           6 :     FunctionInfo<MakeDefaultConstructorFn>(js::MakeDefaultConstructor,
    5099             :                                            "MakeDefaultConstructor");
    5100             : 
    5101             : bool
    5102           0 : BaselineCompiler::emit_JSOP_CLASSCONSTRUCTOR()
    5103             : {
    5104           0 :     frame.syncStack(0);
    5105             : 
    5106             :     // Pass nullptr as prototype to MakeDefaultConstructor
    5107           0 :     prepareVMCall();
    5108           0 :     pushArg(ImmPtr(nullptr));
    5109           0 :     pushArg(ImmPtr(pc));
    5110           0 :     pushArg(ImmGCPtr(script));
    5111           0 :     if (!callVM(MakeDefaultConstructorInfo))
    5112           0 :         return false;
    5113             : 
    5114           0 :     masm.tagValue(JSVAL_TYPE_OBJECT, ReturnReg, R0);
    5115           0 :     frame.push(R0);
    5116           0 :     return true;
    5117             : }
    5118             : 
    5119             : bool
    5120           0 : BaselineCompiler::emit_JSOP_DERIVEDCONSTRUCTOR()
    5121             : {
    5122           0 :     frame.popRegsAndSync(1);
    5123             : 
    5124           0 :     masm.unboxObject(R0, R0.scratchReg());
    5125             : 
    5126           0 :     prepareVMCall();
    5127           0 :     pushArg(R0.scratchReg());
    5128           0 :     pushArg(ImmPtr(pc));
    5129           0 :     pushArg(ImmGCPtr(script));
    5130           0 :     if (!callVM(MakeDefaultConstructorInfo))
    5131           0 :         return false;
    5132             : 
    5133           0 :     masm.tagValue(JSVAL_TYPE_OBJECT, ReturnReg, R0);
    5134           0 :     frame.push(R0);
    5135           0 :     return true;
    5136             : }

Generated by: LCOV version 1.13