js/src/jit/IonBuilder.h

Sat, 03 Jan 2015 20:18:00 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Sat, 03 Jan 2015 20:18:00 +0100
branch
TOR_BUG_3246
changeset 7
129ffea94266
permissions
-rw-r--r--

Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.

     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/. */
     7 #ifndef jit_IonBuilder_h
     8 #define jit_IonBuilder_h
    10 #ifdef JS_ION
    12 // This file declares the data structures for building a MIRGraph from a
    13 // JSScript.
    15 #include "jit/BytecodeAnalysis.h"
    16 #include "jit/IonOptimizationLevels.h"
    17 #include "jit/MIR.h"
    18 #include "jit/MIRGenerator.h"
    19 #include "jit/MIRGraph.h"
    20 #include "jit/TypeDescrSet.h"
    22 namespace js {
    23 namespace jit {
    25 class CodeGenerator;
    26 class CallInfo;
    27 class BaselineInspector;
    28 class BaselineFrameInspector;
    30 // Records information about a baseline frame for compilation that is stable
    31 // when later used off thread.
    32 BaselineFrameInspector *
    33 NewBaselineFrameInspector(TempAllocator *temp, BaselineFrame *frame, CompileInfo *info);
    35 class IonBuilder : public MIRGenerator
    36 {
    37     enum ControlStatus {
    38         ControlStatus_Error,
    39         ControlStatus_Abort,
    40         ControlStatus_Ended,        // There is no continuation/join point.
    41         ControlStatus_Joined,       // Created a join node.
    42         ControlStatus_Jumped,       // Parsing another branch at the same level.
    43         ControlStatus_None          // No control flow.
    44     };
    46     enum SetElemSafety {
    47         // Normal write like a[b] = c.
    48         SetElem_Normal,
    50         // Write due to UnsafePutElements:
    51         // - assumed to be in bounds,
    52         // - not checked for data races
    53         SetElem_Unsafe,
    54     };
    56     struct DeferredEdge : public TempObject
    57     {
    58         MBasicBlock *block;
    59         DeferredEdge *next;
    61         DeferredEdge(MBasicBlock *block, DeferredEdge *next)
    62           : block(block), next(next)
    63         { }
    64     };
    66     struct ControlFlowInfo {
    67         // Entry in the cfgStack.
    68         uint32_t cfgEntry;
    70         // Label that continues go to.
    71         jsbytecode *continuepc;
    73         ControlFlowInfo(uint32_t cfgEntry, jsbytecode *continuepc)
    74           : cfgEntry(cfgEntry),
    75             continuepc(continuepc)
    76         { }
    77     };
    79     // To avoid recursion, the bytecode analyzer uses a stack where each entry
    80     // is a small state machine. As we encounter branches or jumps in the
    81     // bytecode, we push information about the edges on the stack so that the
    82     // CFG can be built in a tree-like fashion.
    83     struct CFGState {
    84         enum State {
    85             IF_TRUE,            // if() { }, no else.
    86             IF_TRUE_EMPTY_ELSE, // if() { }, empty else
    87             IF_ELSE_TRUE,       // if() { X } else { }
    88             IF_ELSE_FALSE,      // if() { } else { X }
    89             DO_WHILE_LOOP_BODY, // do { x } while ()
    90             DO_WHILE_LOOP_COND, // do { } while (x)
    91             WHILE_LOOP_COND,    // while (x) { }
    92             WHILE_LOOP_BODY,    // while () { x }
    93             FOR_LOOP_COND,      // for (; x;) { }
    94             FOR_LOOP_BODY,      // for (; ;) { x }
    95             FOR_LOOP_UPDATE,    // for (; ; x) { }
    96             TABLE_SWITCH,       // switch() { x }
    97             COND_SWITCH_CASE,   // switch() { case X: ... }
    98             COND_SWITCH_BODY,   // switch() { case ...: X }
    99             AND_OR,             // && x, || x
   100             LABEL,              // label: x
   101             TRY                 // try { x } catch(e) { }
   102         };
   104         State state;            // Current state of this control structure.
   105         jsbytecode *stopAt;     // Bytecode at which to stop the processing loop.
   107         // For if structures, this contains branch information.
   108         union {
   109             struct {
   110                 MBasicBlock *ifFalse;
   111                 jsbytecode *falseEnd;
   112                 MBasicBlock *ifTrue;    // Set when the end of the true path is reached.
   113                 MTest *test;
   114             } branch;
   115             struct {
   116                 // Common entry point.
   117                 MBasicBlock *entry;
   119                 // Whether OSR is being performed for this loop.
   120                 bool osr;
   122                 // Position of where the loop body starts and ends.
   123                 jsbytecode *bodyStart;
   124                 jsbytecode *bodyEnd;
   126                 // pc immediately after the loop exits.
   127                 jsbytecode *exitpc;
   129                 // pc for 'continue' jumps.
   130                 jsbytecode *continuepc;
   132                 // Common exit point. Created lazily, so it may be nullptr.
   133                 MBasicBlock *successor;
   135                 // Deferred break and continue targets.
   136                 DeferredEdge *breaks;
   137                 DeferredEdge *continues;
   139                 // Initial state, in case loop processing is restarted.
   140                 State initialState;
   141                 jsbytecode *initialPc;
   142                 jsbytecode *initialStopAt;
   143                 jsbytecode *loopHead;
   145                 // For-loops only.
   146                 jsbytecode *condpc;
   147                 jsbytecode *updatepc;
   148                 jsbytecode *updateEnd;
   149             } loop;
   150             struct {
   151                 // pc immediately after the switch.
   152                 jsbytecode *exitpc;
   154                 // Deferred break and continue targets.
   155                 DeferredEdge *breaks;
   157                 // MIR instruction
   158                 MTableSwitch *ins;
   160                 // The number of current successor that get mapped into a block.
   161                 uint32_t currentBlock;
   163             } tableswitch;
   164             struct {
   165                 // Vector of body blocks to process after the cases.
   166                 FixedList<MBasicBlock *> *bodies;
   168                 // When processing case statements, this counter points at the
   169                 // last uninitialized body.  When processing bodies, this
   170                 // counter targets the next body to process.
   171                 uint32_t currentIdx;
   173                 // Remember the block index of the default case.
   174                 jsbytecode *defaultTarget;
   175                 uint32_t defaultIdx;
   177                 // Block immediately after the switch.
   178                 jsbytecode *exitpc;
   179                 DeferredEdge *breaks;
   180             } condswitch;
   181             struct {
   182                 DeferredEdge *breaks;
   183             } label;
   184             struct {
   185                 MBasicBlock *successor;
   186             } try_;
   187         };
   189         inline bool isLoop() const {
   190             switch (state) {
   191               case DO_WHILE_LOOP_COND:
   192               case DO_WHILE_LOOP_BODY:
   193               case WHILE_LOOP_COND:
   194               case WHILE_LOOP_BODY:
   195               case FOR_LOOP_COND:
   196               case FOR_LOOP_BODY:
   197               case FOR_LOOP_UPDATE:
   198                 return true;
   199               default:
   200                 return false;
   201             }
   202         }
   204         static CFGState If(jsbytecode *join, MTest *test);
   205         static CFGState IfElse(jsbytecode *trueEnd, jsbytecode *falseEnd, MTest *test);
   206         static CFGState AndOr(jsbytecode *join, MBasicBlock *joinStart);
   207         static CFGState TableSwitch(jsbytecode *exitpc, MTableSwitch *ins);
   208         static CFGState CondSwitch(IonBuilder *builder, jsbytecode *exitpc, jsbytecode *defaultTarget);
   209         static CFGState Label(jsbytecode *exitpc);
   210         static CFGState Try(jsbytecode *exitpc, MBasicBlock *successor);
   211     };
   213     static int CmpSuccessors(const void *a, const void *b);
   215   public:
   216     IonBuilder(JSContext *analysisContext, CompileCompartment *comp,
   217                const JitCompileOptions &options, TempAllocator *temp,
   218                MIRGraph *graph, types::CompilerConstraintList *constraints,
   219                BaselineInspector *inspector, CompileInfo *info,
   220                const OptimizationInfo *optimizationInfo, BaselineFrameInspector *baselineFrame,
   221                size_t inliningDepth = 0, uint32_t loopDepth = 0);
   223     bool build();
   224     bool buildInline(IonBuilder *callerBuilder, MResumePoint *callerResumePoint,
   225                      CallInfo &callInfo);
   227   private:
   228     bool traverseBytecode();
   229     ControlStatus snoopControlFlow(JSOp op);
   230     bool processIterators();
   231     bool inspectOpcode(JSOp op);
   232     uint32_t readIndex(jsbytecode *pc);
   233     JSAtom *readAtom(jsbytecode *pc);
   234     bool abort(const char *message, ...);
   235     void spew(const char *message);
   237     JSFunction *getSingleCallTarget(types::TemporaryTypeSet *calleeTypes);
   238     bool getPolyCallTargets(types::TemporaryTypeSet *calleeTypes, bool constructing,
   239                             ObjectVector &targets, uint32_t maxTargets, bool *gotLambda);
   241     void popCfgStack();
   242     DeferredEdge *filterDeadDeferredEdges(DeferredEdge *edge);
   243     bool processDeferredContinues(CFGState &state);
   244     ControlStatus processControlEnd();
   245     ControlStatus processCfgStack();
   246     ControlStatus processCfgEntry(CFGState &state);
   247     ControlStatus processIfEnd(CFGState &state);
   248     ControlStatus processIfElseTrueEnd(CFGState &state);
   249     ControlStatus processIfElseFalseEnd(CFGState &state);
   250     ControlStatus processDoWhileBodyEnd(CFGState &state);
   251     ControlStatus processDoWhileCondEnd(CFGState &state);
   252     ControlStatus processWhileCondEnd(CFGState &state);
   253     ControlStatus processWhileBodyEnd(CFGState &state);
   254     ControlStatus processForCondEnd(CFGState &state);
   255     ControlStatus processForBodyEnd(CFGState &state);
   256     ControlStatus processForUpdateEnd(CFGState &state);
   257     ControlStatus processNextTableSwitchCase(CFGState &state);
   258     ControlStatus processCondSwitchCase(CFGState &state);
   259     ControlStatus processCondSwitchBody(CFGState &state);
   260     ControlStatus processSwitchBreak(JSOp op);
   261     ControlStatus processSwitchEnd(DeferredEdge *breaks, jsbytecode *exitpc);
   262     ControlStatus processAndOrEnd(CFGState &state);
   263     ControlStatus processLabelEnd(CFGState &state);
   264     ControlStatus processTryEnd(CFGState &state);
   265     ControlStatus processReturn(JSOp op);
   266     ControlStatus processThrow();
   267     ControlStatus processContinue(JSOp op);
   268     ControlStatus processBreak(JSOp op, jssrcnote *sn);
   269     ControlStatus maybeLoop(JSOp op, jssrcnote *sn);
   270     bool pushLoop(CFGState::State state, jsbytecode *stopAt, MBasicBlock *entry, bool osr,
   271                   jsbytecode *loopHead, jsbytecode *initialPc,
   272                   jsbytecode *bodyStart, jsbytecode *bodyEnd, jsbytecode *exitpc,
   273                   jsbytecode *continuepc = nullptr);
   274     bool analyzeNewLoopTypes(MBasicBlock *entry, jsbytecode *start, jsbytecode *end);
   276     MBasicBlock *addBlock(MBasicBlock *block, uint32_t loopDepth);
   277     MBasicBlock *newBlock(MBasicBlock *predecessor, jsbytecode *pc);
   278     MBasicBlock *newBlock(MBasicBlock *predecessor, jsbytecode *pc, uint32_t loopDepth);
   279     MBasicBlock *newBlock(MBasicBlock *predecessor, jsbytecode *pc, MResumePoint *priorResumePoint);
   280     MBasicBlock *newBlockPopN(MBasicBlock *predecessor, jsbytecode *pc, uint32_t popped);
   281     MBasicBlock *newBlockAfter(MBasicBlock *at, MBasicBlock *predecessor, jsbytecode *pc);
   282     MBasicBlock *newOsrPreheader(MBasicBlock *header, jsbytecode *loopEntry);
   283     MBasicBlock *newPendingLoopHeader(MBasicBlock *predecessor, jsbytecode *pc, bool osr, bool canOsr,
   284                                       unsigned stackPhiCount);
   285     MBasicBlock *newBlock(jsbytecode *pc) {
   286         return newBlock(nullptr, pc);
   287     }
   288     MBasicBlock *newBlockAfter(MBasicBlock *at, jsbytecode *pc) {
   289         return newBlockAfter(at, nullptr, pc);
   290     }
   292     // Given a list of pending breaks, creates a new block and inserts a Goto
   293     // linking each break to the new block.
   294     MBasicBlock *createBreakCatchBlock(DeferredEdge *edge, jsbytecode *pc);
   296     // Finishes loops that do not actually loop, containing only breaks and
   297     // returns or a do while loop with a condition that is constant false.
   298     ControlStatus processBrokenLoop(CFGState &state);
   300     // Computes loop phis, places them in all successors of a loop, then
   301     // handles any pending breaks.
   302     ControlStatus finishLoop(CFGState &state, MBasicBlock *successor);
   304     // Incorporates a type/typeSet into an OSR value for a loop, after the loop
   305     // body has been processed.
   306     bool addOsrValueTypeBarrier(uint32_t slot, MInstruction **def,
   307                                 MIRType type, types::TemporaryTypeSet *typeSet);
   308     bool maybeAddOsrTypeBarriers();
   310     // Restarts processing of a loop if the type information at its header was
   311     // incomplete.
   312     ControlStatus restartLoop(CFGState state);
   314     void assertValidLoopHeadOp(jsbytecode *pc);
   316     ControlStatus forLoop(JSOp op, jssrcnote *sn);
   317     ControlStatus whileOrForInLoop(jssrcnote *sn);
   318     ControlStatus doWhileLoop(JSOp op, jssrcnote *sn);
   319     ControlStatus tableSwitch(JSOp op, jssrcnote *sn);
   320     ControlStatus condSwitch(JSOp op, jssrcnote *sn);
   322     // Please see the Big Honkin' Comment about how resume points work in
   323     // IonBuilder.cpp, near the definition for this function.
   324     bool resume(MInstruction *ins, jsbytecode *pc, MResumePoint::Mode mode);
   325     bool resumeAt(MInstruction *ins, jsbytecode *pc);
   326     bool resumeAfter(MInstruction *ins);
   327     bool maybeInsertResume();
   329     void insertRecompileCheck();
   331     void initParameters();
   332     void rewriteParameter(uint32_t slotIdx, MDefinition *param, int32_t argIndex);
   333     void rewriteParameters();
   334     bool initScopeChain(MDefinition *callee = nullptr);
   335     bool initArgumentsObject();
   336     bool pushConstant(const Value &v);
   338     MConstant *constant(const Value &v);
   339     MConstant *constantInt(int32_t i);
   341     // Filter the type information at tests
   342     bool filterTypesAtTest(MTest *test);
   344     // Add a guard which ensure that the set of type which goes through this
   345     // generated code correspond to the observed types for the bytecode.
   346     bool pushTypeBarrier(MDefinition *def, types::TemporaryTypeSet *observed, bool needBarrier);
   348     // As pushTypeBarrier, but will compute the needBarrier boolean itself based
   349     // on observed and the JSFunction that we're planning to call. The
   350     // JSFunction must be a DOM method or getter.
   351     bool pushDOMTypeBarrier(MInstruction *ins, types::TemporaryTypeSet *observed, JSFunction* func);
   353     // If definiteType is not known or def already has the right type, just
   354     // returns def.  Otherwise, returns an MInstruction that has that definite
   355     // type, infallibly unboxing ins as needed.  The new instruction will be
   356     // added to |current| in this case.
   357     MDefinition *ensureDefiniteType(MDefinition* def, MIRType definiteType);
   359     // Creates a MDefinition based on the given def improved with type as TypeSet.
   360     MDefinition *ensureDefiniteTypeSet(MDefinition* def, types::TemporaryTypeSet *types);
   362     JSObject *getSingletonPrototype(JSFunction *target);
   364     MDefinition *createThisScripted(MDefinition *callee);
   365     MDefinition *createThisScriptedSingleton(JSFunction *target, MDefinition *callee);
   366     MDefinition *createThis(JSFunction *target, MDefinition *callee);
   367     MInstruction *createDeclEnvObject(MDefinition *callee, MDefinition *scopeObj);
   368     MInstruction *createCallObject(MDefinition *callee, MDefinition *scopeObj);
   370     MDefinition *walkScopeChain(unsigned hops);
   372     MInstruction *addConvertElementsToDoubles(MDefinition *elements);
   373     MInstruction *addBoundsCheck(MDefinition *index, MDefinition *length);
   374     MInstruction *addShapeGuard(MDefinition *obj, Shape *const shape, BailoutKind bailoutKind);
   376     MDefinition *convertShiftToMaskForStaticTypedArray(MDefinition *id,
   377                                                        ArrayBufferView::ViewType viewType);
   379     bool invalidatedIdempotentCache();
   381     bool hasStaticScopeObject(ScopeCoordinate sc, JSObject **pcall);
   382     bool loadSlot(MDefinition *obj, size_t slot, size_t nfixed, MIRType rvalType,
   383                   bool barrier, types::TemporaryTypeSet *types);
   384     bool loadSlot(MDefinition *obj, Shape *shape, MIRType rvalType,
   385                   bool barrier, types::TemporaryTypeSet *types);
   386     bool storeSlot(MDefinition *obj, size_t slot, size_t nfixed,
   387                    MDefinition *value, bool needsBarrier,
   388                    MIRType slotType = MIRType_None);
   389     bool storeSlot(MDefinition *obj, Shape *shape, MDefinition *value, bool needsBarrier,
   390                    MIRType slotType = MIRType_None);
   392     // jsop_getprop() helpers.
   393     bool getPropTryArgumentsLength(bool *emitted);
   394     bool getPropTryConstant(bool *emitted, PropertyName *name,
   395                             types::TemporaryTypeSet *types);
   396     bool getPropTryDefiniteSlot(bool *emitted, PropertyName *name,
   397                                 bool barrier, types::TemporaryTypeSet *types);
   398     bool getPropTryCommonGetter(bool *emitted, PropertyName *name,
   399                                 types::TemporaryTypeSet *types);
   400     bool getPropTryInlineAccess(bool *emitted, PropertyName *name,
   401                                 bool barrier, types::TemporaryTypeSet *types);
   402     bool getPropTryTypedObject(bool *emitted, PropertyName *name,
   403                                types::TemporaryTypeSet *resultTypes);
   404     bool getPropTryScalarPropOfTypedObject(bool *emitted,
   405                                            int32_t fieldOffset,
   406                                            TypeDescrSet fieldTypeReprs,
   407                                            types::TemporaryTypeSet *resultTypes);
   408     bool getPropTryComplexPropOfTypedObject(bool *emitted,
   409                                             int32_t fieldOffset,
   410                                             TypeDescrSet fieldTypeReprs,
   411                                             size_t fieldIndex,
   412                                             types::TemporaryTypeSet *resultTypes);
   413     bool getPropTryCache(bool *emitted, PropertyName *name,
   414                          bool barrier, types::TemporaryTypeSet *types);
   415     bool needsToMonitorMissingProperties(types::TemporaryTypeSet *types);
   417     // jsop_setprop() helpers.
   418     bool setPropTryCommonSetter(bool *emitted, MDefinition *obj,
   419                                 PropertyName *name, MDefinition *value);
   420     bool setPropTryCommonDOMSetter(bool *emitted, MDefinition *obj,
   421                                    MDefinition *value, JSFunction *setter,
   422                                    bool isDOM);
   423     bool setPropTryDefiniteSlot(bool *emitted, MDefinition *obj,
   424                                 PropertyName *name, MDefinition *value,
   425                                 bool barrier, types::TemporaryTypeSet *objTypes);
   426     bool setPropTryInlineAccess(bool *emitted, MDefinition *obj,
   427                                 PropertyName *name, MDefinition *value, bool barrier,
   428                                 types::TemporaryTypeSet *objTypes);
   429     bool setPropTryTypedObject(bool *emitted, MDefinition *obj,
   430                                PropertyName *name, MDefinition *value);
   431     bool setPropTryScalarPropOfTypedObject(bool *emitted,
   432                                            MDefinition *obj,
   433                                            int32_t fieldOffset,
   434                                            MDefinition *value,
   435                                            TypeDescrSet fieldTypeReprs);
   436     bool setPropTryCache(bool *emitted, MDefinition *obj,
   437                          PropertyName *name, MDefinition *value,
   438                          bool barrier, types::TemporaryTypeSet *objTypes);
   440     // binary data lookup helpers.
   441     bool lookupTypeDescrSet(MDefinition *typedObj,
   442                                      TypeDescrSet *out);
   443     bool typeSetToTypeDescrSet(types::TemporaryTypeSet *types,
   444                                         TypeDescrSet *out);
   445     bool lookupTypedObjectField(MDefinition *typedObj,
   446                                 PropertyName *name,
   447                                 int32_t *fieldOffset,
   448                                 TypeDescrSet *fieldTypeReprs,
   449                                 size_t *fieldIndex);
   450     MDefinition *loadTypedObjectType(MDefinition *value);
   451     void loadTypedObjectData(MDefinition *typedObj,
   452                              MDefinition *offset,
   453                              bool canBeNeutered,
   454                              MDefinition **owner,
   455                              MDefinition **ownerOffset);
   456     void loadTypedObjectElements(MDefinition *typedObj,
   457                                  MDefinition *offset,
   458                                  int32_t unit,
   459                                  bool canBeNeutered,
   460                                  MDefinition **ownerElements,
   461                                  MDefinition **ownerScaledOffset);
   462     MDefinition *typeObjectForElementFromArrayStructType(MDefinition *typedObj);
   463     MDefinition *typeObjectForFieldFromStructType(MDefinition *type,
   464                                                   size_t fieldIndex);
   465     bool storeScalarTypedObjectValue(MDefinition *typedObj,
   466                                      MDefinition *offset,
   467                                      ScalarTypeDescr::Type type,
   468                                      bool canBeNeutered,
   469                                      bool racy,
   470                                      MDefinition *value);
   471     bool checkTypedObjectIndexInBounds(int32_t elemSize,
   472                                        MDefinition *obj,
   473                                        MDefinition *index,
   474                                        TypeDescrSet objTypeDescrs,
   475                                        MDefinition **indexAsByteOffset,
   476                                        bool *canBeNeutered);
   477     bool pushDerivedTypedObject(bool *emitted,
   478                                 MDefinition *obj,
   479                                 MDefinition *offset,
   480                                 TypeDescrSet derivedTypeDescrs,
   481                                 MDefinition *derivedTypeObj,
   482                                 bool canBeNeutered);
   483     bool pushScalarLoadFromTypedObject(bool *emitted,
   484                                        MDefinition *obj,
   485                                        MDefinition *offset,
   486                                        ScalarTypeDescr::Type type,
   487                                        bool canBeNeutered);
   488     MDefinition *neuterCheck(MDefinition *obj);
   490     // jsop_setelem() helpers.
   491     bool setElemTryTypedArray(bool *emitted, MDefinition *object,
   492                          MDefinition *index, MDefinition *value);
   493     bool setElemTryTypedObject(bool *emitted, MDefinition *obj,
   494                                MDefinition *index, MDefinition *value);
   495     bool setElemTryTypedStatic(bool *emitted, MDefinition *object,
   496                                MDefinition *index, MDefinition *value);
   497     bool setElemTryDense(bool *emitted, MDefinition *object,
   498                          MDefinition *index, MDefinition *value);
   499     bool setElemTryArguments(bool *emitted, MDefinition *object,
   500                              MDefinition *index, MDefinition *value);
   501     bool setElemTryCache(bool *emitted, MDefinition *object,
   502                          MDefinition *index, MDefinition *value);
   503     bool setElemTryScalarElemOfTypedObject(bool *emitted,
   504                                            MDefinition *obj,
   505                                            MDefinition *index,
   506                                            TypeDescrSet objTypeReprs,
   507                                            MDefinition *value,
   508                                            TypeDescrSet elemTypeReprs,
   509                                            int32_t elemSize);
   511     // jsop_getelem() helpers.
   512     bool getElemTryDense(bool *emitted, MDefinition *obj, MDefinition *index);
   513     bool getElemTryTypedStatic(bool *emitted, MDefinition *obj, MDefinition *index);
   514     bool getElemTryTypedArray(bool *emitted, MDefinition *obj, MDefinition *index);
   515     bool getElemTryTypedObject(bool *emitted, MDefinition *obj, MDefinition *index);
   516     bool getElemTryString(bool *emitted, MDefinition *obj, MDefinition *index);
   517     bool getElemTryArguments(bool *emitted, MDefinition *obj, MDefinition *index);
   518     bool getElemTryArgumentsInlined(bool *emitted, MDefinition *obj, MDefinition *index);
   519     bool getElemTryCache(bool *emitted, MDefinition *obj, MDefinition *index);
   520     bool getElemTryScalarElemOfTypedObject(bool *emitted,
   521                                            MDefinition *obj,
   522                                            MDefinition *index,
   523                                            TypeDescrSet objTypeReprs,
   524                                            TypeDescrSet elemTypeReprs,
   525                                            int32_t elemSize);
   526     bool getElemTryComplexElemOfTypedObject(bool *emitted,
   527                                             MDefinition *obj,
   528                                             MDefinition *index,
   529                                             TypeDescrSet objTypeReprs,
   530                                             TypeDescrSet elemTypeReprs,
   531                                             int32_t elemSize);
   533     enum BoundsChecking { DoBoundsCheck, SkipBoundsCheck };
   535     // Add instructions to compute a typed array's length and data.  Also
   536     // optionally convert |*index| into a bounds-checked definition, if
   537     // requested.
   538     //
   539     // If you only need the array's length, use addTypedArrayLength below.
   540     void addTypedArrayLengthAndData(MDefinition *obj,
   541                                     BoundsChecking checking,
   542                                     MDefinition **index,
   543                                     MInstruction **length, MInstruction **elements);
   545     // Add an instruction to compute a typed array's length to the current
   546     // block.  If you also need the typed array's data, use the above method
   547     // instead.
   548     MInstruction *addTypedArrayLength(MDefinition *obj) {
   549         MInstruction *length;
   550         addTypedArrayLengthAndData(obj, SkipBoundsCheck, nullptr, &length, nullptr);
   551         return length;
   552     }
   555     MDefinition *getCallee();
   557     bool jsop_add(MDefinition *left, MDefinition *right);
   558     bool jsop_bitnot();
   559     bool jsop_bitop(JSOp op);
   560     bool jsop_binary(JSOp op);
   561     bool jsop_binary(JSOp op, MDefinition *left, MDefinition *right);
   562     bool jsop_pos();
   563     bool jsop_neg();
   564     bool jsop_setarg(uint32_t arg);
   565     bool jsop_defvar(uint32_t index);
   566     bool jsop_deffun(uint32_t index);
   567     bool jsop_notearg();
   568     bool jsop_funcall(uint32_t argc);
   569     bool jsop_funapply(uint32_t argc);
   570     bool jsop_funapplyarguments(uint32_t argc);
   571     bool jsop_call(uint32_t argc, bool constructing);
   572     bool jsop_eval(uint32_t argc);
   573     bool jsop_ifeq(JSOp op);
   574     bool jsop_try();
   575     bool jsop_label();
   576     bool jsop_condswitch();
   577     bool jsop_andor(JSOp op);
   578     bool jsop_dup2();
   579     bool jsop_loophead(jsbytecode *pc);
   580     bool jsop_compare(JSOp op);
   581     bool getStaticName(JSObject *staticObject, PropertyName *name, bool *psucceeded);
   582     bool setStaticName(JSObject *staticObject, PropertyName *name);
   583     bool jsop_getgname(PropertyName *name);
   584     bool jsop_getname(PropertyName *name);
   585     bool jsop_intrinsic(PropertyName *name);
   586     bool jsop_bindname(PropertyName *name);
   587     bool jsop_getelem();
   588     bool jsop_getelem_dense(MDefinition *obj, MDefinition *index);
   589     bool jsop_getelem_typed(MDefinition *obj, MDefinition *index, ScalarTypeDescr::Type arrayType);
   590     bool jsop_setelem();
   591     bool jsop_setelem_dense(types::TemporaryTypeSet::DoubleConversion conversion,
   592                             SetElemSafety safety,
   593                             MDefinition *object, MDefinition *index, MDefinition *value);
   594     bool jsop_setelem_typed(ScalarTypeDescr::Type arrayType,
   595                             SetElemSafety safety,
   596                             MDefinition *object, MDefinition *index, MDefinition *value);
   597     bool jsop_setelem_typed_object(ScalarTypeDescr::Type arrayType,
   598                                    SetElemSafety safety, bool racy,
   599                                    MDefinition *object, MDefinition *index, MDefinition *value);
   600     bool jsop_length();
   601     bool jsop_length_fastPath();
   602     bool jsop_arguments();
   603     bool jsop_arguments_length();
   604     bool jsop_arguments_getelem();
   605     bool jsop_runonce();
   606     bool jsop_rest();
   607     bool jsop_not();
   608     bool jsop_getprop(PropertyName *name);
   609     bool jsop_setprop(PropertyName *name);
   610     bool jsop_delprop(PropertyName *name);
   611     bool jsop_delelem();
   612     bool jsop_newarray(uint32_t count);
   613     bool jsop_newobject();
   614     bool jsop_initelem();
   615     bool jsop_initelem_array();
   616     bool jsop_initelem_getter_setter();
   617     bool jsop_mutateproto();
   618     bool jsop_initprop(PropertyName *name);
   619     bool jsop_initprop_getter_setter(PropertyName *name);
   620     bool jsop_regexp(RegExpObject *reobj);
   621     bool jsop_object(JSObject *obj);
   622     bool jsop_lambda(JSFunction *fun);
   623     bool jsop_lambda_arrow(JSFunction *fun);
   624     bool jsop_this();
   625     bool jsop_typeof();
   626     bool jsop_toid();
   627     bool jsop_iter(uint8_t flags);
   628     bool jsop_iternext();
   629     bool jsop_itermore();
   630     bool jsop_iterend();
   631     bool jsop_in();
   632     bool jsop_in_dense();
   633     bool jsop_instanceof();
   634     bool jsop_getaliasedvar(ScopeCoordinate sc);
   635     bool jsop_setaliasedvar(ScopeCoordinate sc);
   637     /* Inlining. */
   639     enum InliningStatus
   640     {
   641         InliningStatus_Error,
   642         InliningStatus_NotInlined,
   643         InliningStatus_Inlined
   644     };
   646     enum InliningDecision
   647     {
   648         InliningDecision_Error,
   649         InliningDecision_Inline,
   650         InliningDecision_DontInline
   651     };
   653     static InliningDecision DontInline(JSScript *targetScript, const char *reason);
   655     // Oracles.
   656     InliningDecision canInlineTarget(JSFunction *target, CallInfo &callInfo);
   657     InliningDecision makeInliningDecision(JSFunction *target, CallInfo &callInfo);
   658     bool selectInliningTargets(ObjectVector &targets, CallInfo &callInfo,
   659                                BoolVector &choiceSet, uint32_t *numInlineable);
   661     // Native inlining helpers.
   662     types::TemporaryTypeSet *getInlineReturnTypeSet();
   663     MIRType getInlineReturnType();
   665     // Array natives.
   666     InliningStatus inlineArray(CallInfo &callInfo);
   667     InliningStatus inlineArrayPopShift(CallInfo &callInfo, MArrayPopShift::Mode mode);
   668     InliningStatus inlineArrayPush(CallInfo &callInfo);
   669     InliningStatus inlineArrayConcat(CallInfo &callInfo);
   670     InliningStatus inlineArraySplice(CallInfo &callInfo);
   672     // Math natives.
   673     InliningStatus inlineMathAbs(CallInfo &callInfo);
   674     InliningStatus inlineMathFloor(CallInfo &callInfo);
   675     InliningStatus inlineMathCeil(CallInfo &callInfo);
   676     InliningStatus inlineMathRound(CallInfo &callInfo);
   677     InliningStatus inlineMathSqrt(CallInfo &callInfo);
   678     InliningStatus inlineMathAtan2(CallInfo &callInfo);
   679     InliningStatus inlineMathHypot(CallInfo &callInfo);
   680     InliningStatus inlineMathMinMax(CallInfo &callInfo, bool max);
   681     InliningStatus inlineMathPow(CallInfo &callInfo);
   682     InliningStatus inlineMathRandom(CallInfo &callInfo);
   683     InliningStatus inlineMathImul(CallInfo &callInfo);
   684     InliningStatus inlineMathFRound(CallInfo &callInfo);
   685     InliningStatus inlineMathFunction(CallInfo &callInfo, MMathFunction::Function function);
   687     // String natives.
   688     InliningStatus inlineStringObject(CallInfo &callInfo);
   689     InliningStatus inlineStringSplit(CallInfo &callInfo);
   690     InliningStatus inlineStrCharCodeAt(CallInfo &callInfo);
   691     InliningStatus inlineStrFromCharCode(CallInfo &callInfo);
   692     InliningStatus inlineStrCharAt(CallInfo &callInfo);
   693     InliningStatus inlineStrReplace(CallInfo &callInfo);
   695     // RegExp natives.
   696     InliningStatus inlineRegExpExec(CallInfo &callInfo);
   697     InliningStatus inlineRegExpTest(CallInfo &callInfo);
   699     // Array intrinsics.
   700     InliningStatus inlineUnsafePutElements(CallInfo &callInfo);
   701     bool inlineUnsafeSetDenseArrayElement(CallInfo &callInfo, uint32_t base);
   702     bool inlineUnsafeSetTypedArrayElement(CallInfo &callInfo, uint32_t base,
   703                                           ScalarTypeDescr::Type arrayType);
   704     bool inlineUnsafeSetTypedObjectArrayElement(CallInfo &callInfo, uint32_t base,
   705                                                 ScalarTypeDescr::Type arrayType);
   706     InliningStatus inlineNewDenseArray(CallInfo &callInfo);
   707     InliningStatus inlineNewDenseArrayForSequentialExecution(CallInfo &callInfo);
   708     InliningStatus inlineNewDenseArrayForParallelExecution(CallInfo &callInfo);
   710     // Slot intrinsics.
   711     InliningStatus inlineUnsafeSetReservedSlot(CallInfo &callInfo);
   712     InliningStatus inlineUnsafeGetReservedSlot(CallInfo &callInfo);
   714     // ForkJoin intrinsics
   715     InliningStatus inlineForkJoinGetSlice(CallInfo &callInfo);
   717     // TypedObject intrinsics.
   718     InliningStatus inlineObjectIsTypeDescr(CallInfo &callInfo);
   719     InliningStatus inlineSetTypedObjectOffset(CallInfo &callInfo);
   720     bool elementAccessIsTypedObjectArrayOfScalarType(MDefinition* obj, MDefinition* id,
   721                                                      ScalarTypeDescr::Type *arrayType);
   723     // Utility intrinsics.
   724     InliningStatus inlineIsCallable(CallInfo &callInfo);
   725     InliningStatus inlineHaveSameClass(CallInfo &callInfo);
   726     InliningStatus inlineToObject(CallInfo &callInfo);
   727     InliningStatus inlineDump(CallInfo &callInfo);
   728     InliningStatus inlineHasClass(CallInfo &callInfo, const Class *clasp) {
   729         return inlineHasClasses(callInfo, clasp, nullptr);
   730     }
   731     InliningStatus inlineHasClasses(CallInfo &callInfo, const Class *clasp1, const Class *clasp2);
   733     // Testing functions.
   734     InliningStatus inlineForceSequentialOrInParallelSection(CallInfo &callInfo);
   735     InliningStatus inlineBailout(CallInfo &callInfo);
   736     InliningStatus inlineAssertFloat32(CallInfo &callInfo);
   738     // Bind function.
   739     InliningStatus inlineBoundFunction(CallInfo &callInfo, JSFunction *target);
   741     // Main inlining functions
   742     InliningStatus inlineNativeCall(CallInfo &callInfo, JSFunction *target);
   743     bool inlineScriptedCall(CallInfo &callInfo, JSFunction *target);
   744     InliningStatus inlineSingleCall(CallInfo &callInfo, JSFunction *target);
   746     // Call functions
   747     InliningStatus inlineCallsite(ObjectVector &targets, ObjectVector &originals,
   748                                   bool lambda, CallInfo &callInfo);
   749     bool inlineCalls(CallInfo &callInfo, ObjectVector &targets, ObjectVector &originals,
   750                      BoolVector &choiceSet, MGetPropertyCache *maybeCache);
   752     // Inlining helpers.
   753     bool inlineGenericFallback(JSFunction *target, CallInfo &callInfo, MBasicBlock *dispatchBlock,
   754                                bool clonedAtCallsite);
   755     bool inlineTypeObjectFallback(CallInfo &callInfo, MBasicBlock *dispatchBlock,
   756                                   MTypeObjectDispatch *dispatch, MGetPropertyCache *cache,
   757                                   MBasicBlock **fallbackTarget);
   759     bool testNeedsArgumentCheck(JSFunction *target, CallInfo &callInfo);
   761     MDefinition *makeCallsiteClone(JSFunction *target, MDefinition *fun);
   762     MCall *makeCallHelper(JSFunction *target, CallInfo &callInfo, bool cloneAtCallsite);
   763     bool makeCall(JSFunction *target, CallInfo &callInfo, bool cloneAtCallsite);
   765     MDefinition *patchInlinedReturn(CallInfo &callInfo, MBasicBlock *exit, MBasicBlock *bottom);
   766     MDefinition *patchInlinedReturns(CallInfo &callInfo, MIRGraphReturns &returns,
   767                                      MBasicBlock *bottom);
   769     bool objectsHaveCommonPrototype(types::TemporaryTypeSet *types, PropertyName *name,
   770                                     bool isGetter, JSObject *foundProto);
   771     void freezePropertiesForCommonPrototype(types::TemporaryTypeSet *types, PropertyName *name,
   772                                             JSObject *foundProto);
   773     MDefinition *testCommonGetterSetter(types::TemporaryTypeSet *types, PropertyName *name,
   774                                         bool isGetter, JSObject *foundProto, Shape *lastProperty);
   775     bool testShouldDOMCall(types::TypeSet *inTypes,
   776                            JSFunction *func, JSJitInfo::OpType opType);
   778     bool annotateGetPropertyCache(MDefinition *obj, MGetPropertyCache *getPropCache,
   779                                   types::TemporaryTypeSet *objTypes,
   780                                   types::TemporaryTypeSet *pushedTypes);
   782     MGetPropertyCache *getInlineableGetPropertyCache(CallInfo &callInfo);
   784     JSObject *testSingletonProperty(JSObject *obj, PropertyName *name);
   785     bool testSingletonPropertyTypes(MDefinition *obj, JSObject *singleton, PropertyName *name,
   786                                     bool *testObject, bool *testString);
   787     bool getDefiniteSlot(types::TemporaryTypeSet *types, PropertyName *name,
   788                          types::HeapTypeSetKey *property);
   789     bool freezePropTypeSets(types::TemporaryTypeSet *types,
   790                             JSObject *foundProto, PropertyName *name);
   792     types::TemporaryTypeSet *bytecodeTypes(jsbytecode *pc);
   794     // Use one of the below methods for updating the current block, rather than
   795     // updating |current| directly. setCurrent() should only be used in cases
   796     // where the block cannot have phis whose type needs to be computed.
   798     bool setCurrentAndSpecializePhis(MBasicBlock *block) {
   799         if (block) {
   800             if (!block->specializePhis())
   801                 return false;
   802         }
   803         setCurrent(block);
   804         return true;
   805     }
   807     void setCurrent(MBasicBlock *block) {
   808         current = block;
   809     }
   811     // A builder is inextricably tied to a particular script.
   812     JSScript *script_;
   814     // If off thread compilation is successful, the final code generator is
   815     // attached here. Code has been generated, but not linked (there is not yet
   816     // an IonScript). This is heap allocated, and must be explicitly destroyed,
   817     // performed by FinishOffThreadBuilder().
   818     CodeGenerator *backgroundCodegen_;
   820   public:
   821     void clearForBackEnd();
   823     JSScript *script() const { return script_; }
   825     CodeGenerator *backgroundCodegen() const { return backgroundCodegen_; }
   826     void setBackgroundCodegen(CodeGenerator *codegen) { backgroundCodegen_ = codegen; }
   828     AbortReason abortReason() { return abortReason_; }
   830     TypeDescrSetHash *getOrCreateDescrSetHash(); // fallible
   832     types::CompilerConstraintList *constraints() {
   833         return constraints_;
   834     }
   836     bool isInlineBuilder() const {
   837         return callerBuilder_ != nullptr;
   838     }
   840     const JSAtomState &names() { return compartment->runtime()->names(); }
   842   private:
   843     bool init();
   845     JSContext *analysisContext;
   846     BaselineFrameInspector *baselineFrame_;
   847     AbortReason abortReason_;
   848     TypeDescrSetHash *descrSetHash_;
   850     // Constraints for recording dependencies on type information.
   851     types::CompilerConstraintList *constraints_;
   853     // Basic analysis information about the script.
   854     BytecodeAnalysis analysis_;
   855     BytecodeAnalysis &analysis() {
   856         return analysis_;
   857     }
   859     types::TemporaryTypeSet *thisTypes, *argTypes, *typeArray;
   860     uint32_t typeArrayHint;
   861     uint32_t *bytecodeTypeMap;
   863     GSNCache gsn;
   864     ScopeCoordinateNameCache scopeCoordinateNameCache;
   866     jsbytecode *pc;
   867     MBasicBlock *current;
   868     uint32_t loopDepth_;
   870     /* Information used for inline-call builders. */
   871     MResumePoint *callerResumePoint_;
   872     jsbytecode *callerPC() {
   873         return callerResumePoint_ ? callerResumePoint_->pc() : nullptr;
   874     }
   875     IonBuilder *callerBuilder_;
   877     bool oom() {
   878         abortReason_ = AbortReason_Alloc;
   879         return false;
   880     }
   882     struct LoopHeader {
   883         jsbytecode *pc;
   884         MBasicBlock *header;
   886         LoopHeader(jsbytecode *pc, MBasicBlock *header)
   887           : pc(pc), header(header)
   888         {}
   889     };
   891     Vector<CFGState, 8, IonAllocPolicy> cfgStack_;
   892     Vector<ControlFlowInfo, 4, IonAllocPolicy> loops_;
   893     Vector<ControlFlowInfo, 0, IonAllocPolicy> switches_;
   894     Vector<ControlFlowInfo, 2, IonAllocPolicy> labels_;
   895     Vector<MInstruction *, 2, IonAllocPolicy> iterators_;
   896     Vector<LoopHeader, 0, IonAllocPolicy> loopHeaders_;
   897     BaselineInspector *inspector;
   899     size_t inliningDepth_;
   901     // Cutoff to disable compilation if excessive time is spent reanalyzing
   902     // loop bodies to compute a fixpoint of the types for loop variables.
   903     static const size_t MAX_LOOP_RESTARTS = 40;
   904     size_t numLoopRestarts_;
   906     // True if script->failedBoundsCheck is set for the current script or
   907     // an outer script.
   908     bool failedBoundsCheck_;
   910     // True if script->failedShapeGuard is set for the current script or
   911     // an outer script.
   912     bool failedShapeGuard_;
   914     // Has an iterator other than 'for in'.
   915     bool nonStringIteration_;
   917     // If this script can use a lazy arguments object, it will be pre-created
   918     // here.
   919     MInstruction *lazyArguments_;
   921     // If this is an inline builder, the call info for the builder.
   922     const CallInfo *inlineCallInfo_;
   923 };
   925 class CallInfo
   926 {
   927     MDefinition *fun_;
   928     MDefinition *thisArg_;
   929     MDefinitionVector args_;
   931     bool constructing_;
   932     bool setter_;
   934   public:
   935     CallInfo(TempAllocator &alloc, bool constructing)
   936       : fun_(nullptr),
   937         thisArg_(nullptr),
   938         args_(alloc),
   939         constructing_(constructing),
   940         setter_(false)
   941     { }
   943     bool init(CallInfo &callInfo) {
   944         JS_ASSERT(constructing_ == callInfo.constructing());
   946         fun_ = callInfo.fun();
   947         thisArg_ = callInfo.thisArg();
   949         if (!args_.appendAll(callInfo.argv()))
   950             return false;
   952         return true;
   953     }
   955     bool init(MBasicBlock *current, uint32_t argc) {
   956         JS_ASSERT(args_.empty());
   958         // Get the arguments in the right order
   959         if (!args_.reserve(argc))
   960             return false;
   961         for (int32_t i = argc; i > 0; i--)
   962             args_.infallibleAppend(current->peek(-i));
   963         current->popn(argc);
   965         // Get |this| and |fun|
   966         setThis(current->pop());
   967         setFun(current->pop());
   969         return true;
   970     }
   972     void popFormals(MBasicBlock *current) {
   973         current->popn(numFormals());
   974     }
   976     void pushFormals(MBasicBlock *current) {
   977         current->push(fun());
   978         current->push(thisArg());
   980         for (uint32_t i = 0; i < argc(); i++)
   981             current->push(getArg(i));
   982     }
   984     uint32_t argc() const {
   985         return args_.length();
   986     }
   987     uint32_t numFormals() const {
   988         return argc() + 2;
   989     }
   991     void setArgs(MDefinitionVector *args) {
   992         JS_ASSERT(args_.empty());
   993         args_.appendAll(*args);
   994     }
   996     MDefinitionVector &argv() {
   997         return args_;
   998     }
  1000     const MDefinitionVector &argv() const {
  1001         return args_;
  1004     MDefinition *getArg(uint32_t i) const {
  1005         JS_ASSERT(i < argc());
  1006         return args_[i];
  1009     void setArg(uint32_t i, MDefinition *def) {
  1010         JS_ASSERT(i < argc());
  1011         args_[i] = def;
  1014     MDefinition *thisArg() const {
  1015         JS_ASSERT(thisArg_);
  1016         return thisArg_;
  1019     void setThis(MDefinition *thisArg) {
  1020         thisArg_ = thisArg;
  1023     bool constructing() const {
  1024         return constructing_;
  1027     bool isSetter() const {
  1028         return setter_;
  1030     void markAsSetter() {
  1031         setter_ = true;
  1034     MDefinition *fun() const {
  1035         JS_ASSERT(fun_);
  1036         return fun_;
  1039     void setFun(MDefinition *fun) {
  1040         fun_ = fun;
  1043     void setImplicitlyUsedUnchecked() {
  1044         fun_->setImplicitlyUsedUnchecked();
  1045         thisArg_->setImplicitlyUsedUnchecked();
  1046         for (uint32_t i = 0; i < argc(); i++)
  1047             getArg(i)->setImplicitlyUsedUnchecked();
  1049 };
  1051 bool TypeSetIncludes(types::TypeSet *types, MIRType input, types::TypeSet *inputTypes);
  1053 bool NeedsPostBarrier(CompileInfo &info, MDefinition *value);
  1055 } // namespace jit
  1056 } // namespace js
  1058 #endif // JS_ION
  1060 #endif /* jit_IonBuilder_h */

mercurial