js/src/jit/MIRGraph.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_MIRGraph_h
     8 #define jit_MIRGraph_h
    10 // This file declares the data structures used to build a control-flow graph
    11 // containing MIR.
    13 #include "jit/FixedList.h"
    14 #include "jit/IonAllocPolicy.h"
    15 #include "jit/MIR.h"
    17 namespace js {
    18 namespace jit {
    20 class BytecodeAnalysis;
    21 class MBasicBlock;
    22 class MIRGraph;
    23 class MStart;
    25 class MDefinitionIterator;
    27 typedef InlineListIterator<MInstruction> MInstructionIterator;
    28 typedef InlineListReverseIterator<MInstruction> MInstructionReverseIterator;
    29 typedef InlineForwardListIterator<MPhi> MPhiIterator;
    30 typedef InlineForwardListIterator<MResumePoint> MResumePointIterator;
    32 class LBlock;
    34 class MBasicBlock : public TempObject, public InlineListNode<MBasicBlock>
    35 {
    36   public:
    37     enum Kind {
    38         NORMAL,
    39         PENDING_LOOP_HEADER,
    40         LOOP_HEADER,
    41         SPLIT_EDGE,
    42         DEAD
    43     };
    45   private:
    46     MBasicBlock(MIRGraph &graph, CompileInfo &info, jsbytecode *pc, Kind kind);
    47     bool init();
    48     void copySlots(MBasicBlock *from);
    49     bool inherit(TempAllocator &alloc, BytecodeAnalysis *analysis, MBasicBlock *pred,
    50                  uint32_t popped, unsigned stackPhiCount = 0);
    51     bool inheritResumePoint(MBasicBlock *pred);
    52     void assertUsesAreNotWithin(MUseIterator use, MUseIterator end);
    54     // This block cannot be reached by any means.
    55     bool unreachable_;
    57     // Pushes a copy of a local variable or argument.
    58     void pushVariable(uint32_t slot);
    60     // Sets a variable slot to the top of the stack, correctly creating copies
    61     // as needed.
    62     void setVariable(uint32_t slot);
    64   public:
    65     ///////////////////////////////////////////////////////
    66     ////////// BEGIN GRAPH BUILDING INSTRUCTIONS //////////
    67     ///////////////////////////////////////////////////////
    69     // Creates a new basic block for a MIR generator. If |pred| is not nullptr,
    70     // its slots and stack depth are initialized from |pred|.
    71     static MBasicBlock *New(MIRGraph &graph, BytecodeAnalysis *analysis, CompileInfo &info,
    72                             MBasicBlock *pred, jsbytecode *entryPc, Kind kind);
    73     static MBasicBlock *NewPopN(MIRGraph &graph, CompileInfo &info,
    74                                 MBasicBlock *pred, jsbytecode *entryPc, Kind kind, uint32_t popn);
    75     static MBasicBlock *NewWithResumePoint(MIRGraph &graph, CompileInfo &info,
    76                                            MBasicBlock *pred, jsbytecode *entryPc,
    77                                            MResumePoint *resumePoint);
    78     static MBasicBlock *NewPendingLoopHeader(MIRGraph &graph, CompileInfo &info,
    79                                              MBasicBlock *pred, jsbytecode *entryPc,
    80                                              unsigned loopStateSlots);
    81     static MBasicBlock *NewSplitEdge(MIRGraph &graph, CompileInfo &info, MBasicBlock *pred);
    82     static MBasicBlock *NewAbortPar(MIRGraph &graph, CompileInfo &info,
    83                                     MBasicBlock *pred, jsbytecode *entryPc,
    84                                     MResumePoint *resumePoint);
    85     static MBasicBlock *NewAsmJS(MIRGraph &graph, CompileInfo &info,
    86                                  MBasicBlock *pred, Kind kind);
    88     bool dominates(const MBasicBlock *other) const;
    90     void setId(uint32_t id) {
    91         id_ = id;
    92     }
    94     // Mark the current block and all dominated blocks as unreachable.
    95     void setUnreachable();
    96     bool unreachable() const {
    97         return unreachable_;
    98     }
    99     // Move the definition to the top of the stack.
   100     void pick(int32_t depth);
   102     // Exchange 2 stack slots at the defined depth
   103     void swapAt(int32_t depth);
   105     // Gets the instruction associated with various slot types.
   106     MDefinition *peek(int32_t depth);
   108     MDefinition *scopeChain();
   109     MDefinition *argumentsObject();
   111     // Increase the number of slots available
   112     bool increaseSlots(size_t num);
   113     bool ensureHasSlots(size_t num);
   115     // Initializes a slot value; must not be called for normal stack
   116     // operations, as it will not create new SSA names for copies.
   117     void initSlot(uint32_t index, MDefinition *ins);
   119     // Discard the slot at the given depth, lowering all slots above.
   120     void shimmySlots(int discardDepth);
   122     // In an OSR block, set all MOsrValues to use the MResumePoint attached to
   123     // the MStart.
   124     void linkOsrValues(MStart *start);
   126     // Sets the instruction associated with various slot types. The
   127     // instruction must lie at the top of the stack.
   128     void setLocal(uint32_t local);
   129     void setArg(uint32_t arg);
   130     void setSlot(uint32_t slot);
   131     void setSlot(uint32_t slot, MDefinition *ins);
   133     // Rewrites a slot directly, bypassing the stack transition. This should
   134     // not be used under most circumstances.
   135     void rewriteSlot(uint32_t slot, MDefinition *ins);
   137     // Rewrites a slot based on its depth (same as argument to peek()).
   138     void rewriteAtDepth(int32_t depth, MDefinition *ins);
   140     // Tracks an instruction as being pushed onto the operand stack.
   141     void push(MDefinition *ins);
   142     void pushArg(uint32_t arg);
   143     void pushLocal(uint32_t local);
   144     void pushSlot(uint32_t slot);
   145     void setScopeChain(MDefinition *ins);
   146     void setArgumentsObject(MDefinition *ins);
   148     // Returns the top of the stack, then decrements the virtual stack pointer.
   149     MDefinition *pop();
   150     void popn(uint32_t n);
   152     // Adds an instruction to this block's instruction list. |ins| may be
   153     // nullptr to simplify OOM checking.
   154     void add(MInstruction *ins);
   156     // Marks the last instruction of the block; no further instructions
   157     // can be added.
   158     void end(MControlInstruction *ins);
   160     // Adds a phi instruction, but does not set successorWithPhis.
   161     void addPhi(MPhi *phi);
   163     // Adds a resume point to this block.
   164     void addResumePoint(MResumePoint *resume) {
   165         resumePoints_.pushFront(resume);
   166     }
   168     // Adds a predecessor. Every predecessor must have the same exit stack
   169     // depth as the entry state to this block. Adding a predecessor
   170     // automatically creates phi nodes and rewrites uses as needed.
   171     bool addPredecessor(TempAllocator &alloc, MBasicBlock *pred);
   172     bool addPredecessorPopN(TempAllocator &alloc, MBasicBlock *pred, uint32_t popped);
   174     // Stranger utilities used for inlining.
   175     bool addPredecessorWithoutPhis(MBasicBlock *pred);
   176     void inheritSlots(MBasicBlock *parent);
   177     bool initEntrySlots(TempAllocator &alloc);
   179     // Replaces an edge for a given block with a new block. This is
   180     // used for critical edge splitting and also for inserting
   181     // bailouts during ParallelSafetyAnalysis.
   182     //
   183     // Note: If successorWithPhis is set, you must not be replacing it.
   184     void replacePredecessor(MBasicBlock *old, MBasicBlock *split);
   185     void replaceSuccessor(size_t pos, MBasicBlock *split);
   187     // Removes `pred` from the predecessor list.  `pred` should not be
   188     // the final predecessor. If this block defines phis, removes the
   189     // entry for `pred` and updates the indices of later entries.
   190     // This may introduce redundant phis if the new block has fewer
   191     // than two predecessors.
   192     void removePredecessor(MBasicBlock *pred);
   194     // Resets all the dominator info so that it can be recomputed.
   195     void clearDominatorInfo();
   197     // Sets a back edge. This places phi nodes and rewrites instructions within
   198     // the current loop as necessary. If the backedge introduces new types for
   199     // phis at the loop header, returns a disabling abort.
   200     AbortReason setBackedge(MBasicBlock *block);
   201     bool setBackedgeAsmJS(MBasicBlock *block);
   203     // Resets a LOOP_HEADER block to a NORMAL block.  This is needed when
   204     // optimizations remove the backedge.
   205     void clearLoopHeader();
   207     // Propagates phis placed in a loop header down to this successor block.
   208     void inheritPhis(MBasicBlock *header);
   210     // Compute the types for phis in this block according to their inputs.
   211     bool specializePhis();
   213     void insertBefore(MInstruction *at, MInstruction *ins);
   214     void insertAfter(MInstruction *at, MInstruction *ins);
   216     // Add an instruction to this block, from elsewhere in the graph.
   217     void addFromElsewhere(MInstruction *ins);
   219     // Move an instruction. Movement may cross block boundaries.
   220     void moveBefore(MInstruction *at, MInstruction *ins);
   222     // Removes an instruction with the intention to discard it.
   223     void discard(MInstruction *ins);
   224     void discardLastIns();
   225     MInstructionIterator discardAt(MInstructionIterator &iter);
   226     MInstructionReverseIterator discardAt(MInstructionReverseIterator &iter);
   227     MDefinitionIterator discardDefAt(MDefinitionIterator &iter);
   228     void discardAllInstructions();
   229     void discardAllPhiOperands();
   230     void discardAllPhis();
   231     void discardAllResumePoints(bool discardEntry = true);
   233     // Discards a phi instruction and updates predecessor successorWithPhis.
   234     MPhiIterator discardPhiAt(MPhiIterator &at);
   236     // Mark this block as having been removed from the graph.
   237     void markAsDead() {
   238         kind_ = DEAD;
   239     }
   241     ///////////////////////////////////////////////////////
   242     /////////// END GRAPH BUILDING INSTRUCTIONS ///////////
   243     ///////////////////////////////////////////////////////
   245     MIRGraph &graph() {
   246         return graph_;
   247     }
   248     CompileInfo &info() const {
   249         return info_;
   250     }
   251     jsbytecode *pc() const {
   252         return pc_;
   253     }
   254     uint32_t nslots() const {
   255         return slots_.length();
   256     }
   257     uint32_t id() const {
   258         return id_;
   259     }
   260     uint32_t numPredecessors() const {
   261         return predecessors_.length();
   262     }
   264     uint32_t domIndex() const {
   265         JS_ASSERT(!isDead());
   266         return domIndex_;
   267     }
   268     void setDomIndex(uint32_t d) {
   269         domIndex_ = d;
   270     }
   272     MBasicBlock *getPredecessor(uint32_t i) const {
   273         return predecessors_[i];
   274     }
   275     MControlInstruction *lastIns() const {
   276         return lastIns_;
   277     }
   278     MPhiIterator phisBegin() const {
   279         return phis_.begin();
   280     }
   281     MPhiIterator phisEnd() const {
   282         return phis_.end();
   283     }
   284     bool phisEmpty() const {
   285         return phis_.empty();
   286     }
   287     MResumePointIterator resumePointsBegin() const {
   288         return resumePoints_.begin();
   289     }
   290     MResumePointIterator resumePointsEnd() const {
   291         return resumePoints_.end();
   292     }
   293     bool resumePointsEmpty() const {
   294         return resumePoints_.empty();
   295     }
   296     MInstructionIterator begin() {
   297         return instructions_.begin();
   298     }
   299     MInstructionIterator begin(MInstruction *at) {
   300         JS_ASSERT(at->block() == this);
   301         return instructions_.begin(at);
   302     }
   303     MInstructionIterator end() {
   304         return instructions_.end();
   305     }
   306     MInstructionReverseIterator rbegin() {
   307         return instructions_.rbegin();
   308     }
   309     MInstructionReverseIterator rbegin(MInstruction *at) {
   310         JS_ASSERT(at->block() == this);
   311         return instructions_.rbegin(at);
   312     }
   313     MInstructionReverseIterator rend() {
   314         return instructions_.rend();
   315     }
   316     bool isLoopHeader() const {
   317         return kind_ == LOOP_HEADER;
   318     }
   319     bool hasUniqueBackedge() const {
   320         JS_ASSERT(isLoopHeader());
   321         JS_ASSERT(numPredecessors() >= 2);
   322         return numPredecessors() == 2;
   323     }
   324     MBasicBlock *backedge() const {
   325         JS_ASSERT(hasUniqueBackedge());
   326         return getPredecessor(numPredecessors() - 1);
   327     }
   328     MBasicBlock *loopHeaderOfBackedge() const {
   329         JS_ASSERT(isLoopBackedge());
   330         return getSuccessor(numSuccessors() - 1);
   331     }
   332     MBasicBlock *loopPredecessor() const {
   333         JS_ASSERT(isLoopHeader());
   334         return getPredecessor(0);
   335     }
   336     bool isLoopBackedge() const {
   337         if (!numSuccessors())
   338             return false;
   339         MBasicBlock *lastSuccessor = getSuccessor(numSuccessors() - 1);
   340         return lastSuccessor->isLoopHeader() &&
   341                lastSuccessor->hasUniqueBackedge() &&
   342                lastSuccessor->backedge() == this;
   343     }
   344     bool isSplitEdge() const {
   345         return kind_ == SPLIT_EDGE;
   346     }
   347     bool isDead() const {
   348         return kind_ == DEAD;
   349     }
   351     uint32_t stackDepth() const {
   352         return stackPosition_;
   353     }
   354     void setStackDepth(uint32_t depth) {
   355         stackPosition_ = depth;
   356     }
   357     bool isMarked() const {
   358         return mark_;
   359     }
   360     void mark() {
   361         mark_ = true;
   362     }
   363     void unmark() {
   364         mark_ = false;
   365     }
   366     void makeStart(MStart *start) {
   367         add(start);
   368         start_ = start;
   369     }
   370     MStart *start() const {
   371         return start_;
   372     }
   374     MBasicBlock *immediateDominator() const {
   375         return immediateDominator_;
   376     }
   378     void setImmediateDominator(MBasicBlock *dom) {
   379         immediateDominator_ = dom;
   380     }
   382     MTest *immediateDominatorBranch(BranchDirection *pdirection);
   384     size_t numImmediatelyDominatedBlocks() const {
   385         return immediatelyDominated_.length();
   386     }
   388     MBasicBlock *getImmediatelyDominatedBlock(size_t i) const {
   389         return immediatelyDominated_[i];
   390     }
   392     MBasicBlock **immediatelyDominatedBlocksBegin() {
   393         return immediatelyDominated_.begin();
   394     }
   396     MBasicBlock **immediatelyDominatedBlocksEnd() {
   397         return immediatelyDominated_.end();
   398     }
   400     size_t numDominated() const {
   401         return numDominated_;
   402     }
   404     void addNumDominated(size_t n) {
   405         numDominated_ += n;
   406     }
   408     bool addImmediatelyDominatedBlock(MBasicBlock *child);
   410     // This function retrieves the internal instruction associated with a
   411     // slot, and should not be used for normal stack operations. It is an
   412     // internal helper that is also used to enhance spew.
   413     MDefinition *getSlot(uint32_t index);
   415     MResumePoint *entryResumePoint() const {
   416         return entryResumePoint_;
   417     }
   418     MResumePoint *callerResumePoint() {
   419         return entryResumePoint()->caller();
   420     }
   421     void setCallerResumePoint(MResumePoint *caller) {
   422         entryResumePoint()->setCaller(caller);
   423     }
   424     size_t numEntrySlots() const {
   425         return entryResumePoint()->numOperands();
   426     }
   427     MDefinition *getEntrySlot(size_t i) const {
   428         JS_ASSERT(i < numEntrySlots());
   429         return entryResumePoint()->getOperand(i);
   430     }
   432     LBlock *lir() const {
   433         return lir_;
   434     }
   435     void assignLir(LBlock *lir) {
   436         JS_ASSERT(!lir_);
   437         lir_ = lir;
   438     }
   440     MBasicBlock *successorWithPhis() const {
   441         return successorWithPhis_;
   442     }
   443     uint32_t positionInPhiSuccessor() const {
   444         return positionInPhiSuccessor_;
   445     }
   446     void setSuccessorWithPhis(MBasicBlock *successor, uint32_t id) {
   447         successorWithPhis_ = successor;
   448         positionInPhiSuccessor_ = id;
   449     }
   450     size_t numSuccessors() const;
   451     MBasicBlock *getSuccessor(size_t index) const;
   452     size_t getSuccessorIndex(MBasicBlock *) const;
   454     void setLoopDepth(uint32_t loopDepth) {
   455         loopDepth_ = loopDepth;
   456     }
   457     uint32_t loopDepth() const {
   458         return loopDepth_;
   459     }
   461     bool strict() const {
   462         return info_.script()->strict();
   463     }
   465     void dumpStack(FILE *fp);
   467     void dump(FILE *fp);
   468     void dump();
   470     // Track bailouts by storing the current pc in MIR instruction added at this
   471     // cycle. This is also used for tracking calls when profiling.
   472     void updateTrackedPc(jsbytecode *pc) {
   473         trackedPc_ = pc;
   474     }
   476     jsbytecode *trackedPc() {
   477         return trackedPc_;
   478     }
   480   private:
   481     MIRGraph &graph_;
   482     CompileInfo &info_; // Each block originates from a particular script.
   483     InlineList<MInstruction> instructions_;
   484     Vector<MBasicBlock *, 1, IonAllocPolicy> predecessors_;
   485     InlineForwardList<MPhi> phis_;
   486     InlineForwardList<MResumePoint> resumePoints_;
   487     FixedList<MDefinition *> slots_;
   488     uint32_t stackPosition_;
   489     MControlInstruction *lastIns_;
   490     jsbytecode *pc_;
   491     uint32_t id_;
   492     uint32_t domIndex_; // Index in the dominator tree.
   493     LBlock *lir_;
   494     MStart *start_;
   495     MResumePoint *entryResumePoint_;
   496     MBasicBlock *successorWithPhis_;
   497     uint32_t positionInPhiSuccessor_;
   498     Kind kind_;
   499     uint32_t loopDepth_;
   501     // Utility mark for traversal algorithms.
   502     bool mark_;
   504     Vector<MBasicBlock *, 1, IonAllocPolicy> immediatelyDominated_;
   505     MBasicBlock *immediateDominator_;
   506     size_t numDominated_;
   508     jsbytecode *trackedPc_;
   510 #if defined (JS_ION_PERF)
   511     unsigned lineno_;
   512     unsigned columnIndex_;
   514   public:
   515     void setLineno(unsigned l) { lineno_ = l; }
   516     unsigned lineno() const { return lineno_; }
   517     void setColumnIndex(unsigned c) { columnIndex_ = c; }
   518     unsigned columnIndex() const { return columnIndex_; }
   519 #endif
   520 };
   522 typedef InlineListIterator<MBasicBlock> MBasicBlockIterator;
   523 typedef InlineListIterator<MBasicBlock> ReversePostorderIterator;
   524 typedef InlineListReverseIterator<MBasicBlock> PostorderIterator;
   526 typedef Vector<MBasicBlock *, 1, IonAllocPolicy> MIRGraphReturns;
   528 class MIRGraph
   529 {
   530     InlineList<MBasicBlock> blocks_;
   531     TempAllocator *alloc_;
   532     MIRGraphReturns *returnAccumulator_;
   533     uint32_t blockIdGen_;
   534     uint32_t idGen_;
   535     MBasicBlock *osrBlock_;
   536     MStart *osrStart_;
   538     size_t numBlocks_;
   539     bool hasTryBlock_;
   541   public:
   542     MIRGraph(TempAllocator *alloc)
   543       : alloc_(alloc),
   544         returnAccumulator_(nullptr),
   545         blockIdGen_(0),
   546         idGen_(1),
   547         osrBlock_(nullptr),
   548         osrStart_(nullptr),
   549         numBlocks_(0),
   550         hasTryBlock_(false)
   551     { }
   553     TempAllocator &alloc() const {
   554         return *alloc_;
   555     }
   557     void addBlock(MBasicBlock *block);
   558     void insertBlockAfter(MBasicBlock *at, MBasicBlock *block);
   560     void unmarkBlocks();
   562     void setReturnAccumulator(MIRGraphReturns *accum) {
   563         returnAccumulator_ = accum;
   564     }
   565     MIRGraphReturns *returnAccumulator() const {
   566         return returnAccumulator_;
   567     }
   569     bool addReturn(MBasicBlock *returnBlock) {
   570         if (!returnAccumulator_)
   571             return true;
   573         return returnAccumulator_->append(returnBlock);
   574     }
   576     MBasicBlock *entryBlock() {
   577         return *blocks_.begin();
   578     }
   580     void clearBlockList() {
   581         blocks_.clear();
   582         blockIdGen_ = 0;
   583         numBlocks_ = 0;
   584     }
   585     void resetInstructionNumber() {
   586         // This intentionally starts above 0. The id 0 is in places used to
   587         // indicate a failure to perform an operation on an instruction.
   588         idGen_ = 1;
   589     }
   590     MBasicBlockIterator begin() {
   591         return blocks_.begin();
   592     }
   593     MBasicBlockIterator begin(MBasicBlock *at) {
   594         return blocks_.begin(at);
   595     }
   596     MBasicBlockIterator end() {
   597         return blocks_.end();
   598     }
   599     PostorderIterator poBegin() {
   600         return blocks_.rbegin();
   601     }
   602     PostorderIterator poEnd() {
   603         return blocks_.rend();
   604     }
   605     ReversePostorderIterator rpoBegin() {
   606         return blocks_.begin();
   607     }
   608     ReversePostorderIterator rpoBegin(MBasicBlock *at) {
   609         return blocks_.begin(at);
   610     }
   611     ReversePostorderIterator rpoEnd() {
   612         return blocks_.end();
   613     }
   614     void removeBlocksAfter(MBasicBlock *block);
   615     void removeBlock(MBasicBlock *block);
   616     void moveBlockToEnd(MBasicBlock *block) {
   617         JS_ASSERT(block->id());
   618         blocks_.remove(block);
   619         blocks_.pushBack(block);
   620     }
   621     size_t numBlocks() const {
   622         return numBlocks_;
   623     }
   624     uint32_t numBlockIds() const {
   625         return blockIdGen_;
   626     }
   627     void allocDefinitionId(MDefinition *ins) {
   628         ins->setId(idGen_++);
   629     }
   630     uint32_t getNumInstructionIds() {
   631         return idGen_;
   632     }
   633     MResumePoint *entryResumePoint() {
   634         return blocks_.begin()->entryResumePoint();
   635     }
   637     void copyIds(const MIRGraph &other) {
   638         idGen_ = other.idGen_;
   639         blockIdGen_ = other.blockIdGen_;
   640         numBlocks_ = other.numBlocks_;
   641     }
   643     void setOsrBlock(MBasicBlock *osrBlock) {
   644         JS_ASSERT(!osrBlock_);
   645         osrBlock_ = osrBlock;
   646     }
   647     MBasicBlock *osrBlock() {
   648         return osrBlock_;
   649     }
   650     void setOsrStart(MStart *osrStart) {
   651         osrStart_ = osrStart;
   652     }
   653     MStart *osrStart() {
   654         return osrStart_;
   655     }
   657     bool hasTryBlock() const {
   658         return hasTryBlock_;
   659     }
   660     void setHasTryBlock() {
   661         hasTryBlock_ = true;
   662     }
   664     // The per-thread context. So as not to modify the calling convention for
   665     // parallel code, we obtain the current ForkJoinContext from thread-local
   666     // storage.  This helper method will lazilly insert an MForkJoinContext
   667     // instruction in the entry block and return the definition.
   668     MDefinition *forkJoinContext();
   670     void dump(FILE *fp);
   671     void dump();
   672 };
   674 class MDefinitionIterator
   675 {
   677   friend class MBasicBlock;
   679   private:
   680     MBasicBlock *block_;
   681     MPhiIterator phiIter_;
   682     MInstructionIterator iter_;
   684     bool atPhi() const {
   685         return phiIter_ != block_->phisEnd();
   686     }
   688     MDefinition *getIns() {
   689         if (atPhi())
   690             return *phiIter_;
   691         return *iter_;
   692     }
   694     void next() {
   695         if (atPhi())
   696             phiIter_++;
   697         else
   698             iter_++;
   699     }
   701     bool more() const {
   702         return atPhi() || (*iter_) != block_->lastIns();
   703     }
   705   public:
   706     MDefinitionIterator(MBasicBlock *block)
   707       : block_(block),
   708         phiIter_(block->phisBegin()),
   709         iter_(block->begin())
   710     { }
   712     MDefinitionIterator operator ++(int) {
   713         MDefinitionIterator old(*this);
   714         if (more())
   715             next();
   716         return old;
   717     }
   719     operator bool() const {
   720         return more();
   721     }
   723     MDefinition *operator *() {
   724         return getIns();
   725     }
   727     MDefinition *operator ->() {
   728         return getIns();
   729     }
   731 };
   733 } // namespace jit
   734 } // namespace js
   736 #endif /* jit_MIRGraph_h */

mercurial