1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/js/src/jit/MIRGraph.h Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,736 @@ 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_MIRGraph_h 1.11 +#define jit_MIRGraph_h 1.12 + 1.13 +// This file declares the data structures used to build a control-flow graph 1.14 +// containing MIR. 1.15 + 1.16 +#include "jit/FixedList.h" 1.17 +#include "jit/IonAllocPolicy.h" 1.18 +#include "jit/MIR.h" 1.19 + 1.20 +namespace js { 1.21 +namespace jit { 1.22 + 1.23 +class BytecodeAnalysis; 1.24 +class MBasicBlock; 1.25 +class MIRGraph; 1.26 +class MStart; 1.27 + 1.28 +class MDefinitionIterator; 1.29 + 1.30 +typedef InlineListIterator<MInstruction> MInstructionIterator; 1.31 +typedef InlineListReverseIterator<MInstruction> MInstructionReverseIterator; 1.32 +typedef InlineForwardListIterator<MPhi> MPhiIterator; 1.33 +typedef InlineForwardListIterator<MResumePoint> MResumePointIterator; 1.34 + 1.35 +class LBlock; 1.36 + 1.37 +class MBasicBlock : public TempObject, public InlineListNode<MBasicBlock> 1.38 +{ 1.39 + public: 1.40 + enum Kind { 1.41 + NORMAL, 1.42 + PENDING_LOOP_HEADER, 1.43 + LOOP_HEADER, 1.44 + SPLIT_EDGE, 1.45 + DEAD 1.46 + }; 1.47 + 1.48 + private: 1.49 + MBasicBlock(MIRGraph &graph, CompileInfo &info, jsbytecode *pc, Kind kind); 1.50 + bool init(); 1.51 + void copySlots(MBasicBlock *from); 1.52 + bool inherit(TempAllocator &alloc, BytecodeAnalysis *analysis, MBasicBlock *pred, 1.53 + uint32_t popped, unsigned stackPhiCount = 0); 1.54 + bool inheritResumePoint(MBasicBlock *pred); 1.55 + void assertUsesAreNotWithin(MUseIterator use, MUseIterator end); 1.56 + 1.57 + // This block cannot be reached by any means. 1.58 + bool unreachable_; 1.59 + 1.60 + // Pushes a copy of a local variable or argument. 1.61 + void pushVariable(uint32_t slot); 1.62 + 1.63 + // Sets a variable slot to the top of the stack, correctly creating copies 1.64 + // as needed. 1.65 + void setVariable(uint32_t slot); 1.66 + 1.67 + public: 1.68 + /////////////////////////////////////////////////////// 1.69 + ////////// BEGIN GRAPH BUILDING INSTRUCTIONS ////////// 1.70 + /////////////////////////////////////////////////////// 1.71 + 1.72 + // Creates a new basic block for a MIR generator. If |pred| is not nullptr, 1.73 + // its slots and stack depth are initialized from |pred|. 1.74 + static MBasicBlock *New(MIRGraph &graph, BytecodeAnalysis *analysis, CompileInfo &info, 1.75 + MBasicBlock *pred, jsbytecode *entryPc, Kind kind); 1.76 + static MBasicBlock *NewPopN(MIRGraph &graph, CompileInfo &info, 1.77 + MBasicBlock *pred, jsbytecode *entryPc, Kind kind, uint32_t popn); 1.78 + static MBasicBlock *NewWithResumePoint(MIRGraph &graph, CompileInfo &info, 1.79 + MBasicBlock *pred, jsbytecode *entryPc, 1.80 + MResumePoint *resumePoint); 1.81 + static MBasicBlock *NewPendingLoopHeader(MIRGraph &graph, CompileInfo &info, 1.82 + MBasicBlock *pred, jsbytecode *entryPc, 1.83 + unsigned loopStateSlots); 1.84 + static MBasicBlock *NewSplitEdge(MIRGraph &graph, CompileInfo &info, MBasicBlock *pred); 1.85 + static MBasicBlock *NewAbortPar(MIRGraph &graph, CompileInfo &info, 1.86 + MBasicBlock *pred, jsbytecode *entryPc, 1.87 + MResumePoint *resumePoint); 1.88 + static MBasicBlock *NewAsmJS(MIRGraph &graph, CompileInfo &info, 1.89 + MBasicBlock *pred, Kind kind); 1.90 + 1.91 + bool dominates(const MBasicBlock *other) const; 1.92 + 1.93 + void setId(uint32_t id) { 1.94 + id_ = id; 1.95 + } 1.96 + 1.97 + // Mark the current block and all dominated blocks as unreachable. 1.98 + void setUnreachable(); 1.99 + bool unreachable() const { 1.100 + return unreachable_; 1.101 + } 1.102 + // Move the definition to the top of the stack. 1.103 + void pick(int32_t depth); 1.104 + 1.105 + // Exchange 2 stack slots at the defined depth 1.106 + void swapAt(int32_t depth); 1.107 + 1.108 + // Gets the instruction associated with various slot types. 1.109 + MDefinition *peek(int32_t depth); 1.110 + 1.111 + MDefinition *scopeChain(); 1.112 + MDefinition *argumentsObject(); 1.113 + 1.114 + // Increase the number of slots available 1.115 + bool increaseSlots(size_t num); 1.116 + bool ensureHasSlots(size_t num); 1.117 + 1.118 + // Initializes a slot value; must not be called for normal stack 1.119 + // operations, as it will not create new SSA names for copies. 1.120 + void initSlot(uint32_t index, MDefinition *ins); 1.121 + 1.122 + // Discard the slot at the given depth, lowering all slots above. 1.123 + void shimmySlots(int discardDepth); 1.124 + 1.125 + // In an OSR block, set all MOsrValues to use the MResumePoint attached to 1.126 + // the MStart. 1.127 + void linkOsrValues(MStart *start); 1.128 + 1.129 + // Sets the instruction associated with various slot types. The 1.130 + // instruction must lie at the top of the stack. 1.131 + void setLocal(uint32_t local); 1.132 + void setArg(uint32_t arg); 1.133 + void setSlot(uint32_t slot); 1.134 + void setSlot(uint32_t slot, MDefinition *ins); 1.135 + 1.136 + // Rewrites a slot directly, bypassing the stack transition. This should 1.137 + // not be used under most circumstances. 1.138 + void rewriteSlot(uint32_t slot, MDefinition *ins); 1.139 + 1.140 + // Rewrites a slot based on its depth (same as argument to peek()). 1.141 + void rewriteAtDepth(int32_t depth, MDefinition *ins); 1.142 + 1.143 + // Tracks an instruction as being pushed onto the operand stack. 1.144 + void push(MDefinition *ins); 1.145 + void pushArg(uint32_t arg); 1.146 + void pushLocal(uint32_t local); 1.147 + void pushSlot(uint32_t slot); 1.148 + void setScopeChain(MDefinition *ins); 1.149 + void setArgumentsObject(MDefinition *ins); 1.150 + 1.151 + // Returns the top of the stack, then decrements the virtual stack pointer. 1.152 + MDefinition *pop(); 1.153 + void popn(uint32_t n); 1.154 + 1.155 + // Adds an instruction to this block's instruction list. |ins| may be 1.156 + // nullptr to simplify OOM checking. 1.157 + void add(MInstruction *ins); 1.158 + 1.159 + // Marks the last instruction of the block; no further instructions 1.160 + // can be added. 1.161 + void end(MControlInstruction *ins); 1.162 + 1.163 + // Adds a phi instruction, but does not set successorWithPhis. 1.164 + void addPhi(MPhi *phi); 1.165 + 1.166 + // Adds a resume point to this block. 1.167 + void addResumePoint(MResumePoint *resume) { 1.168 + resumePoints_.pushFront(resume); 1.169 + } 1.170 + 1.171 + // Adds a predecessor. Every predecessor must have the same exit stack 1.172 + // depth as the entry state to this block. Adding a predecessor 1.173 + // automatically creates phi nodes and rewrites uses as needed. 1.174 + bool addPredecessor(TempAllocator &alloc, MBasicBlock *pred); 1.175 + bool addPredecessorPopN(TempAllocator &alloc, MBasicBlock *pred, uint32_t popped); 1.176 + 1.177 + // Stranger utilities used for inlining. 1.178 + bool addPredecessorWithoutPhis(MBasicBlock *pred); 1.179 + void inheritSlots(MBasicBlock *parent); 1.180 + bool initEntrySlots(TempAllocator &alloc); 1.181 + 1.182 + // Replaces an edge for a given block with a new block. This is 1.183 + // used for critical edge splitting and also for inserting 1.184 + // bailouts during ParallelSafetyAnalysis. 1.185 + // 1.186 + // Note: If successorWithPhis is set, you must not be replacing it. 1.187 + void replacePredecessor(MBasicBlock *old, MBasicBlock *split); 1.188 + void replaceSuccessor(size_t pos, MBasicBlock *split); 1.189 + 1.190 + // Removes `pred` from the predecessor list. `pred` should not be 1.191 + // the final predecessor. If this block defines phis, removes the 1.192 + // entry for `pred` and updates the indices of later entries. 1.193 + // This may introduce redundant phis if the new block has fewer 1.194 + // than two predecessors. 1.195 + void removePredecessor(MBasicBlock *pred); 1.196 + 1.197 + // Resets all the dominator info so that it can be recomputed. 1.198 + void clearDominatorInfo(); 1.199 + 1.200 + // Sets a back edge. This places phi nodes and rewrites instructions within 1.201 + // the current loop as necessary. If the backedge introduces new types for 1.202 + // phis at the loop header, returns a disabling abort. 1.203 + AbortReason setBackedge(MBasicBlock *block); 1.204 + bool setBackedgeAsmJS(MBasicBlock *block); 1.205 + 1.206 + // Resets a LOOP_HEADER block to a NORMAL block. This is needed when 1.207 + // optimizations remove the backedge. 1.208 + void clearLoopHeader(); 1.209 + 1.210 + // Propagates phis placed in a loop header down to this successor block. 1.211 + void inheritPhis(MBasicBlock *header); 1.212 + 1.213 + // Compute the types for phis in this block according to their inputs. 1.214 + bool specializePhis(); 1.215 + 1.216 + void insertBefore(MInstruction *at, MInstruction *ins); 1.217 + void insertAfter(MInstruction *at, MInstruction *ins); 1.218 + 1.219 + // Add an instruction to this block, from elsewhere in the graph. 1.220 + void addFromElsewhere(MInstruction *ins); 1.221 + 1.222 + // Move an instruction. Movement may cross block boundaries. 1.223 + void moveBefore(MInstruction *at, MInstruction *ins); 1.224 + 1.225 + // Removes an instruction with the intention to discard it. 1.226 + void discard(MInstruction *ins); 1.227 + void discardLastIns(); 1.228 + MInstructionIterator discardAt(MInstructionIterator &iter); 1.229 + MInstructionReverseIterator discardAt(MInstructionReverseIterator &iter); 1.230 + MDefinitionIterator discardDefAt(MDefinitionIterator &iter); 1.231 + void discardAllInstructions(); 1.232 + void discardAllPhiOperands(); 1.233 + void discardAllPhis(); 1.234 + void discardAllResumePoints(bool discardEntry = true); 1.235 + 1.236 + // Discards a phi instruction and updates predecessor successorWithPhis. 1.237 + MPhiIterator discardPhiAt(MPhiIterator &at); 1.238 + 1.239 + // Mark this block as having been removed from the graph. 1.240 + void markAsDead() { 1.241 + kind_ = DEAD; 1.242 + } 1.243 + 1.244 + /////////////////////////////////////////////////////// 1.245 + /////////// END GRAPH BUILDING INSTRUCTIONS /////////// 1.246 + /////////////////////////////////////////////////////// 1.247 + 1.248 + MIRGraph &graph() { 1.249 + return graph_; 1.250 + } 1.251 + CompileInfo &info() const { 1.252 + return info_; 1.253 + } 1.254 + jsbytecode *pc() const { 1.255 + return pc_; 1.256 + } 1.257 + uint32_t nslots() const { 1.258 + return slots_.length(); 1.259 + } 1.260 + uint32_t id() const { 1.261 + return id_; 1.262 + } 1.263 + uint32_t numPredecessors() const { 1.264 + return predecessors_.length(); 1.265 + } 1.266 + 1.267 + uint32_t domIndex() const { 1.268 + JS_ASSERT(!isDead()); 1.269 + return domIndex_; 1.270 + } 1.271 + void setDomIndex(uint32_t d) { 1.272 + domIndex_ = d; 1.273 + } 1.274 + 1.275 + MBasicBlock *getPredecessor(uint32_t i) const { 1.276 + return predecessors_[i]; 1.277 + } 1.278 + MControlInstruction *lastIns() const { 1.279 + return lastIns_; 1.280 + } 1.281 + MPhiIterator phisBegin() const { 1.282 + return phis_.begin(); 1.283 + } 1.284 + MPhiIterator phisEnd() const { 1.285 + return phis_.end(); 1.286 + } 1.287 + bool phisEmpty() const { 1.288 + return phis_.empty(); 1.289 + } 1.290 + MResumePointIterator resumePointsBegin() const { 1.291 + return resumePoints_.begin(); 1.292 + } 1.293 + MResumePointIterator resumePointsEnd() const { 1.294 + return resumePoints_.end(); 1.295 + } 1.296 + bool resumePointsEmpty() const { 1.297 + return resumePoints_.empty(); 1.298 + } 1.299 + MInstructionIterator begin() { 1.300 + return instructions_.begin(); 1.301 + } 1.302 + MInstructionIterator begin(MInstruction *at) { 1.303 + JS_ASSERT(at->block() == this); 1.304 + return instructions_.begin(at); 1.305 + } 1.306 + MInstructionIterator end() { 1.307 + return instructions_.end(); 1.308 + } 1.309 + MInstructionReverseIterator rbegin() { 1.310 + return instructions_.rbegin(); 1.311 + } 1.312 + MInstructionReverseIterator rbegin(MInstruction *at) { 1.313 + JS_ASSERT(at->block() == this); 1.314 + return instructions_.rbegin(at); 1.315 + } 1.316 + MInstructionReverseIterator rend() { 1.317 + return instructions_.rend(); 1.318 + } 1.319 + bool isLoopHeader() const { 1.320 + return kind_ == LOOP_HEADER; 1.321 + } 1.322 + bool hasUniqueBackedge() const { 1.323 + JS_ASSERT(isLoopHeader()); 1.324 + JS_ASSERT(numPredecessors() >= 2); 1.325 + return numPredecessors() == 2; 1.326 + } 1.327 + MBasicBlock *backedge() const { 1.328 + JS_ASSERT(hasUniqueBackedge()); 1.329 + return getPredecessor(numPredecessors() - 1); 1.330 + } 1.331 + MBasicBlock *loopHeaderOfBackedge() const { 1.332 + JS_ASSERT(isLoopBackedge()); 1.333 + return getSuccessor(numSuccessors() - 1); 1.334 + } 1.335 + MBasicBlock *loopPredecessor() const { 1.336 + JS_ASSERT(isLoopHeader()); 1.337 + return getPredecessor(0); 1.338 + } 1.339 + bool isLoopBackedge() const { 1.340 + if (!numSuccessors()) 1.341 + return false; 1.342 + MBasicBlock *lastSuccessor = getSuccessor(numSuccessors() - 1); 1.343 + return lastSuccessor->isLoopHeader() && 1.344 + lastSuccessor->hasUniqueBackedge() && 1.345 + lastSuccessor->backedge() == this; 1.346 + } 1.347 + bool isSplitEdge() const { 1.348 + return kind_ == SPLIT_EDGE; 1.349 + } 1.350 + bool isDead() const { 1.351 + return kind_ == DEAD; 1.352 + } 1.353 + 1.354 + uint32_t stackDepth() const { 1.355 + return stackPosition_; 1.356 + } 1.357 + void setStackDepth(uint32_t depth) { 1.358 + stackPosition_ = depth; 1.359 + } 1.360 + bool isMarked() const { 1.361 + return mark_; 1.362 + } 1.363 + void mark() { 1.364 + mark_ = true; 1.365 + } 1.366 + void unmark() { 1.367 + mark_ = false; 1.368 + } 1.369 + void makeStart(MStart *start) { 1.370 + add(start); 1.371 + start_ = start; 1.372 + } 1.373 + MStart *start() const { 1.374 + return start_; 1.375 + } 1.376 + 1.377 + MBasicBlock *immediateDominator() const { 1.378 + return immediateDominator_; 1.379 + } 1.380 + 1.381 + void setImmediateDominator(MBasicBlock *dom) { 1.382 + immediateDominator_ = dom; 1.383 + } 1.384 + 1.385 + MTest *immediateDominatorBranch(BranchDirection *pdirection); 1.386 + 1.387 + size_t numImmediatelyDominatedBlocks() const { 1.388 + return immediatelyDominated_.length(); 1.389 + } 1.390 + 1.391 + MBasicBlock *getImmediatelyDominatedBlock(size_t i) const { 1.392 + return immediatelyDominated_[i]; 1.393 + } 1.394 + 1.395 + MBasicBlock **immediatelyDominatedBlocksBegin() { 1.396 + return immediatelyDominated_.begin(); 1.397 + } 1.398 + 1.399 + MBasicBlock **immediatelyDominatedBlocksEnd() { 1.400 + return immediatelyDominated_.end(); 1.401 + } 1.402 + 1.403 + size_t numDominated() const { 1.404 + return numDominated_; 1.405 + } 1.406 + 1.407 + void addNumDominated(size_t n) { 1.408 + numDominated_ += n; 1.409 + } 1.410 + 1.411 + bool addImmediatelyDominatedBlock(MBasicBlock *child); 1.412 + 1.413 + // This function retrieves the internal instruction associated with a 1.414 + // slot, and should not be used for normal stack operations. It is an 1.415 + // internal helper that is also used to enhance spew. 1.416 + MDefinition *getSlot(uint32_t index); 1.417 + 1.418 + MResumePoint *entryResumePoint() const { 1.419 + return entryResumePoint_; 1.420 + } 1.421 + MResumePoint *callerResumePoint() { 1.422 + return entryResumePoint()->caller(); 1.423 + } 1.424 + void setCallerResumePoint(MResumePoint *caller) { 1.425 + entryResumePoint()->setCaller(caller); 1.426 + } 1.427 + size_t numEntrySlots() const { 1.428 + return entryResumePoint()->numOperands(); 1.429 + } 1.430 + MDefinition *getEntrySlot(size_t i) const { 1.431 + JS_ASSERT(i < numEntrySlots()); 1.432 + return entryResumePoint()->getOperand(i); 1.433 + } 1.434 + 1.435 + LBlock *lir() const { 1.436 + return lir_; 1.437 + } 1.438 + void assignLir(LBlock *lir) { 1.439 + JS_ASSERT(!lir_); 1.440 + lir_ = lir; 1.441 + } 1.442 + 1.443 + MBasicBlock *successorWithPhis() const { 1.444 + return successorWithPhis_; 1.445 + } 1.446 + uint32_t positionInPhiSuccessor() const { 1.447 + return positionInPhiSuccessor_; 1.448 + } 1.449 + void setSuccessorWithPhis(MBasicBlock *successor, uint32_t id) { 1.450 + successorWithPhis_ = successor; 1.451 + positionInPhiSuccessor_ = id; 1.452 + } 1.453 + size_t numSuccessors() const; 1.454 + MBasicBlock *getSuccessor(size_t index) const; 1.455 + size_t getSuccessorIndex(MBasicBlock *) const; 1.456 + 1.457 + void setLoopDepth(uint32_t loopDepth) { 1.458 + loopDepth_ = loopDepth; 1.459 + } 1.460 + uint32_t loopDepth() const { 1.461 + return loopDepth_; 1.462 + } 1.463 + 1.464 + bool strict() const { 1.465 + return info_.script()->strict(); 1.466 + } 1.467 + 1.468 + void dumpStack(FILE *fp); 1.469 + 1.470 + void dump(FILE *fp); 1.471 + void dump(); 1.472 + 1.473 + // Track bailouts by storing the current pc in MIR instruction added at this 1.474 + // cycle. This is also used for tracking calls when profiling. 1.475 + void updateTrackedPc(jsbytecode *pc) { 1.476 + trackedPc_ = pc; 1.477 + } 1.478 + 1.479 + jsbytecode *trackedPc() { 1.480 + return trackedPc_; 1.481 + } 1.482 + 1.483 + private: 1.484 + MIRGraph &graph_; 1.485 + CompileInfo &info_; // Each block originates from a particular script. 1.486 + InlineList<MInstruction> instructions_; 1.487 + Vector<MBasicBlock *, 1, IonAllocPolicy> predecessors_; 1.488 + InlineForwardList<MPhi> phis_; 1.489 + InlineForwardList<MResumePoint> resumePoints_; 1.490 + FixedList<MDefinition *> slots_; 1.491 + uint32_t stackPosition_; 1.492 + MControlInstruction *lastIns_; 1.493 + jsbytecode *pc_; 1.494 + uint32_t id_; 1.495 + uint32_t domIndex_; // Index in the dominator tree. 1.496 + LBlock *lir_; 1.497 + MStart *start_; 1.498 + MResumePoint *entryResumePoint_; 1.499 + MBasicBlock *successorWithPhis_; 1.500 + uint32_t positionInPhiSuccessor_; 1.501 + Kind kind_; 1.502 + uint32_t loopDepth_; 1.503 + 1.504 + // Utility mark for traversal algorithms. 1.505 + bool mark_; 1.506 + 1.507 + Vector<MBasicBlock *, 1, IonAllocPolicy> immediatelyDominated_; 1.508 + MBasicBlock *immediateDominator_; 1.509 + size_t numDominated_; 1.510 + 1.511 + jsbytecode *trackedPc_; 1.512 + 1.513 +#if defined (JS_ION_PERF) 1.514 + unsigned lineno_; 1.515 + unsigned columnIndex_; 1.516 + 1.517 + public: 1.518 + void setLineno(unsigned l) { lineno_ = l; } 1.519 + unsigned lineno() const { return lineno_; } 1.520 + void setColumnIndex(unsigned c) { columnIndex_ = c; } 1.521 + unsigned columnIndex() const { return columnIndex_; } 1.522 +#endif 1.523 +}; 1.524 + 1.525 +typedef InlineListIterator<MBasicBlock> MBasicBlockIterator; 1.526 +typedef InlineListIterator<MBasicBlock> ReversePostorderIterator; 1.527 +typedef InlineListReverseIterator<MBasicBlock> PostorderIterator; 1.528 + 1.529 +typedef Vector<MBasicBlock *, 1, IonAllocPolicy> MIRGraphReturns; 1.530 + 1.531 +class MIRGraph 1.532 +{ 1.533 + InlineList<MBasicBlock> blocks_; 1.534 + TempAllocator *alloc_; 1.535 + MIRGraphReturns *returnAccumulator_; 1.536 + uint32_t blockIdGen_; 1.537 + uint32_t idGen_; 1.538 + MBasicBlock *osrBlock_; 1.539 + MStart *osrStart_; 1.540 + 1.541 + size_t numBlocks_; 1.542 + bool hasTryBlock_; 1.543 + 1.544 + public: 1.545 + MIRGraph(TempAllocator *alloc) 1.546 + : alloc_(alloc), 1.547 + returnAccumulator_(nullptr), 1.548 + blockIdGen_(0), 1.549 + idGen_(1), 1.550 + osrBlock_(nullptr), 1.551 + osrStart_(nullptr), 1.552 + numBlocks_(0), 1.553 + hasTryBlock_(false) 1.554 + { } 1.555 + 1.556 + TempAllocator &alloc() const { 1.557 + return *alloc_; 1.558 + } 1.559 + 1.560 + void addBlock(MBasicBlock *block); 1.561 + void insertBlockAfter(MBasicBlock *at, MBasicBlock *block); 1.562 + 1.563 + void unmarkBlocks(); 1.564 + 1.565 + void setReturnAccumulator(MIRGraphReturns *accum) { 1.566 + returnAccumulator_ = accum; 1.567 + } 1.568 + MIRGraphReturns *returnAccumulator() const { 1.569 + return returnAccumulator_; 1.570 + } 1.571 + 1.572 + bool addReturn(MBasicBlock *returnBlock) { 1.573 + if (!returnAccumulator_) 1.574 + return true; 1.575 + 1.576 + return returnAccumulator_->append(returnBlock); 1.577 + } 1.578 + 1.579 + MBasicBlock *entryBlock() { 1.580 + return *blocks_.begin(); 1.581 + } 1.582 + 1.583 + void clearBlockList() { 1.584 + blocks_.clear(); 1.585 + blockIdGen_ = 0; 1.586 + numBlocks_ = 0; 1.587 + } 1.588 + void resetInstructionNumber() { 1.589 + // This intentionally starts above 0. The id 0 is in places used to 1.590 + // indicate a failure to perform an operation on an instruction. 1.591 + idGen_ = 1; 1.592 + } 1.593 + MBasicBlockIterator begin() { 1.594 + return blocks_.begin(); 1.595 + } 1.596 + MBasicBlockIterator begin(MBasicBlock *at) { 1.597 + return blocks_.begin(at); 1.598 + } 1.599 + MBasicBlockIterator end() { 1.600 + return blocks_.end(); 1.601 + } 1.602 + PostorderIterator poBegin() { 1.603 + return blocks_.rbegin(); 1.604 + } 1.605 + PostorderIterator poEnd() { 1.606 + return blocks_.rend(); 1.607 + } 1.608 + ReversePostorderIterator rpoBegin() { 1.609 + return blocks_.begin(); 1.610 + } 1.611 + ReversePostorderIterator rpoBegin(MBasicBlock *at) { 1.612 + return blocks_.begin(at); 1.613 + } 1.614 + ReversePostorderIterator rpoEnd() { 1.615 + return blocks_.end(); 1.616 + } 1.617 + void removeBlocksAfter(MBasicBlock *block); 1.618 + void removeBlock(MBasicBlock *block); 1.619 + void moveBlockToEnd(MBasicBlock *block) { 1.620 + JS_ASSERT(block->id()); 1.621 + blocks_.remove(block); 1.622 + blocks_.pushBack(block); 1.623 + } 1.624 + size_t numBlocks() const { 1.625 + return numBlocks_; 1.626 + } 1.627 + uint32_t numBlockIds() const { 1.628 + return blockIdGen_; 1.629 + } 1.630 + void allocDefinitionId(MDefinition *ins) { 1.631 + ins->setId(idGen_++); 1.632 + } 1.633 + uint32_t getNumInstructionIds() { 1.634 + return idGen_; 1.635 + } 1.636 + MResumePoint *entryResumePoint() { 1.637 + return blocks_.begin()->entryResumePoint(); 1.638 + } 1.639 + 1.640 + void copyIds(const MIRGraph &other) { 1.641 + idGen_ = other.idGen_; 1.642 + blockIdGen_ = other.blockIdGen_; 1.643 + numBlocks_ = other.numBlocks_; 1.644 + } 1.645 + 1.646 + void setOsrBlock(MBasicBlock *osrBlock) { 1.647 + JS_ASSERT(!osrBlock_); 1.648 + osrBlock_ = osrBlock; 1.649 + } 1.650 + MBasicBlock *osrBlock() { 1.651 + return osrBlock_; 1.652 + } 1.653 + void setOsrStart(MStart *osrStart) { 1.654 + osrStart_ = osrStart; 1.655 + } 1.656 + MStart *osrStart() { 1.657 + return osrStart_; 1.658 + } 1.659 + 1.660 + bool hasTryBlock() const { 1.661 + return hasTryBlock_; 1.662 + } 1.663 + void setHasTryBlock() { 1.664 + hasTryBlock_ = true; 1.665 + } 1.666 + 1.667 + // The per-thread context. So as not to modify the calling convention for 1.668 + // parallel code, we obtain the current ForkJoinContext from thread-local 1.669 + // storage. This helper method will lazilly insert an MForkJoinContext 1.670 + // instruction in the entry block and return the definition. 1.671 + MDefinition *forkJoinContext(); 1.672 + 1.673 + void dump(FILE *fp); 1.674 + void dump(); 1.675 +}; 1.676 + 1.677 +class MDefinitionIterator 1.678 +{ 1.679 + 1.680 + friend class MBasicBlock; 1.681 + 1.682 + private: 1.683 + MBasicBlock *block_; 1.684 + MPhiIterator phiIter_; 1.685 + MInstructionIterator iter_; 1.686 + 1.687 + bool atPhi() const { 1.688 + return phiIter_ != block_->phisEnd(); 1.689 + } 1.690 + 1.691 + MDefinition *getIns() { 1.692 + if (atPhi()) 1.693 + return *phiIter_; 1.694 + return *iter_; 1.695 + } 1.696 + 1.697 + void next() { 1.698 + if (atPhi()) 1.699 + phiIter_++; 1.700 + else 1.701 + iter_++; 1.702 + } 1.703 + 1.704 + bool more() const { 1.705 + return atPhi() || (*iter_) != block_->lastIns(); 1.706 + } 1.707 + 1.708 + public: 1.709 + MDefinitionIterator(MBasicBlock *block) 1.710 + : block_(block), 1.711 + phiIter_(block->phisBegin()), 1.712 + iter_(block->begin()) 1.713 + { } 1.714 + 1.715 + MDefinitionIterator operator ++(int) { 1.716 + MDefinitionIterator old(*this); 1.717 + if (more()) 1.718 + next(); 1.719 + return old; 1.720 + } 1.721 + 1.722 + operator bool() const { 1.723 + return more(); 1.724 + } 1.725 + 1.726 + MDefinition *operator *() { 1.727 + return getIns(); 1.728 + } 1.729 + 1.730 + MDefinition *operator ->() { 1.731 + return getIns(); 1.732 + } 1.733 + 1.734 +}; 1.735 + 1.736 +} // namespace jit 1.737 +} // namespace js 1.738 + 1.739 +#endif /* jit_MIRGraph_h */