LCOV - code coverage report
Current view: top level - js/src/jit - IonBuilder.h (source / functions) Hit Total Coverage
Test: output.info Lines: 146 190 76.8 %
Date: 2017-07-14 16:53:18 Functions: 48 56 85.7 %
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             : #ifndef jit_IonBuilder_h
       8             : #define jit_IonBuilder_h
       9             : 
      10             : // This file declares the data structures for building a MIRGraph from a
      11             : // JSScript.
      12             : 
      13             : #include "mozilla/LinkedList.h"
      14             : 
      15             : #include "jit/BaselineInspector.h"
      16             : #include "jit/BytecodeAnalysis.h"
      17             : #include "jit/IonAnalysis.h"
      18             : #include "jit/IonControlFlow.h"
      19             : #include "jit/IonOptimizationLevels.h"
      20             : #include "jit/MIR.h"
      21             : #include "jit/MIRGenerator.h"
      22             : #include "jit/MIRGraph.h"
      23             : #include "jit/OptimizationTracking.h"
      24             : 
      25             : namespace js {
      26             : namespace jit {
      27             : 
      28             : class CodeGenerator;
      29             : class CallInfo;
      30             : class BaselineFrameInspector;
      31             : 
      32             : enum class InlinableNative : uint16_t;
      33             : 
      34             : // Records information about a baseline frame for compilation that is stable
      35             : // when later used off thread.
      36             : BaselineFrameInspector*
      37             : NewBaselineFrameInspector(TempAllocator* temp, BaselineFrame* frame, CompileInfo* info);
      38             : 
      39         169 : class IonBuilder
      40             :   : public MIRGenerator,
      41             :     public mozilla::LinkedListElement<IonBuilder>
      42             : {
      43             : 
      44             :   public:
      45             :     IonBuilder(JSContext* analysisContext, CompileCompartment* comp,
      46             :                const JitCompileOptions& options, TempAllocator* temp,
      47             :                MIRGraph* graph, CompilerConstraintList* constraints,
      48             :                BaselineInspector* inspector, CompileInfo* info,
      49             :                const OptimizationInfo* optimizationInfo, BaselineFrameInspector* baselineFrame,
      50             :                size_t inliningDepth = 0, uint32_t loopDepth = 0);
      51             : 
      52             :     // Callers of build() and buildInline() should always check whether the
      53             :     // call overrecursed, if false is returned.  Overrecursion is not
      54             :     // signaled as OOM and will not in general be caught by OOM paths.
      55             :     AbortReasonOr<Ok> build();
      56             :     AbortReasonOr<Ok> buildInline(IonBuilder* callerBuilder, MResumePoint* callerResumePoint,
      57             :                                   CallInfo& callInfo);
      58             : 
      59             :     mozilla::GenericErrorResult<AbortReason> abort(AbortReason r);
      60             :     mozilla::GenericErrorResult<AbortReason>
      61             :     abort(AbortReason r, const char* message, ...) MOZ_FORMAT_PRINTF(3, 4);
      62             : 
      63             :   private:
      64             :     AbortReasonOr<Ok> traverseBytecode();
      65             :     AbortReasonOr<Ok> processIterators();
      66             :     AbortReasonOr<Ok> inspectOpcode(JSOp op);
      67             :     uint32_t readIndex(jsbytecode* pc);
      68             :     JSAtom* readAtom(jsbytecode* pc);
      69             : 
      70             :     void trackActionableAbort(const char* message);
      71             :     void spew(const char* message);
      72             : 
      73             :     JSFunction* getSingleCallTarget(TemporaryTypeSet* calleeTypes);
      74             :     AbortReasonOr<Ok> getPolyCallTargets(TemporaryTypeSet* calleeTypes, bool constructing,
      75             :                                          InliningTargets& targets, uint32_t maxTargets);
      76             : 
      77             :     AbortReasonOr<Ok> analyzeNewLoopTypes(const CFGBlock* loopEntryBlock);
      78             : 
      79             :     AbortReasonOr<MBasicBlock*> newBlock(MBasicBlock* predecessor, jsbytecode* pc);
      80             :     AbortReasonOr<MBasicBlock*> newBlock(MBasicBlock* predecessor, jsbytecode* pc,
      81             :                                          MResumePoint* priorResumePoint);
      82             :     AbortReasonOr<MBasicBlock*> newBlockPopN(MBasicBlock* predecessor, jsbytecode* pc,
      83             :                                              uint32_t popped);
      84             :     AbortReasonOr<MBasicBlock*> newBlockAfter(MBasicBlock* at, MBasicBlock* predecessor,
      85             :                                               jsbytecode* pc);
      86             :     AbortReasonOr<MBasicBlock*> newOsrPreheader(MBasicBlock* header, jsbytecode* loopEntry,
      87             :                                                 jsbytecode* beforeLoopEntry);
      88             :     AbortReasonOr<MBasicBlock*> newPendingLoopHeader(MBasicBlock* predecessor, jsbytecode* pc,
      89             :                                                      bool osr, bool canOsr, unsigned stackPhiCount);
      90         179 :     AbortReasonOr<MBasicBlock*> newBlock(jsbytecode* pc) {
      91         179 :         return newBlock(nullptr, pc);
      92             :     }
      93           4 :     AbortReasonOr<MBasicBlock*> newBlockAfter(MBasicBlock* at, jsbytecode* pc) {
      94           4 :         return newBlockAfter(at, nullptr, pc);
      95             :     }
      96             : 
      97             :     AbortReasonOr<Ok> visitBlock(const CFGBlock* hblock, MBasicBlock* mblock);
      98             :     AbortReasonOr<Ok> visitControlInstruction(CFGControlInstruction* ins, bool* restarted);
      99             :     AbortReasonOr<Ok> visitTest(CFGTest* test);
     100             :     AbortReasonOr<Ok> visitCompare(CFGCompare* compare);
     101             :     AbortReasonOr<Ok> visitLoopEntry(CFGLoopEntry* loopEntry);
     102             :     AbortReasonOr<Ok> visitReturn(CFGControlInstruction* ins);
     103             :     AbortReasonOr<Ok> visitGoto(CFGGoto* ins);
     104             :     AbortReasonOr<Ok> visitBackEdge(CFGBackEdge* ins, bool* restarted);
     105             :     AbortReasonOr<Ok> visitTry(CFGTry* test);
     106             :     AbortReasonOr<Ok> visitThrow(CFGThrow* ins);
     107             :     AbortReasonOr<Ok> visitTableSwitch(CFGTableSwitch* ins);
     108             : 
     109             :     // We want to make sure that our MTest instructions all check whether the
     110             :     // thing being tested might emulate undefined.  So we funnel their creation
     111             :     // through this method, to make sure that happens.  We don't want to just do
     112             :     // the check in MTest::New, because that can run on background compilation
     113             :     // threads, and we're not sure it's safe to touch that part of the typeset
     114             :     // from a background thread.
     115             :     MTest* newTest(MDefinition* ins, MBasicBlock* ifTrue, MBasicBlock* ifFalse);
     116             : 
     117             :     // Incorporates a type/typeSet into an OSR value for a loop, after the loop
     118             :     // body has been processed.
     119             :     AbortReasonOr<Ok> addOsrValueTypeBarrier(uint32_t slot, MInstruction** def,
     120             :                                              MIRType type, TemporaryTypeSet* typeSet);
     121             :     AbortReasonOr<Ok> maybeAddOsrTypeBarriers();
     122             : 
     123             :     // Restarts processing of a loop if the type information at its header was
     124             :     // incomplete.
     125             :     AbortReasonOr<Ok> restartLoop(const CFGBlock* header);
     126             :     bool initLoopEntry();
     127             : 
     128             :     // Please see the Big Honkin' Comment about how resume points work in
     129             :     // IonBuilder.cpp, near the definition for this function.
     130             :     AbortReasonOr<Ok> resume(MInstruction* ins, jsbytecode* pc, MResumePoint::Mode mode);
     131             :     AbortReasonOr<Ok> resumeAt(MInstruction* ins, jsbytecode* pc);
     132             :     AbortReasonOr<Ok> resumeAfter(MInstruction* ins);
     133             :     AbortReasonOr<Ok> maybeInsertResume();
     134             : 
     135             :     bool blockIsOSREntry(const CFGBlock* block, const CFGBlock* predecessor);
     136             : 
     137             :     void insertRecompileCheck();
     138             : 
     139             :     AbortReasonOr<Ok> initParameters();
     140             :     void initLocals();
     141             :     void rewriteParameter(uint32_t slotIdx, MDefinition* param, int32_t argIndex);
     142             :     AbortReasonOr<Ok> rewriteParameters();
     143             :     AbortReasonOr<Ok> initEnvironmentChain(MDefinition* callee = nullptr);
     144             :     void initArgumentsObject();
     145             :     void pushConstant(const Value& v);
     146             : 
     147             :     MConstant* constant(const Value& v);
     148             :     MConstant* constantInt(int32_t i);
     149             :     MInstruction* initializedLength(MDefinition* obj, MDefinition* elements,
     150             :                                     JSValueType unboxedType);
     151             :     MInstruction* setInitializedLength(MDefinition* obj, JSValueType unboxedType, size_t count);
     152             : 
     153             :     // Improve the type information at tests
     154             :     AbortReasonOr<Ok> improveTypesAtTest(MDefinition* ins, bool trueBranch, MTest* test);
     155             :     AbortReasonOr<Ok> improveTypesAtCompare(MCompare* ins, bool trueBranch, MTest* test);
     156             :     AbortReasonOr<Ok> improveTypesAtNullOrUndefinedCompare(MCompare* ins, bool trueBranch,
     157             :                                                            MTest* test);
     158             :     AbortReasonOr<Ok> improveTypesAtTypeOfCompare(MCompare* ins, bool trueBranch, MTest* test);
     159             : 
     160             :     // Used to detect triangular structure at test.
     161             :     bool detectAndOrStructure(MPhi* ins, bool* branchIsTrue);
     162             :     AbortReasonOr<Ok> replaceTypeSet(MDefinition* subject, TemporaryTypeSet* type, MTest* test);
     163             : 
     164             :     // Add a guard which ensure that the set of type which goes through this
     165             :     // generated code correspond to the observed types for the bytecode.
     166             :     MDefinition* addTypeBarrier(MDefinition* def, TemporaryTypeSet* observed,
     167             :                                 BarrierKind kind, MTypeBarrier** pbarrier = nullptr);
     168             :     AbortReasonOr<Ok> pushTypeBarrier(MDefinition* def, TemporaryTypeSet* observed,
     169             :                                       BarrierKind kind);
     170             : 
     171             :     // As pushTypeBarrier, but will compute the needBarrier boolean itself based
     172             :     // on observed and the JSFunction that we're planning to call. The
     173             :     // JSFunction must be a DOM method or getter.
     174             :     AbortReasonOr<Ok> pushDOMTypeBarrier(MInstruction* ins, TemporaryTypeSet* observed,
     175             :                                          JSFunction* func);
     176             : 
     177             :     // If definiteType is not known or def already has the right type, just
     178             :     // returns def.  Otherwise, returns an MInstruction that has that definite
     179             :     // type, infallibly unboxing ins as needed.  The new instruction will be
     180             :     // added to |current| in this case.
     181             :     MDefinition* ensureDefiniteType(MDefinition* def, MIRType definiteType);
     182             : 
     183             :     // Creates a MDefinition based on the given def improved with type as TypeSet.
     184             :     MDefinition* ensureDefiniteTypeSet(MDefinition* def, TemporaryTypeSet* types);
     185             : 
     186             :     void maybeMarkEmpty(MDefinition* ins);
     187             : 
     188             :     JSObject* getSingletonPrototype(JSFunction* target);
     189             : 
     190             :     MDefinition* createThisScripted(MDefinition* callee, MDefinition* newTarget);
     191             :     MDefinition* createThisScriptedSingleton(JSFunction* target, MDefinition* callee);
     192             :     MDefinition* createThisScriptedBaseline(MDefinition* callee);
     193             :     MDefinition* createThis(JSFunction* target, MDefinition* callee, MDefinition* newTarget);
     194             :     MInstruction* createNamedLambdaObject(MDefinition* callee, MDefinition* envObj);
     195             :     AbortReasonOr<MInstruction*> createCallObject(MDefinition* callee, MDefinition* envObj);
     196             : 
     197             :     MDefinition* walkEnvironmentChain(unsigned hops);
     198             : 
     199             :     MInstruction* addConvertElementsToDoubles(MDefinition* elements);
     200             :     MDefinition* addMaybeCopyElementsForWrite(MDefinition* object, bool checkNative);
     201             :     MInstruction* addBoundsCheck(MDefinition* index, MDefinition* length);
     202             :     MInstruction* addShapeGuard(MDefinition* obj, Shape* const shape, BailoutKind bailoutKind);
     203             :     MInstruction* addGroupGuard(MDefinition* obj, ObjectGroup* group, BailoutKind bailoutKind);
     204             :     MInstruction* addUnboxedExpandoGuard(MDefinition* obj, bool hasExpando, BailoutKind bailoutKind);
     205             :     MInstruction* addSharedTypedArrayGuard(MDefinition* obj);
     206             : 
     207             :     MInstruction*
     208             :     addGuardReceiverPolymorphic(MDefinition* obj, const BaselineInspector::ReceiverVector& receivers);
     209             : 
     210             :     MDefinition* convertShiftToMaskForStaticTypedArray(MDefinition* id,
     211             :                                                        Scalar::Type viewType);
     212             : 
     213             :     bool invalidatedIdempotentCache();
     214             : 
     215             :     bool hasStaticEnvironmentObject(EnvironmentCoordinate ec, JSObject** pcall);
     216             :     AbortReasonOr<Ok> loadSlot(MDefinition* obj, size_t slot, size_t nfixed, MIRType rvalType,
     217             :                                BarrierKind barrier, TemporaryTypeSet* types);
     218             :     AbortReasonOr<Ok> loadSlot(MDefinition* obj, Shape* shape, MIRType rvalType,
     219             :                                BarrierKind barrier, TemporaryTypeSet* types);
     220             :     AbortReasonOr<Ok> storeSlot(MDefinition* obj, size_t slot, size_t nfixed, MDefinition* value,
     221             :                                 bool needsBarrier, MIRType slotType = MIRType::None);
     222             :     AbortReasonOr<Ok> storeSlot(MDefinition* obj, Shape* shape, MDefinition* value,
     223             :                                 bool needsBarrier, MIRType slotType = MIRType::None);
     224             :     bool shouldAbortOnPreliminaryGroups(MDefinition *obj);
     225             : 
     226             :     MDefinition* tryInnerizeWindow(MDefinition* obj);
     227             :     MDefinition* maybeUnboxForPropertyAccess(MDefinition* def);
     228             : 
     229             :     // jsop_getprop() helpers.
     230             :     AbortReasonOr<Ok> checkIsDefinitelyOptimizedArguments(MDefinition* obj, bool* isOptimizedArgs);
     231             :     AbortReasonOr<Ok> getPropTryInferredConstant(bool* emitted, MDefinition* obj,
     232             :                                                  PropertyName* name, TemporaryTypeSet* types);
     233             :     AbortReasonOr<Ok> getPropTryArgumentsLength(bool* emitted, MDefinition* obj);
     234             :     AbortReasonOr<Ok> getPropTryArgumentsCallee(bool* emitted, MDefinition* obj,
     235             :                                                 PropertyName* name);
     236             :     AbortReasonOr<Ok> getPropTryConstant(bool* emitted, MDefinition* obj, jsid id,
     237             :                                          TemporaryTypeSet* types);
     238             :     AbortReasonOr<Ok> getPropTryNotDefined(bool* emitted, MDefinition* obj, jsid id,
     239             :                                            TemporaryTypeSet* types);
     240             :     AbortReasonOr<Ok> getPropTryDefiniteSlot(bool* emitted, MDefinition* obj, PropertyName* name,
     241             :                                              BarrierKind barrier, TemporaryTypeSet* types);
     242             :     AbortReasonOr<Ok> getPropTryModuleNamespace(bool* emitted, MDefinition* obj, PropertyName* name,
     243             :                                                 BarrierKind barrier, TemporaryTypeSet* types);
     244             :     AbortReasonOr<Ok> getPropTryUnboxed(bool* emitted, MDefinition* obj, PropertyName* name,
     245             :                                         BarrierKind barrier, TemporaryTypeSet* types);
     246             :     AbortReasonOr<Ok> getPropTryCommonGetter(bool* emitted, MDefinition* obj, PropertyName* name,
     247             :                                              TemporaryTypeSet* types, bool innerized = false);
     248             :     AbortReasonOr<Ok> getPropTryInlineAccess(bool* emitted, MDefinition* obj, PropertyName* name,
     249             :                                              BarrierKind barrier, TemporaryTypeSet* types);
     250             :     AbortReasonOr<Ok> getPropTryTypedObject(bool* emitted, MDefinition* obj, PropertyName* name);
     251             :     AbortReasonOr<Ok> getPropTryScalarPropOfTypedObject(bool* emitted, MDefinition* typedObj,
     252             :                                                         int32_t fieldOffset,
     253             :                                                         TypedObjectPrediction fieldTypeReprs);
     254             :     AbortReasonOr<Ok> getPropTryReferencePropOfTypedObject(bool* emitted, MDefinition* typedObj,
     255             :                                                            int32_t fieldOffset,
     256             :                                                            TypedObjectPrediction fieldPrediction,
     257             :                                                            PropertyName* name);
     258             :     AbortReasonOr<Ok> getPropTryComplexPropOfTypedObject(bool* emitted, MDefinition* typedObj,
     259             :                                                          int32_t fieldOffset,
     260             :                                                          TypedObjectPrediction fieldTypeReprs,
     261             :                                                          size_t fieldIndex);
     262             :     AbortReasonOr<Ok> getPropTryInnerize(bool* emitted, MDefinition* obj, PropertyName* name,
     263             :                                          TemporaryTypeSet* types);
     264             :     AbortReasonOr<Ok> getPropAddCache(MDefinition* obj, PropertyName* name,
     265             :                                       BarrierKind barrier, TemporaryTypeSet* types);
     266             : 
     267             :     // jsop_setprop() helpers.
     268             :     AbortReasonOr<Ok> setPropTryCommonSetter(bool* emitted, MDefinition* obj,
     269             :                                              PropertyName* name, MDefinition* value);
     270             :     AbortReasonOr<Ok> setPropTryCommonDOMSetter(bool* emitted, MDefinition* obj,
     271             :                                                 MDefinition* value, JSFunction* setter,
     272             :                                                 TemporaryTypeSet* objTypes);
     273             :     AbortReasonOr<Ok> setPropTryDefiniteSlot(bool* emitted, MDefinition* obj,
     274             :                                              PropertyName* name, MDefinition* value,
     275             :                                              bool barrier, TemporaryTypeSet* objTypes);
     276             :     AbortReasonOr<Ok> setPropTryUnboxed(bool* emitted, MDefinition* obj,
     277             :                                         PropertyName* name, MDefinition* value,
     278             :                                         bool barrier, TemporaryTypeSet* objTypes);
     279             :     AbortReasonOr<Ok> setPropTryInlineAccess(bool* emitted, MDefinition* obj,
     280             :                                              PropertyName* name, MDefinition* value,
     281             :                                              bool barrier, TemporaryTypeSet* objTypes);
     282             :     AbortReasonOr<Ok> setPropTryTypedObject(bool* emitted, MDefinition* obj,
     283             :                                             PropertyName* name, MDefinition* value);
     284             :     AbortReasonOr<Ok> setPropTryReferencePropOfTypedObject(bool* emitted, MDefinition* obj,
     285             :                                                            int32_t fieldOffset, MDefinition* value,
     286             :                                                            TypedObjectPrediction fieldPrediction,
     287             :                                                            PropertyName* name);
     288             :     AbortReasonOr<Ok> setPropTryScalarPropOfTypedObject(bool* emitted,
     289             :                                                         MDefinition* obj,
     290             :                                                         int32_t fieldOffset,
     291             :                                                         MDefinition* value,
     292             :                                                         TypedObjectPrediction fieldTypeReprs);
     293             :     AbortReasonOr<Ok> setPropTryCache(bool* emitted, MDefinition* obj,
     294             :                                       PropertyName* name, MDefinition* value,
     295             :                                       bool barrier, TemporaryTypeSet* objTypes);
     296             : 
     297             :     // jsop_binary_arith helpers.
     298             :     MBinaryArithInstruction* binaryArithInstruction(JSOp op, MDefinition* left, MDefinition* right);
     299             :     AbortReasonOr<Ok> binaryArithTryConcat(bool* emitted, JSOp op, MDefinition* left,
     300             :                                            MDefinition* right);
     301             :     AbortReasonOr<Ok> binaryArithTrySpecialized(bool* emitted, JSOp op, MDefinition* left,
     302             :                                                 MDefinition* right);
     303             :     AbortReasonOr<Ok> binaryArithTrySpecializedOnBaselineInspector(bool* emitted, JSOp op,
     304             :                                                                    MDefinition* left,
     305             :                                                                    MDefinition* right);
     306             :     AbortReasonOr<Ok> arithTrySharedStub(bool* emitted, JSOp op, MDefinition* left,
     307             :                                          MDefinition* right);
     308             : 
     309             :     // jsop_bitnot helpers.
     310             :     AbortReasonOr<Ok> bitnotTrySpecialized(bool* emitted, MDefinition* input);
     311             : 
     312             :     // jsop_pow helpers.
     313             :     AbortReasonOr<Ok> powTrySpecialized(bool* emitted, MDefinition* base, MDefinition* power,
     314             :                                         MIRType outputType);
     315             : 
     316             :     // jsop_compare helpers.
     317             :     AbortReasonOr<Ok> compareTrySpecialized(bool* emitted, JSOp op, MDefinition* left,
     318             :                                             MDefinition* right);
     319             :     AbortReasonOr<Ok> compareTryBitwise(bool* emitted, JSOp op, MDefinition* left,
     320             :                                         MDefinition* right);
     321             :     AbortReasonOr<Ok> compareTrySpecializedOnBaselineInspector(bool* emitted, JSOp op,
     322             :                                                                MDefinition* left,
     323             :                                                                MDefinition* right);
     324             :     AbortReasonOr<Ok> compareTrySharedStub(bool* emitted, JSOp op, MDefinition* left,
     325             :                                            MDefinition* right);
     326             : 
     327             :     // jsop_newarray helpers.
     328             :     AbortReasonOr<Ok> newArrayTrySharedStub(bool* emitted);
     329             :     AbortReasonOr<Ok> newArrayTryTemplateObject(bool* emitted, JSObject* templateObject,
     330             :                                                 uint32_t length);
     331             :     AbortReasonOr<Ok> newArrayTryVM(bool* emitted, JSObject* templateObject, uint32_t length);
     332             : 
     333             :     // jsop_newobject helpers.
     334             :     AbortReasonOr<Ok> newObjectTrySharedStub(bool* emitted);
     335             :     AbortReasonOr<Ok> newObjectTryTemplateObject(bool* emitted, JSObject* templateObject);
     336             :     AbortReasonOr<Ok> newObjectTryVM(bool* emitted, JSObject* templateObject);
     337             : 
     338             :     // jsop_in/jsop_hasown helpers.
     339             :     AbortReasonOr<Ok> inTryDense(bool* emitted, MDefinition* obj, MDefinition* id);
     340             :     AbortReasonOr<Ok> hasTryNotDefined(bool* emitted, MDefinition* obj, MDefinition* id, bool ownProperty);
     341             : 
     342             :     // binary data lookup helpers.
     343             :     TypedObjectPrediction typedObjectPrediction(MDefinition* typedObj);
     344             :     TypedObjectPrediction typedObjectPrediction(TemporaryTypeSet* types);
     345             :     bool typedObjectHasField(MDefinition* typedObj,
     346             :                              PropertyName* name,
     347             :                              size_t* fieldOffset,
     348             :                              TypedObjectPrediction* fieldTypeReprs,
     349             :                              size_t* fieldIndex);
     350             :     MDefinition* loadTypedObjectType(MDefinition* value);
     351             :     AbortReasonOr<Ok> loadTypedObjectData(MDefinition* typedObj,
     352             :                                           MDefinition** owner,
     353             :                                           LinearSum* ownerOffset);
     354             :     AbortReasonOr<Ok> loadTypedObjectElements(MDefinition* typedObj,
     355             :                                               const LinearSum& byteOffset,
     356             :                                               uint32_t scale,
     357             :                                               MDefinition** ownerElements,
     358             :                                               MDefinition** ownerScaledOffset,
     359             :                                               int32_t* ownerByteAdjustment);
     360             :     MDefinition* typeObjectForElementFromArrayStructType(MDefinition* typedObj);
     361             :     MDefinition* typeObjectForFieldFromStructType(MDefinition* type,
     362             :                                                   size_t fieldIndex);
     363             :     AbortReasonOr<bool> storeReferenceTypedObjectValue(MDefinition* typedObj,
     364             :                                                        const LinearSum& byteOffset,
     365             :                                                        ReferenceTypeDescr::Type type,
     366             :                                                        MDefinition* value,
     367             :                                                        PropertyName* name);
     368             :     AbortReasonOr<Ok> storeScalarTypedObjectValue(MDefinition* typedObj,
     369             :                                                   const LinearSum& byteOffset,
     370             :                                                   ScalarTypeDescr::Type type,
     371             :                                                   MDefinition* value);
     372             :     bool checkTypedObjectIndexInBounds(uint32_t elemSize,
     373             :                                        MDefinition* obj,
     374             :                                        MDefinition* index,
     375             :                                        TypedObjectPrediction objTypeDescrs,
     376             :                                        LinearSum* indexAsByteOffset);
     377             :     AbortReasonOr<Ok> pushDerivedTypedObject(bool* emitted,
     378             :                                              MDefinition* obj,
     379             :                                              const LinearSum& byteOffset,
     380             :                                              TypedObjectPrediction derivedTypeDescrs,
     381             :                                              MDefinition* derivedTypeObj);
     382             :     AbortReasonOr<Ok> pushScalarLoadFromTypedObject(MDefinition* obj,
     383             :                                                     const LinearSum& byteoffset,
     384             :                                                     ScalarTypeDescr::Type type);
     385             :     AbortReasonOr<Ok> pushReferenceLoadFromTypedObject(MDefinition* typedObj,
     386             :                                                        const LinearSum& byteOffset,
     387             :                                                        ReferenceTypeDescr::Type type,
     388             :                                                        PropertyName* name);
     389             :     AbortReasonOr<JSObject*> getStaticTypedArrayObject(MDefinition* obj, MDefinition* index);
     390             : 
     391             :     // jsop_setelem() helpers.
     392             :     AbortReasonOr<Ok> setElemTryTypedArray(bool* emitted, MDefinition* object,
     393             :                                            MDefinition* index, MDefinition* value);
     394             :     AbortReasonOr<Ok> setElemTryTypedObject(bool* emitted, MDefinition* obj,
     395             :                                             MDefinition* index, MDefinition* value);
     396             :     AbortReasonOr<Ok> setElemTryTypedStatic(bool* emitted, MDefinition* object,
     397             :                                             MDefinition* index, MDefinition* value);
     398             :     AbortReasonOr<Ok> initOrSetElemTryDense(bool* emitted, MDefinition* object,
     399             :                                             MDefinition* index, MDefinition* value,
     400             :                                             bool writeHole);
     401             :     AbortReasonOr<Ok> setElemTryArguments(bool* emitted, MDefinition* object,
     402             :                                           MDefinition* index, MDefinition* value);
     403             :     AbortReasonOr<Ok> initOrSetElemTryCache(bool* emitted, MDefinition* object,
     404             :                                             MDefinition* index, MDefinition* value);
     405             :     AbortReasonOr<Ok> setElemTryReferenceElemOfTypedObject(bool* emitted,
     406             :                                                            MDefinition* obj,
     407             :                                                            MDefinition* index,
     408             :                                                            TypedObjectPrediction objPrediction,
     409             :                                                            MDefinition* value,
     410             :                                                            TypedObjectPrediction elemPrediction);
     411             :     AbortReasonOr<Ok> setElemTryScalarElemOfTypedObject(bool* emitted,
     412             :                                                         MDefinition* obj,
     413             :                                                         MDefinition* index,
     414             :                                                         TypedObjectPrediction objTypeReprs,
     415             :                                                         MDefinition* value,
     416             :                                                         TypedObjectPrediction elemTypeReprs,
     417             :                                                         uint32_t elemSize);
     418             :     AbortReasonOr<Ok> initializeArrayElement(MDefinition* obj, size_t index, MDefinition* value,
     419             :                                              JSValueType unboxedType,
     420             :                                              bool addResumePointAndIncrementInitializedLength);
     421             : 
     422             :     // jsop_getelem() helpers.
     423             :     AbortReasonOr<Ok> getElemTryDense(bool* emitted, MDefinition* obj, MDefinition* index);
     424             :     AbortReasonOr<Ok> getElemTryGetProp(bool* emitted, MDefinition* obj, MDefinition* index);
     425             :     AbortReasonOr<Ok> getElemTryTypedStatic(bool* emitted, MDefinition* obj, MDefinition* index);
     426             :     AbortReasonOr<Ok> getElemTryTypedArray(bool* emitted, MDefinition* obj, MDefinition* index);
     427             :     AbortReasonOr<Ok> getElemTryTypedObject(bool* emitted, MDefinition* obj, MDefinition* index);
     428             :     AbortReasonOr<Ok> getElemTryString(bool* emitted, MDefinition* obj, MDefinition* index);
     429             :     AbortReasonOr<Ok> getElemTryArguments(bool* emitted, MDefinition* obj, MDefinition* index);
     430             :     AbortReasonOr<Ok> getElemTryArgumentsInlined(bool* emitted, MDefinition* obj,
     431             :                                                  MDefinition* index);
     432             :     AbortReasonOr<Ok> getElemAddCache(MDefinition* obj, MDefinition* index);
     433             :     AbortReasonOr<Ok> getElemTryScalarElemOfTypedObject(bool* emitted,
     434             :                                                         MDefinition* obj,
     435             :                                                         MDefinition* index,
     436             :                                                         TypedObjectPrediction objTypeReprs,
     437             :                                                         TypedObjectPrediction elemTypeReprs,
     438             :                                                         uint32_t elemSize);
     439             :     AbortReasonOr<Ok> getElemTryReferenceElemOfTypedObject(bool* emitted,
     440             :                                                            MDefinition* obj,
     441             :                                                            MDefinition* index,
     442             :                                                            TypedObjectPrediction objPrediction,
     443             :                                                            TypedObjectPrediction elemPrediction);
     444             :     AbortReasonOr<Ok> getElemTryComplexElemOfTypedObject(bool* emitted,
     445             :                                                          MDefinition* obj,
     446             :                                                          MDefinition* index,
     447             :                                                          TypedObjectPrediction objTypeReprs,
     448             :                                                          TypedObjectPrediction elemTypeReprs,
     449             :                                                          uint32_t elemSize);
     450             :     TemporaryTypeSet* computeHeapType(const TemporaryTypeSet* objTypes, const jsid id);
     451             : 
     452             :     enum BoundsChecking { DoBoundsCheck, SkipBoundsCheck };
     453             : 
     454             :     MInstruction* addArrayBufferByteLength(MDefinition* obj);
     455             : 
     456             :     // Add instructions to compute a typed array's length and data.  Also
     457             :     // optionally convert |*index| into a bounds-checked definition, if
     458             :     // requested.
     459             :     //
     460             :     // If you only need the array's length, use addTypedArrayLength below.
     461             :     void addTypedArrayLengthAndData(MDefinition* obj,
     462             :                                     BoundsChecking checking,
     463             :                                     MDefinition** index,
     464             :                                     MInstruction** length, MInstruction** elements);
     465             : 
     466             :     // Add an instruction to compute a typed array's length to the current
     467             :     // block.  If you also need the typed array's data, use the above method
     468             :     // instead.
     469           0 :     MInstruction* addTypedArrayLength(MDefinition* obj) {
     470             :         MInstruction* length;
     471           0 :         addTypedArrayLengthAndData(obj, SkipBoundsCheck, nullptr, &length, nullptr);
     472           0 :         return length;
     473             :     }
     474             : 
     475             :     AbortReasonOr<Ok> improveThisTypesForCall();
     476             : 
     477             :     MDefinition* getCallee();
     478             :     MDefinition* getAliasedVar(EnvironmentCoordinate ec);
     479             :     AbortReasonOr<MDefinition*> addLexicalCheck(MDefinition* input);
     480             : 
     481             :     MDefinition* convertToBoolean(MDefinition* input);
     482             : 
     483             :     AbortReasonOr<Ok> tryFoldInstanceOf(bool* emitted, MDefinition* lhs, JSObject* protoObject);
     484             :     AbortReasonOr<bool> hasOnProtoChain(TypeSet::ObjectKey* key, JSObject* protoObject, bool* onProto);
     485             : 
     486             :     AbortReasonOr<Ok> jsop_add(MDefinition* left, MDefinition* right);
     487             :     AbortReasonOr<Ok> jsop_bitnot();
     488             :     AbortReasonOr<Ok> jsop_bitop(JSOp op);
     489             :     AbortReasonOr<Ok> jsop_binary_arith(JSOp op);
     490             :     AbortReasonOr<Ok> jsop_binary_arith(JSOp op, MDefinition* left, MDefinition* right);
     491             :     AbortReasonOr<Ok> jsop_pow();
     492             :     AbortReasonOr<Ok> jsop_pos();
     493             :     AbortReasonOr<Ok> jsop_neg();
     494             :     AbortReasonOr<Ok> jsop_tostring();
     495             :     AbortReasonOr<Ok> jsop_setarg(uint32_t arg);
     496             :     AbortReasonOr<Ok> jsop_defvar(uint32_t index);
     497             :     AbortReasonOr<Ok> jsop_deflexical(uint32_t index);
     498             :     AbortReasonOr<Ok> jsop_deffun(uint32_t index);
     499             :     AbortReasonOr<Ok> jsop_notearg();
     500             :     AbortReasonOr<Ok> jsop_throwsetconst();
     501             :     AbortReasonOr<Ok> jsop_checklexical();
     502             :     AbortReasonOr<Ok> jsop_checkaliasedlexical(EnvironmentCoordinate ec);
     503             :     AbortReasonOr<Ok> jsop_funcall(uint32_t argc);
     504             :     AbortReasonOr<Ok> jsop_funapply(uint32_t argc);
     505             :     AbortReasonOr<Ok> jsop_funapplyarguments(uint32_t argc);
     506             :     AbortReasonOr<Ok> jsop_funapplyarray(uint32_t argc);
     507             :     AbortReasonOr<Ok> jsop_spreadcall();
     508             :     AbortReasonOr<Ok> jsop_call(uint32_t argc, bool constructing, bool ignoresReturnValue);
     509             :     AbortReasonOr<Ok> jsop_eval(uint32_t argc);
     510             :     AbortReasonOr<Ok> jsop_label();
     511             :     AbortReasonOr<Ok> jsop_andor(JSOp op);
     512             :     AbortReasonOr<Ok> jsop_dup2();
     513             :     AbortReasonOr<Ok> jsop_loophead(jsbytecode* pc);
     514             :     AbortReasonOr<Ok> jsop_compare(JSOp op);
     515             :     AbortReasonOr<Ok> jsop_compare(JSOp op, MDefinition* left, MDefinition* right);
     516             :     AbortReasonOr<Ok> getStaticName(bool* emitted, JSObject* staticObject, PropertyName* name,
     517             :                                     MDefinition* lexicalCheck = nullptr);
     518             :     AbortReasonOr<Ok> loadStaticSlot(JSObject* staticObject, BarrierKind barrier,
     519             :                                      TemporaryTypeSet* types, uint32_t slot);
     520             :     AbortReasonOr<Ok> setStaticName(JSObject* staticObject, PropertyName* name);
     521             :     AbortReasonOr<Ok> jsop_getgname(PropertyName* name);
     522             :     AbortReasonOr<Ok> jsop_getname(PropertyName* name);
     523             :     AbortReasonOr<Ok> jsop_intrinsic(PropertyName* name);
     524             :     AbortReasonOr<Ok> jsop_getimport(PropertyName* name);
     525             :     AbortReasonOr<Ok> jsop_bindname(PropertyName* name);
     526             :     AbortReasonOr<Ok> jsop_bindvar();
     527             :     AbortReasonOr<Ok> jsop_getelem();
     528             :     AbortReasonOr<Ok> jsop_getelem_dense(MDefinition* obj, MDefinition* index,
     529             :                                          JSValueType unboxedType);
     530             :     AbortReasonOr<Ok> jsop_getelem_typed(MDefinition* obj, MDefinition* index,
     531             :                                          ScalarTypeDescr::Type arrayType);
     532             :     AbortReasonOr<Ok> jsop_setelem();
     533             :     AbortReasonOr<Ok> initOrSetElemDense(TemporaryTypeSet::DoubleConversion conversion,
     534             :                                          MDefinition* object, MDefinition* index,
     535             :                                          MDefinition* value, JSValueType unboxedType,
     536             :                                          bool writeHole, bool* emitted);
     537             :     AbortReasonOr<Ok> jsop_setelem_typed(ScalarTypeDescr::Type arrayType,
     538             :                                          MDefinition* object, MDefinition* index,
     539             :                                          MDefinition* value);
     540             :     AbortReasonOr<Ok> jsop_length();
     541             :     bool jsop_length_fastPath();
     542             :     AbortReasonOr<Ok> jsop_arguments();
     543             :     AbortReasonOr<Ok> jsop_arguments_getelem();
     544             :     AbortReasonOr<Ok> jsop_runonce();
     545             :     AbortReasonOr<Ok> jsop_rest();
     546             :     AbortReasonOr<Ok> jsop_not();
     547             :     AbortReasonOr<Ok> jsop_getprop(PropertyName* name);
     548             :     AbortReasonOr<Ok> jsop_setprop(PropertyName* name);
     549             :     AbortReasonOr<Ok> jsop_delprop(PropertyName* name);
     550             :     AbortReasonOr<Ok> jsop_delelem();
     551             :     AbortReasonOr<Ok> jsop_newarray(uint32_t length);
     552             :     AbortReasonOr<Ok> jsop_newarray(JSObject* templateObject, uint32_t length);
     553             :     AbortReasonOr<Ok> jsop_newarray_copyonwrite();
     554             :     AbortReasonOr<Ok> jsop_newobject();
     555             :     AbortReasonOr<Ok> jsop_initelem();
     556             :     AbortReasonOr<Ok> jsop_initelem_inc();
     557             :     AbortReasonOr<Ok> jsop_initelem_array();
     558             :     AbortReasonOr<Ok> jsop_initelem_getter_setter();
     559             :     AbortReasonOr<Ok> jsop_mutateproto();
     560             :     AbortReasonOr<Ok> jsop_initprop(PropertyName* name);
     561             :     AbortReasonOr<Ok> jsop_initprop_getter_setter(PropertyName* name);
     562             :     AbortReasonOr<Ok> jsop_regexp(RegExpObject* reobj);
     563             :     AbortReasonOr<Ok> jsop_object(JSObject* obj);
     564             :     AbortReasonOr<Ok> jsop_lambda(JSFunction* fun);
     565             :     AbortReasonOr<Ok> jsop_lambda_arrow(JSFunction* fun);
     566             :     AbortReasonOr<Ok> jsop_setfunname(uint8_t prefixKind);
     567             :     AbortReasonOr<Ok> jsop_pushlexicalenv(uint32_t index);
     568             :     AbortReasonOr<Ok> jsop_copylexicalenv(bool copySlots);
     569             :     AbortReasonOr<Ok> jsop_functionthis();
     570             :     AbortReasonOr<Ok> jsop_globalthis();
     571             :     AbortReasonOr<Ok> jsop_typeof();
     572             :     AbortReasonOr<Ok> jsop_toasync();
     573             :     AbortReasonOr<Ok> jsop_toasyncgen();
     574             :     AbortReasonOr<Ok> jsop_toasynciter();
     575             :     AbortReasonOr<Ok> jsop_toid();
     576             :     AbortReasonOr<Ok> jsop_iter(uint8_t flags);
     577             :     AbortReasonOr<Ok> jsop_itermore();
     578             :     AbortReasonOr<Ok> jsop_isnoiter();
     579             :     AbortReasonOr<Ok> jsop_iterend();
     580             :     AbortReasonOr<Ok> jsop_in();
     581             :     AbortReasonOr<Ok> jsop_hasown();
     582             :     AbortReasonOr<Ok> jsop_instanceof();
     583             :     AbortReasonOr<Ok> jsop_getaliasedvar(EnvironmentCoordinate ec);
     584             :     AbortReasonOr<Ok> jsop_setaliasedvar(EnvironmentCoordinate ec);
     585             :     AbortReasonOr<Ok> jsop_debugger();
     586             :     AbortReasonOr<Ok> jsop_newtarget();
     587             :     AbortReasonOr<Ok> jsop_checkisobj(uint8_t kind);
     588             :     AbortReasonOr<Ok> jsop_checkiscallable(uint8_t kind);
     589             :     AbortReasonOr<Ok> jsop_checkobjcoercible();
     590             :     AbortReasonOr<Ok> jsop_pushcallobj();
     591             : 
     592             :     /* Inlining. */
     593             : 
     594             :     enum InliningStatus
     595             :     {
     596             :         InliningStatus_NotInlined,
     597             :         InliningStatus_WarmUpCountTooLow,
     598             :         InliningStatus_Inlined
     599             :     };
     600             :     using InliningResult = AbortReasonOr<InliningStatus>;
     601             : 
     602             :     enum InliningDecision
     603             :     {
     604             :         InliningDecision_Error,
     605             :         InliningDecision_Inline,
     606             :         InliningDecision_DontInline,
     607             :         InliningDecision_WarmUpCountTooLow
     608             :     };
     609             : 
     610             :     static InliningDecision DontInline(JSScript* targetScript, const char* reason);
     611             : 
     612             :     // Helper function for canInlineTarget
     613             :     bool hasCommonInliningPath(const JSScript* scriptToInline);
     614             : 
     615             :     // Oracles.
     616             :     InliningDecision canInlineTarget(JSFunction* target, CallInfo& callInfo);
     617             :     InliningDecision makeInliningDecision(JSObject* target, CallInfo& callInfo);
     618             :     AbortReasonOr<Ok> selectInliningTargets(const InliningTargets& targets, CallInfo& callInfo,
     619             :                                             BoolVector& choiceSet, uint32_t* numInlineable);
     620             : 
     621             :     // Native inlining helpers.
     622             :     // The typeset for the return value of our function.  These are
     623             :     // the types it's been observed returning in the past.
     624             :     TemporaryTypeSet* getInlineReturnTypeSet();
     625             :     // The known MIR type of getInlineReturnTypeSet.
     626             :     MIRType getInlineReturnType();
     627             : 
     628             :     // Array natives.
     629             :     InliningResult inlineArray(CallInfo& callInfo);
     630             :     InliningResult inlineArrayIsArray(CallInfo& callInfo);
     631             :     InliningResult inlineArrayPopShift(CallInfo& callInfo, MArrayPopShift::Mode mode);
     632             :     InliningResult inlineArrayPush(CallInfo& callInfo);
     633             :     InliningResult inlineArraySlice(CallInfo& callInfo);
     634             :     InliningResult inlineArrayJoin(CallInfo& callInfo);
     635             : 
     636             :     // Boolean natives.
     637             :     InliningResult inlineBoolean(CallInfo& callInfo);
     638             : 
     639             :     // Iterator intrinsics.
     640             :     InliningResult inlineNewIterator(CallInfo& callInfo, MNewIterator::Type type);
     641             : 
     642             :     // Math natives.
     643             :     InliningResult inlineMathAbs(CallInfo& callInfo);
     644             :     InliningResult inlineMathFloor(CallInfo& callInfo);
     645             :     InliningResult inlineMathCeil(CallInfo& callInfo);
     646             :     InliningResult inlineMathClz32(CallInfo& callInfo);
     647             :     InliningResult inlineMathRound(CallInfo& callInfo);
     648             :     InliningResult inlineMathSqrt(CallInfo& callInfo);
     649             :     InliningResult inlineMathAtan2(CallInfo& callInfo);
     650             :     InliningResult inlineMathHypot(CallInfo& callInfo);
     651             :     InliningResult inlineMathMinMax(CallInfo& callInfo, bool max);
     652             :     InliningResult inlineMathPow(CallInfo& callInfo);
     653             :     InliningResult inlineMathRandom(CallInfo& callInfo);
     654             :     InliningResult inlineMathImul(CallInfo& callInfo);
     655             :     InliningResult inlineMathFRound(CallInfo& callInfo);
     656             :     InliningResult inlineMathFunction(CallInfo& callInfo, MMathFunction::Function function);
     657             : 
     658             :     // String natives.
     659             :     InliningResult inlineStringObject(CallInfo& callInfo);
     660             :     InliningResult inlineStrCharCodeAt(CallInfo& callInfo);
     661             :     InliningResult inlineConstantCharCodeAt(CallInfo& callInfo);
     662             :     InliningResult inlineStrFromCharCode(CallInfo& callInfo);
     663             :     InliningResult inlineStrFromCodePoint(CallInfo& callInfo);
     664             :     InliningResult inlineStrCharAt(CallInfo& callInfo);
     665             : 
     666             :     // String intrinsics.
     667             :     InliningResult inlineStringReplaceString(CallInfo& callInfo);
     668             :     InliningResult inlineConstantStringSplitString(CallInfo& callInfo);
     669             :     InliningResult inlineStringSplitString(CallInfo& callInfo);
     670             : 
     671             :     // RegExp intrinsics.
     672             :     InliningResult inlineRegExpMatcher(CallInfo& callInfo);
     673             :     InliningResult inlineRegExpSearcher(CallInfo& callInfo);
     674             :     InliningResult inlineRegExpTester(CallInfo& callInfo);
     675             :     InliningResult inlineIsRegExpObject(CallInfo& callInfo);
     676             :     InliningResult inlineRegExpPrototypeOptimizable(CallInfo& callInfo);
     677             :     InliningResult inlineRegExpInstanceOptimizable(CallInfo& callInfo);
     678             :     InliningResult inlineGetFirstDollarIndex(CallInfo& callInfo);
     679             : 
     680             :     // Object natives and intrinsics.
     681             :     InliningResult inlineObjectCreate(CallInfo& callInfo);
     682             :     InliningResult inlineDefineDataProperty(CallInfo& callInfo);
     683             : 
     684             :     // Atomics natives.
     685             :     InliningResult inlineAtomicsCompareExchange(CallInfo& callInfo);
     686             :     InliningResult inlineAtomicsExchange(CallInfo& callInfo);
     687             :     InliningResult inlineAtomicsLoad(CallInfo& callInfo);
     688             :     InliningResult inlineAtomicsStore(CallInfo& callInfo);
     689             :     InliningResult inlineAtomicsBinop(CallInfo& callInfo, InlinableNative target);
     690             :     InliningResult inlineAtomicsIsLockFree(CallInfo& callInfo);
     691             : 
     692             :     // Slot intrinsics.
     693             :     InliningResult inlineUnsafeSetReservedSlot(CallInfo& callInfo);
     694             :     InliningResult inlineUnsafeGetReservedSlot(CallInfo& callInfo,
     695             :                                                MIRType knownValueType);
     696             : 
     697             :     // Map and Set intrinsics.
     698             :     InliningResult inlineGetNextEntryForIterator(CallInfo& callInfo,
     699             :                                                  MGetNextEntryForIterator::Mode mode);
     700             : 
     701             :     // ArrayBuffer intrinsics.
     702             :     InliningResult inlineArrayBufferByteLength(CallInfo& callInfo);
     703             :     InliningResult inlinePossiblyWrappedArrayBufferByteLength(CallInfo& callInfo);
     704             : 
     705             :     // TypedArray intrinsics.
     706             :     enum WrappingBehavior { AllowWrappedTypedArrays, RejectWrappedTypedArrays };
     707             :     InliningResult inlineTypedArray(CallInfo& callInfo, Native native);
     708             :     InliningResult inlineIsTypedArrayHelper(CallInfo& callInfo, WrappingBehavior wrappingBehavior);
     709             :     InliningResult inlineIsTypedArray(CallInfo& callInfo);
     710             :     InliningResult inlineIsPossiblyWrappedTypedArray(CallInfo& callInfo);
     711             :     InliningResult inlineTypedArrayLength(CallInfo& callInfo);
     712             :     InliningResult inlinePossiblyWrappedTypedArrayLength(CallInfo& callInfo);
     713             :     InliningResult inlineSetDisjointTypedElements(CallInfo& callInfo);
     714             : 
     715             :     // TypedObject intrinsics and natives.
     716             :     InliningResult inlineObjectIsTypeDescr(CallInfo& callInfo);
     717             :     InliningResult inlineSetTypedObjectOffset(CallInfo& callInfo);
     718             :     InliningResult inlineConstructTypedObject(CallInfo& callInfo, TypeDescr* target);
     719             : 
     720             :     // SIMD intrinsics and natives.
     721             :     InliningResult inlineConstructSimdObject(CallInfo& callInfo, SimdTypeDescr* target);
     722             : 
     723             :     // SIMD helpers.
     724             :     bool canInlineSimd(CallInfo& callInfo, JSNative native, unsigned numArgs,
     725             :                        InlineTypedObject** templateObj);
     726             :     MDefinition* unboxSimd(MDefinition* ins, SimdType type);
     727             :     InliningResult boxSimd(CallInfo& callInfo, MDefinition* ins, InlineTypedObject* templateObj);
     728             :     MDefinition* convertToBooleanSimdLane(MDefinition* scalar);
     729             : 
     730             :     InliningResult inlineSimd(CallInfo& callInfo, JSFunction* target, SimdType type);
     731             : 
     732             :     InliningResult inlineSimdBinaryArith(CallInfo& callInfo, JSNative native,
     733             :                                          MSimdBinaryArith::Operation op, SimdType type);
     734             :     InliningResult inlineSimdBinaryBitwise(CallInfo& callInfo, JSNative native,
     735             :                                            MSimdBinaryBitwise::Operation op, SimdType type);
     736             :     InliningResult inlineSimdBinarySaturating(CallInfo& callInfo, JSNative native,
     737             :                                               MSimdBinarySaturating::Operation op, SimdType type);
     738             :     InliningResult inlineSimdShift(CallInfo& callInfo, JSNative native, MSimdShift::Operation op,
     739             :                                    SimdType type);
     740             :     InliningResult inlineSimdComp(CallInfo& callInfo, JSNative native,
     741             :                                   MSimdBinaryComp::Operation op, SimdType type);
     742             :     InliningResult inlineSimdUnary(CallInfo& callInfo, JSNative native,
     743             :                                    MSimdUnaryArith::Operation op, SimdType type);
     744             :     InliningResult inlineSimdExtractLane(CallInfo& callInfo, JSNative native, SimdType type);
     745             :     InliningResult inlineSimdReplaceLane(CallInfo& callInfo, JSNative native, SimdType type);
     746             :     InliningResult inlineSimdSplat(CallInfo& callInfo, JSNative native, SimdType type);
     747             :     InliningResult inlineSimdShuffle(CallInfo& callInfo, JSNative native, SimdType type,
     748             :                                      unsigned numVectors);
     749             :     InliningResult inlineSimdCheck(CallInfo& callInfo, JSNative native, SimdType type);
     750             :     InliningResult inlineSimdConvert(CallInfo& callInfo, JSNative native, bool isCast,
     751             :                                      SimdType from, SimdType to);
     752             :     InliningResult inlineSimdSelect(CallInfo& callInfo, JSNative native, SimdType type);
     753             : 
     754             :     bool prepareForSimdLoadStore(CallInfo& callInfo, Scalar::Type simdType,
     755             :                                  MInstruction** elements, MDefinition** index,
     756             :                                  Scalar::Type* arrayType);
     757             :     InliningResult inlineSimdLoad(CallInfo& callInfo, JSNative native, SimdType type,
     758             :                                   unsigned numElems);
     759             :     InliningResult inlineSimdStore(CallInfo& callInfo, JSNative native, SimdType type,
     760             :                                    unsigned numElems);
     761             : 
     762             :     InliningResult inlineSimdAnyAllTrue(CallInfo& callInfo, bool IsAllTrue, JSNative native,
     763             :                                         SimdType type);
     764             : 
     765             :     // Utility intrinsics.
     766             :     InliningResult inlineIsCallable(CallInfo& callInfo);
     767             :     InliningResult inlineIsConstructor(CallInfo& callInfo);
     768             :     InliningResult inlineIsObject(CallInfo& callInfo);
     769             :     InliningResult inlineToObject(CallInfo& callInfo);
     770             :     InliningResult inlineIsWrappedArrayConstructor(CallInfo& callInfo);
     771             :     InliningResult inlineToInteger(CallInfo& callInfo);
     772             :     InliningResult inlineToString(CallInfo& callInfo);
     773             :     InliningResult inlineDump(CallInfo& callInfo);
     774             :     InliningResult inlineHasClass(CallInfo& callInfo, const Class* clasp,
     775             :                                   const Class* clasp2 = nullptr,
     776             :                                   const Class* clasp3 = nullptr,
     777             :                                   const Class* clasp4 = nullptr);
     778             :     InliningResult inlineIsConstructing(CallInfo& callInfo);
     779             :     InliningResult inlineSubstringKernel(CallInfo& callInfo);
     780             :     InliningResult inlineObjectHasPrototype(CallInfo& callInfo);
     781             :     InliningResult inlineFinishBoundFunctionInit(CallInfo& callInfo);
     782             : 
     783             :     // Testing functions.
     784             :     InliningResult inlineBailout(CallInfo& callInfo);
     785             :     InliningResult inlineAssertFloat32(CallInfo& callInfo);
     786             :     InliningResult inlineAssertRecoveredOnBailout(CallInfo& callInfo);
     787             : 
     788             :     // Bind function.
     789             :     InliningResult inlineBoundFunction(CallInfo& callInfo, JSFunction* target);
     790             : 
     791             :     // Main inlining functions
     792             :     InliningResult inlineNativeCall(CallInfo& callInfo, JSFunction* target);
     793             :     InliningResult inlineNativeGetter(CallInfo& callInfo, JSFunction* target);
     794             :     InliningResult inlineNonFunctionCall(CallInfo& callInfo, JSObject* target);
     795             :     InliningResult inlineScriptedCall(CallInfo& callInfo, JSFunction* target);
     796             :     InliningResult inlineSingleCall(CallInfo& callInfo, JSObject* target);
     797             : 
     798             :     // Call functions
     799             :     InliningResult inlineCallsite(const InliningTargets& targets, CallInfo& callInfo);
     800             :     AbortReasonOr<Ok> inlineCalls(CallInfo& callInfo, const InliningTargets& targets,
     801             :                                   BoolVector& choiceSet, MGetPropertyCache* maybeCache);
     802             : 
     803             :     // Inlining helpers.
     804             :     AbortReasonOr<Ok> inlineGenericFallback(JSFunction* target, CallInfo& callInfo,
     805             :                                             MBasicBlock* dispatchBlock);
     806             :     AbortReasonOr<Ok> inlineObjectGroupFallback(CallInfo& callInfo, MBasicBlock* dispatchBlock,
     807             :                                                 MObjectGroupDispatch* dispatch,
     808             :                                                 MGetPropertyCache* cache,
     809             :                                                 MBasicBlock** fallbackTarget);
     810             : 
     811             :     enum AtomicCheckResult {
     812             :         DontCheckAtomicResult,
     813             :         DoCheckAtomicResult
     814             :     };
     815             : 
     816             :     bool atomicsMeetsPreconditions(CallInfo& callInfo, Scalar::Type* arrayElementType,
     817             :                                    bool* requiresDynamicCheck,
     818             :                                    AtomicCheckResult checkResult=DoCheckAtomicResult);
     819             :     void atomicsCheckBounds(CallInfo& callInfo, MInstruction** elements, MDefinition** index);
     820             : 
     821             :     bool testNeedsArgumentCheck(JSFunction* target, CallInfo& callInfo);
     822             : 
     823             :     AbortReasonOr<MCall*> makeCallHelper(JSFunction* target, CallInfo& callInfo);
     824             :     AbortReasonOr<Ok> makeCall(JSFunction* target, CallInfo& callInfo);
     825             : 
     826             :     MDefinition* patchInlinedReturn(CallInfo& callInfo, MBasicBlock* exit, MBasicBlock* bottom);
     827             :     MDefinition* patchInlinedReturns(CallInfo& callInfo, MIRGraphReturns& returns,
     828             :                                      MBasicBlock* bottom);
     829             :     MDefinition* specializeInlinedReturn(MDefinition* rdef, MBasicBlock* exit);
     830             : 
     831             :     NativeObject* commonPrototypeWithGetterSetter(TemporaryTypeSet* types, PropertyName* name,
     832             :                                                   bool isGetter, JSFunction* getterOrSetter,
     833             :                                                   bool* guardGlobal);
     834             :     void freezePropertiesForCommonPrototype(TemporaryTypeSet* types, PropertyName* name,
     835             :                                             JSObject* foundProto, bool allowEmptyTypesForGlobal = false);
     836             :     /*
     837             :      * Callers must pass a non-null globalGuard if they pass a non-null globalShape.
     838             :      */
     839             :     bool testCommonGetterSetter(TemporaryTypeSet* types, PropertyName* name,
     840             :                                 bool isGetter, JSFunction* getterOrSetter,
     841             :                                 MDefinition** guard, Shape* globalShape = nullptr,
     842             :                                 MDefinition** globalGuard = nullptr);
     843             :     AbortReasonOr<bool> testShouldDOMCall(TypeSet* inTypes,
     844             :                                           JSFunction* func, JSJitInfo::OpType opType);
     845             : 
     846             :     MDefinition*
     847             :     addShapeGuardsForGetterSetter(MDefinition* obj, JSObject* holder, Shape* holderShape,
     848             :                                   const BaselineInspector::ReceiverVector& receivers,
     849             :                                   const BaselineInspector::ObjectGroupVector& convertUnboxedGroups,
     850             :                                   bool isOwnProperty);
     851             : 
     852             :     AbortReasonOr<Ok> annotateGetPropertyCache(MDefinition* obj, PropertyName* name,
     853             :                                                MGetPropertyCache* getPropCache,
     854             :                                                TemporaryTypeSet* objTypes,
     855             :                                                TemporaryTypeSet* pushedTypes);
     856             : 
     857             :     MGetPropertyCache* getInlineableGetPropertyCache(CallInfo& callInfo);
     858             : 
     859             :     JSObject* testGlobalLexicalBinding(PropertyName* name);
     860             : 
     861             :     JSObject* testSingletonProperty(JSObject* obj, jsid id);
     862             :     JSObject* testSingletonPropertyTypes(MDefinition* obj, jsid id);
     863             : 
     864             :     AbortReasonOr<bool> testNotDefinedProperty(MDefinition* obj, jsid id, bool ownProperty = false);
     865             : 
     866             :     uint32_t getDefiniteSlot(TemporaryTypeSet* types, PropertyName* name, uint32_t* pnfixed);
     867             :     MDefinition* convertUnboxedObjects(MDefinition* obj);
     868             :     MDefinition* convertUnboxedObjects(MDefinition* obj,
     869             :                                        const BaselineInspector::ObjectGroupVector& list);
     870             :     uint32_t getUnboxedOffset(TemporaryTypeSet* types, PropertyName* name,
     871             :                               JSValueType* punboxedType);
     872             :     MInstruction* loadUnboxedProperty(MDefinition* obj, size_t offset, JSValueType unboxedType,
     873             :                                       BarrierKind barrier, TemporaryTypeSet* types);
     874             :     MInstruction* loadUnboxedValue(MDefinition* elements, size_t elementsOffset,
     875             :                                    MDefinition* scaledOffset, JSValueType unboxedType,
     876             :                                    BarrierKind barrier, TemporaryTypeSet* types);
     877             :     MInstruction* storeUnboxedProperty(MDefinition* obj, size_t offset, JSValueType unboxedType,
     878             :                                        MDefinition* value);
     879             :     MInstruction* storeUnboxedValue(MDefinition* obj,
     880             :                                     MDefinition* elements, int32_t elementsOffset,
     881             :                                     MDefinition* scaledOffset, JSValueType unboxedType,
     882             :                                     MDefinition* value, bool preBarrier = true);
     883             :     AbortReasonOr<Ok> checkPreliminaryGroups(MDefinition *obj);
     884             :     AbortReasonOr<Ok> freezePropTypeSets(TemporaryTypeSet* types,
     885             :                                          JSObject* foundProto, PropertyName* name);
     886             :     bool canInlinePropertyOpShapes(const BaselineInspector::ReceiverVector& receivers);
     887             : 
     888             :     TemporaryTypeSet* bytecodeTypes(jsbytecode* pc);
     889             : 
     890             :     // Use one of the below methods for updating the current block, rather than
     891             :     // updating |current| directly. setCurrent() should only be used in cases
     892             :     // where the block cannot have phis whose type needs to be computed.
     893             : 
     894        4762 :     AbortReasonOr<Ok> setCurrentAndSpecializePhis(MBasicBlock* block) {
     895        4762 :         if (block) {
     896        4762 :             if (!block->specializePhis(alloc()))
     897           0 :                 return abort(AbortReason::Alloc);
     898             :         }
     899        4762 :         setCurrent(block);
     900        4762 :         return Ok();
     901             :     }
     902             : 
     903        5446 :     void setCurrent(MBasicBlock* block) {
     904        5446 :         current = block;
     905        5446 :     }
     906             : 
     907             :     // A builder is inextricably tied to a particular script.
     908             :     JSScript* script_;
     909             : 
     910             :     // script->hasIonScript() at the start of the compilation. Used to avoid
     911             :     // calling hasIonScript() from background compilation threads.
     912             :     bool scriptHasIonScript_;
     913             : 
     914             :     // If off thread compilation is successful, the final code generator is
     915             :     // attached here. Code has been generated, but not linked (there is not yet
     916             :     // an IonScript). This is heap allocated, and must be explicitly destroyed,
     917             :     // performed by FinishOffThreadBuilder().
     918             :     CodeGenerator* backgroundCodegen_;
     919             : 
     920             :     // Some aborts are actionable (e.g., using an unsupported bytecode). When
     921             :     // optimization tracking is enabled, the location and message of the abort
     922             :     // are recorded here so they may be propagated to the script's
     923             :     // corresponding JitcodeGlobalEntry::BaselineEntry.
     924             :     JSScript* actionableAbortScript_;
     925             :     jsbytecode* actionableAbortPc_;
     926             :     const char* actionableAbortMessage_;
     927             : 
     928             :     MRootList* rootList_;
     929             : 
     930             :   public:
     931           8 :     void setRootList(MRootList& rootList) {
     932           8 :         MOZ_ASSERT(!rootList_);
     933           8 :         rootList_ = &rootList;
     934           8 :     }
     935             :     void clearForBackEnd();
     936             :     JSObject* checkNurseryObject(JSObject* obj);
     937             : 
     938       15831 :     JSScript* script() const { return script_; }
     939           2 :     bool scriptHasIonScript() const { return scriptHasIonScript_; }
     940             : 
     941          15 :     CodeGenerator* backgroundCodegen() const { return backgroundCodegen_; }
     942           8 :     void setBackgroundCodegen(CodeGenerator* codegen) { backgroundCodegen_ = codegen; }
     943             : 
     944        7951 :     CompilerConstraintList* constraints() {
     945        7951 :         return constraints_;
     946             :     }
     947             : 
     948           5 :     bool isInlineBuilder() const {
     949           5 :         return callerBuilder_ != nullptr;
     950             :     }
     951             : 
     952         209 :     const JSAtomState& names() { return compartment->runtime()->names(); }
     953             : 
     954           2 :     bool hadActionableAbort() const {
     955           2 :         MOZ_ASSERT(!actionableAbortScript_ ||
     956             :                    (actionableAbortPc_ && actionableAbortMessage_));
     957           2 :         return actionableAbortScript_ != nullptr;
     958             :     }
     959             : 
     960           1 :     TraceLoggerThread *traceLogger() {
     961           1 :         return TraceLoggerForCurrentThread();
     962             :     }
     963             : 
     964           0 :     void actionableAbortLocationAndMessage(JSScript** abortScript, jsbytecode** abortPc,
     965             :                                            const char** abortMessage)
     966             :     {
     967           0 :         MOZ_ASSERT(hadActionableAbort());
     968           0 :         *abortScript = actionableAbortScript_;
     969           0 :         *abortPc = actionableAbortPc_;
     970           0 :         *abortMessage = actionableAbortMessage_;
     971           0 :     }
     972             : 
     973             :     void trace(JSTracer* trc);
     974             : 
     975             :   private:
     976             :     AbortReasonOr<Ok> init();
     977             : 
     978             :     JSContext* analysisContext;
     979             :     BaselineFrameInspector* baselineFrame_;
     980             : 
     981             :     // Constraints for recording dependencies on type information.
     982             :     CompilerConstraintList* constraints_;
     983             : 
     984             :     // Basic analysis information about the script.
     985             :     BytecodeAnalysis analysis_;
     986        4487 :     BytecodeAnalysis& analysis() {
     987        4487 :         return analysis_;
     988             :     }
     989             : 
     990             :     TemporaryTypeSet* thisTypes;
     991             :     TemporaryTypeSet* argTypes;
     992             :     TemporaryTypeSet* typeArray;
     993             :     uint32_t typeArrayHint;
     994             :     uint32_t* bytecodeTypeMap;
     995             : 
     996             :     GSNCache gsn;
     997             :     EnvironmentCoordinateNameCache envCoordinateNameCache;
     998             : 
     999             :     jsbytecode* pc;
    1000             :     MBasicBlock* current;
    1001             :     uint32_t loopDepth_;
    1002             :     Vector<MBasicBlock*, 0, JitAllocPolicy> blockWorklist;
    1003             :     const CFGBlock* cfgCurrent;
    1004             :     const ControlFlowGraph* cfg;
    1005             : 
    1006             :     Vector<BytecodeSite*, 0, JitAllocPolicy> trackedOptimizationSites_;
    1007             : 
    1008       23065 :     BytecodeSite* bytecodeSite(jsbytecode* pc) {
    1009       23065 :         MOZ_ASSERT(info().inlineScriptTree()->script()->containsPC(pc));
    1010             :         // See comment in maybeTrackedOptimizationSite.
    1011       23065 :         if (isOptimizationTrackingEnabled()) {
    1012           0 :             if (BytecodeSite* site = maybeTrackedOptimizationSite(pc))
    1013           0 :                 return site;
    1014             :         }
    1015       23065 :         return new(alloc()) BytecodeSite(info().inlineScriptTree(), pc);
    1016             :     }
    1017             : 
    1018             :     BytecodeSite* maybeTrackedOptimizationSite(jsbytecode* pc);
    1019             : 
    1020             :     MDefinition* lexicalCheck_;
    1021             : 
    1022           0 :     void setLexicalCheck(MDefinition* lexical) {
    1023           0 :         MOZ_ASSERT(!lexicalCheck_);
    1024           0 :         lexicalCheck_ = lexical;
    1025           0 :     }
    1026         633 :     MDefinition* takeLexicalCheck() {
    1027         633 :         MDefinition* lexical = lexicalCheck_;
    1028         633 :         lexicalCheck_ = nullptr;
    1029         633 :         return lexical;
    1030             :     }
    1031             : 
    1032             :     /* Information used for inline-call builders. */
    1033             :     MResumePoint* callerResumePoint_;
    1034             :     jsbytecode* callerPC() {
    1035             :         return callerResumePoint_ ? callerResumePoint_->pc() : nullptr;
    1036             :     }
    1037             :     IonBuilder* callerBuilder_;
    1038             : 
    1039             :     IonBuilder* outermostBuilder();
    1040             : 
    1041             :     struct LoopHeader {
    1042             :         jsbytecode* pc;
    1043             :         MBasicBlock* header;
    1044             : 
    1045         118 :         LoopHeader(jsbytecode* pc, MBasicBlock* header)
    1046         118 :           : pc(pc), header(header)
    1047         118 :         {}
    1048             :     };
    1049             : 
    1050             :     Vector<MDefinition*, 2, JitAllocPolicy> iterators_;
    1051             :     Vector<LoopHeader, 0, JitAllocPolicy> loopHeaders_;
    1052             :     Vector<MBasicBlock*, 0, JitAllocPolicy> loopHeaderStack_;
    1053             : #ifdef DEBUG
    1054             :     Vector<const CFGBlock*, 0, JitAllocPolicy> cfgLoopHeaderStack_;
    1055             : #endif
    1056             : 
    1057             :     BaselineInspector* inspector;
    1058             : 
    1059             :     size_t inliningDepth_;
    1060             : 
    1061             :     // Total bytecode length of all inlined scripts. Only tracked for the
    1062             :     // outermost builder.
    1063             :     size_t inlinedBytecodeLength_;
    1064             : 
    1065             :     // Cutoff to disable compilation if excessive time is spent reanalyzing
    1066             :     // loop bodies to compute a fixpoint of the types for loop variables.
    1067             :     static const size_t MAX_LOOP_RESTARTS = 40;
    1068             :     size_t numLoopRestarts_;
    1069             : 
    1070             :     // True if script->failedBoundsCheck is set for the current script or
    1071             :     // an outer script.
    1072             :     bool failedBoundsCheck_;
    1073             : 
    1074             :     // True if script->failedShapeGuard is set for the current script or
    1075             :     // an outer script.
    1076             :     bool failedShapeGuard_;
    1077             : 
    1078             :     // True if script->failedLexicalCheck_ is set for the current script or
    1079             :     // an outer script.
    1080             :     bool failedLexicalCheck_;
    1081             : 
    1082             :     // Has an iterator other than 'for in'.
    1083             :     bool nonStringIteration_;
    1084             : 
    1085             : #ifdef DEBUG
    1086             :     // If this script uses the lazy arguments object.
    1087             :     bool hasLazyArguments_;
    1088             : #endif
    1089             : 
    1090             :     // If this is an inline builder, the call info for the builder.
    1091             :     const CallInfo* inlineCallInfo_;
    1092             : 
    1093             :     // When compiling a call with multiple targets, we are first creating a
    1094             :     // MGetPropertyCache.  This MGetPropertyCache is following the bytecode, and
    1095             :     // is used to recover the JSFunction.  In some cases, the Type of the object
    1096             :     // which own the property is enough for dispatching to the right function.
    1097             :     // In such cases we do not have read the property, except when the type
    1098             :     // object is unknown.
    1099             :     //
    1100             :     // As an optimization, we can dispatch a call based on the object group,
    1101             :     // without doing the MGetPropertyCache.  This is what is achieved by
    1102             :     // |IonBuilder::inlineCalls|.  As we might not know all the functions, we
    1103             :     // are adding a fallback path, where this MGetPropertyCache would be moved
    1104             :     // into.
    1105             :     //
    1106             :     // In order to build the fallback path, we have to capture a resume point
    1107             :     // ahead, for the potential fallback path.  This resume point is captured
    1108             :     // while building MGetPropertyCache.  It is capturing the state of Baseline
    1109             :     // before the execution of the MGetPropertyCache, such as we can safely do
    1110             :     // it in the fallback path.
    1111             :     //
    1112             :     // This field is used to discard the resume point if it is not used for
    1113             :     // building a fallback path.
    1114             : 
    1115             :     // Discard the prior resume point while setting a new MGetPropertyCache.
    1116             :     void replaceMaybeFallbackFunctionGetter(MGetPropertyCache* cache);
    1117             : 
    1118             :     // Discard the MGetPropertyCache if it is handled by WrapMGetPropertyCache.
    1119         357 :     void keepFallbackFunctionGetter(MGetPropertyCache* cache) {
    1120         357 :         if (cache == maybeFallbackFunctionGetter_)
    1121         357 :             maybeFallbackFunctionGetter_ = nullptr;
    1122         357 :     }
    1123             : 
    1124             :     MGetPropertyCache* maybeFallbackFunctionGetter_;
    1125             : 
    1126             :     // Used in tracking outcomes of optimization strategies for devtools.
    1127             :     void startTrackingOptimizations();
    1128             : 
    1129             :     // The track* methods below are called often. Do not combine them with the
    1130             :     // unchecked variants, despite the unchecked variants having no other
    1131             :     // callers.
    1132        2940 :     void trackTypeInfo(JS::TrackedTypeSite site, MIRType mirType,
    1133             :                        TemporaryTypeSet* typeSet)
    1134             :     {
    1135        2940 :         if (MOZ_UNLIKELY(current->trackedSite()->hasOptimizations()))
    1136           0 :             trackTypeInfoUnchecked(site, mirType, typeSet);
    1137        2940 :     }
    1138         363 :     void trackTypeInfo(JS::TrackedTypeSite site, JSObject* obj) {
    1139         363 :         if (MOZ_UNLIKELY(current->trackedSite()->hasOptimizations()))
    1140           0 :             trackTypeInfoUnchecked(site, obj);
    1141         363 :     }
    1142           0 :     void trackTypeInfo(CallInfo& callInfo) {
    1143           0 :         if (MOZ_UNLIKELY(current->trackedSite()->hasOptimizations()))
    1144           0 :             trackTypeInfoUnchecked(callInfo);
    1145           0 :     }
    1146        4723 :     void trackOptimizationAttempt(JS::TrackedStrategy strategy) {
    1147        4723 :         if (MOZ_UNLIKELY(current->trackedSite()->hasOptimizations()))
    1148           0 :             trackOptimizationAttemptUnchecked(strategy);
    1149        4723 :     }
    1150           4 :     void amendOptimizationAttempt(uint32_t index) {
    1151           4 :         if (MOZ_UNLIKELY(current->trackedSite()->hasOptimizations()))
    1152           0 :             amendOptimizationAttemptUnchecked(index);
    1153           4 :     }
    1154        3831 :     void trackOptimizationOutcome(JS::TrackedOutcome outcome) {
    1155        3831 :         if (MOZ_UNLIKELY(current->trackedSite()->hasOptimizations()))
    1156           0 :             trackOptimizationOutcomeUnchecked(outcome);
    1157        3831 :     }
    1158         900 :     void trackOptimizationSuccess() {
    1159         900 :         if (MOZ_UNLIKELY(current->trackedSite()->hasOptimizations()))
    1160           0 :             trackOptimizationSuccessUnchecked();
    1161         900 :     }
    1162         149 :     void trackInlineSuccess(InliningStatus status = InliningStatus_Inlined) {
    1163         149 :         if (MOZ_UNLIKELY(current->trackedSite()->hasOptimizations()))
    1164           0 :             trackInlineSuccessUnchecked(status);
    1165         149 :     }
    1166             : 
    1167        1210 :     bool forceInlineCaches() {
    1168        1210 :         return MOZ_UNLIKELY(JitOptions.forceInlineCaches);
    1169             :     }
    1170             : 
    1171             :     // Out-of-line variants that don't check if optimization tracking is
    1172             :     // enabled.
    1173             :     void trackTypeInfoUnchecked(JS::TrackedTypeSite site, MIRType mirType,
    1174             :                                 TemporaryTypeSet* typeSet);
    1175             :     void trackTypeInfoUnchecked(JS::TrackedTypeSite site, JSObject* obj);
    1176             :     void trackTypeInfoUnchecked(CallInfo& callInfo);
    1177             :     void trackOptimizationAttemptUnchecked(JS::TrackedStrategy strategy);
    1178             :     void amendOptimizationAttemptUnchecked(uint32_t index);
    1179             :     void trackOptimizationOutcomeUnchecked(JS::TrackedOutcome outcome);
    1180             :     void trackOptimizationSuccessUnchecked();
    1181             :     void trackInlineSuccessUnchecked(InliningStatus status);
    1182             : };
    1183             : 
    1184        1282 : class CallInfo
    1185             : {
    1186             :     MDefinition* fun_;
    1187             :     MDefinition* thisArg_;
    1188             :     MDefinition* newTargetArg_;
    1189             :     MDefinitionVector args_;
    1190             : 
    1191             :     bool constructing_:1;
    1192             : 
    1193             :     // True if the caller does not use the return value.
    1194             :     bool ignoresReturnValue_:1;
    1195             : 
    1196             :     bool setter_:1;
    1197             : 
    1198             :   public:
    1199        1282 :     CallInfo(TempAllocator& alloc, bool constructing, bool ignoresReturnValue)
    1200        1282 :       : fun_(nullptr),
    1201             :         thisArg_(nullptr),
    1202             :         newTargetArg_(nullptr),
    1203             :         args_(alloc),
    1204             :         constructing_(constructing),
    1205             :         ignoresReturnValue_(ignoresReturnValue),
    1206        1282 :         setter_(false)
    1207        1282 :     { }
    1208             : 
    1209           8 :     MOZ_MUST_USE bool init(CallInfo& callInfo) {
    1210           8 :         MOZ_ASSERT(constructing_ == callInfo.constructing());
    1211             : 
    1212           8 :         fun_ = callInfo.fun();
    1213           8 :         thisArg_ = callInfo.thisArg();
    1214           8 :         ignoresReturnValue_ = callInfo.ignoresReturnValue();
    1215             : 
    1216           8 :         if (constructing())
    1217           0 :             newTargetArg_ = callInfo.getNewTarget();
    1218             : 
    1219           8 :         if (!args_.appendAll(callInfo.argv()))
    1220           0 :             return false;
    1221             : 
    1222           8 :         return true;
    1223             :     }
    1224             : 
    1225        1274 :     MOZ_MUST_USE bool init(MBasicBlock* current, uint32_t argc) {
    1226        1274 :         MOZ_ASSERT(args_.empty());
    1227             : 
    1228             :         // Get the arguments in the right order
    1229        1274 :         if (!args_.reserve(argc))
    1230           0 :             return false;
    1231             : 
    1232        1274 :         if (constructing())
    1233         140 :             setNewTarget(current->pop());
    1234             : 
    1235        3693 :         for (int32_t i = argc; i > 0; i--)
    1236        2419 :             args_.infallibleAppend(current->peek(-i));
    1237        1274 :         current->popn(argc);
    1238             : 
    1239             :         // Get |this| and |fun|
    1240        1274 :         setThis(current->pop());
    1241        1274 :         setFun(current->pop());
    1242             : 
    1243        1274 :         return true;
    1244             :     }
    1245             : 
    1246          45 :     void popFormals(MBasicBlock* current) {
    1247          45 :         current->popn(numFormals());
    1248          45 :     }
    1249             : 
    1250          37 :     void pushFormals(MBasicBlock* current) {
    1251          37 :         current->push(fun());
    1252          37 :         current->push(thisArg());
    1253             : 
    1254          88 :         for (uint32_t i = 0; i < argc(); i++)
    1255          51 :             current->push(getArg(i));
    1256             : 
    1257          37 :         if (constructing())
    1258           0 :             current->push(getNewTarget());
    1259          37 :     }
    1260             : 
    1261        9241 :     uint32_t argc() const {
    1262        9241 :         return args_.length();
    1263             :     }
    1264          86 :     uint32_t numFormals() const {
    1265          86 :         return argc() + 2 + constructing();
    1266             :     }
    1267             : 
    1268           0 :     MOZ_MUST_USE bool setArgs(const MDefinitionVector& args) {
    1269           0 :         MOZ_ASSERT(args_.empty());
    1270           0 :         return args_.appendAll(args);
    1271             :     }
    1272             : 
    1273           8 :     MDefinitionVector& argv() {
    1274           8 :         return args_;
    1275             :     }
    1276             : 
    1277           0 :     const MDefinitionVector& argv() const {
    1278           0 :         return args_;
    1279             :     }
    1280             : 
    1281        3212 :     MDefinition* getArg(uint32_t i) const {
    1282        3212 :         MOZ_ASSERT(i < argc());
    1283        3212 :         return args_[i];
    1284             :     }
    1285             : 
    1286           0 :     MDefinition* getArgWithDefault(uint32_t i, MDefinition* defaultValue) const {
    1287           0 :         if (i < argc())
    1288           0 :             return args_[i];
    1289             : 
    1290           0 :         return defaultValue;
    1291             :     }
    1292             : 
    1293             :     void setArg(uint32_t i, MDefinition* def) {
    1294             :         MOZ_ASSERT(i < argc());
    1295             :         args_[i] = def;
    1296             :     }
    1297             : 
    1298        2299 :     MDefinition* thisArg() const {
    1299        2299 :         MOZ_ASSERT(thisArg_);
    1300        2299 :         return thisArg_;
    1301             :     }
    1302             : 
    1303        1414 :     void setThis(MDefinition* thisArg) {
    1304        1414 :         thisArg_ = thisArg;
    1305        1414 :     }
    1306             : 
    1307        8396 :     bool constructing() const {
    1308        8396 :         return constructing_;
    1309             :     }
    1310             : 
    1311        1161 :     bool ignoresReturnValue() const {
    1312        1161 :         return ignoresReturnValue_;
    1313             :     }
    1314             : 
    1315         141 :     void setNewTarget(MDefinition* newTarget) {
    1316         141 :         MOZ_ASSERT(constructing());
    1317         141 :         newTargetArg_ = newTarget;
    1318         141 :     }
    1319         281 :     MDefinition* getNewTarget() const {
    1320         281 :         MOZ_ASSERT(newTargetArg_);
    1321         281 :         return newTargetArg_;
    1322             :     }
    1323             : 
    1324         120 :     bool isSetter() const {
    1325         120 :         return setter_;
    1326             :     }
    1327           0 :     void markAsSetter() {
    1328           0 :         setter_ = true;
    1329           0 :     }
    1330             : 
    1331        1572 :     MDefinition* fun() const {
    1332        1572 :         MOZ_ASSERT(fun_);
    1333        1572 :         return fun_;
    1334             :     }
    1335             : 
    1336        1420 :     void setFun(MDefinition* fun) {
    1337        1420 :         fun_ = fun;
    1338        1420 :     }
    1339             : 
    1340         137 :     void setImplicitlyUsedUnchecked() {
    1341         137 :         fun_->setImplicitlyUsedUnchecked();
    1342         137 :         thisArg_->setImplicitlyUsedUnchecked();
    1343         137 :         if (newTargetArg_)
    1344           0 :             newTargetArg_->setImplicitlyUsedUnchecked();
    1345         373 :         for (uint32_t i = 0; i < argc(); i++)
    1346         236 :             getArg(i)->setImplicitlyUsedUnchecked();
    1347         137 :     }
    1348             : };
    1349             : 
    1350             : bool NeedsPostBarrier(MDefinition* value);
    1351             : 
    1352             : } // namespace jit
    1353             : } // namespace js
    1354             : 
    1355             : #endif /* jit_IonBuilder_h */

Generated by: LCOV version 1.13