js/src/jit/IonBuilder.h

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/js/src/jit/IonBuilder.h	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,1060 @@
     1.4 +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
     1.5 + * vim: set ts=8 sts=4 et sw=4 tw=99:
     1.6 + * This Source Code Form is subject to the terms of the Mozilla Public
     1.7 + * License, v. 2.0. If a copy of the MPL was not distributed with this
     1.8 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     1.9 +
    1.10 +#ifndef jit_IonBuilder_h
    1.11 +#define jit_IonBuilder_h
    1.12 +
    1.13 +#ifdef JS_ION
    1.14 +
    1.15 +// This file declares the data structures for building a MIRGraph from a
    1.16 +// JSScript.
    1.17 +
    1.18 +#include "jit/BytecodeAnalysis.h"
    1.19 +#include "jit/IonOptimizationLevels.h"
    1.20 +#include "jit/MIR.h"
    1.21 +#include "jit/MIRGenerator.h"
    1.22 +#include "jit/MIRGraph.h"
    1.23 +#include "jit/TypeDescrSet.h"
    1.24 +
    1.25 +namespace js {
    1.26 +namespace jit {
    1.27 +
    1.28 +class CodeGenerator;
    1.29 +class CallInfo;
    1.30 +class BaselineInspector;
    1.31 +class BaselineFrameInspector;
    1.32 +
    1.33 +// Records information about a baseline frame for compilation that is stable
    1.34 +// when later used off thread.
    1.35 +BaselineFrameInspector *
    1.36 +NewBaselineFrameInspector(TempAllocator *temp, BaselineFrame *frame, CompileInfo *info);
    1.37 +
    1.38 +class IonBuilder : public MIRGenerator
    1.39 +{
    1.40 +    enum ControlStatus {
    1.41 +        ControlStatus_Error,
    1.42 +        ControlStatus_Abort,
    1.43 +        ControlStatus_Ended,        // There is no continuation/join point.
    1.44 +        ControlStatus_Joined,       // Created a join node.
    1.45 +        ControlStatus_Jumped,       // Parsing another branch at the same level.
    1.46 +        ControlStatus_None          // No control flow.
    1.47 +    };
    1.48 +
    1.49 +    enum SetElemSafety {
    1.50 +        // Normal write like a[b] = c.
    1.51 +        SetElem_Normal,
    1.52 +
    1.53 +        // Write due to UnsafePutElements:
    1.54 +        // - assumed to be in bounds,
    1.55 +        // - not checked for data races
    1.56 +        SetElem_Unsafe,
    1.57 +    };
    1.58 +
    1.59 +    struct DeferredEdge : public TempObject
    1.60 +    {
    1.61 +        MBasicBlock *block;
    1.62 +        DeferredEdge *next;
    1.63 +
    1.64 +        DeferredEdge(MBasicBlock *block, DeferredEdge *next)
    1.65 +          : block(block), next(next)
    1.66 +        { }
    1.67 +    };
    1.68 +
    1.69 +    struct ControlFlowInfo {
    1.70 +        // Entry in the cfgStack.
    1.71 +        uint32_t cfgEntry;
    1.72 +
    1.73 +        // Label that continues go to.
    1.74 +        jsbytecode *continuepc;
    1.75 +
    1.76 +        ControlFlowInfo(uint32_t cfgEntry, jsbytecode *continuepc)
    1.77 +          : cfgEntry(cfgEntry),
    1.78 +            continuepc(continuepc)
    1.79 +        { }
    1.80 +    };
    1.81 +
    1.82 +    // To avoid recursion, the bytecode analyzer uses a stack where each entry
    1.83 +    // is a small state machine. As we encounter branches or jumps in the
    1.84 +    // bytecode, we push information about the edges on the stack so that the
    1.85 +    // CFG can be built in a tree-like fashion.
    1.86 +    struct CFGState {
    1.87 +        enum State {
    1.88 +            IF_TRUE,            // if() { }, no else.
    1.89 +            IF_TRUE_EMPTY_ELSE, // if() { }, empty else
    1.90 +            IF_ELSE_TRUE,       // if() { X } else { }
    1.91 +            IF_ELSE_FALSE,      // if() { } else { X }
    1.92 +            DO_WHILE_LOOP_BODY, // do { x } while ()
    1.93 +            DO_WHILE_LOOP_COND, // do { } while (x)
    1.94 +            WHILE_LOOP_COND,    // while (x) { }
    1.95 +            WHILE_LOOP_BODY,    // while () { x }
    1.96 +            FOR_LOOP_COND,      // for (; x;) { }
    1.97 +            FOR_LOOP_BODY,      // for (; ;) { x }
    1.98 +            FOR_LOOP_UPDATE,    // for (; ; x) { }
    1.99 +            TABLE_SWITCH,       // switch() { x }
   1.100 +            COND_SWITCH_CASE,   // switch() { case X: ... }
   1.101 +            COND_SWITCH_BODY,   // switch() { case ...: X }
   1.102 +            AND_OR,             // && x, || x
   1.103 +            LABEL,              // label: x
   1.104 +            TRY                 // try { x } catch(e) { }
   1.105 +        };
   1.106 +
   1.107 +        State state;            // Current state of this control structure.
   1.108 +        jsbytecode *stopAt;     // Bytecode at which to stop the processing loop.
   1.109 +
   1.110 +        // For if structures, this contains branch information.
   1.111 +        union {
   1.112 +            struct {
   1.113 +                MBasicBlock *ifFalse;
   1.114 +                jsbytecode *falseEnd;
   1.115 +                MBasicBlock *ifTrue;    // Set when the end of the true path is reached.
   1.116 +                MTest *test;
   1.117 +            } branch;
   1.118 +            struct {
   1.119 +                // Common entry point.
   1.120 +                MBasicBlock *entry;
   1.121 +
   1.122 +                // Whether OSR is being performed for this loop.
   1.123 +                bool osr;
   1.124 +
   1.125 +                // Position of where the loop body starts and ends.
   1.126 +                jsbytecode *bodyStart;
   1.127 +                jsbytecode *bodyEnd;
   1.128 +
   1.129 +                // pc immediately after the loop exits.
   1.130 +                jsbytecode *exitpc;
   1.131 +
   1.132 +                // pc for 'continue' jumps.
   1.133 +                jsbytecode *continuepc;
   1.134 +
   1.135 +                // Common exit point. Created lazily, so it may be nullptr.
   1.136 +                MBasicBlock *successor;
   1.137 +
   1.138 +                // Deferred break and continue targets.
   1.139 +                DeferredEdge *breaks;
   1.140 +                DeferredEdge *continues;
   1.141 +
   1.142 +                // Initial state, in case loop processing is restarted.
   1.143 +                State initialState;
   1.144 +                jsbytecode *initialPc;
   1.145 +                jsbytecode *initialStopAt;
   1.146 +                jsbytecode *loopHead;
   1.147 +
   1.148 +                // For-loops only.
   1.149 +                jsbytecode *condpc;
   1.150 +                jsbytecode *updatepc;
   1.151 +                jsbytecode *updateEnd;
   1.152 +            } loop;
   1.153 +            struct {
   1.154 +                // pc immediately after the switch.
   1.155 +                jsbytecode *exitpc;
   1.156 +
   1.157 +                // Deferred break and continue targets.
   1.158 +                DeferredEdge *breaks;
   1.159 +
   1.160 +                // MIR instruction
   1.161 +                MTableSwitch *ins;
   1.162 +
   1.163 +                // The number of current successor that get mapped into a block.
   1.164 +                uint32_t currentBlock;
   1.165 +
   1.166 +            } tableswitch;
   1.167 +            struct {
   1.168 +                // Vector of body blocks to process after the cases.
   1.169 +                FixedList<MBasicBlock *> *bodies;
   1.170 +
   1.171 +                // When processing case statements, this counter points at the
   1.172 +                // last uninitialized body.  When processing bodies, this
   1.173 +                // counter targets the next body to process.
   1.174 +                uint32_t currentIdx;
   1.175 +
   1.176 +                // Remember the block index of the default case.
   1.177 +                jsbytecode *defaultTarget;
   1.178 +                uint32_t defaultIdx;
   1.179 +
   1.180 +                // Block immediately after the switch.
   1.181 +                jsbytecode *exitpc;
   1.182 +                DeferredEdge *breaks;
   1.183 +            } condswitch;
   1.184 +            struct {
   1.185 +                DeferredEdge *breaks;
   1.186 +            } label;
   1.187 +            struct {
   1.188 +                MBasicBlock *successor;
   1.189 +            } try_;
   1.190 +        };
   1.191 +
   1.192 +        inline bool isLoop() const {
   1.193 +            switch (state) {
   1.194 +              case DO_WHILE_LOOP_COND:
   1.195 +              case DO_WHILE_LOOP_BODY:
   1.196 +              case WHILE_LOOP_COND:
   1.197 +              case WHILE_LOOP_BODY:
   1.198 +              case FOR_LOOP_COND:
   1.199 +              case FOR_LOOP_BODY:
   1.200 +              case FOR_LOOP_UPDATE:
   1.201 +                return true;
   1.202 +              default:
   1.203 +                return false;
   1.204 +            }
   1.205 +        }
   1.206 +
   1.207 +        static CFGState If(jsbytecode *join, MTest *test);
   1.208 +        static CFGState IfElse(jsbytecode *trueEnd, jsbytecode *falseEnd, MTest *test);
   1.209 +        static CFGState AndOr(jsbytecode *join, MBasicBlock *joinStart);
   1.210 +        static CFGState TableSwitch(jsbytecode *exitpc, MTableSwitch *ins);
   1.211 +        static CFGState CondSwitch(IonBuilder *builder, jsbytecode *exitpc, jsbytecode *defaultTarget);
   1.212 +        static CFGState Label(jsbytecode *exitpc);
   1.213 +        static CFGState Try(jsbytecode *exitpc, MBasicBlock *successor);
   1.214 +    };
   1.215 +
   1.216 +    static int CmpSuccessors(const void *a, const void *b);
   1.217 +
   1.218 +  public:
   1.219 +    IonBuilder(JSContext *analysisContext, CompileCompartment *comp,
   1.220 +               const JitCompileOptions &options, TempAllocator *temp,
   1.221 +               MIRGraph *graph, types::CompilerConstraintList *constraints,
   1.222 +               BaselineInspector *inspector, CompileInfo *info,
   1.223 +               const OptimizationInfo *optimizationInfo, BaselineFrameInspector *baselineFrame,
   1.224 +               size_t inliningDepth = 0, uint32_t loopDepth = 0);
   1.225 +
   1.226 +    bool build();
   1.227 +    bool buildInline(IonBuilder *callerBuilder, MResumePoint *callerResumePoint,
   1.228 +                     CallInfo &callInfo);
   1.229 +
   1.230 +  private:
   1.231 +    bool traverseBytecode();
   1.232 +    ControlStatus snoopControlFlow(JSOp op);
   1.233 +    bool processIterators();
   1.234 +    bool inspectOpcode(JSOp op);
   1.235 +    uint32_t readIndex(jsbytecode *pc);
   1.236 +    JSAtom *readAtom(jsbytecode *pc);
   1.237 +    bool abort(const char *message, ...);
   1.238 +    void spew(const char *message);
   1.239 +
   1.240 +    JSFunction *getSingleCallTarget(types::TemporaryTypeSet *calleeTypes);
   1.241 +    bool getPolyCallTargets(types::TemporaryTypeSet *calleeTypes, bool constructing,
   1.242 +                            ObjectVector &targets, uint32_t maxTargets, bool *gotLambda);
   1.243 +
   1.244 +    void popCfgStack();
   1.245 +    DeferredEdge *filterDeadDeferredEdges(DeferredEdge *edge);
   1.246 +    bool processDeferredContinues(CFGState &state);
   1.247 +    ControlStatus processControlEnd();
   1.248 +    ControlStatus processCfgStack();
   1.249 +    ControlStatus processCfgEntry(CFGState &state);
   1.250 +    ControlStatus processIfEnd(CFGState &state);
   1.251 +    ControlStatus processIfElseTrueEnd(CFGState &state);
   1.252 +    ControlStatus processIfElseFalseEnd(CFGState &state);
   1.253 +    ControlStatus processDoWhileBodyEnd(CFGState &state);
   1.254 +    ControlStatus processDoWhileCondEnd(CFGState &state);
   1.255 +    ControlStatus processWhileCondEnd(CFGState &state);
   1.256 +    ControlStatus processWhileBodyEnd(CFGState &state);
   1.257 +    ControlStatus processForCondEnd(CFGState &state);
   1.258 +    ControlStatus processForBodyEnd(CFGState &state);
   1.259 +    ControlStatus processForUpdateEnd(CFGState &state);
   1.260 +    ControlStatus processNextTableSwitchCase(CFGState &state);
   1.261 +    ControlStatus processCondSwitchCase(CFGState &state);
   1.262 +    ControlStatus processCondSwitchBody(CFGState &state);
   1.263 +    ControlStatus processSwitchBreak(JSOp op);
   1.264 +    ControlStatus processSwitchEnd(DeferredEdge *breaks, jsbytecode *exitpc);
   1.265 +    ControlStatus processAndOrEnd(CFGState &state);
   1.266 +    ControlStatus processLabelEnd(CFGState &state);
   1.267 +    ControlStatus processTryEnd(CFGState &state);
   1.268 +    ControlStatus processReturn(JSOp op);
   1.269 +    ControlStatus processThrow();
   1.270 +    ControlStatus processContinue(JSOp op);
   1.271 +    ControlStatus processBreak(JSOp op, jssrcnote *sn);
   1.272 +    ControlStatus maybeLoop(JSOp op, jssrcnote *sn);
   1.273 +    bool pushLoop(CFGState::State state, jsbytecode *stopAt, MBasicBlock *entry, bool osr,
   1.274 +                  jsbytecode *loopHead, jsbytecode *initialPc,
   1.275 +                  jsbytecode *bodyStart, jsbytecode *bodyEnd, jsbytecode *exitpc,
   1.276 +                  jsbytecode *continuepc = nullptr);
   1.277 +    bool analyzeNewLoopTypes(MBasicBlock *entry, jsbytecode *start, jsbytecode *end);
   1.278 +
   1.279 +    MBasicBlock *addBlock(MBasicBlock *block, uint32_t loopDepth);
   1.280 +    MBasicBlock *newBlock(MBasicBlock *predecessor, jsbytecode *pc);
   1.281 +    MBasicBlock *newBlock(MBasicBlock *predecessor, jsbytecode *pc, uint32_t loopDepth);
   1.282 +    MBasicBlock *newBlock(MBasicBlock *predecessor, jsbytecode *pc, MResumePoint *priorResumePoint);
   1.283 +    MBasicBlock *newBlockPopN(MBasicBlock *predecessor, jsbytecode *pc, uint32_t popped);
   1.284 +    MBasicBlock *newBlockAfter(MBasicBlock *at, MBasicBlock *predecessor, jsbytecode *pc);
   1.285 +    MBasicBlock *newOsrPreheader(MBasicBlock *header, jsbytecode *loopEntry);
   1.286 +    MBasicBlock *newPendingLoopHeader(MBasicBlock *predecessor, jsbytecode *pc, bool osr, bool canOsr,
   1.287 +                                      unsigned stackPhiCount);
   1.288 +    MBasicBlock *newBlock(jsbytecode *pc) {
   1.289 +        return newBlock(nullptr, pc);
   1.290 +    }
   1.291 +    MBasicBlock *newBlockAfter(MBasicBlock *at, jsbytecode *pc) {
   1.292 +        return newBlockAfter(at, nullptr, pc);
   1.293 +    }
   1.294 +
   1.295 +    // Given a list of pending breaks, creates a new block and inserts a Goto
   1.296 +    // linking each break to the new block.
   1.297 +    MBasicBlock *createBreakCatchBlock(DeferredEdge *edge, jsbytecode *pc);
   1.298 +
   1.299 +    // Finishes loops that do not actually loop, containing only breaks and
   1.300 +    // returns or a do while loop with a condition that is constant false.
   1.301 +    ControlStatus processBrokenLoop(CFGState &state);
   1.302 +
   1.303 +    // Computes loop phis, places them in all successors of a loop, then
   1.304 +    // handles any pending breaks.
   1.305 +    ControlStatus finishLoop(CFGState &state, MBasicBlock *successor);
   1.306 +
   1.307 +    // Incorporates a type/typeSet into an OSR value for a loop, after the loop
   1.308 +    // body has been processed.
   1.309 +    bool addOsrValueTypeBarrier(uint32_t slot, MInstruction **def,
   1.310 +                                MIRType type, types::TemporaryTypeSet *typeSet);
   1.311 +    bool maybeAddOsrTypeBarriers();
   1.312 +
   1.313 +    // Restarts processing of a loop if the type information at its header was
   1.314 +    // incomplete.
   1.315 +    ControlStatus restartLoop(CFGState state);
   1.316 +
   1.317 +    void assertValidLoopHeadOp(jsbytecode *pc);
   1.318 +
   1.319 +    ControlStatus forLoop(JSOp op, jssrcnote *sn);
   1.320 +    ControlStatus whileOrForInLoop(jssrcnote *sn);
   1.321 +    ControlStatus doWhileLoop(JSOp op, jssrcnote *sn);
   1.322 +    ControlStatus tableSwitch(JSOp op, jssrcnote *sn);
   1.323 +    ControlStatus condSwitch(JSOp op, jssrcnote *sn);
   1.324 +
   1.325 +    // Please see the Big Honkin' Comment about how resume points work in
   1.326 +    // IonBuilder.cpp, near the definition for this function.
   1.327 +    bool resume(MInstruction *ins, jsbytecode *pc, MResumePoint::Mode mode);
   1.328 +    bool resumeAt(MInstruction *ins, jsbytecode *pc);
   1.329 +    bool resumeAfter(MInstruction *ins);
   1.330 +    bool maybeInsertResume();
   1.331 +
   1.332 +    void insertRecompileCheck();
   1.333 +
   1.334 +    void initParameters();
   1.335 +    void rewriteParameter(uint32_t slotIdx, MDefinition *param, int32_t argIndex);
   1.336 +    void rewriteParameters();
   1.337 +    bool initScopeChain(MDefinition *callee = nullptr);
   1.338 +    bool initArgumentsObject();
   1.339 +    bool pushConstant(const Value &v);
   1.340 +
   1.341 +    MConstant *constant(const Value &v);
   1.342 +    MConstant *constantInt(int32_t i);
   1.343 +
   1.344 +    // Filter the type information at tests
   1.345 +    bool filterTypesAtTest(MTest *test);
   1.346 +
   1.347 +    // Add a guard which ensure that the set of type which goes through this
   1.348 +    // generated code correspond to the observed types for the bytecode.
   1.349 +    bool pushTypeBarrier(MDefinition *def, types::TemporaryTypeSet *observed, bool needBarrier);
   1.350 +
   1.351 +    // As pushTypeBarrier, but will compute the needBarrier boolean itself based
   1.352 +    // on observed and the JSFunction that we're planning to call. The
   1.353 +    // JSFunction must be a DOM method or getter.
   1.354 +    bool pushDOMTypeBarrier(MInstruction *ins, types::TemporaryTypeSet *observed, JSFunction* func);
   1.355 +
   1.356 +    // If definiteType is not known or def already has the right type, just
   1.357 +    // returns def.  Otherwise, returns an MInstruction that has that definite
   1.358 +    // type, infallibly unboxing ins as needed.  The new instruction will be
   1.359 +    // added to |current| in this case.
   1.360 +    MDefinition *ensureDefiniteType(MDefinition* def, MIRType definiteType);
   1.361 +
   1.362 +    // Creates a MDefinition based on the given def improved with type as TypeSet.
   1.363 +    MDefinition *ensureDefiniteTypeSet(MDefinition* def, types::TemporaryTypeSet *types);
   1.364 +
   1.365 +    JSObject *getSingletonPrototype(JSFunction *target);
   1.366 +
   1.367 +    MDefinition *createThisScripted(MDefinition *callee);
   1.368 +    MDefinition *createThisScriptedSingleton(JSFunction *target, MDefinition *callee);
   1.369 +    MDefinition *createThis(JSFunction *target, MDefinition *callee);
   1.370 +    MInstruction *createDeclEnvObject(MDefinition *callee, MDefinition *scopeObj);
   1.371 +    MInstruction *createCallObject(MDefinition *callee, MDefinition *scopeObj);
   1.372 +
   1.373 +    MDefinition *walkScopeChain(unsigned hops);
   1.374 +
   1.375 +    MInstruction *addConvertElementsToDoubles(MDefinition *elements);
   1.376 +    MInstruction *addBoundsCheck(MDefinition *index, MDefinition *length);
   1.377 +    MInstruction *addShapeGuard(MDefinition *obj, Shape *const shape, BailoutKind bailoutKind);
   1.378 +
   1.379 +    MDefinition *convertShiftToMaskForStaticTypedArray(MDefinition *id,
   1.380 +                                                       ArrayBufferView::ViewType viewType);
   1.381 +
   1.382 +    bool invalidatedIdempotentCache();
   1.383 +
   1.384 +    bool hasStaticScopeObject(ScopeCoordinate sc, JSObject **pcall);
   1.385 +    bool loadSlot(MDefinition *obj, size_t slot, size_t nfixed, MIRType rvalType,
   1.386 +                  bool barrier, types::TemporaryTypeSet *types);
   1.387 +    bool loadSlot(MDefinition *obj, Shape *shape, MIRType rvalType,
   1.388 +                  bool barrier, types::TemporaryTypeSet *types);
   1.389 +    bool storeSlot(MDefinition *obj, size_t slot, size_t nfixed,
   1.390 +                   MDefinition *value, bool needsBarrier,
   1.391 +                   MIRType slotType = MIRType_None);
   1.392 +    bool storeSlot(MDefinition *obj, Shape *shape, MDefinition *value, bool needsBarrier,
   1.393 +                   MIRType slotType = MIRType_None);
   1.394 +
   1.395 +    // jsop_getprop() helpers.
   1.396 +    bool getPropTryArgumentsLength(bool *emitted);
   1.397 +    bool getPropTryConstant(bool *emitted, PropertyName *name,
   1.398 +                            types::TemporaryTypeSet *types);
   1.399 +    bool getPropTryDefiniteSlot(bool *emitted, PropertyName *name,
   1.400 +                                bool barrier, types::TemporaryTypeSet *types);
   1.401 +    bool getPropTryCommonGetter(bool *emitted, PropertyName *name,
   1.402 +                                types::TemporaryTypeSet *types);
   1.403 +    bool getPropTryInlineAccess(bool *emitted, PropertyName *name,
   1.404 +                                bool barrier, types::TemporaryTypeSet *types);
   1.405 +    bool getPropTryTypedObject(bool *emitted, PropertyName *name,
   1.406 +                               types::TemporaryTypeSet *resultTypes);
   1.407 +    bool getPropTryScalarPropOfTypedObject(bool *emitted,
   1.408 +                                           int32_t fieldOffset,
   1.409 +                                           TypeDescrSet fieldTypeReprs,
   1.410 +                                           types::TemporaryTypeSet *resultTypes);
   1.411 +    bool getPropTryComplexPropOfTypedObject(bool *emitted,
   1.412 +                                            int32_t fieldOffset,
   1.413 +                                            TypeDescrSet fieldTypeReprs,
   1.414 +                                            size_t fieldIndex,
   1.415 +                                            types::TemporaryTypeSet *resultTypes);
   1.416 +    bool getPropTryCache(bool *emitted, PropertyName *name,
   1.417 +                         bool barrier, types::TemporaryTypeSet *types);
   1.418 +    bool needsToMonitorMissingProperties(types::TemporaryTypeSet *types);
   1.419 +
   1.420 +    // jsop_setprop() helpers.
   1.421 +    bool setPropTryCommonSetter(bool *emitted, MDefinition *obj,
   1.422 +                                PropertyName *name, MDefinition *value);
   1.423 +    bool setPropTryCommonDOMSetter(bool *emitted, MDefinition *obj,
   1.424 +                                   MDefinition *value, JSFunction *setter,
   1.425 +                                   bool isDOM);
   1.426 +    bool setPropTryDefiniteSlot(bool *emitted, MDefinition *obj,
   1.427 +                                PropertyName *name, MDefinition *value,
   1.428 +                                bool barrier, types::TemporaryTypeSet *objTypes);
   1.429 +    bool setPropTryInlineAccess(bool *emitted, MDefinition *obj,
   1.430 +                                PropertyName *name, MDefinition *value, bool barrier,
   1.431 +                                types::TemporaryTypeSet *objTypes);
   1.432 +    bool setPropTryTypedObject(bool *emitted, MDefinition *obj,
   1.433 +                               PropertyName *name, MDefinition *value);
   1.434 +    bool setPropTryScalarPropOfTypedObject(bool *emitted,
   1.435 +                                           MDefinition *obj,
   1.436 +                                           int32_t fieldOffset,
   1.437 +                                           MDefinition *value,
   1.438 +                                           TypeDescrSet fieldTypeReprs);
   1.439 +    bool setPropTryCache(bool *emitted, MDefinition *obj,
   1.440 +                         PropertyName *name, MDefinition *value,
   1.441 +                         bool barrier, types::TemporaryTypeSet *objTypes);
   1.442 +
   1.443 +    // binary data lookup helpers.
   1.444 +    bool lookupTypeDescrSet(MDefinition *typedObj,
   1.445 +                                     TypeDescrSet *out);
   1.446 +    bool typeSetToTypeDescrSet(types::TemporaryTypeSet *types,
   1.447 +                                        TypeDescrSet *out);
   1.448 +    bool lookupTypedObjectField(MDefinition *typedObj,
   1.449 +                                PropertyName *name,
   1.450 +                                int32_t *fieldOffset,
   1.451 +                                TypeDescrSet *fieldTypeReprs,
   1.452 +                                size_t *fieldIndex);
   1.453 +    MDefinition *loadTypedObjectType(MDefinition *value);
   1.454 +    void loadTypedObjectData(MDefinition *typedObj,
   1.455 +                             MDefinition *offset,
   1.456 +                             bool canBeNeutered,
   1.457 +                             MDefinition **owner,
   1.458 +                             MDefinition **ownerOffset);
   1.459 +    void loadTypedObjectElements(MDefinition *typedObj,
   1.460 +                                 MDefinition *offset,
   1.461 +                                 int32_t unit,
   1.462 +                                 bool canBeNeutered,
   1.463 +                                 MDefinition **ownerElements,
   1.464 +                                 MDefinition **ownerScaledOffset);
   1.465 +    MDefinition *typeObjectForElementFromArrayStructType(MDefinition *typedObj);
   1.466 +    MDefinition *typeObjectForFieldFromStructType(MDefinition *type,
   1.467 +                                                  size_t fieldIndex);
   1.468 +    bool storeScalarTypedObjectValue(MDefinition *typedObj,
   1.469 +                                     MDefinition *offset,
   1.470 +                                     ScalarTypeDescr::Type type,
   1.471 +                                     bool canBeNeutered,
   1.472 +                                     bool racy,
   1.473 +                                     MDefinition *value);
   1.474 +    bool checkTypedObjectIndexInBounds(int32_t elemSize,
   1.475 +                                       MDefinition *obj,
   1.476 +                                       MDefinition *index,
   1.477 +                                       TypeDescrSet objTypeDescrs,
   1.478 +                                       MDefinition **indexAsByteOffset,
   1.479 +                                       bool *canBeNeutered);
   1.480 +    bool pushDerivedTypedObject(bool *emitted,
   1.481 +                                MDefinition *obj,
   1.482 +                                MDefinition *offset,
   1.483 +                                TypeDescrSet derivedTypeDescrs,
   1.484 +                                MDefinition *derivedTypeObj,
   1.485 +                                bool canBeNeutered);
   1.486 +    bool pushScalarLoadFromTypedObject(bool *emitted,
   1.487 +                                       MDefinition *obj,
   1.488 +                                       MDefinition *offset,
   1.489 +                                       ScalarTypeDescr::Type type,
   1.490 +                                       bool canBeNeutered);
   1.491 +    MDefinition *neuterCheck(MDefinition *obj);
   1.492 +
   1.493 +    // jsop_setelem() helpers.
   1.494 +    bool setElemTryTypedArray(bool *emitted, MDefinition *object,
   1.495 +                         MDefinition *index, MDefinition *value);
   1.496 +    bool setElemTryTypedObject(bool *emitted, MDefinition *obj,
   1.497 +                               MDefinition *index, MDefinition *value);
   1.498 +    bool setElemTryTypedStatic(bool *emitted, MDefinition *object,
   1.499 +                               MDefinition *index, MDefinition *value);
   1.500 +    bool setElemTryDense(bool *emitted, MDefinition *object,
   1.501 +                         MDefinition *index, MDefinition *value);
   1.502 +    bool setElemTryArguments(bool *emitted, MDefinition *object,
   1.503 +                             MDefinition *index, MDefinition *value);
   1.504 +    bool setElemTryCache(bool *emitted, MDefinition *object,
   1.505 +                         MDefinition *index, MDefinition *value);
   1.506 +    bool setElemTryScalarElemOfTypedObject(bool *emitted,
   1.507 +                                           MDefinition *obj,
   1.508 +                                           MDefinition *index,
   1.509 +                                           TypeDescrSet objTypeReprs,
   1.510 +                                           MDefinition *value,
   1.511 +                                           TypeDescrSet elemTypeReprs,
   1.512 +                                           int32_t elemSize);
   1.513 +
   1.514 +    // jsop_getelem() helpers.
   1.515 +    bool getElemTryDense(bool *emitted, MDefinition *obj, MDefinition *index);
   1.516 +    bool getElemTryTypedStatic(bool *emitted, MDefinition *obj, MDefinition *index);
   1.517 +    bool getElemTryTypedArray(bool *emitted, MDefinition *obj, MDefinition *index);
   1.518 +    bool getElemTryTypedObject(bool *emitted, MDefinition *obj, MDefinition *index);
   1.519 +    bool getElemTryString(bool *emitted, MDefinition *obj, MDefinition *index);
   1.520 +    bool getElemTryArguments(bool *emitted, MDefinition *obj, MDefinition *index);
   1.521 +    bool getElemTryArgumentsInlined(bool *emitted, MDefinition *obj, MDefinition *index);
   1.522 +    bool getElemTryCache(bool *emitted, MDefinition *obj, MDefinition *index);
   1.523 +    bool getElemTryScalarElemOfTypedObject(bool *emitted,
   1.524 +                                           MDefinition *obj,
   1.525 +                                           MDefinition *index,
   1.526 +                                           TypeDescrSet objTypeReprs,
   1.527 +                                           TypeDescrSet elemTypeReprs,
   1.528 +                                           int32_t elemSize);
   1.529 +    bool getElemTryComplexElemOfTypedObject(bool *emitted,
   1.530 +                                            MDefinition *obj,
   1.531 +                                            MDefinition *index,
   1.532 +                                            TypeDescrSet objTypeReprs,
   1.533 +                                            TypeDescrSet elemTypeReprs,
   1.534 +                                            int32_t elemSize);
   1.535 +
   1.536 +    enum BoundsChecking { DoBoundsCheck, SkipBoundsCheck };
   1.537 +
   1.538 +    // Add instructions to compute a typed array's length and data.  Also
   1.539 +    // optionally convert |*index| into a bounds-checked definition, if
   1.540 +    // requested.
   1.541 +    //
   1.542 +    // If you only need the array's length, use addTypedArrayLength below.
   1.543 +    void addTypedArrayLengthAndData(MDefinition *obj,
   1.544 +                                    BoundsChecking checking,
   1.545 +                                    MDefinition **index,
   1.546 +                                    MInstruction **length, MInstruction **elements);
   1.547 +
   1.548 +    // Add an instruction to compute a typed array's length to the current
   1.549 +    // block.  If you also need the typed array's data, use the above method
   1.550 +    // instead.
   1.551 +    MInstruction *addTypedArrayLength(MDefinition *obj) {
   1.552 +        MInstruction *length;
   1.553 +        addTypedArrayLengthAndData(obj, SkipBoundsCheck, nullptr, &length, nullptr);
   1.554 +        return length;
   1.555 +    }
   1.556 +
   1.557 +
   1.558 +    MDefinition *getCallee();
   1.559 +
   1.560 +    bool jsop_add(MDefinition *left, MDefinition *right);
   1.561 +    bool jsop_bitnot();
   1.562 +    bool jsop_bitop(JSOp op);
   1.563 +    bool jsop_binary(JSOp op);
   1.564 +    bool jsop_binary(JSOp op, MDefinition *left, MDefinition *right);
   1.565 +    bool jsop_pos();
   1.566 +    bool jsop_neg();
   1.567 +    bool jsop_setarg(uint32_t arg);
   1.568 +    bool jsop_defvar(uint32_t index);
   1.569 +    bool jsop_deffun(uint32_t index);
   1.570 +    bool jsop_notearg();
   1.571 +    bool jsop_funcall(uint32_t argc);
   1.572 +    bool jsop_funapply(uint32_t argc);
   1.573 +    bool jsop_funapplyarguments(uint32_t argc);
   1.574 +    bool jsop_call(uint32_t argc, bool constructing);
   1.575 +    bool jsop_eval(uint32_t argc);
   1.576 +    bool jsop_ifeq(JSOp op);
   1.577 +    bool jsop_try();
   1.578 +    bool jsop_label();
   1.579 +    bool jsop_condswitch();
   1.580 +    bool jsop_andor(JSOp op);
   1.581 +    bool jsop_dup2();
   1.582 +    bool jsop_loophead(jsbytecode *pc);
   1.583 +    bool jsop_compare(JSOp op);
   1.584 +    bool getStaticName(JSObject *staticObject, PropertyName *name, bool *psucceeded);
   1.585 +    bool setStaticName(JSObject *staticObject, PropertyName *name);
   1.586 +    bool jsop_getgname(PropertyName *name);
   1.587 +    bool jsop_getname(PropertyName *name);
   1.588 +    bool jsop_intrinsic(PropertyName *name);
   1.589 +    bool jsop_bindname(PropertyName *name);
   1.590 +    bool jsop_getelem();
   1.591 +    bool jsop_getelem_dense(MDefinition *obj, MDefinition *index);
   1.592 +    bool jsop_getelem_typed(MDefinition *obj, MDefinition *index, ScalarTypeDescr::Type arrayType);
   1.593 +    bool jsop_setelem();
   1.594 +    bool jsop_setelem_dense(types::TemporaryTypeSet::DoubleConversion conversion,
   1.595 +                            SetElemSafety safety,
   1.596 +                            MDefinition *object, MDefinition *index, MDefinition *value);
   1.597 +    bool jsop_setelem_typed(ScalarTypeDescr::Type arrayType,
   1.598 +                            SetElemSafety safety,
   1.599 +                            MDefinition *object, MDefinition *index, MDefinition *value);
   1.600 +    bool jsop_setelem_typed_object(ScalarTypeDescr::Type arrayType,
   1.601 +                                   SetElemSafety safety, bool racy,
   1.602 +                                   MDefinition *object, MDefinition *index, MDefinition *value);
   1.603 +    bool jsop_length();
   1.604 +    bool jsop_length_fastPath();
   1.605 +    bool jsop_arguments();
   1.606 +    bool jsop_arguments_length();
   1.607 +    bool jsop_arguments_getelem();
   1.608 +    bool jsop_runonce();
   1.609 +    bool jsop_rest();
   1.610 +    bool jsop_not();
   1.611 +    bool jsop_getprop(PropertyName *name);
   1.612 +    bool jsop_setprop(PropertyName *name);
   1.613 +    bool jsop_delprop(PropertyName *name);
   1.614 +    bool jsop_delelem();
   1.615 +    bool jsop_newarray(uint32_t count);
   1.616 +    bool jsop_newobject();
   1.617 +    bool jsop_initelem();
   1.618 +    bool jsop_initelem_array();
   1.619 +    bool jsop_initelem_getter_setter();
   1.620 +    bool jsop_mutateproto();
   1.621 +    bool jsop_initprop(PropertyName *name);
   1.622 +    bool jsop_initprop_getter_setter(PropertyName *name);
   1.623 +    bool jsop_regexp(RegExpObject *reobj);
   1.624 +    bool jsop_object(JSObject *obj);
   1.625 +    bool jsop_lambda(JSFunction *fun);
   1.626 +    bool jsop_lambda_arrow(JSFunction *fun);
   1.627 +    bool jsop_this();
   1.628 +    bool jsop_typeof();
   1.629 +    bool jsop_toid();
   1.630 +    bool jsop_iter(uint8_t flags);
   1.631 +    bool jsop_iternext();
   1.632 +    bool jsop_itermore();
   1.633 +    bool jsop_iterend();
   1.634 +    bool jsop_in();
   1.635 +    bool jsop_in_dense();
   1.636 +    bool jsop_instanceof();
   1.637 +    bool jsop_getaliasedvar(ScopeCoordinate sc);
   1.638 +    bool jsop_setaliasedvar(ScopeCoordinate sc);
   1.639 +
   1.640 +    /* Inlining. */
   1.641 +
   1.642 +    enum InliningStatus
   1.643 +    {
   1.644 +        InliningStatus_Error,
   1.645 +        InliningStatus_NotInlined,
   1.646 +        InliningStatus_Inlined
   1.647 +    };
   1.648 +
   1.649 +    enum InliningDecision
   1.650 +    {
   1.651 +        InliningDecision_Error,
   1.652 +        InliningDecision_Inline,
   1.653 +        InliningDecision_DontInline
   1.654 +    };
   1.655 +
   1.656 +    static InliningDecision DontInline(JSScript *targetScript, const char *reason);
   1.657 +
   1.658 +    // Oracles.
   1.659 +    InliningDecision canInlineTarget(JSFunction *target, CallInfo &callInfo);
   1.660 +    InliningDecision makeInliningDecision(JSFunction *target, CallInfo &callInfo);
   1.661 +    bool selectInliningTargets(ObjectVector &targets, CallInfo &callInfo,
   1.662 +                               BoolVector &choiceSet, uint32_t *numInlineable);
   1.663 +
   1.664 +    // Native inlining helpers.
   1.665 +    types::TemporaryTypeSet *getInlineReturnTypeSet();
   1.666 +    MIRType getInlineReturnType();
   1.667 +
   1.668 +    // Array natives.
   1.669 +    InliningStatus inlineArray(CallInfo &callInfo);
   1.670 +    InliningStatus inlineArrayPopShift(CallInfo &callInfo, MArrayPopShift::Mode mode);
   1.671 +    InliningStatus inlineArrayPush(CallInfo &callInfo);
   1.672 +    InliningStatus inlineArrayConcat(CallInfo &callInfo);
   1.673 +    InliningStatus inlineArraySplice(CallInfo &callInfo);
   1.674 +
   1.675 +    // Math natives.
   1.676 +    InliningStatus inlineMathAbs(CallInfo &callInfo);
   1.677 +    InliningStatus inlineMathFloor(CallInfo &callInfo);
   1.678 +    InliningStatus inlineMathCeil(CallInfo &callInfo);
   1.679 +    InliningStatus inlineMathRound(CallInfo &callInfo);
   1.680 +    InliningStatus inlineMathSqrt(CallInfo &callInfo);
   1.681 +    InliningStatus inlineMathAtan2(CallInfo &callInfo);
   1.682 +    InliningStatus inlineMathHypot(CallInfo &callInfo);
   1.683 +    InliningStatus inlineMathMinMax(CallInfo &callInfo, bool max);
   1.684 +    InliningStatus inlineMathPow(CallInfo &callInfo);
   1.685 +    InliningStatus inlineMathRandom(CallInfo &callInfo);
   1.686 +    InliningStatus inlineMathImul(CallInfo &callInfo);
   1.687 +    InliningStatus inlineMathFRound(CallInfo &callInfo);
   1.688 +    InliningStatus inlineMathFunction(CallInfo &callInfo, MMathFunction::Function function);
   1.689 +
   1.690 +    // String natives.
   1.691 +    InliningStatus inlineStringObject(CallInfo &callInfo);
   1.692 +    InliningStatus inlineStringSplit(CallInfo &callInfo);
   1.693 +    InliningStatus inlineStrCharCodeAt(CallInfo &callInfo);
   1.694 +    InliningStatus inlineStrFromCharCode(CallInfo &callInfo);
   1.695 +    InliningStatus inlineStrCharAt(CallInfo &callInfo);
   1.696 +    InliningStatus inlineStrReplace(CallInfo &callInfo);
   1.697 +
   1.698 +    // RegExp natives.
   1.699 +    InliningStatus inlineRegExpExec(CallInfo &callInfo);
   1.700 +    InliningStatus inlineRegExpTest(CallInfo &callInfo);
   1.701 +
   1.702 +    // Array intrinsics.
   1.703 +    InliningStatus inlineUnsafePutElements(CallInfo &callInfo);
   1.704 +    bool inlineUnsafeSetDenseArrayElement(CallInfo &callInfo, uint32_t base);
   1.705 +    bool inlineUnsafeSetTypedArrayElement(CallInfo &callInfo, uint32_t base,
   1.706 +                                          ScalarTypeDescr::Type arrayType);
   1.707 +    bool inlineUnsafeSetTypedObjectArrayElement(CallInfo &callInfo, uint32_t base,
   1.708 +                                                ScalarTypeDescr::Type arrayType);
   1.709 +    InliningStatus inlineNewDenseArray(CallInfo &callInfo);
   1.710 +    InliningStatus inlineNewDenseArrayForSequentialExecution(CallInfo &callInfo);
   1.711 +    InliningStatus inlineNewDenseArrayForParallelExecution(CallInfo &callInfo);
   1.712 +
   1.713 +    // Slot intrinsics.
   1.714 +    InliningStatus inlineUnsafeSetReservedSlot(CallInfo &callInfo);
   1.715 +    InliningStatus inlineUnsafeGetReservedSlot(CallInfo &callInfo);
   1.716 +
   1.717 +    // ForkJoin intrinsics
   1.718 +    InliningStatus inlineForkJoinGetSlice(CallInfo &callInfo);
   1.719 +
   1.720 +    // TypedObject intrinsics.
   1.721 +    InliningStatus inlineObjectIsTypeDescr(CallInfo &callInfo);
   1.722 +    InliningStatus inlineSetTypedObjectOffset(CallInfo &callInfo);
   1.723 +    bool elementAccessIsTypedObjectArrayOfScalarType(MDefinition* obj, MDefinition* id,
   1.724 +                                                     ScalarTypeDescr::Type *arrayType);
   1.725 +
   1.726 +    // Utility intrinsics.
   1.727 +    InliningStatus inlineIsCallable(CallInfo &callInfo);
   1.728 +    InliningStatus inlineHaveSameClass(CallInfo &callInfo);
   1.729 +    InliningStatus inlineToObject(CallInfo &callInfo);
   1.730 +    InliningStatus inlineDump(CallInfo &callInfo);
   1.731 +    InliningStatus inlineHasClass(CallInfo &callInfo, const Class *clasp) {
   1.732 +        return inlineHasClasses(callInfo, clasp, nullptr);
   1.733 +    }
   1.734 +    InliningStatus inlineHasClasses(CallInfo &callInfo, const Class *clasp1, const Class *clasp2);
   1.735 +
   1.736 +    // Testing functions.
   1.737 +    InliningStatus inlineForceSequentialOrInParallelSection(CallInfo &callInfo);
   1.738 +    InliningStatus inlineBailout(CallInfo &callInfo);
   1.739 +    InliningStatus inlineAssertFloat32(CallInfo &callInfo);
   1.740 +
   1.741 +    // Bind function.
   1.742 +    InliningStatus inlineBoundFunction(CallInfo &callInfo, JSFunction *target);
   1.743 +
   1.744 +    // Main inlining functions
   1.745 +    InliningStatus inlineNativeCall(CallInfo &callInfo, JSFunction *target);
   1.746 +    bool inlineScriptedCall(CallInfo &callInfo, JSFunction *target);
   1.747 +    InliningStatus inlineSingleCall(CallInfo &callInfo, JSFunction *target);
   1.748 +
   1.749 +    // Call functions
   1.750 +    InliningStatus inlineCallsite(ObjectVector &targets, ObjectVector &originals,
   1.751 +                                  bool lambda, CallInfo &callInfo);
   1.752 +    bool inlineCalls(CallInfo &callInfo, ObjectVector &targets, ObjectVector &originals,
   1.753 +                     BoolVector &choiceSet, MGetPropertyCache *maybeCache);
   1.754 +
   1.755 +    // Inlining helpers.
   1.756 +    bool inlineGenericFallback(JSFunction *target, CallInfo &callInfo, MBasicBlock *dispatchBlock,
   1.757 +                               bool clonedAtCallsite);
   1.758 +    bool inlineTypeObjectFallback(CallInfo &callInfo, MBasicBlock *dispatchBlock,
   1.759 +                                  MTypeObjectDispatch *dispatch, MGetPropertyCache *cache,
   1.760 +                                  MBasicBlock **fallbackTarget);
   1.761 +
   1.762 +    bool testNeedsArgumentCheck(JSFunction *target, CallInfo &callInfo);
   1.763 +
   1.764 +    MDefinition *makeCallsiteClone(JSFunction *target, MDefinition *fun);
   1.765 +    MCall *makeCallHelper(JSFunction *target, CallInfo &callInfo, bool cloneAtCallsite);
   1.766 +    bool makeCall(JSFunction *target, CallInfo &callInfo, bool cloneAtCallsite);
   1.767 +
   1.768 +    MDefinition *patchInlinedReturn(CallInfo &callInfo, MBasicBlock *exit, MBasicBlock *bottom);
   1.769 +    MDefinition *patchInlinedReturns(CallInfo &callInfo, MIRGraphReturns &returns,
   1.770 +                                     MBasicBlock *bottom);
   1.771 +
   1.772 +    bool objectsHaveCommonPrototype(types::TemporaryTypeSet *types, PropertyName *name,
   1.773 +                                    bool isGetter, JSObject *foundProto);
   1.774 +    void freezePropertiesForCommonPrototype(types::TemporaryTypeSet *types, PropertyName *name,
   1.775 +                                            JSObject *foundProto);
   1.776 +    MDefinition *testCommonGetterSetter(types::TemporaryTypeSet *types, PropertyName *name,
   1.777 +                                        bool isGetter, JSObject *foundProto, Shape *lastProperty);
   1.778 +    bool testShouldDOMCall(types::TypeSet *inTypes,
   1.779 +                           JSFunction *func, JSJitInfo::OpType opType);
   1.780 +
   1.781 +    bool annotateGetPropertyCache(MDefinition *obj, MGetPropertyCache *getPropCache,
   1.782 +                                  types::TemporaryTypeSet *objTypes,
   1.783 +                                  types::TemporaryTypeSet *pushedTypes);
   1.784 +
   1.785 +    MGetPropertyCache *getInlineableGetPropertyCache(CallInfo &callInfo);
   1.786 +
   1.787 +    JSObject *testSingletonProperty(JSObject *obj, PropertyName *name);
   1.788 +    bool testSingletonPropertyTypes(MDefinition *obj, JSObject *singleton, PropertyName *name,
   1.789 +                                    bool *testObject, bool *testString);
   1.790 +    bool getDefiniteSlot(types::TemporaryTypeSet *types, PropertyName *name,
   1.791 +                         types::HeapTypeSetKey *property);
   1.792 +    bool freezePropTypeSets(types::TemporaryTypeSet *types,
   1.793 +                            JSObject *foundProto, PropertyName *name);
   1.794 +
   1.795 +    types::TemporaryTypeSet *bytecodeTypes(jsbytecode *pc);
   1.796 +
   1.797 +    // Use one of the below methods for updating the current block, rather than
   1.798 +    // updating |current| directly. setCurrent() should only be used in cases
   1.799 +    // where the block cannot have phis whose type needs to be computed.
   1.800 +
   1.801 +    bool setCurrentAndSpecializePhis(MBasicBlock *block) {
   1.802 +        if (block) {
   1.803 +            if (!block->specializePhis())
   1.804 +                return false;
   1.805 +        }
   1.806 +        setCurrent(block);
   1.807 +        return true;
   1.808 +    }
   1.809 +
   1.810 +    void setCurrent(MBasicBlock *block) {
   1.811 +        current = block;
   1.812 +    }
   1.813 +
   1.814 +    // A builder is inextricably tied to a particular script.
   1.815 +    JSScript *script_;
   1.816 +
   1.817 +    // If off thread compilation is successful, the final code generator is
   1.818 +    // attached here. Code has been generated, but not linked (there is not yet
   1.819 +    // an IonScript). This is heap allocated, and must be explicitly destroyed,
   1.820 +    // performed by FinishOffThreadBuilder().
   1.821 +    CodeGenerator *backgroundCodegen_;
   1.822 +
   1.823 +  public:
   1.824 +    void clearForBackEnd();
   1.825 +
   1.826 +    JSScript *script() const { return script_; }
   1.827 +
   1.828 +    CodeGenerator *backgroundCodegen() const { return backgroundCodegen_; }
   1.829 +    void setBackgroundCodegen(CodeGenerator *codegen) { backgroundCodegen_ = codegen; }
   1.830 +
   1.831 +    AbortReason abortReason() { return abortReason_; }
   1.832 +
   1.833 +    TypeDescrSetHash *getOrCreateDescrSetHash(); // fallible
   1.834 +
   1.835 +    types::CompilerConstraintList *constraints() {
   1.836 +        return constraints_;
   1.837 +    }
   1.838 +
   1.839 +    bool isInlineBuilder() const {
   1.840 +        return callerBuilder_ != nullptr;
   1.841 +    }
   1.842 +
   1.843 +    const JSAtomState &names() { return compartment->runtime()->names(); }
   1.844 +
   1.845 +  private:
   1.846 +    bool init();
   1.847 +
   1.848 +    JSContext *analysisContext;
   1.849 +    BaselineFrameInspector *baselineFrame_;
   1.850 +    AbortReason abortReason_;
   1.851 +    TypeDescrSetHash *descrSetHash_;
   1.852 +
   1.853 +    // Constraints for recording dependencies on type information.
   1.854 +    types::CompilerConstraintList *constraints_;
   1.855 +
   1.856 +    // Basic analysis information about the script.
   1.857 +    BytecodeAnalysis analysis_;
   1.858 +    BytecodeAnalysis &analysis() {
   1.859 +        return analysis_;
   1.860 +    }
   1.861 +
   1.862 +    types::TemporaryTypeSet *thisTypes, *argTypes, *typeArray;
   1.863 +    uint32_t typeArrayHint;
   1.864 +    uint32_t *bytecodeTypeMap;
   1.865 +
   1.866 +    GSNCache gsn;
   1.867 +    ScopeCoordinateNameCache scopeCoordinateNameCache;
   1.868 +
   1.869 +    jsbytecode *pc;
   1.870 +    MBasicBlock *current;
   1.871 +    uint32_t loopDepth_;
   1.872 +
   1.873 +    /* Information used for inline-call builders. */
   1.874 +    MResumePoint *callerResumePoint_;
   1.875 +    jsbytecode *callerPC() {
   1.876 +        return callerResumePoint_ ? callerResumePoint_->pc() : nullptr;
   1.877 +    }
   1.878 +    IonBuilder *callerBuilder_;
   1.879 +
   1.880 +    bool oom() {
   1.881 +        abortReason_ = AbortReason_Alloc;
   1.882 +        return false;
   1.883 +    }
   1.884 +
   1.885 +    struct LoopHeader {
   1.886 +        jsbytecode *pc;
   1.887 +        MBasicBlock *header;
   1.888 +
   1.889 +        LoopHeader(jsbytecode *pc, MBasicBlock *header)
   1.890 +          : pc(pc), header(header)
   1.891 +        {}
   1.892 +    };
   1.893 +
   1.894 +    Vector<CFGState, 8, IonAllocPolicy> cfgStack_;
   1.895 +    Vector<ControlFlowInfo, 4, IonAllocPolicy> loops_;
   1.896 +    Vector<ControlFlowInfo, 0, IonAllocPolicy> switches_;
   1.897 +    Vector<ControlFlowInfo, 2, IonAllocPolicy> labels_;
   1.898 +    Vector<MInstruction *, 2, IonAllocPolicy> iterators_;
   1.899 +    Vector<LoopHeader, 0, IonAllocPolicy> loopHeaders_;
   1.900 +    BaselineInspector *inspector;
   1.901 +
   1.902 +    size_t inliningDepth_;
   1.903 +
   1.904 +    // Cutoff to disable compilation if excessive time is spent reanalyzing
   1.905 +    // loop bodies to compute a fixpoint of the types for loop variables.
   1.906 +    static const size_t MAX_LOOP_RESTARTS = 40;
   1.907 +    size_t numLoopRestarts_;
   1.908 +
   1.909 +    // True if script->failedBoundsCheck is set for the current script or
   1.910 +    // an outer script.
   1.911 +    bool failedBoundsCheck_;
   1.912 +
   1.913 +    // True if script->failedShapeGuard is set for the current script or
   1.914 +    // an outer script.
   1.915 +    bool failedShapeGuard_;
   1.916 +
   1.917 +    // Has an iterator other than 'for in'.
   1.918 +    bool nonStringIteration_;
   1.919 +
   1.920 +    // If this script can use a lazy arguments object, it will be pre-created
   1.921 +    // here.
   1.922 +    MInstruction *lazyArguments_;
   1.923 +
   1.924 +    // If this is an inline builder, the call info for the builder.
   1.925 +    const CallInfo *inlineCallInfo_;
   1.926 +};
   1.927 +
   1.928 +class CallInfo
   1.929 +{
   1.930 +    MDefinition *fun_;
   1.931 +    MDefinition *thisArg_;
   1.932 +    MDefinitionVector args_;
   1.933 +
   1.934 +    bool constructing_;
   1.935 +    bool setter_;
   1.936 +
   1.937 +  public:
   1.938 +    CallInfo(TempAllocator &alloc, bool constructing)
   1.939 +      : fun_(nullptr),
   1.940 +        thisArg_(nullptr),
   1.941 +        args_(alloc),
   1.942 +        constructing_(constructing),
   1.943 +        setter_(false)
   1.944 +    { }
   1.945 +
   1.946 +    bool init(CallInfo &callInfo) {
   1.947 +        JS_ASSERT(constructing_ == callInfo.constructing());
   1.948 +
   1.949 +        fun_ = callInfo.fun();
   1.950 +        thisArg_ = callInfo.thisArg();
   1.951 +
   1.952 +        if (!args_.appendAll(callInfo.argv()))
   1.953 +            return false;
   1.954 +
   1.955 +        return true;
   1.956 +    }
   1.957 +
   1.958 +    bool init(MBasicBlock *current, uint32_t argc) {
   1.959 +        JS_ASSERT(args_.empty());
   1.960 +
   1.961 +        // Get the arguments in the right order
   1.962 +        if (!args_.reserve(argc))
   1.963 +            return false;
   1.964 +        for (int32_t i = argc; i > 0; i--)
   1.965 +            args_.infallibleAppend(current->peek(-i));
   1.966 +        current->popn(argc);
   1.967 +
   1.968 +        // Get |this| and |fun|
   1.969 +        setThis(current->pop());
   1.970 +        setFun(current->pop());
   1.971 +
   1.972 +        return true;
   1.973 +    }
   1.974 +
   1.975 +    void popFormals(MBasicBlock *current) {
   1.976 +        current->popn(numFormals());
   1.977 +    }
   1.978 +
   1.979 +    void pushFormals(MBasicBlock *current) {
   1.980 +        current->push(fun());
   1.981 +        current->push(thisArg());
   1.982 +
   1.983 +        for (uint32_t i = 0; i < argc(); i++)
   1.984 +            current->push(getArg(i));
   1.985 +    }
   1.986 +
   1.987 +    uint32_t argc() const {
   1.988 +        return args_.length();
   1.989 +    }
   1.990 +    uint32_t numFormals() const {
   1.991 +        return argc() + 2;
   1.992 +    }
   1.993 +
   1.994 +    void setArgs(MDefinitionVector *args) {
   1.995 +        JS_ASSERT(args_.empty());
   1.996 +        args_.appendAll(*args);
   1.997 +    }
   1.998 +
   1.999 +    MDefinitionVector &argv() {
  1.1000 +        return args_;
  1.1001 +    }
  1.1002 +
  1.1003 +    const MDefinitionVector &argv() const {
  1.1004 +        return args_;
  1.1005 +    }
  1.1006 +
  1.1007 +    MDefinition *getArg(uint32_t i) const {
  1.1008 +        JS_ASSERT(i < argc());
  1.1009 +        return args_[i];
  1.1010 +    }
  1.1011 +
  1.1012 +    void setArg(uint32_t i, MDefinition *def) {
  1.1013 +        JS_ASSERT(i < argc());
  1.1014 +        args_[i] = def;
  1.1015 +    }
  1.1016 +
  1.1017 +    MDefinition *thisArg() const {
  1.1018 +        JS_ASSERT(thisArg_);
  1.1019 +        return thisArg_;
  1.1020 +    }
  1.1021 +
  1.1022 +    void setThis(MDefinition *thisArg) {
  1.1023 +        thisArg_ = thisArg;
  1.1024 +    }
  1.1025 +
  1.1026 +    bool constructing() const {
  1.1027 +        return constructing_;
  1.1028 +    }
  1.1029 +
  1.1030 +    bool isSetter() const {
  1.1031 +        return setter_;
  1.1032 +    }
  1.1033 +    void markAsSetter() {
  1.1034 +        setter_ = true;
  1.1035 +    }
  1.1036 +
  1.1037 +    MDefinition *fun() const {
  1.1038 +        JS_ASSERT(fun_);
  1.1039 +        return fun_;
  1.1040 +    }
  1.1041 +
  1.1042 +    void setFun(MDefinition *fun) {
  1.1043 +        fun_ = fun;
  1.1044 +    }
  1.1045 +
  1.1046 +    void setImplicitlyUsedUnchecked() {
  1.1047 +        fun_->setImplicitlyUsedUnchecked();
  1.1048 +        thisArg_->setImplicitlyUsedUnchecked();
  1.1049 +        for (uint32_t i = 0; i < argc(); i++)
  1.1050 +            getArg(i)->setImplicitlyUsedUnchecked();
  1.1051 +    }
  1.1052 +};
  1.1053 +
  1.1054 +bool TypeSetIncludes(types::TypeSet *types, MIRType input, types::TypeSet *inputTypes);
  1.1055 +
  1.1056 +bool NeedsPostBarrier(CompileInfo &info, MDefinition *value);
  1.1057 +
  1.1058 +} // namespace jit
  1.1059 +} // namespace js
  1.1060 +
  1.1061 +#endif // JS_ION
  1.1062 +
  1.1063 +#endif /* jit_IonBuilder_h */

mercurial